diff --git a/.github/workflows/api-ee.yaml b/.github/workflows/api-ee.yaml index e77a80565..9eb23910a 100644 --- a/.github/workflows/api-ee.yaml +++ b/.github/workflows/api-ee.yaml @@ -1,6 +1,11 @@ # This action will push the chalice changes to aws on: workflow_dispatch: + inputs: + skip_security_checks: + description: 'Skip Security checks if there is a unfixable vuln or error. Value: true/false' + required: false + default: 'false' push: branches: - dev @@ -43,11 +48,26 @@ jobs: id: build-image env: DOCKER_REPO: ${{ secrets.EE_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }}-ee + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }}-ee ENVIRONMENT: staging run: | + skip_security_checks=${{ github.event.inputs.skip_security_checks }} cd api - PUSH_IMAGE=1 bash build.sh ee + PUSH_IMAGE=0 bash -x ./build.sh ee + [[ "x$skip_security_checks" == "xtrue" ]] || { + curl -L https://github.com/aquasecurity/trivy/releases/download/v0.34.0/trivy_0.34.0_Linux-64bit.tar.gz | tar -xzf - -C ./ + images=("chalice" "alerts") + for image in ${images[*]};do + ./trivy image --exit-code 1 --security-checks vuln --vuln-type os,library --severity "HIGH,CRITICAL" --ignore-unfixed $DOCKER_REPO/$image:$IMAGE_TAG + done + err_code=$? + [[ $err_code -ne 0 ]] && { + exit $err_code + } + } && { + echo "Skipping Security Checks" + } + PUSH_IMAGE=1 bash -x ./build.sh ee - name: Creating old image input run: | # @@ -91,9 +111,20 @@ jobs: env: DOCKER_REPO: ${{ secrets.EE_REGISTRY_URL }} # We're not passing -ee flag, because helm will add that. - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging + - name: Alert slack + if: ${{ failure() }} + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_CHANNEL: ee + SLACK_TITLE: "Failed ${{ github.workflow }}" + SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff' + SLACK_WEBHOOK: ${{ secrets.SLACK_WEB_HOOK }} + SLACK_USERNAME: "OR Bot" + SLACK_MESSAGE: 'Build failed :bomb:' + # - name: Debug Job # if: ${{ failure() }} # uses: mxschmitt/action-tmate@v3 diff --git a/.github/workflows/api.yaml b/.github/workflows/api.yaml index 2f11de7e4..e4d85ff24 100644 --- a/.github/workflows/api.yaml +++ b/.github/workflows/api.yaml @@ -1,6 +1,11 @@ # This action will push the chalice changes to aws on: workflow_dispatch: + inputs: + skip_security_checks: + description: 'Skip Security checks if there is a unfixable vuln or error. Value: true/false' + required: false + default: 'false' push: branches: - dev @@ -42,11 +47,26 @@ jobs: id: build-image env: DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging run: | + skip_security_checks=${{ github.event.inputs.skip_security_checks }} cd api - PUSH_IMAGE=1 bash build.sh + PUSH_IMAGE=0 bash -x ./build.sh + [[ "x$skip_security_checks" == "xtrue" ]] || { + curl -L https://github.com/aquasecurity/trivy/releases/download/v0.34.0/trivy_0.34.0_Linux-64bit.tar.gz | tar -xzf - -C ./ + images=("chalice" "alerts") + for image in ${images[*]};do + ./trivy image --exit-code 1 --security-checks vuln --vuln-type os,library --severity "HIGH,CRITICAL" --ignore-unfixed $DOCKER_REPO/$image:$IMAGE_TAG + done + err_code=$? + [[ $err_code -ne 0 ]] && { + exit $err_code + } + } && { + echo "Skipping Security Checks" + } + PUSH_IMAGE=1 bash -x ./build.sh - name: Creating old image input run: | # @@ -90,9 +110,20 @@ jobs: helm template openreplay -n app openreplay -f vars.yaml -f /tmp/image_override.yaml --set ingress-nginx.enabled=false --set skipMigration=true --no-hooks | kubectl apply -n app -f - env: DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging + - name: Alert slack + if: ${{ failure() }} + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_CHANNEL: foss + SLACK_TITLE: "Failed ${{ github.workflow }}" + SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff' + SLACK_WEBHOOK: ${{ secrets.SLACK_WEB_HOOK }} + SLACK_USERNAME: "OR Bot" + SLACK_MESSAGE: 'Build failed :bomb:' + # - name: Debug Job # if: ${{ failure() }} # uses: mxschmitt/action-tmate@v3 diff --git a/.github/workflows/frontend.yaml b/.github/workflows/frontend.yaml index 4b2d9cd93..2f2fd3989 100644 --- a/.github/workflows/frontend.yaml +++ b/.github/workflows/frontend.yaml @@ -41,7 +41,7 @@ jobs: id: build-image env: DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging run: | set -x @@ -84,7 +84,7 @@ jobs: helm template openreplay -n app openreplay -f vars.yaml -f /tmp/image_override.yaml --set ingress-nginx.enabled=false --set skipMigration=true --no-hooks | kubectl apply -n app -f - env: DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging @@ -130,7 +130,7 @@ jobs: env: DOCKER_REPO: ${{ secrets.EE_REGISTRY_URL }} # We're not passing -ee flag, because helm will add that. - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging # - name: Debug Job diff --git a/.github/workflows/sourcemaps-reader.yaml b/.github/workflows/sourcemaps-reader.yaml new file mode 100644 index 000000000..547295425 --- /dev/null +++ b/.github/workflows/sourcemaps-reader.yaml @@ -0,0 +1,103 @@ +# This action will push the chalice changes to aws +on: + workflow_dispatch: + push: + branches: + - dev + paths: + - sourcemap-reader/** + +name: Build and Deploy Chalice + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + # We need to diff with old commit + # to see which workers got changed. + fetch-depth: 2 + + - name: Docker login + run: | + docker login ${{ secrets.OSS_REGISTRY_URL }} -u ${{ secrets.OSS_DOCKER_USERNAME }} -p "${{ secrets.OSS_REGISTRY_TOKEN }}" + + - uses: azure/k8s-set-context@v1 + with: + method: kubeconfig + kubeconfig: ${{ secrets.OSS_KUBECONFIG }} # Use content of kubeconfig in secret. + id: setcontext + + # Caching docker images + - uses: satackey/action-docker-layer-caching@v0.0.11 + # Ignore the failure of a step and avoid terminating the job. + continue-on-error: true + + + - name: Building and Pusing sourcemaps-reader image + id: build-image + env: + DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} + ENVIRONMENT: staging + run: | + cd sourcemap-reader + PUSH_IMAGE=1 bash build.sh + - name: Creating old image input + run: | + # + # Create yaml with existing image tags + # + kubectl get pods -n app -o jsonpath="{.items[*].spec.containers[*].image}" |\ + tr -s '[[:space:]]' '\n' | sort | uniq -c | grep '/foss/' | cut -d '/' -f3 > /tmp/image_tag.txt + + echo > /tmp/image_override.yaml + + for line in `cat /tmp/image_tag.txt`; + do + image_array=($(echo "$line" | tr ':' '\n')) + cat <> /tmp/image_override.yaml + ${image_array[0]}: + image: + tag: ${image_array[1]} + EOF + done + + - name: Deploy to kubernetes + run: | + cd scripts/helmcharts/ + + ## Update secerts + sed -i "s#openReplayContainerRegistry.*#openReplayContainerRegistry: \"${{ secrets.OSS_REGISTRY_URL }}\"#g" vars.yaml + sed -i "s/postgresqlPassword: \"changeMePassword\"/postgresqlPassword: \"${{ secrets.OSS_PG_PASSWORD }}\"/g" vars.yaml + sed -i "s/accessKey: \"changeMeMinioAccessKey\"/accessKey: \"${{ secrets.OSS_MINIO_ACCESS_KEY }}\"/g" vars.yaml + sed -i "s/secretKey: \"changeMeMinioPassword\"/secretKey: \"${{ secrets.OSS_MINIO_SECRET_KEY }}\"/g" vars.yaml + sed -i "s/jwt_secret: \"SetARandomStringHere\"/jwt_secret: \"${{ secrets.OSS_JWT_SECRET }}\"/g" vars.yaml + sed -i "s/domainName: \"\"/domainName: \"${{ secrets.OSS_DOMAIN_NAME }}\"/g" vars.yaml + + # Update changed image tag + sed -i "/chalice/{n;n;s/.*/ tag: ${IMAGE_TAG}/}" /tmp/image_override.yaml + + cat /tmp/image_override.yaml + # Deploy command + mv openreplay/charts/{ingress-nginx,chalice,quickwit} /tmp + rm -rf openreplay/charts/* + mv /tmp/{ingress-nginx,chalice,quickwit} openreplay/charts/ + helm template openreplay -n app openreplay -f vars.yaml -f /tmp/image_override.yaml --set ingress-nginx.enabled=false --set skipMigration=true --no-hooks | kubectl apply -n app -f - + env: + DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} + ENVIRONMENT: staging + + # - name: Debug Job + # if: ${{ failure() }} + # uses: mxschmitt/action-tmate@v3 + # env: + # DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} + # IMAGE_TAG: ${{ github.sha }} + # ENVIRONMENT: staging + # diff --git a/.github/workflows/utilities.yaml b/.github/workflows/utilities.yaml index 8a1e5b457..92e130c84 100644 --- a/.github/workflows/utilities.yaml +++ b/.github/workflows/utilities.yaml @@ -36,7 +36,7 @@ jobs: id: build-image env: DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging run: | cd utilities @@ -53,7 +53,7 @@ jobs: bash kube-install.sh --app utilities env: DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging # - name: Debug Job diff --git a/.github/workflows/workers-ee.yaml b/.github/workflows/workers-ee.yaml index d1b06a9fb..c573dff26 100644 --- a/.github/workflows/workers-ee.yaml +++ b/.github/workflows/workers-ee.yaml @@ -7,6 +7,10 @@ on: description: 'Name of a single service to build(in small letters). "all" to build everything' required: false default: 'false' + skip_security_checks: + description: 'Skip Security checks if there is a unfixable vuln or error. Value: true/false' + required: false + default: 'false' push: branches: - dev @@ -49,7 +53,7 @@ jobs: id: build-image env: DOCKER_REPO: ${{ secrets.EE_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }}-ee + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }}-ee ENVIRONMENT: staging run: | # @@ -61,6 +65,7 @@ jobs: # set -x touch /tmp/images_to_build.txt + skip_security_checks=${{ github.event.inputs.skip_security_checks }} tmp_param=${{ github.event.inputs.build_service }} build_param=${tmp_param:-'false'} case ${build_param} in @@ -81,7 +86,11 @@ jobs: ;; esac - [[ $(cat /tmp/images_to_build.txt) != "" ]] || (echo "Nothing to build here"; exit 1) + if [[ $(cat /tmp/images_to_build.txt) == "" ]]; then + echo "Nothing to build here" + touch /tmp/nothing-to-build-here + exit 0 + fi # # Pushing image to registry # @@ -89,6 +98,17 @@ jobs: for image in $(cat /tmp/images_to_build.txt); do echo "Bulding $image" + PUSH_IMAGE=0 bash -x ./build.sh ee $image + [[ "x$skip_security_checks" == "xtrue" ]] || { + curl -L https://github.com/aquasecurity/trivy/releases/download/v0.34.0/trivy_0.34.0_Linux-64bit.tar.gz | tar -xzf - -C ./ + ./trivy image --exit-code 1 --vuln-type os,library --severity "HIGH,CRITICAL" --ignore-unfixed $DOCKER_REPO/$image:$IMAGE_TAG + err_code=$? + [[ $err_code -ne 0 ]] && { + exit $err_code + } + } && { + echo "Skipping Security Checks" + } PUSH_IMAGE=1 bash -x ./build.sh ee $image echo "::set-output name=image::$DOCKER_REPO/$image:$IMAGE_TAG" done @@ -96,12 +116,13 @@ jobs: - name: Deploying to kuberntes env: # We're not passing -ee flag, because helm will add that. - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} run: | # # Deploying image to environment. # set -x + [[ -f /tmp/nothing-to-build-here ]] && exit 0 cd scripts/helmcharts/ ## Update secerts @@ -140,6 +161,18 @@ jobs: # Deploy command helm template openreplay -n app openreplay -f vars.yaml -f /tmp/image_override.yaml --set ingress-nginx.enabled=false --set skipMigration=true | kubectl apply -f - + #- name: Alert slack + # if: ${{ failure() }} + # uses: rtCamp/action-slack-notify@v2 + # env: + # SLACK_CHANNEL: ee + # SLACK_TITLE: "Failed ${{ github.workflow }}" + # SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff' + # SLACK_WEBHOOK: ${{ secrets.SLACK_WEB_HOOK }} + # SLACK_USERNAME: "OR Bot" + # SLACK_MESSAGE: 'Build failed :bomb:' + + # - name: Debug Job # if: ${{ failure() }} # uses: mxschmitt/action-tmate@v3 diff --git a/.github/workflows/workers.yaml b/.github/workflows/workers.yaml index 1b8c7f495..e222e00fb 100644 --- a/.github/workflows/workers.yaml +++ b/.github/workflows/workers.yaml @@ -53,7 +53,7 @@ jobs: id: build-image env: DOCKER_REPO: ${{ secrets.OSS_REGISTRY_URL }} - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} ENVIRONMENT: staging run: | # @@ -63,7 +63,7 @@ jobs: # # Getting the images to build # - set -x + set -xe touch /tmp/images_to_build.txt skip_security_checks=${{ github.event.inputs.skip_security_checks }} tmp_param=${{ github.event.inputs.build_service }} @@ -86,7 +86,11 @@ jobs: ;; esac - [[ $(cat /tmp/images_to_build.txt) != "" ]] || (echo "Nothing to build here"; exit 1) + if [[ $(cat /tmp/images_to_build.txt) == "" ]]; then + echo "Nothing to build here" + touch /tmp/nothing-to-build-here + exit 0 + fi # # Pushing image to registry # @@ -94,17 +98,30 @@ jobs: for image in $(cat /tmp/images_to_build.txt); do echo "Bulding $image" + PUSH_IMAGE=0 bash -x ./build.sh skip $image + [[ "x$skip_security_checks" == "xtrue" ]] || { + curl -L https://github.com/aquasecurity/trivy/releases/download/v0.34.0/trivy_0.34.0_Linux-64bit.tar.gz | tar -xzf - -C ./ + ./trivy image --exit-code 1 --vuln-type os,library --severity "HIGH,CRITICAL" --ignore-unfixed $DOCKER_REPO/$image:$IMAGE_TAG + err_code=$? + [[ $err_code -ne 0 ]] && { + exit $err_code + } + } && { + echo "Skipping Security Checks" + } PUSH_IMAGE=1 bash -x ./build.sh skip $image echo "::set-output name=image::$DOCKER_REPO/$image:$IMAGE_TAG" done - name: Deploying to kuberntes env: - IMAGE_TAG: ${{ github.sha }} + IMAGE_TAG: ${{ github.ref_name }}_${{ github.sha }} run: | # # Deploying image to environment. # + set -x + [[ -f /tmp/nothing-to-build-here ]] && exit 0 cd scripts/helmcharts/ ## Update secerts @@ -142,6 +159,16 @@ jobs: # Deploy command helm template openreplay -n app openreplay -f vars.yaml -f /tmp/image_override.yaml --set ingress-nginx.enabled=false --set skipMigration=true | kubectl apply -f - + - name: Alert slack + if: ${{ failure() }} + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_CHANNEL: foss + SLACK_TITLE: "Failed ${{ github.workflow }}" + SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff' + SLACK_WEBHOOK: ${{ secrets.SLACK_WEB_HOOK }} + SLACK_USERNAME: "OR Bot" + SLACK_MESSAGE: 'Build failed :bomb:' # - name: Debug Job # if: ${{ failure() }} # uses: mxschmitt/action-tmate@v3 diff --git a/api/Dockerfile b/api/Dockerfile index d02dda8ba..036dcb0f2 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -1,28 +1,22 @@ FROM python:3.10-alpine LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" -RUN apk add --no-cache build-base nodejs npm tini +RUN apk add --no-cache build-base tini ARG envarg # Add Tini # Startup daemon ENV SOURCE_MAP_VERSION=0.7.4 \ APP_NAME=chalice \ LISTEN_PORT=8000 \ - MAPPING_WASM=/work/sourcemap-reader/mappings.wasm \ + PRIVATE_ENDPOINTS=false \ ENTERPRISE_BUILD=${envarg} -ADD https://unpkg.com/source-map@${SOURCE_MAP_VERSION}/lib/mappings.wasm /mappings.wasm - -WORKDIR /work_tmp -COPY requirements.txt /work_tmp/requirements.txt -RUN pip install --no-cache-dir --upgrade -r /work_tmp/requirements.txt -COPY sourcemap-reader/*.json /work_tmp/ -RUN cd /work_tmp && npm install - WORKDIR /work +COPY requirements.txt ./requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + COPY . . -RUN mv env.default .env && mv /work_tmp/node_modules sourcemap-reader/. \ - && mv /mappings.wasm ${MAPPING_WASM} && chmod 644 ${MAPPING_WASM} +RUN mv env.default .env RUN adduser -u 1001 openreplay -D USER 1001 diff --git a/api/.dockerignore b/api/Dockerfile.dockerignore similarity index 54% rename from api/.dockerignore rename to api/Dockerfile.dockerignore index 04ff72f11..48f747b28 100644 --- a/api/.dockerignore +++ b/api/Dockerfile.dockerignore @@ -4,4 +4,8 @@ **/build.sh **/build_*.sh **/*deploy.sh -Dockerfile* \ No newline at end of file +Dockerfile* + +app_alerts.py +requirements-alerts.txt +entrypoint_alerts.sh \ No newline at end of file diff --git a/api/Dockerfile.alerts b/api/Dockerfile_alerts similarity index 73% rename from api/Dockerfile.alerts rename to api/Dockerfile_alerts index ab3732c91..881b21fb9 100644 --- a/api/Dockerfile.alerts +++ b/api/Dockerfile_alerts @@ -4,15 +4,16 @@ LABEL Maintainer="KRAIEM Taha Yassine" RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=alerts \ - pg_minconn=1 \ - pg_maxconn=10 \ + PG_MINCONN=1 \ + PG_MAXCONN=10 \ LISTEN_PORT=8000 \ + PRIVATE_ENDPOINTS=true \ ENTERPRISE_BUILD=${envarg} -COPY requirements.txt /work_tmp/requirements.txt -RUN pip install --no-cache-dir --upgrade -r /work_tmp/requirements.txt - WORKDIR /work +COPY requirements-alerts.txt ./requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + COPY . . RUN mv env.default .env && mv app_alerts.py app.py && mv entrypoint_alerts.sh entrypoint.sh diff --git a/api/Dockerfile.alerts.dockerignore b/api/Dockerfile_alerts.dockerignore similarity index 85% rename from api/Dockerfile.alerts.dockerignore rename to api/Dockerfile_alerts.dockerignore index bb4179739..3084253b3 100644 --- a/api/Dockerfile.alerts.dockerignore +++ b/api/Dockerfile_alerts.dockerignore @@ -7,5 +7,5 @@ Dockerfile* app.py -entrypoint_alerts.sh +entrypoint.sh requirements.txt \ No newline at end of file diff --git a/api/Dockerfile.bundle b/api/Dockerfile_bundle similarity index 100% rename from api/Dockerfile.bundle rename to api/Dockerfile_bundle diff --git a/api/app.py b/api/app.py index 974d7d8d9..26342484c 100644 --- a/api/app.py +++ b/api/app.py @@ -20,22 +20,14 @@ app.add_middleware(GZipMiddleware, minimum_size=1000) @app.middleware('http') async def or_middleware(request: Request, call_next): - global OR_SESSION_TOKEN - OR_SESSION_TOKEN = request.headers.get('vnd.openreplay.com.sid', request.headers.get('vnd.asayer.io.sid')) - - try: - if helper.TRACK_TIME: - import time - now = int(time.time() * 1000) - response: StreamingResponse = await call_next(request) - if helper.TRACK_TIME: - now = int(time.time() * 1000) - now - if now > 500: - print(f"Execution time: {now} ms") - except Exception as e: - pg_client.close() - raise e - pg_client.close() + if helper.TRACK_TIME: + import time + now = int(time.time() * 1000) + response: StreamingResponse = await call_next(request) + if helper.TRACK_TIME: + now = int(time.time() * 1000) - now + if now > 500: + logging.info(f"Execution time: {now} ms") return response @@ -61,14 +53,38 @@ app.include_router(metrics.app) app.include_router(insights.app) app.include_router(v1_api.app_apikey) -Schedule = AsyncIOScheduler() -Schedule.start() +loglevel = config("LOGLEVEL", default=logging.INFO) +print(f">Loglevel set to: {loglevel}") +logging.basicConfig(level=loglevel) +ap_logger = logging.getLogger('apscheduler') +ap_logger.setLevel(loglevel) +app.schedule = AsyncIOScheduler() -for job in core_crons.cron_jobs + core_dynamic_crons.cron_jobs: - Schedule.add_job(id=job["func"].__name__, **job) -for job in Schedule.get_jobs(): - print({"Name": str(job.id), "Run Frequency": str(job.trigger), "Next Run": str(job.next_run_time)}) +@app.on_event("startup") +async def startup(): + logging.info(">>>>> starting up <<<<<") + await pg_client.init() + app.schedule.start() -logging.basicConfig(level=config("LOGLEVEL", default=logging.INFO)) -logging.getLogger('apscheduler').setLevel(config("LOGLEVEL", default=logging.INFO)) + for job in core_crons.cron_jobs + core_dynamic_crons.cron_jobs: + app.schedule.add_job(id=job["func"].__name__, **job) + + ap_logger.info(">Scheduled jobs:") + for job in app.schedule.get_jobs(): + ap_logger.info({"Name": str(job.id), "Run Frequency": str(job.trigger), "Next Run": str(job.next_run_time)}) + + +@app.on_event("shutdown") +async def shutdown(): + logging.info(">>>>> shutting down <<<<<") + app.schedule.shutdown(wait=False) + await pg_client.terminate() + + +@app.get('/private/shutdown', tags=["private"]) +async def stop_server(): + logging.info("Requested shutdown") + await shutdown() + import os, signal + os.kill(1, signal.SIGTERM) diff --git a/api/app_alerts.py b/api/app_alerts.py index 4e05ab1a8..7107423de 100644 --- a/api/app_alerts.py +++ b/api/app_alerts.py @@ -3,11 +3,12 @@ import logging from apscheduler.schedulers.asyncio import AsyncIOScheduler from decouple import config from fastapi import FastAPI +from chalicelib.utils import pg_client from chalicelib.core import alerts_processor app = FastAPI(root_path="/alerts", docs_url=config("docs_url", default=""), redoc_url=config("redoc_url", default="")) -print("============= ALERTS =============") +logging.info("============= ALERTS =============") @app.get("/") @@ -16,12 +17,39 @@ async def root(): app.schedule = AsyncIOScheduler() -app.schedule.start() -app.schedule.add_job(id="alerts_processor", **{"func": alerts_processor.process, "trigger": "interval", - "minutes": config("ALERTS_INTERVAL", cast=int, default=5), - "misfire_grace_time": 20}) -for job in app.schedule.get_jobs(): - print({"Name": str(job.id), "Run Frequency": str(job.trigger), "Next Run": str(job.next_run_time)}) -logging.basicConfig(level=config("LOGLEVEL", default=logging.INFO)) -logging.getLogger('apscheduler').setLevel(config("LOGLEVEL", default=logging.INFO)) +loglevel = config("LOGLEVEL", default=logging.INFO) +print(f">Loglevel set to: {loglevel}") +logging.basicConfig(level=loglevel) +ap_logger = logging.getLogger('apscheduler') +ap_logger.setLevel(loglevel) +app.schedule = AsyncIOScheduler() + + +@app.on_event("startup") +async def startup(): + logging.info(">>>>> starting up <<<<<") + await pg_client.init() + app.schedule.start() + app.schedule.add_job(id="alerts_processor", **{"func": alerts_processor.process, "trigger": "interval", + "minutes": config("ALERTS_INTERVAL", cast=int, default=5), + "misfire_grace_time": 20}) + + ap_logger.info(">Scheduled jobs:") + for job in app.schedule.get_jobs(): + ap_logger.info({"Name": str(job.id), "Run Frequency": str(job.trigger), "Next Run": str(job.next_run_time)}) + + +@app.on_event("shutdown") +async def shutdown(): + logging.info(">>>>> shutting down <<<<<") + app.schedule.shutdown(wait=False) + await pg_client.terminate() + + +@app.get('/private/shutdown', tags=["private"]) +async def stop_server(): + logging.info("Requested shutdown") + await shutdown() + import os, signal + os.kill(1, signal.SIGTERM) diff --git a/api/auth/auth_jwt.py b/api/auth/auth_jwt.py index 4eff80789..e8824b6b9 100644 --- a/api/auth/auth_jwt.py +++ b/api/auth/auth_jwt.py @@ -6,14 +6,14 @@ from starlette import status from starlette.exceptions import HTTPException from chalicelib.core import authorizers, users -from schemas import CurrentContext +import schemas class JWTAuth(HTTPBearer): def __init__(self, auto_error: bool = True): super(JWTAuth, self).__init__(auto_error=auto_error) - async def __call__(self, request: Request) -> Optional[CurrentContext]: + async def __call__(self, request: Request) -> Optional[schemas.CurrentContext]: credentials: HTTPAuthorizationCredentials = await super(JWTAuth, self).__call__(request) if credentials: if not credentials.scheme == "Bearer": @@ -49,9 +49,9 @@ class JWTAuth(HTTPBearer): jwt_payload["authorizer_identity"] = "jwt" print(jwt_payload) request.state.authorizer_identity = "jwt" - request.state.currentContext = CurrentContext(tenant_id=jwt_payload.get("tenantId", -1), - user_id=jwt_payload.get("userId", -1), - email=user["email"]) + request.state.currentContext = schemas.CurrentContext(tenant_id=jwt_payload.get("tenantId", -1), + user_id=jwt_payload.get("userId", -1), + email=user["email"]) return request.state.currentContext else: diff --git a/api/auth/auth_project.py b/api/auth/auth_project.py index 6f842916b..0f28b4162 100644 --- a/api/auth/auth_project.py +++ b/api/auth/auth_project.py @@ -17,8 +17,8 @@ class ProjectAuthorizer: current_user: schemas.CurrentContext = await OR_context(request) value = request.path_params[self.project_identifier] if (self.project_identifier == "projectId" \ - and not (isinstance(value, int) or isinstance(value, str) and value.isnumeric()) - and projects.get_project(project_id=value, tenant_id=current_user.tenant_id) is None) \ + and (not (isinstance(value, int) or isinstance(value, str) and value.isnumeric()) + or projects.get_project(project_id=value, tenant_id=current_user.tenant_id) is None)) \ or (self.project_identifier == "projectKey" \ and projects.get_internal_project_id(project_key=value) is None): print("project not found") diff --git a/api/build.sh b/api/build.sh index 46c54ab2e..895f9bb8e 100644 --- a/api/build.sh +++ b/api/build.sh @@ -7,6 +7,15 @@ # Usage: IMAGE_TAG=latest DOCKER_REPO=myDockerHubID bash build.sh +# Helper function +exit_err() { + err_code=$1 + if [[ err_code != 0 ]]; then + exit $err_code + fi +} + +environment=$1 git_sha1=${IMAGE_TAG:-$(git rev-parse HEAD)} envarg="default-foss" check_prereq() { @@ -18,10 +27,12 @@ check_prereq() { } function build_api(){ - cp -R ../api ../_api - cd ../_api - cp -R ../utilities/utils ../sourcemap-reader/. - cp -R ../sourcemap-reader . + destination="_api" + [[ $1 == "ee" ]] && { + destination="_api_ee" + } + cp -R ../api ../${destination} + cd ../${destination} tag="" # Copy enterprise code [[ $1 == "ee" ]] && { @@ -29,9 +40,10 @@ function build_api(){ envarg="default-ee" tag="ee-" } + mv Dockerfile.dockerignore .dockerignore docker build -f ./Dockerfile --build-arg envarg=$envarg -t ${DOCKER_REPO:-'local'}/chalice:${git_sha1} . cd ../api - rm -rf ../_api + rm -rf ../${destination} [[ $PUSH_IMAGE -eq 1 ]] && { docker push ${DOCKER_REPO:-'local'}/chalice:${git_sha1} docker tag ${DOCKER_REPO:-'local'}/chalice:${git_sha1} ${DOCKER_REPO:-'local'}/chalice:${tag}latest @@ -41,11 +53,13 @@ function build_api(){ } check_prereq -build_api $1 +build_api $environment echo buil_complete IMAGE_TAG=$IMAGE_TAG PUSH_IMAGE=$PUSH_IMAGE DOCKER_REPO=$DOCKER_REPO bash build_alerts.sh $1 -[[ $1 == "ee" ]] && { +[[ $environment == "ee" ]] && { cp ../ee/api/build_crons.sh . IMAGE_TAG=$IMAGE_TAG PUSH_IMAGE=$PUSH_IMAGE DOCKER_REPO=$DOCKER_REPO bash build_crons.sh $1 -} \ No newline at end of file + exit_err $? + rm build_crons.sh +} || true diff --git a/api/build_alerts.sh b/api/build_alerts.sh index 9ab21e6af..a36472a8d 100644 --- a/api/build_alerts.sh +++ b/api/build_alerts.sh @@ -16,9 +16,13 @@ check_prereq() { } } -function build_api(){ - cp -R ../api ../_alerts - cd ../_alerts +function build_alerts(){ + destination="_alerts" + [[ $1 == "ee" ]] && { + destination="_alerts_ee" + } + cp -R ../api ../${destination} + cd ../${destination} tag="" # Copy enterprise code [[ $1 == "ee" ]] && { @@ -26,9 +30,10 @@ function build_api(){ envarg="default-ee" tag="ee-" } - docker build -f ./Dockerfile.alerts --build-arg envarg=$envarg -t ${DOCKER_REPO:-'local'}/alerts:${git_sha1} . + mv Dockerfile_alerts.dockerignore .dockerignore + docker build -f ./Dockerfile_alerts --build-arg envarg=$envarg -t ${DOCKER_REPO:-'local'}/alerts:${git_sha1} . cd ../api - rm -rf ../_alerts + rm -rf ../${destination} [[ $PUSH_IMAGE -eq 1 ]] && { docker push ${DOCKER_REPO:-'local'}/alerts:${git_sha1} docker tag ${DOCKER_REPO:-'local'}/alerts:${git_sha1} ${DOCKER_REPO:-'local'}/alerts:${tag}latest @@ -38,4 +43,4 @@ function build_api(){ } check_prereq -build_api $1 +build_alerts $1 diff --git a/api/chalicelib/core/alerts_processor.py b/api/chalicelib/core/alerts_processor.py index dbc4aaf41..76ae5c615 100644 --- a/api/chalicelib/core/alerts_processor.py +++ b/api/chalicelib/core/alerts_processor.py @@ -103,6 +103,7 @@ def Build(a): params = {"project_id": a["projectId"], "now": now} full_args = {} j_s = True + main_table = "" if a["seriesId"] is not None: a["filter"]["sort"] = "session_id" a["filter"]["order"] = schemas.SortOrderType.desc @@ -120,16 +121,16 @@ def Build(a): WHERE project_id = %(project_id)s {"AND " + colDef["condition"] if colDef.get("condition") is not None else ""}""" j_s = colDef.get("joinSessions", True) - + main_table = colDef["table"] + is_ss = main_table == "public.sessions" q = f"""SELECT coalesce(value,0) AS value, coalesce(value,0) {a["query"]["operator"]} {a["query"]["right"]} AS valid""" if a["detectionMethod"] == schemas.AlertDetectionMethod.threshold: if a["seriesId"] is not None: q += f""" FROM ({subQ}) AS stat""" else: - q += f""" FROM ({subQ} AND timestamp>=%(startDate)s AND timestamp<=%(now)s - {"AND sessions.start_ts >= %(startDate)s" if j_s else ""} - {"AND sessions.start_ts <= %(now)s" if j_s else ""}) AS stat""" + q += f""" FROM ({subQ} {"AND timestamp >= %(startDate)s AND timestamp <= %(now)s" if not is_ss else ""} + {"AND start_ts >= %(startDate)s AND start_ts <= %(now)s" if j_s else ""}) AS stat""" params = {**params, **full_args, "startDate": TimeUTC.now() - a["options"]["currentPeriod"] * 60 * 1000} else: if a["change"] == schemas.AlertDetectionType.change: @@ -142,13 +143,11 @@ def Build(a): "timestamp_sub2": TimeUTC.now() - 2 * a["options"]["currentPeriod"] * 60 * 1000} else: sub1 = f"""{subQ} AND timestamp>=%(startDate)s - AND datetime<=toDateTime(%(now)s/1000) - {"AND sessions.start_ts >= %(startDate)s" if j_s else ""} - {"AND sessions.start_ts <= %(now)s" if j_s else ""}""" + AND timestamp<=%(now)s + {"AND start_ts >= %(startDate)s AND start_ts <= %(now)s" if j_s else ""}""" params["startDate"] = TimeUTC.now() - a["options"]["currentPeriod"] * 60 * 1000 - sub2 = f"""{subQ} AND timestamp<%(startDate)s - AND timestamp>=%(timestamp_sub2)s - {"AND sessions.start_ts < %(startDate)s AND sessions.start_ts >= %(timestamp_sub2)s" if j_s else ""}""" + sub2 = f"""{subQ} {"AND timestamp < %(startDate)s AND timestamp >= %(timestamp_sub2)s" if not is_ss else ""} + {"AND start_ts < %(startDate)s AND start_ts >= %(timestamp_sub2)s" if j_s else ""}""" params["timestamp_sub2"] = TimeUTC.now() - 2 * a["options"]["currentPeriod"] * 60 * 1000 sub1 = f"SELECT (( {sub1} )-( {sub2} )) AS value" q += f" FROM ( {sub1} ) AS stat" @@ -164,13 +163,11 @@ def Build(a): - (a["options"]["currentPeriod"] + a["options"]["currentPeriod"]) \ * 60 * 1000} else: - sub1 = f"""{subQ} AND timestamp>=%(startDate)s AND timestamp<=%(now)s - {"AND sessions.start_ts >= %(startDate)s" if j_s else ""} - {"AND sessions.start_ts <= %(now)s" if j_s else ""}""" + sub1 = f"""{subQ} {"AND timestamp >= %(startDate)s AND timestamp <= %(now)s" if not is_ss else ""} + {"AND start_ts >= %(startDate)s AND start_ts <= %(now)s" if j_s else ""}""" params["startDate"] = TimeUTC.now() - a["options"]["currentPeriod"] * 60 * 1000 - sub2 = f"""{subQ} AND timestamp<%(startDate)s - AND timestamp>=%(timestamp_sub2)s - {"AND sessions.start_ts < %(startDate)s AND sessions.start_ts >= %(timestamp_sub2)s" if j_s else ""}""" + sub2 = f"""{subQ} {"AND timestamp < %(startDate)s AND timestamp >= %(timestamp_sub2)s" if not is_ss else ""} + {"AND start_ts < %(startDate)s AND start_ts >= %(timestamp_sub2)s" if j_s else ""}""" params["timestamp_sub2"] = TimeUTC.now() \ - (a["options"]["currentPeriod"] + a["options"]["currentPeriod"]) * 60 * 1000 sub1 = f"SELECT (({sub1})/NULLIF(({sub2}),0)-1)*100 AS value" @@ -185,21 +182,28 @@ def process(): with pg_client.PostgresClient() as cur: for alert in all_alerts: if can_check(alert): - logging.info(f"Querying alertId:{alert['alertId']} name: {alert['name']}") query, params = Build(alert) - query = cur.mogrify(query, params) + try: + query = cur.mogrify(query, params) + except Exception as e: + logging.error( + f"!!!Error while building alert query for alertId:{alert['alertId']} name: {alert['name']}") + logging.error(e) + continue logging.debug(alert) logging.debug(query) try: cur.execute(query) result = cur.fetchone() if result["valid"]: - logging.info("Valid alert, notifying users") + logging.info(f"Valid alert, notifying users, alertId:{alert['alertId']} name: {alert['name']}") notifications.append(generate_notification(alert, result)) except Exception as e: - logging.error(f"!!!Error while running alert query for alertId:{alert['alertId']}") - logging.error(str(e)) + logging.error( + f"!!!Error while running alert query for alertId:{alert['alertId']} name: {alert['name']}") logging.error(query) + logging.error(e) + cur = cur.recreate(rollback=True) if len(notifications) > 0: cur.execute( cur.mogrify(f"""UPDATE public.Alerts @@ -209,12 +213,22 @@ def process(): alerts.process_notifications(notifications) +def __format_value(x): + if x % 1 == 0: + x = int(x) + else: + x = round(x, 2) + return f"{x:,}" + + def generate_notification(alert, result): + left = __format_value(result['value']) + right = __format_value(alert['query']['right']) return { "alertId": alert["alertId"], "tenantId": alert["tenantId"], "title": alert["name"], - "description": f"has been triggered, {alert['query']['left']} = {round(result['value'], 2)} ({alert['query']['operator']} {alert['query']['right']}).", + "description": f"has been triggered, {alert['query']['left']} = {left} ({alert['query']['operator']} {right}).", "buttonText": "Check metrics for more details", "buttonUrl": f"/{alert['projectId']}/metrics", "imageUrl": None, diff --git a/api/chalicelib/core/assist.py b/api/chalicelib/core/assist.py index 8c4053a9b..7fd68e029 100644 --- a/api/chalicelib/core/assist.py +++ b/api/chalicelib/core/assist.py @@ -1,10 +1,14 @@ +from os import access, R_OK +from os.path import exists as path_exists, getsize + +import jwt import requests from decouple import config -from os.path import exists +from starlette.exceptions import HTTPException + import schemas from chalicelib.core import projects -from starlette.exceptions import HTTPException -from os import access, R_OK +from chalicelib.utils.TimeUTC import TimeUTC ASSIST_KEY = config("ASSIST_KEY") ASSIST_URL = config("ASSIST_URL") % ASSIST_KEY @@ -49,22 +53,22 @@ def get_live_sessions_ws(project_id, body: schemas.LiveSessionsSearchPayloadSche def __get_live_sessions_ws(project_id, data): project_key = projects.get_project_key(project_id) try: - connected_peers = requests.post(ASSIST_URL + config("assist") + f"/{project_key}", - json=data, timeout=config("assistTimeout", cast=int, default=5)) - if connected_peers.status_code != 200: - print("!! issue with the peer-server") - print(connected_peers.text) + results = requests.post(ASSIST_URL + config("assist") + f"/{project_key}", + json=data, timeout=config("assistTimeout", cast=int, default=5)) + if results.status_code != 200: + print(f"!! issue with the peer-server code:{results.status_code}") + print(results.text) return {"total": 0, "sessions": []} - live_peers = connected_peers.json().get("data", []) + live_peers = results.json().get("data", []) except requests.exceptions.Timeout: - print("Timeout getting Assist response") + print("!! Timeout getting Assist response") live_peers = {"total": 0, "sessions": []} except Exception as e: - print("issue getting Live-Assist response") + print("!! Issue getting Live-Assist response") print(str(e)) print("expected JSON, received:") try: - print(connected_peers.text) + print(results.text) except: print("couldn't get response") live_peers = {"total": 0, "sessions": []} @@ -77,58 +81,76 @@ def __get_live_sessions_ws(project_id, data): return live_peers +def __get_agent_token(project_id, project_key, session_id): + iat = TimeUTC.now() + return jwt.encode( + payload={ + "projectKey": project_key, + "projectId": project_id, + "sessionId": session_id, + "iat": iat // 1000, + "exp": iat // 1000 + config("ASSIST_JWT_EXPIRATION", cast=int) + TimeUTC.get_utc_offset() // 1000, + "iss": config("JWT_ISSUER"), + "aud": f"openreplay:agent" + }, + key=config("ASSIST_JWT_SECRET"), + algorithm=config("jwt_algorithm") + ) + + def get_live_session_by_id(project_id, session_id): project_key = projects.get_project_key(project_id) try: - connected_peers = requests.get(ASSIST_URL + config("assist") + f"/{project_key}/{session_id}", - timeout=config("assistTimeout", cast=int, default=5)) - if connected_peers.status_code != 200: - print("!! issue with the peer-server") - print(connected_peers.text) - return False - connected_peers = connected_peers.json().get("data") - if connected_peers is None: + results = requests.get(ASSIST_URL + config("assist") + f"/{project_key}/{session_id}", + timeout=config("assistTimeout", cast=int, default=5)) + if results.status_code != 200: + print(f"!! issue with the peer-server code:{results.status_code}") + print(results.text) return None - connected_peers["live"] = True + results = results.json().get("data") + if results is None: + return None + results["live"] = True + results["agentToken"] = __get_agent_token(project_id=project_id, project_key=project_key, session_id=session_id) except requests.exceptions.Timeout: - print("Timeout getting Assist response") + print("!! Timeout getting Assist response") return None except Exception as e: - print("issue getting Assist response") + print("!! Issue getting Assist response") print(str(e)) print("expected JSON, received:") try: - print(connected_peers.text) + print(results.text) except: print("couldn't get response") return None - return connected_peers + return results def is_live(project_id, session_id, project_key=None): if project_key is None: project_key = projects.get_project_key(project_id) try: - connected_peers = requests.get(ASSIST_URL + config("assistList") + f"/{project_key}/{session_id}", - timeout=config("assistTimeout", cast=int, default=5)) - if connected_peers.status_code != 200: - print("!! issue with the peer-server") - print(connected_peers.text) + results = requests.get(ASSIST_URL + config("assistList") + f"/{project_key}/{session_id}", + timeout=config("assistTimeout", cast=int, default=5)) + if results.status_code != 200: + print(f"!! issue with the peer-server code:{results.status_code}") + print(results.text) return False - connected_peers = connected_peers.json().get("data") + results = results.json().get("data") except requests.exceptions.Timeout: - print("Timeout getting Assist response") + print("!! Timeout getting Assist response") return False except Exception as e: - print("issue getting Assist response") + print("!! Issue getting Assist response") print(str(e)) print("expected JSON, received:") try: - print(connected_peers.text) + print(results.text) except: print("couldn't get response") return False - return str(session_id) == connected_peers + return str(session_id) == results def autocomplete(project_id, q: str, key: str = None): @@ -141,15 +163,15 @@ def autocomplete(project_id, q: str, key: str = None): ASSIST_URL + config("assistList") + f"/{project_key}/autocomplete", params=params, timeout=config("assistTimeout", cast=int, default=5)) if results.status_code != 200: - print("!! issue with the peer-server") + print(f"!! issue with the peer-server code:{results.status_code}") print(results.text) return {"errors": [f"Something went wrong wile calling assist:{results.text}"]} results = results.json().get("data", []) except requests.exceptions.Timeout: - print("Timeout getting Assist response") + print("!! Timeout getting Assist response") return {"errors": ["Assist request timeout"]} except Exception as e: - print("issue getting Assist response") + print("!! Issue getting Assist response") print(str(e)) print("expected JSON, received:") try: @@ -165,21 +187,76 @@ def get_ice_servers(): and len(config("iceServers")) > 0 else None -def get_raw_mob_by_id(project_id, session_id): +def __get_efs_path(): efs_path = config("FS_DIR") - if not exists(efs_path): + if not path_exists(efs_path): raise HTTPException(400, f"EFS not found in path: {efs_path}") if not access(efs_path, R_OK): raise HTTPException(400, f"EFS found under: {efs_path}; but it is not readable, please check permissions") + return efs_path - path_to_file = efs_path + "/" + str(session_id) - if exists(path_to_file): +def __get_mob_path(project_id, session_id): + params = {"projectId": project_id, "sessionId": session_id} + return config("EFS_SESSION_MOB_PATTERN", default="%(sessionId)s") % params + + +def get_raw_mob_by_id(project_id, session_id): + efs_path = __get_efs_path() + path_to_file = efs_path + "/" + __get_mob_path(project_id=project_id, session_id=session_id) + if path_exists(path_to_file): if not access(path_to_file, R_OK): - raise HTTPException(400, f"Replay file found under: {efs_path};" + raise HTTPException(400, f"Replay file found under: {efs_path};" + + f" but it is not readable, please check permissions") + # getsize return size in bytes, UNPROCESSED_MAX_SIZE is in Kb + if (getsize(path_to_file) / 1000) >= config("UNPROCESSED_MAX_SIZE", cast=int, default=200 * 1000): + raise HTTPException(413, "Replay file too large") + return path_to_file + + return None + + +def __get_devtools_path(project_id, session_id): + params = {"projectId": project_id, "sessionId": session_id} + return config("EFS_DEVTOOLS_MOB_PATTERN", default="%(sessionId)s") % params + + +def get_raw_devtools_by_id(project_id, session_id): + efs_path = __get_efs_path() + path_to_file = efs_path + "/" + __get_devtools_path(project_id=project_id, session_id=session_id) + if path_exists(path_to_file): + if not access(path_to_file, R_OK): + raise HTTPException(400, f"Devtools file found under: {efs_path};" f" but it is not readable, please check permissions") return path_to_file return None + + +def session_exists(project_id, session_id): + project_key = projects.get_project_key(project_id) + try: + results = requests.get(ASSIST_URL + config("assist") + f"/{project_key}/{session_id}", + timeout=config("assistTimeout", cast=int, default=5)) + if results.status_code != 200: + print(f"!! issue with the peer-server code:{results.status_code}") + print(results.text) + return None + results = results.json().get("data") + if results is None: + return False + return True + except requests.exceptions.Timeout: + print("!! Timeout getting Assist response") + return False + except Exception as e: + print("!! Issue getting Assist response") + print(str(e)) + print("expected JSON, received:") + try: + print(results.text) + except: + print("couldn't get response") + return False diff --git a/api/chalicelib/core/authorizers.py b/api/chalicelib/core/authorizers.py index 5756e82ab..2ec3fa01f 100644 --- a/api/chalicelib/core/authorizers.py +++ b/api/chalicelib/core/authorizers.py @@ -15,7 +15,7 @@ def jwt_authorizer(token): token[1], config("jwt_secret"), algorithms=config("jwt_algorithm"), - audience=[f"plugin:{helper.get_stage_name()}", f"front:{helper.get_stage_name()}"] + audience=[ f"front:{helper.get_stage_name()}"] ) except jwt.ExpiredSignatureError: print("! JWT Expired signature") @@ -42,8 +42,8 @@ def generate_jwt(id, tenant_id, iat, aud): payload={ "userId": id, "tenantId": tenant_id, - "exp": iat // 1000 + config("jwt_exp_delta_seconds", cast=int) + TimeUTC.get_utc_offset() // 1000, - "iss": config("jwt_issuer"), + "exp": iat // 1000 + config("JWT_EXPIRATION", cast=int) + TimeUTC.get_utc_offset() // 1000, + "iss": config("JWT_ISSUER"), "iat": iat // 1000, "aud": aud }, diff --git a/api/chalicelib/core/collaboration_slack.py b/api/chalicelib/core/collaboration_slack.py index bd0ae7f21..5e7797430 100644 --- a/api/chalicelib/core/collaboration_slack.py +++ b/api/chalicelib/core/collaboration_slack.py @@ -35,24 +35,57 @@ class Slack: return True @classmethod - def send_text(cls, tenant_id, webhook_id, text, **args): + def send_text_attachments(cls, tenant_id, webhook_id, text, **args): integration = cls.__get(tenant_id=tenant_id, integration_id=webhook_id) if integration is None: return {"errors": ["slack integration not found"]} - print("====> sending slack notification") - r = requests.post( - url=integration["endpoint"], - json={ - "attachments": [ - { - "text": text, - "ts": datetime.now().timestamp(), - **args - } - ] - }) - print(r) - print(r.text) + try: + r = requests.post( + url=integration["endpoint"], + json={ + "attachments": [ + { + "text": text, + "ts": datetime.now().timestamp(), + **args + } + ] + }, + timeout=5) + if r.status_code != 200: + print(f"!! issue sending slack text attachments; webhookId:{webhook_id} code:{r.status_code}") + print(r.text) + return None + except requests.exceptions.Timeout: + print(f"!! Timeout sending slack text attachments webhookId:{webhook_id}") + return None + except Exception as e: + print(f"!! Issue sending slack text attachments webhookId:{webhook_id}") + print(str(e)) + return None + return {"data": r.text} + + @classmethod + def send_raw(cls, tenant_id, webhook_id, body): + integration = cls.__get(tenant_id=tenant_id, integration_id=webhook_id) + if integration is None: + return {"errors": ["slack integration not found"]} + try: + r = requests.post( + url=integration["endpoint"], + json=body, + timeout=5) + if r.status_code != 200: + print(f"!! issue sending slack raw; webhookId:{webhook_id} code:{r.status_code}") + print(r.text) + return None + except requests.exceptions.Timeout: + print(f"!! Timeout sending slack raw webhookId:{webhook_id}") + return None + except Exception as e: + print(f"!! Issue sending slack raw webhookId:{webhook_id}") + print(str(e)) + return None return {"data": r.text} @classmethod @@ -66,7 +99,8 @@ class Slack: url=integration["endpoint"], json={"attachments": attachments[i:i + 100]}) if r.status_code != 200: - print("!!!! something went wrong") + print("!!!! something went wrong while sending to:") + print(integration) print(r) print(r.text) diff --git a/api/chalicelib/core/custom_metrics.py b/api/chalicelib/core/custom_metrics.py index 29c4b6fa9..743ca41e5 100644 --- a/api/chalicelib/core/custom_metrics.py +++ b/api/chalicelib/core/custom_metrics.py @@ -266,7 +266,8 @@ def update(metric_id, user_id, project_id, data: schemas.UpdateCustomMetricsSche params = {"metric_id": metric_id, "is_public": data.is_public, "name": data.name, "user_id": user_id, "project_id": project_id, "view_type": data.view_type, "metric_type": data.metric_type, "metric_of": data.metric_of, - "metric_value": data.metric_value, "metric_format": data.metric_format} + "metric_value": data.metric_value, "metric_format": data.metric_format, + "config": json.dumps(data.config.dict())} for i, s in enumerate(data.series): prefix = "u_" if s.index is None: @@ -316,7 +317,8 @@ def update(metric_id, user_id, project_id, data: schemas.UpdateCustomMetricsSche view_type= %(view_type)s, metric_type= %(metric_type)s, metric_of= %(metric_of)s, metric_value= %(metric_value)s, metric_format= %(metric_format)s, - edited_at = timezone('utc'::text, now()) + edited_at = timezone('utc'::text, now()), + default_config = %(config)s WHERE metric_id = %(metric_id)s AND project_id = %(project_id)s AND (user_id = %(user_id)s OR is_public) diff --git a/api/chalicelib/core/dashboards.py b/api/chalicelib/core/dashboards.py index 9d1dc4c81..ac98b44e7 100644 --- a/api/chalicelib/core/dashboards.py +++ b/api/chalicelib/core/dashboards.py @@ -111,6 +111,8 @@ def get_dashboard(project_id, user_id, dashboard_id): for w in row["widgets"]: w["created_at"] = TimeUTC.datetime_to_timestamp(w["created_at"]) w["edited_at"] = TimeUTC.datetime_to_timestamp(w["edited_at"]) + w["config"]["col"] = w["default_config"]["col"] + w["config"]["row"] = w["default_config"]["row"] for s in w["series"]: s["created_at"] = TimeUTC.datetime_to_timestamp(s["created_at"]) return helper.dict_to_camel_case(row) diff --git a/api/chalicelib/core/errors.py b/api/chalicelib/core/errors.py index 1c7ed94c9..9c89844f9 100644 --- a/api/chalicelib/core/errors.py +++ b/api/chalicelib/core/errors.py @@ -83,6 +83,19 @@ def __process_tags(row): def get_details(project_id, error_id, user_id, **data): pg_sub_query24 = __get_basic_constraints(time_constraint=False, chart=True, step_size_name="step_size24") pg_sub_query24.append("error_id = %(error_id)s") + pg_sub_query30_session = __get_basic_constraints(time_constraint=True, chart=False, + startTime_arg_name="startDate30", + endTime_arg_name="endDate30", project_key="sessions.project_id") + pg_sub_query30_session.append("sessions.start_ts >= %(startDate30)s") + pg_sub_query30_session.append("sessions.start_ts <= %(endDate30)s") + pg_sub_query30_session.append("error_id = %(error_id)s") + pg_sub_query30_err = __get_basic_constraints(time_constraint=True, chart=False, startTime_arg_name="startDate30", + endTime_arg_name="endDate30", project_key="errors.project_id") + pg_sub_query30_err.append("sessions.project_id = %(project_id)s") + pg_sub_query30_err.append("sessions.start_ts >= %(startDate30)s") + pg_sub_query30_err.append("sessions.start_ts <= %(endDate30)s") + pg_sub_query30_err.append("error_id = %(error_id)s") + pg_sub_query30_err.append("source ='js_exception'") pg_sub_query30 = __get_basic_constraints(time_constraint=False, chart=True, step_size_name="step_size30") pg_sub_query30.append("error_id = %(error_id)s") pg_basic_query = __get_basic_constraints(time_constraint=False) @@ -121,50 +134,49 @@ def get_details(project_id, error_id, user_id, **data): device_partition, country_partition, chart24, - chart30 + chart30, + custom_tags FROM (SELECT error_id, name, message, - COUNT(DISTINCT user_uuid) AS users, + COUNT(DISTINCT user_id) AS users, COUNT(DISTINCT session_id) AS sessions FROM public.errors INNER JOIN events.errors AS s_errors USING (error_id) INNER JOIN public.sessions USING (session_id) - WHERE error_id = %(error_id)s + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY error_id, name, message) AS details - INNER JOIN (SELECT error_id, - MAX(timestamp) AS last_occurrence, + INNER JOIN (SELECT MAX(timestamp) AS last_occurrence, MIN(timestamp) AS first_occurrence FROM events.errors WHERE error_id = %(error_id)s - GROUP BY error_id) AS time_details USING (error_id) - INNER JOIN (SELECT error_id, - session_id AS last_session_id, - user_os, - user_os_version, - user_browser, - user_browser_version, - user_device, - user_device_type, - user_uuid - FROM events.errors INNER JOIN public.sessions USING (session_id) + GROUP BY error_id) AS time_details ON (TRUE) + INNER JOIN (SELECT session_id AS last_session_id, + coalesce(custom_tags, '[]')::jsonb AS custom_tags + FROM events.errors + LEFT JOIN LATERAL ( + SELECT jsonb_agg(jsonb_build_object(errors_tags.key, errors_tags.value)) AS custom_tags + FROM errors_tags + WHERE errors_tags.error_id = %(error_id)s + AND errors_tags.session_id = errors.session_id + AND errors_tags.message_id = errors.message_id) AS errors_tags ON (TRUE) WHERE error_id = %(error_id)s ORDER BY errors.timestamp DESC - LIMIT 1) AS last_session_details USING (error_id) + LIMIT 1) AS last_session_details ON (TRUE) INNER JOIN (SELECT jsonb_agg(browser_details) AS browsers_partition FROM (SELECT * FROM (SELECT user_browser AS name, COUNT(session_id) AS count FROM events.errors INNER JOIN sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} GROUP BY user_browser ORDER BY count DESC) AS count_per_browser_query INNER JOIN LATERAL (SELECT JSONB_AGG(version_details) AS partition FROM (SELECT user_browser_version AS version, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} AND sessions.user_browser = count_per_browser_query.name GROUP BY user_browser_version ORDER BY count DESC) AS version_details @@ -174,13 +186,13 @@ def get_details(project_id, error_id, user_id, **data): FROM (SELECT user_os AS name, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} GROUP BY user_os ORDER BY count DESC) AS count_per_os_details INNER JOIN LATERAL (SELECT jsonb_agg(count_per_version_details) AS partition FROM (SELECT COALESCE(user_os_version,'unknown') AS version, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} AND sessions.user_os = count_per_os_details.name GROUP BY user_os_version ORDER BY count DESC) AS count_per_version_details @@ -191,7 +203,7 @@ def get_details(project_id, error_id, user_id, **data): FROM (SELECT user_device_type AS name, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} GROUP BY user_device_type ORDER BY count DESC) AS count_per_device_details INNER JOIN LATERAL (SELECT jsonb_agg(count_per_device_v_details) AS partition @@ -201,7 +213,7 @@ def get_details(project_id, error_id, user_id, **data): ELSE user_device END AS version, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} AND sessions.user_device_type = count_per_device_details.name GROUP BY user_device ORDER BY count DESC) AS count_per_device_v_details @@ -211,7 +223,7 @@ def get_details(project_id, error_id, user_id, **data): FROM (SELECT user_country AS name, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} GROUP BY user_country ORDER BY count DESC) AS count_per_country_details) AS country_details ON (TRUE) INNER JOIN (SELECT jsonb_agg(chart_details) AS chart24 @@ -709,36 +721,6 @@ def __status_rank(status): }.get(status) -def merge(error_ids): - error_ids = list(set(error_ids)) - errors = get_batch(error_ids) - if len(error_ids) <= 1 or len(error_ids) > len(errors): - return {"errors": ["invalid list of ids"]} - error_ids = [e["errorId"] for e in errors] - parent_error_id = error_ids[0] - status = "unresolved" - for e in errors: - if __status_rank(status) < __status_rank(e["status"]): - status = e["status"] - if __status_rank(status) == MAX_RANK: - break - params = { - "error_ids": tuple(error_ids), - "parent_error_id": parent_error_id, - "status": status - } - with pg_client.PostgresClient() as cur: - query = cur.mogrify( - """UPDATE public.errors - SET parent_error_id = %(parent_error_id)s, status = %(status)s - WHERE error_id IN %(error_ids)s OR parent_error_id IN %(error_ids)s;""", - params) - cur.execute(query=query) - # row = cur.fetchone() - - return {"data": "success"} - - def format_first_stack_frame(error): error["stack"] = sourcemaps.format_payload(error.pop("payload"), truncate_to_first=True) for s in error["stack"]: diff --git a/api/chalicelib/core/jobs.py b/api/chalicelib/core/jobs.py index 4b7ba85ee..2d244e366 100644 --- a/api/chalicelib/core/jobs.py +++ b/api/chalicelib/core/jobs.py @@ -144,7 +144,7 @@ def execute_jobs(): ) sessions.delete_sessions_by_session_ids(session_ids) - sessions_mobs.delete_mobs(session_ids) + sessions_mobs.delete_mobs(session_ids=session_ids, project_id=job["projectId"]) else: raise Exception(f"The action {job['action']} not supported.") diff --git a/api/chalicelib/core/log_tool_elasticsearch.py b/api/chalicelib/core/log_tool_elasticsearch.py index ba20636c4..7b00074c6 100644 --- a/api/chalicelib/core/log_tool_elasticsearch.py +++ b/api/chalicelib/core/log_tool_elasticsearch.py @@ -1,7 +1,6 @@ # from elasticsearch import Elasticsearch, RequestsHttpConnection from elasticsearch import Elasticsearch from chalicelib.core import log_tools -import base64 import logging logging.getLogger('elasticsearch').level = logging.ERROR diff --git a/api/chalicelib/core/metadata.py b/api/chalicelib/core/metadata.py index c245e44bf..0f73d0962 100644 --- a/api/chalicelib/core/metadata.py +++ b/api/chalicelib/core/metadata.py @@ -1,7 +1,7 @@ import re from chalicelib.core import projects -from chalicelib.utils import pg_client, dev +from chalicelib.utils import pg_client MAX_INDEXES = 10 diff --git a/api/chalicelib/core/metrics.py b/api/chalicelib/core/metrics.py index bf388c093..b25b441ed 100644 --- a/api/chalicelib/core/metrics.py +++ b/api/chalicelib/core/metrics.py @@ -419,7 +419,7 @@ def get_slowest_images(project_id, startTimestamp=TimeUTC.now(delta_days=-1), pg_sub_query_chart = __get_constraints(project_id=project_id, time_constraint=True, chart=True, data=args) pg_sub_query_chart.append("resources.type = 'img'") - pg_sub_query_chart.append("resources.url = top_img.url") + pg_sub_query_chart.append("resources.url_hostpath = top_img.url_hostpath") pg_sub_query_subset = __get_constraints(project_id=project_id, time_constraint=True, chart=False, data=args) @@ -431,13 +431,13 @@ def get_slowest_images(project_id, startTimestamp=TimeUTC.now(delta_days=-1), with pg_client.PostgresClient() as cur: pg_query = f"""SELECT * - FROM (SELECT resources.url, + FROM (SELECT resources.url_hostpath, COALESCE(AVG(resources.duration), 0) AS avg_duration, COUNT(resources.session_id) AS sessions_count FROM events.resources INNER JOIN sessions USING (session_id) WHERE {" AND ".join(pg_sub_query_subset)} - GROUP BY resources.url + GROUP BY resources.url_hostpath ORDER BY avg_duration DESC LIMIT 10) AS top_img LEFT JOIN LATERAL ( @@ -485,13 +485,13 @@ def get_performance(project_id, startTimestamp=TimeUTC.now(delta_days=-1), endTi if resources and len(resources) > 0: for r in resources: if r["type"] == "IMG": - img_constraints.append(f"resources.url = %(val_{len(img_constraints)})s") + img_constraints.append(f"resources.url_hostpath = %(val_{len(img_constraints)})s") img_constraints_vals["val_" + str(len(img_constraints) - 1)] = r['value'] elif r["type"] == "LOCATION": location_constraints.append(f"pages.path = %(val_{len(location_constraints)})s") location_constraints_vals["val_" + str(len(location_constraints) - 1)] = r['value'] else: - request_constraints.append(f"resources.url = %(val_{len(request_constraints)})s") + request_constraints.append(f"resources.url_hostpath = %(val_{len(request_constraints)})s") request_constraints_vals["val_" + str(len(request_constraints) - 1)] = r['value'] params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, "endTimestamp": endTimestamp} @@ -627,12 +627,12 @@ def search(text, resource_type, project_id, performance=False, pages_only=False, pg_sub_query.append("url_hostpath ILIKE %(value)s") with pg_client.PostgresClient() as cur: pg_query = f"""SELECT key, value - FROM ( SELECT DISTINCT ON (url) ROW_NUMBER() OVER (PARTITION BY type ORDER BY url) AS r, - url AS value, + FROM ( SELECT DISTINCT ON (url_hostpath) ROW_NUMBER() OVER (PARTITION BY type ORDER BY url_hostpath) AS r, + url_hostpath AS value, type AS key FROM events.resources INNER JOIN public.sessions USING (session_id) WHERE {" AND ".join(pg_sub_query)} - ORDER BY url, type ASC) AS ranked_values + ORDER BY url_hostpath, type ASC) AS ranked_values WHERE ranked_values.r<=5;""" cur.execute(cur.mogrify(pg_query, {"project_id": project_id, "value": helper.string_to_sql_like(text)})) rows = cur.fetchall() @@ -893,7 +893,7 @@ def get_resources_loading_time(project_id, startTimestamp=TimeUTC.now(delta_days if type is not None: pg_sub_query_subset.append(f"resources.type = '{__get_resource_db_type_from_type(type)}'") if url is not None: - pg_sub_query_subset.append(f"resources.url = %(value)s") + pg_sub_query_subset.append(f"resources.url_hostpath = %(value)s") with pg_client.PostgresClient() as cur: pg_query = f"""WITH resources AS (SELECT resources.duration, timestamp @@ -1009,7 +1009,7 @@ def get_slowest_resources(project_id, startTimestamp=TimeUTC.now(delta_days=-1), ORDER BY avg DESC LIMIT 10) AS main_list INNER JOIN LATERAL ( - SELECT url, type + SELECT url_hostpath AS url, type FROM events.resources INNER JOIN public.sessions USING (session_id) WHERE {" AND ".join(pg_sub_query)} diff --git a/api/chalicelib/core/projects.py b/api/chalicelib/core/projects.py index ba334e101..10d1e7aee 100644 --- a/api/chalicelib/core/projects.py +++ b/api/chalicelib/core/projects.py @@ -2,7 +2,7 @@ import json import schemas from chalicelib.core import users -from chalicelib.utils import pg_client, helper, dev +from chalicelib.utils import pg_client, helper from chalicelib.utils.TimeUTC import TimeUTC @@ -48,7 +48,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st if gdpr: extra_projection += ',s.gdpr' if recorded: - extra_projection += """, COALESCE(nullif(EXTRACT(EPOCH FROM s.first_recorded_session_at) * 1000, NULL)::BIGINT, + extra_projection += """,COALESCE(nullif(EXTRACT(EPOCH FROM s.first_recorded_session_at) * 1000, NULL)::BIGINT, (SELECT MIN(sessions.start_ts) FROM public.sessions WHERE sessions.project_id = s.project_id @@ -76,19 +76,21 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st rows = cur.fetchall() # if recorded is requested, check if it was saved or computed if recorded: - for r in rows: + u_values = [] + params = {} + for i, r in enumerate(rows): if r["first_recorded_session_at"] is None: - extra_update = "" - if r["recorded"]: - extra_update = ", first_recorded_session_at=to_timestamp(%(first_recorded)s/1000)" - query = cur.mogrify(f"""UPDATE public.projects - SET sessions_last_check_at=(now() at time zone 'utc') - {extra_update} - WHERE project_id=%(project_id)s""", - {"project_id": r["project_id"], "first_recorded": r["first_recorded"]}) - cur.execute(query) + u_values.append(f"(%(project_id_{i})s,to_timestamp(%(first_recorded_{i})s/1000))") + params[f"project_id_{i}"] = r["project_id"] + params[f"first_recorded_{i}"] = r["first_recorded"] if r["recorded"] else None r.pop("first_recorded_session_at") r.pop("first_recorded") + if len(u_values) > 0: + query = cur.mogrify(f"""UPDATE public.projects + SET sessions_last_check_at=(now() at time zone 'utc'), first_recorded_session_at=u.first_recorded + FROM (VALUES {",".join(u_values)}) AS u(project_id,first_recorded) + WHERE projects.project_id=u.project_id;""", params) + cur.execute(query) if recording_state and len(rows) > 0: project_ids = [f'({r["project_id"]})' for r in rows] diff --git a/api/chalicelib/core/reset_password.py b/api/chalicelib/core/reset_password.py index 2026cd829..782b63ad4 100644 --- a/api/chalicelib/core/reset_password.py +++ b/api/chalicelib/core/reset_password.py @@ -11,11 +11,7 @@ def reset(data: schemas.ForgetPasswordPayloadSchema): if not helper.has_smtp(): return {"errors": ["no SMTP configuration found, you can ask your admin to reset your password"]} a_users = users.get_by_email_only(data.email) - if len(a_users) > 1: - print(f"multiple users found for [{data.email}] please contact our support") - return {"errors": ["multiple users, please contact our support"]} - elif len(a_users) == 1: - a_users = a_users[0] + if a_users: invitation_link = users.generate_new_invitation(user_id=a_users["id"]) email_helper.send_forgot_password(recipient=data.email, invitation_link=invitation_link) else: diff --git a/api/chalicelib/core/sessions.py b/api/chalicelib/core/sessions.py index 6c846eb42..91efb967f 100644 --- a/api/chalicelib/core/sessions.py +++ b/api/chalicelib/core/sessions.py @@ -2,7 +2,8 @@ from typing import List import schemas from chalicelib.core import events, metadata, events_ios, \ - sessions_mobs, issues, projects, errors, resources, assist, performance_event, sessions_viewed, sessions_favorite + sessions_mobs, issues, projects, errors, resources, assist, performance_event, sessions_viewed, sessions_favorite, \ + sessions_devtool, sessions_notes from chalicelib.utils import pg_client, helper, metrics_helper SESSION_PROJECTION_COLS = """s.project_id, @@ -39,8 +40,8 @@ def __group_metadata(session, project_metadata): return meta -def get_by_id2_pg(project_id, session_id, user_id, full_data=False, include_fav_viewed=False, group_metadata=False, - live=True): +def get_by_id2_pg(project_id, session_id, context: schemas.CurrentContext, full_data=False, include_fav_viewed=False, + group_metadata=False, live=True): with pg_client.PostgresClient() as cur: extra_query = [] if include_fav_viewed: @@ -63,7 +64,7 @@ def get_by_id2_pg(project_id, session_id, user_id, full_data=False, include_fav_ FROM public.sessions AS s {"INNER JOIN public.projects AS p USING (project_id)" if group_metadata else ""} WHERE s.project_id = %(project_id)s AND s.session_id = %(session_id)s;""", - {"project_id": project_id, "session_id": session_id, "userId": user_id} + {"project_id": project_id, "session_id": session_id, "userId": context.user_id} ) # print("===============") # print(query) @@ -81,27 +82,29 @@ def get_by_id2_pg(project_id, session_id, user_id, full_data=False, include_fav_ data['crashes'] = events_ios.get_crashes_by_session_id(session_id=session_id) data['userEvents'] = events_ios.get_customs_by_sessionId(project_id=project_id, session_id=session_id) - data['mobsUrl'] = sessions_mobs.get_ios(sessionId=session_id) + data['mobsUrl'] = sessions_mobs.get_ios(session_id=session_id) else: data['events'] = events.get_by_sessionId2_pg(project_id=project_id, session_id=session_id, group_clickrage=True) all_errors = events.get_errors_by_session_id(session_id=session_id, project_id=project_id) data['stackEvents'] = [e for e in all_errors if e['source'] != "js_exception"] # to keep only the first stack - data['errors'] = [errors.format_first_stack_frame(e) for e in all_errors if - e['source'] == "js_exception"][ - :500] # limit the number of errors to reduce the response-body size + # limit the number of errors to reduce the response-body size + data['errors'] = [errors.format_first_stack_frame(e) for e in all_errors + if e['source'] == "js_exception"][:500] data['userEvents'] = events.get_customs_by_sessionId2_pg(project_id=project_id, session_id=session_id) - data['mobsUrl'] = sessions_mobs.get_web(sessionId=session_id) + data['domURL'] = sessions_mobs.get_urls(session_id=session_id, project_id=project_id) + data['mobsUrl'] = sessions_mobs.get_urls_depercated(session_id=session_id) + data['devtoolsURL'] = sessions_devtool.get_urls(session_id=session_id, project_id=project_id) data['resources'] = resources.get_by_session_id(session_id=session_id, project_id=project_id, - start_ts=data["startTs"], - duration=data["duration"]) + start_ts=data["startTs"], duration=data["duration"]) + data['notes'] = sessions_notes.get_session_notes(tenant_id=context.tenant_id, project_id=project_id, + session_id=session_id, user_id=context.user_id) data['metadata'] = __group_metadata(project_metadata=data.pop("projectMetadata"), session=data) data['issues'] = issues.get_by_session_id(session_id=session_id, project_id=project_id) - data['live'] = live and assist.is_live(project_id=project_id, - session_id=session_id, + data['live'] = live and assist.is_live(project_id=project_id, session_id=session_id, project_key=data["projectKey"]) data["inDB"] = True return data @@ -174,7 +177,7 @@ def _isUndefined_operator(op: schemas.SearchEventOperator): # This function executes the query and return result def search_sessions(data: schemas.SessionsSearchPayloadSchema, project_id, user_id, errors_only=False, - error_status=schemas.ErrorStatus.all, count_only=False, issue=None): + error_status=schemas.ErrorStatus.all, count_only=False, issue=None, ids_only=False): if data.bookmarked: data.startDate, data.endDate = sessions_favorite.get_start_end_timestamp(project_id, user_id) @@ -182,9 +185,11 @@ def search_sessions(data: schemas.SessionsSearchPayloadSchema, project_id, user_ favorite_only=data.bookmarked, issue=issue, project_id=project_id, user_id=user_id) if data.limit is not None and data.page is not None: + full_args["sessions_limit"] = data.limit full_args["sessions_limit_s"] = (data.page - 1) * data.limit full_args["sessions_limit_e"] = data.page * data.limit else: + full_args["sessions_limit"] = 200 full_args["sessions_limit_s"] = 1 full_args["sessions_limit_e"] = 200 @@ -232,6 +237,12 @@ def search_sessions(data: schemas.SessionsSearchPayloadSchema, project_id, user_ GROUP BY user_id ) AS users_sessions;""", full_args) + elif ids_only: + main_query = cur.mogrify(f"""SELECT DISTINCT ON(s.session_id) s.session_id + {query_part} + ORDER BY s.session_id desc + LIMIT %(sessions_limit)s OFFSET %(sessions_limit_s)s;""", + full_args) else: if data.order is None: data.order = schemas.SortOrderType.desc @@ -239,7 +250,6 @@ def search_sessions(data: schemas.SessionsSearchPayloadSchema, project_id, user_ if data.sort is not None and data.sort != "session_id": # sort += " " + data.order + "," + helper.key_to_snake_case(data.sort) sort = helper.key_to_snake_case(data.sort) - meta_keys = metadata.get(project_id=project_id) main_query = cur.mogrify(f"""SELECT COUNT(full_sessions) AS count, COALESCE(JSONB_AGG(full_sessions) @@ -263,7 +273,7 @@ def search_sessions(data: schemas.SessionsSearchPayloadSchema, project_id, user_ print(data.json()) print("--------------------") raise err - if errors_only: + if errors_only or ids_only: return helper.list_to_camel_case(cur.fetchall()) sessions = cur.fetchone() @@ -329,7 +339,15 @@ def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, d # print("--------------------") # print(main_query) # print("--------------------") - cur.execute(main_query) + try: + cur.execute(main_query) + except Exception as err: + print("--------- SESSIONS-SERIES QUERY EXCEPTION -----------") + print(main_query.decode('UTF-8')) + print("--------- PAYLOAD -----------") + print(data.json()) + print("--------------------") + raise err if view_type == schemas.MetricTimeseriesViewType.line_chart: sessions = cur.fetchall() else: @@ -1237,3 +1255,15 @@ def count_all(): with pg_client.PostgresClient(unlimited_query=True) as cur: row = cur.execute(query="SELECT COUNT(session_id) AS count FROM public.sessions") return row.get("count", 0) + + +def session_exists(project_id, session_id): + with pg_client.PostgresClient() as cur: + query = cur.mogrify("""SELECT 1 + FROM public.sessions + WHERE session_id=%(session_id)s + AND project_id=%(project_id)s""", + {"project_id": project_id, "session_id": session_id}) + cur.execute(query) + row = cur.fetchone() + return row is not None diff --git a/api/chalicelib/core/sessions_assignments.py b/api/chalicelib/core/sessions_assignments.py index 4491f62d0..567200b07 100644 --- a/api/chalicelib/core/sessions_assignments.py +++ b/api/chalicelib/core/sessions_assignments.py @@ -23,7 +23,8 @@ def __get_saved_data(project_id, session_id, issue_id, tool): return helper.dict_to_camel_case(cur.fetchone()) -def create_new_assignment(tenant_id, project_id, session_id, creator_id, assignee, description, title, issue_type, integration_project_id): +def create_new_assignment(tenant_id, project_id, session_id, creator_id, assignee, description, title, issue_type, + integration_project_id): error, integration = integrations_manager.get_integration(tenant_id=tenant_id, user_id=creator_id) if error is not None: return error @@ -40,7 +41,7 @@ def create_new_assignment(tenant_id, project_id, session_id, creator_id, assigne integration_project_id=integration_project_id) except integration_base_issue.RequestException as e: return integration_base_issue.proxy_issues_handler(e) - if issue is not None and "id" not in issue: + if issue is None or "id" not in issue: return {"errors": ["something went wrong while creating the issue"]} with pg_client.PostgresClient() as cur: query = cur.mogrify("""\ diff --git a/api/chalicelib/core/sessions_devtool.py b/api/chalicelib/core/sessions_devtool.py new file mode 100644 index 000000000..2afc3c366 --- /dev/null +++ b/api/chalicelib/core/sessions_devtool.py @@ -0,0 +1,24 @@ +from decouple import config + +from chalicelib.utils import s3 + + +def __get_devtools_keys(project_id, session_id): + params = { + "sessionId": session_id, + "projectId": project_id + } + return [ + config("DEVTOOLS_MOB_PATTERN", default="%(sessionId)sdevtools") % params + ] + + +def get_urls(session_id, project_id): + results = [] + for k in __get_devtools_keys(project_id=project_id, session_id=session_id): + results.append(s3.client.generate_presigned_url( + 'get_object', + Params={'Bucket': config("sessions_bucket"), 'Key': k}, + ExpiresIn=config("PRESIGNED_URL_EXPIRATION", cast=int, default=900) + )) + return results diff --git a/api/chalicelib/core/sessions_favorite.py b/api/chalicelib/core/sessions_favorite.py index 98d7f18ce..4c456d385 100644 --- a/api/chalicelib/core/sessions_favorite.py +++ b/api/chalicelib/core/sessions_favorite.py @@ -1,37 +1,39 @@ +import schemas from chalicelib.core import sessions from chalicelib.utils import pg_client -def add_favorite_session(project_id, user_id, session_id): +def add_favorite_session(context: schemas.CurrentContext, project_id, session_id): with pg_client.PostgresClient() as cur: cur.execute( cur.mogrify(f"""\ INSERT INTO public.user_favorite_sessions(user_id, session_id) - VALUES (%(userId)s,%(sessionId)s);""", - {"userId": user_id, "sessionId": session_id}) + VALUES (%(userId)s,%(session_id)s);""", + {"userId": context.user_id, "session_id": session_id}) ) - return sessions.get_by_id2_pg(project_id=project_id, session_id=session_id, user_id=user_id, full_data=False, - include_fav_viewed=True) + return sessions.get_by_id2_pg(context=context, project_id=project_id, session_id=session_id, + full_data=False, include_fav_viewed=True) -def remove_favorite_session(project_id, user_id, session_id): +def remove_favorite_session(context: schemas.CurrentContext, project_id, session_id): with pg_client.PostgresClient() as cur: cur.execute( cur.mogrify(f"""\ DELETE FROM public.user_favorite_sessions WHERE user_id = %(userId)s - AND session_id = %(sessionId)s;""", - {"userId": user_id, "sessionId": session_id}) + AND session_id = %(session_id)s;""", + {"userId": context.user_id, "session_id": session_id}) ) - return sessions.get_by_id2_pg(project_id=project_id, session_id=session_id, user_id=user_id, full_data=False, - include_fav_viewed=True) + return sessions.get_by_id2_pg(context=context, project_id=project_id, session_id=session_id, + full_data=False, include_fav_viewed=True) -def favorite_session(project_id, user_id, session_id): - if favorite_session_exists(user_id=user_id, session_id=session_id): - return remove_favorite_session(project_id=project_id, user_id=user_id, session_id=session_id) +def favorite_session(context: schemas.CurrentContext, project_id, session_id): + if favorite_session_exists(user_id=context.user_id, session_id=session_id): + return remove_favorite_session(context=context, project_id=project_id, + session_id=session_id) - return add_favorite_session(project_id=project_id, user_id=user_id, session_id=session_id) + return add_favorite_session(context=context, project_id=project_id, session_id=session_id) def favorite_session_exists(user_id, session_id): @@ -42,8 +44,8 @@ def favorite_session_exists(user_id, session_id): FROM public.user_favorite_sessions WHERE user_id = %(userId)s - AND session_id = %(sessionId)s""", - {"userId": user_id, "sessionId": session_id}) + AND session_id = %(session_id)s""", + {"userId": user_id, "session_id": session_id}) ) r = cur.fetchone() return r is not None @@ -61,4 +63,4 @@ def get_start_end_timestamp(project_id, user_id): {"userId": user_id, "project_id": project_id}) ) r = cur.fetchone() - return (0, 0) if r is None else (r["max_start_ts"], r["min_start_ts"]) + return (0, 0) if r is None else (r["min_start_ts"], r["max_start_ts"]) diff --git a/api/chalicelib/core/sessions_mobs.py b/api/chalicelib/core/sessions_mobs.py index ccbda20bb..9a9237be8 100644 --- a/api/chalicelib/core/sessions_mobs.py +++ b/api/chalicelib/core/sessions_mobs.py @@ -1,40 +1,57 @@ from decouple import config from chalicelib.utils import s3 -from chalicelib.utils.s3 import client -def get_web(sessionId): +def __get_mob_keys(project_id, session_id): + params = { + "sessionId": session_id, + "projectId": project_id + } return [ - client.generate_presigned_url( - 'get_object', - Params={ - 'Bucket': config("sessions_bucket"), - 'Key': str(sessionId) - }, - ExpiresIn=100000 - ), - client.generate_presigned_url( - 'get_object', - Params={ - 'Bucket': config("sessions_bucket"), - 'Key': str(sessionId) + "e" - }, - ExpiresIn=100000 - )] + config("SESSION_MOB_PATTERN_S", default="%(sessionId)s") % params, + config("SESSION_MOB_PATTERN_E", default="%(sessionId)se") % params + ] -def get_ios(sessionId): - return client.generate_presigned_url( +def __get_mob_keys_deprecated(session_id): + return [str(session_id), str(session_id) + "e"] + + +def get_urls(project_id, session_id): + results = [] + for k in __get_mob_keys(project_id=project_id, session_id=session_id): + results.append(s3.client.generate_presigned_url( + 'get_object', + Params={'Bucket': config("sessions_bucket"), 'Key': k}, + ExpiresIn=config("PRESIGNED_URL_EXPIRATION", cast=int, default=900) + )) + return results + + +def get_urls_depercated(session_id): + results = [] + for k in __get_mob_keys_deprecated(session_id=session_id): + results.append(s3.client.generate_presigned_url( + 'get_object', + Params={'Bucket': config("sessions_bucket"), 'Key': k}, + ExpiresIn=100000 + )) + return results + + +def get_ios(session_id): + return s3.client.generate_presigned_url( 'get_object', Params={ 'Bucket': config("ios_bucket"), - 'Key': str(sessionId) + 'Key': str(session_id) }, - ExpiresIn=100000 + ExpiresIn=config("PRESIGNED_URL_EXPIRATION", cast=int, default=900) ) -def delete_mobs(session_ids): +def delete_mobs(project_id, session_ids): for session_id in session_ids: - s3.schedule_for_deletion(config("sessions_bucket"), session_id) + for k in __get_mob_keys(project_id=project_id, session_id=session_id): + s3.schedule_for_deletion(config("sessions_bucket"), k) diff --git a/api/chalicelib/core/sessions_notes.py b/api/chalicelib/core/sessions_notes.py new file mode 100644 index 000000000..661c94efd --- /dev/null +++ b/api/chalicelib/core/sessions_notes.py @@ -0,0 +1,166 @@ +from urllib.parse import urljoin + +from decouple import config + +import schemas +from chalicelib.core import sessions +from chalicelib.core.collaboration_slack import Slack +from chalicelib.utils import pg_client, helper +from chalicelib.utils.TimeUTC import TimeUTC + + +def get_note(tenant_id, project_id, user_id, note_id, share=None): + with pg_client.PostgresClient() as cur: + query = cur.mogrify(f"""SELECT sessions_notes.*, users.name AS creator_name + {",(SELECT name FROM users WHERE user_id=%(share)s AND deleted_at ISNULL) AS share_name" if share else ""} + FROM sessions_notes INNER JOIN users USING (user_id) + WHERE sessions_notes.project_id = %(project_id)s + AND sessions_notes.note_id = %(note_id)s + AND sessions_notes.deleted_at IS NULL + AND (sessions_notes.user_id = %(user_id)s OR sessions_notes.is_public);""", + {"project_id": project_id, "user_id": user_id, "tenant_id": tenant_id, + "note_id": note_id, "share": share}) + + cur.execute(query=query) + row = cur.fetchone() + row = helper.dict_to_camel_case(row) + if row: + row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"]) + return row + + +def get_session_notes(tenant_id, project_id, session_id, user_id): + with pg_client.PostgresClient() as cur: + query = cur.mogrify(f"""SELECT sessions_notes.* + FROM sessions_notes + WHERE sessions_notes.project_id = %(project_id)s + AND sessions_notes.deleted_at IS NULL + AND sessions_notes.session_id = %(session_id)s + AND (sessions_notes.user_id = %(user_id)s + OR sessions_notes.is_public) + ORDER BY created_at DESC;""", + {"project_id": project_id, "user_id": user_id, + "tenant_id": tenant_id, "session_id": session_id}) + + cur.execute(query=query) + rows = cur.fetchall() + rows = helper.list_to_camel_case(rows) + for row in rows: + row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"]) + return rows + + +def get_all_notes_by_project_id(tenant_id, project_id, user_id, data: schemas.SearchNoteSchema): + with pg_client.PostgresClient() as cur: + conditions = ["sessions_notes.project_id = %(project_id)s", "sessions_notes.deleted_at IS NULL"] + extra_params = {} + if data.tags and len(data.tags) > 0: + k = "tag_value" + conditions.append( + sessions._multiple_conditions(f"%({k})s = sessions_notes.tag", data.tags, value_key=k)) + extra_params = sessions._multiple_values(data.tags, value_key=k) + if data.shared_only: + conditions.append("sessions_notes.is_public") + elif data.mine_only: + conditions.append("sessions_notes.user_id = %(user_id)s") + else: + conditions.append("(sessions_notes.user_id = %(user_id)s OR sessions_notes.is_public)") + query = cur.mogrify(f"""SELECT sessions_notes.* + FROM sessions_notes + WHERE {" AND ".join(conditions)} + ORDER BY created_at {data.order} + LIMIT {data.limit} OFFSET {data.limit * (data.page - 1)};""", + {"project_id": project_id, "user_id": user_id, "tenant_id": tenant_id, **extra_params}) + + cur.execute(query=query) + rows = cur.fetchall() + rows = helper.list_to_camel_case(rows) + for row in rows: + row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"]) + return rows + + +def create(tenant_id, user_id, project_id, session_id, data: schemas.SessionNoteSchema): + with pg_client.PostgresClient() as cur: + query = cur.mogrify(f"""INSERT INTO public.sessions_notes (message, user_id, tag, session_id, project_id, timestamp, is_public) + VALUES (%(message)s, %(user_id)s, %(tag)s, %(session_id)s, %(project_id)s, %(timestamp)s, %(is_public)s) + RETURNING *;""", + {"user_id": user_id, "project_id": project_id, "session_id": session_id, **data.dict()}) + cur.execute(query) + result = helper.dict_to_camel_case(cur.fetchone()) + if result: + result["createdAt"] = TimeUTC.datetime_to_timestamp(result["createdAt"]) + return result + + +def edit(tenant_id, user_id, project_id, note_id, data: schemas.SessionUpdateNoteSchema): + sub_query = [] + if data.message is not None: + sub_query.append("message = %(message)s") + if data.tag is not None and len(data.tag) > 0: + sub_query.append("tag = %(tag)s") + if data.is_public is not None: + sub_query.append("is_public = %(is_public)s") + if data.timestamp is not None: + sub_query.append("timestamp = %(timestamp)s") + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify(f"""UPDATE public.sessions_notes + SET + {" ,".join(sub_query)} + WHERE + project_id = %(project_id)s + AND user_id = %(user_id)s + AND note_id = %(note_id)s + AND deleted_at ISNULL + RETURNING *;""", + {"project_id": project_id, "user_id": user_id, "note_id": note_id, **data.dict()}) + ) + row = helper.dict_to_camel_case(cur.fetchone()) + if row: + row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"]) + return row + + +def delete(tenant_id, user_id, project_id, note_id): + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify(""" UPDATE public.sessions_notes + SET deleted_at = timezone('utc'::text, now()) + WHERE note_id = %(note_id)s + AND project_id = %(project_id)s + AND user_id = %(user_id)s + AND deleted_at ISNULL;""", + {"project_id": project_id, "user_id": user_id, "note_id": note_id}) + ) + return {"data": {"state": "success"}} + + +def share_to_slack(tenant_id, user_id, project_id, note_id, webhook_id): + note = get_note(tenant_id=tenant_id, project_id=project_id, user_id=user_id, note_id=note_id, share=user_id) + if note is None: + return {"errors": ["Note not found"]} + session_url = urljoin(config('SITE_URL'), f"{note['projectId']}/session/{note['sessionId']}") + title = f"<{session_url}|Note for session {note['sessionId']}>" + + blocks = [{"type": "section", + "fields": [{"type": "mrkdwn", + "text": title}]}, + {"type": "section", + "fields": [{"type": "plain_text", + "text": note["message"]}]}] + if note["tag"]: + blocks.append({"type": "context", + "elements": [{"type": "plain_text", + "text": f"Tag: *{note['tag']}*"}]}) + bottom = f"Created by {note['creatorName'].capitalize()}" + if user_id != note["userId"]: + bottom += f"\nSent by {note['shareName']}: " + blocks.append({"type": "context", + "elements": [{"type": "plain_text", + "text": bottom}]}) + return Slack.send_raw( + tenant_id=tenant_id, + webhook_id=webhook_id, + body={"blocks": blocks} + ) diff --git a/api/chalicelib/core/sessions_viewed.py b/api/chalicelib/core/sessions_viewed.py index c9b2c9b46..d84483bf2 100644 --- a/api/chalicelib/core/sessions_viewed.py +++ b/api/chalicelib/core/sessions_viewed.py @@ -5,7 +5,7 @@ def view_session(project_id, user_id, session_id): with pg_client.PostgresClient() as cur: cur.execute( cur.mogrify("""INSERT INTO public.user_viewed_sessions(user_id, session_id) - VALUES (%(userId)s,%(sessionId)s) + VALUES (%(userId)s,%(session_id)s) ON CONFLICT DO NOTHING;""", - {"userId": user_id, "sessionId": session_id}) + {"userId": user_id, "session_id": session_id}) ) diff --git a/api/chalicelib/core/significance.py b/api/chalicelib/core/significance.py index d31b8aea0..c4a4fcaac 100644 --- a/api/chalicelib/core/significance.py +++ b/api/chalicelib/core/significance.py @@ -3,7 +3,6 @@ __maintainer__ = "KRAIEM Taha Yassine" import schemas from chalicelib.core import events, metadata, sessions -from chalicelib.utils import dev """ todo: remove LIMIT from the query @@ -182,9 +181,7 @@ def get_stages_and_events(filter_d, project_id) -> List[RealDictRow]: values=s["value"], value_key=f"value{i + 1}") n_stages_query.append(f""" (SELECT main.session_id, - {"MIN(main.timestamp)" if i + 1 < len(stages) else "MAX(main.timestamp)"} AS stage{i + 1}_timestamp, - '{event_type}' AS type, - '{s["operator"]}' AS operator + {"MIN(main.timestamp)" if i + 1 < len(stages) else "MAX(main.timestamp)"} AS stage{i + 1}_timestamp FROM {next_table} AS main {" ".join(extra_from)} WHERE main.timestamp >= {f"T{i}.stage{i}_timestamp" if i > 0 else "%(startTimestamp)s"} {f"AND main.session_id=T1.session_id" if i > 0 else ""} @@ -192,45 +189,55 @@ def get_stages_and_events(filter_d, project_id) -> List[RealDictRow]: {(" AND " + " AND ".join(stage_constraints)) if len(stage_constraints) > 0 else ""} {(" AND " + " AND ".join(first_stage_extra_constraints)) if len(first_stage_extra_constraints) > 0 and i == 0 else ""} GROUP BY main.session_id) - AS T{i + 1} {"USING (session_id)" if i > 0 else ""} + AS T{i + 1} {"ON (TRUE)" if i > 0 else ""} """) - if len(n_stages_query) == 0: + n_stages = len(n_stages_query) + if n_stages == 0: return [] n_stages_query = " LEFT JOIN LATERAL ".join(n_stages_query) n_stages_query += ") AS stages_t" n_stages_query = f""" - SELECT stages_and_issues_t.*,sessions.session_id, sessions.user_uuid FROM ( + SELECT stages_and_issues_t.*, sessions.user_uuid + FROM ( SELECT * FROM ( - SELECT * FROM - {n_stages_query} + SELECT T1.session_id, {",".join([f"stage{i + 1}_timestamp" for i in range(n_stages)])} + FROM {n_stages_query} LEFT JOIN LATERAL - ( - SELECT * FROM - (SELECT ISE.session_id, - ISS.type as issue_type, + ( SELECT ISS.type as issue_type, ISE.timestamp AS issue_timestamp, - ISS.context_string as issue_context, + COALESCE(ISS.context_string,'') as issue_context, ISS.issue_id as issue_id FROM events_common.issues AS ISE INNER JOIN issues AS ISS USING (issue_id) WHERE ISE.timestamp >= stages_t.stage1_timestamp AND ISE.timestamp <= stages_t.stage{i + 1}_timestamp AND ISS.project_id=%(project_id)s - {"AND ISS.type IN %(issueTypes)s" if len(filter_issues) > 0 else ""}) AS base_t - ) AS issues_t - USING (session_id)) AS stages_and_issues_t - inner join sessions USING(session_id); + AND ISE.session_id = stages_t.session_id + AND ISS.type!='custom' -- ignore custom issues because they are massive + {"AND ISS.type IN %(issueTypes)s" if len(filter_issues) > 0 else ""} + LIMIT 10 -- remove the limit to get exact stats + ) AS issues_t ON (TRUE) + ) AS stages_and_issues_t INNER JOIN sessions USING(session_id); """ # LIMIT 10000 params = {"project_id": project_id, "startTimestamp": filter_d["startDate"], "endTimestamp": filter_d["endDate"], "issueTypes": tuple(filter_issues), **values} with pg_client.PostgresClient() as cur: + query = cur.mogrify(n_stages_query, params) # print("---------------------------------------------------") - # print(cur.mogrify(n_stages_query, params)) + # print(query) # print("---------------------------------------------------") - cur.execute(cur.mogrify(n_stages_query, params)) - rows = cur.fetchall() + try: + cur.execute(query) + rows = cur.fetchall() + except Exception as err: + print("--------- FUNNEL SEARCH QUERY EXCEPTION -----------") + print(query.decode('UTF-8')) + print("--------- PAYLOAD -----------") + print(filter_d) + print("--------------------") + raise err return rows @@ -292,7 +299,21 @@ def pearson_corr(x: list, y: list): return r, confidence, False -def get_transitions_and_issues_of_each_type(rows: List[RealDictRow], all_issues_with_context, first_stage, last_stage): +# def tuple_or(t: tuple): +# x = 0 +# for el in t: +# x |= el # | is for bitwise OR +# return x +# +# The following function is correct optimization of the previous function because t is a list of 0,1 +def tuple_or(t: tuple): + for el in t: + if el > 0: + return 1 + return 0 + + +def get_transitions_and_issues_of_each_type(rows: List[RealDictRow], all_issues, first_stage, last_stage): """ Returns two lists with binary values 0/1: @@ -311,12 +332,6 @@ def get_transitions_and_issues_of_each_type(rows: List[RealDictRow], all_issues_ transitions = [] n_sess_affected = 0 errors = {} - for issue in all_issues_with_context: - split = issue.split('__^__') - errors[issue] = { - "errors": [], - "issue_type": split[0], - "context": split[1]} for row in rows: t = 0 @@ -324,38 +339,26 @@ def get_transitions_and_issues_of_each_type(rows: List[RealDictRow], all_issues_ last_ts = row[f'stage{last_stage}_timestamp'] if first_ts is None: continue - elif first_ts is not None and last_ts is not None: + elif last_ts is not None: t = 1 transitions.append(t) ic_present = False - for issue_type_with_context in errors: + for error_id in all_issues: + if error_id not in errors: + errors[error_id] = [] ic = 0 - issue_type = errors[issue_type_with_context]["issue_type"] - context = errors[issue_type_with_context]["context"] - if row['issue_type'] is not None: + row_issue_id = row['issue_id'] + if row_issue_id is not None: if last_ts is None or (first_ts < row['issue_timestamp'] < last_ts): - context_in_row = row['issue_context'] if row['issue_context'] is not None else '' - if issue_type == row['issue_type'] and context == context_in_row: + if error_id == row_issue_id: ic = 1 ic_present = True - errors[issue_type_with_context]["errors"].append(ic) + errors[error_id].append(ic) if ic_present and t: n_sess_affected += 1 - # def tuple_or(t: tuple): - # x = 0 - # for el in t: - # x |= el - # return x - def tuple_or(t: tuple): - for el in t: - if el > 0: - return 1 - return 0 - - errors = {key: errors[key]["errors"] for key in errors} all_errors = [tuple_or(t) for t in zip(*errors.values())] return transitions, errors, all_errors, n_sess_affected @@ -371,10 +374,9 @@ def get_affected_users_for_all_issues(rows, first_stage, last_stage): """ affected_users = defaultdict(lambda: set()) affected_sessions = defaultdict(lambda: set()) - contexts = defaultdict(lambda: None) + all_issues = {} n_affected_users_dict = defaultdict(lambda: None) n_affected_sessions_dict = defaultdict(lambda: None) - all_issues_with_context = set() n_issues_dict = defaultdict(lambda: 0) issues_by_session = defaultdict(lambda: 0) @@ -390,15 +392,13 @@ def get_affected_users_for_all_issues(rows, first_stage, last_stage): # check that the issue exists and belongs to subfunnel: if iss is not None and (row[f'stage{last_stage}_timestamp'] is None or (row[f'stage{first_stage}_timestamp'] < iss_ts < row[f'stage{last_stage}_timestamp'])): - context_string = row['issue_context'] if row['issue_context'] is not None else '' - issue_with_context = iss + '__^__' + context_string - contexts[issue_with_context] = {"context": context_string, "id": row["issue_id"]} - all_issues_with_context.add(issue_with_context) - n_issues_dict[issue_with_context] += 1 + if row["issue_id"] not in all_issues: + all_issues[row["issue_id"]] = {"context": row['issue_context'], "issue_type": row["issue_type"]} + n_issues_dict[row["issue_id"]] += 1 if row['user_uuid'] is not None: - affected_users[issue_with_context].add(row['user_uuid']) + affected_users[row["issue_id"]].add(row['user_uuid']) - affected_sessions[issue_with_context].add(row['session_id']) + affected_sessions[row["issue_id"]].add(row['session_id']) issues_by_session[row[f'session_id']] += 1 if len(affected_users) > 0: @@ -409,29 +409,28 @@ def get_affected_users_for_all_issues(rows, first_stage, last_stage): n_affected_sessions_dict.update({ iss: len(affected_sessions[iss]) for iss in affected_sessions }) - return all_issues_with_context, n_issues_dict, n_affected_users_dict, n_affected_sessions_dict, contexts + return all_issues, n_issues_dict, n_affected_users_dict, n_affected_sessions_dict def count_sessions(rows, n_stages): session_counts = {i: set() for i in range(1, n_stages + 1)} - for ind, row in enumerate(rows): + for row in rows: for i in range(1, n_stages + 1): if row[f"stage{i}_timestamp"] is not None: session_counts[i].add(row[f"session_id"]) + session_counts = {i: len(session_counts[i]) for i in session_counts} return session_counts def count_users(rows, n_stages): - users_in_stages = defaultdict(lambda: set()) - - for ind, row in enumerate(rows): + users_in_stages = {i: set() for i in range(1, n_stages + 1)} + for row in rows: for i in range(1, n_stages + 1): if row[f"stage{i}_timestamp"] is not None: users_in_stages[i].add(row["user_uuid"]) users_count = {i: len(users_in_stages[i]) for i in range(1, n_stages + 1)} - return users_count @@ -484,18 +483,18 @@ def get_issues(stages, rows, first_stage=None, last_stage=None, drop_only=False) last_stage = n_stages n_critical_issues = 0 - issues_dict = dict({"significant": [], - "insignificant": []}) + issues_dict = {"significant": [], + "insignificant": []} session_counts = count_sessions(rows, n_stages) drop = session_counts[first_stage] - session_counts[last_stage] - all_issues_with_context, n_issues_dict, affected_users_dict, affected_sessions, contexts = get_affected_users_for_all_issues( + all_issues, n_issues_dict, affected_users_dict, affected_sessions = get_affected_users_for_all_issues( rows, first_stage, last_stage) transitions, errors, all_errors, n_sess_affected = get_transitions_and_issues_of_each_type(rows, - all_issues_with_context, + all_issues, first_stage, last_stage) - # print("len(transitions) =", len(transitions)) + del rows if any(all_errors): total_drop_corr, conf, is_sign = pearson_corr(transitions, all_errors) @@ -508,33 +507,35 @@ def get_issues(stages, rows, first_stage=None, last_stage=None, drop_only=False) if drop_only: return total_drop_due_to_issues - for issue in all_issues_with_context: + for issue_id in all_issues: - if not any(errors[issue]): + if not any(errors[issue_id]): continue - r, confidence, is_sign = pearson_corr(transitions, errors[issue]) + r, confidence, is_sign = pearson_corr(transitions, errors[issue_id]) if r is not None and drop is not None and is_sign: - lost_conversions = int(r * affected_sessions[issue]) + lost_conversions = int(r * affected_sessions[issue_id]) else: lost_conversions = None if r is None: r = 0 - split = issue.split('__^__') issues_dict['significant' if is_sign else 'insignificant'].append({ - "type": split[0], - "title": helper.get_issue_title(split[0]), - "affected_sessions": affected_sessions[issue], - "unaffected_sessions": session_counts[1] - affected_sessions[issue], + "type": all_issues[issue_id]["issue_type"], + "title": helper.get_issue_title(all_issues[issue_id]["issue_type"]), + "affected_sessions": affected_sessions[issue_id], + "unaffected_sessions": session_counts[1] - affected_sessions[issue_id], "lost_conversions": lost_conversions, - "affected_users": affected_users_dict[issue], + "affected_users": affected_users_dict[issue_id], "conversion_impact": round(r * 100), - "context_string": contexts[issue]["context"], - "issue_id": contexts[issue]["id"] + "context_string": all_issues[issue_id]["context"], + "issue_id": issue_id }) if is_sign: - n_critical_issues += n_issues_dict[issue] + n_critical_issues += n_issues_dict[issue_id] + # To limit the number of returned issues to the frontend + issues_dict["significant"] = issues_dict["significant"][:20] + issues_dict["insignificant"] = issues_dict["insignificant"][:20] return n_critical_issues, issues_dict, total_drop_due_to_issues @@ -559,8 +560,8 @@ def get_top_insights(filter_d, project_id): "dropDueToIssues": 0 }] - counts = sessions.search_sessions(data=schemas.SessionsSearchCountSchema.parse_obj(filter_d), project_id=project_id, - user_id=None, count_only=True) + counts = sessions.search_sessions(data=schemas.SessionsSearchCountSchema.parse_obj(filter_d), + project_id=project_id, user_id=None, count_only=True) output[0]["sessionsCount"] = counts["countSessions"] output[0]["usersCount"] = counts["countUsers"] return output, 0 diff --git a/api/chalicelib/core/signup.py b/api/chalicelib/core/signup.py index 23c2c8744..3a56f9186 100644 --- a/api/chalicelib/core/signup.py +++ b/api/chalicelib/core/signup.py @@ -1,7 +1,5 @@ import json -from decouple import config - import schemas from chalicelib.core import users, telemetry, tenants from chalicelib.utils import captcha @@ -20,55 +18,41 @@ def create_step1(data: schemas.UserSignupSchema): print(f"=====================> {email}") password = data.password - print("Verifying email validity") - if email is None or len(email) < 5 or not helper.is_valid_email(email): + if email is None or len(email) < 5: errors.append("Invalid email address.") else: - print("Verifying email existance") if users.email_exists(email): errors.append("Email address already in use.") if users.get_deleted_user_by_email(email) is not None: errors.append("Email address previously deleted.") - print("Verifying captcha") if helper.allow_captcha() and not captcha.is_valid(data.g_recaptcha_response): errors.append("Invalid captcha.") - print("Verifying password validity") if len(password) < 6: errors.append("Password is too short, it must be at least 6 characters long.") - print("Verifying fullname validity") fullname = data.fullname if fullname is None or len(fullname) < 1 or not helper.is_alphabet_space_dash(fullname): errors.append("Invalid full name.") - print("Verifying company's name validity") - company_name = data.organizationName - if company_name is None or len(company_name) < 1: - errors.append("invalid organization's name") - - print("Verifying project's name validity") - project_name = data.projectName - if project_name is None or len(project_name) < 1: - project_name = "my first project" + organization_name = data.organizationName + if organization_name is None or len(organization_name) < 1: + errors.append("Invalid organization name.") if len(errors) > 0: - print("==> error") + print(f"==> error for email:{data.email}, fullname:{data.fullname}, organizationName:{data.organizationName}") print(errors) return {"errors": errors} - print("No errors detected") + + project_name = "my first project" params = { - "email": email, "password": password, - "fullname": fullname, - "projectName": project_name, - "data": json.dumps({"lastAnnouncementView": TimeUTC.now()}), - "organizationName": company_name + "email": email, "password": password, "fullname": fullname, "projectName": project_name, + "data": json.dumps({"lastAnnouncementView": TimeUTC.now()}), "organizationName": organization_name } - query = f"""\ - WITH t AS ( - INSERT INTO public.tenants (name, version_number) - VALUES (%(organizationName)s, (SELECT openreplay_version())) + query = f"""WITH t AS ( + INSERT INTO public.tenants (name) + VALUES (%(organizationName)s) RETURNING api_key ), u AS ( @@ -76,8 +60,8 @@ def create_step1(data: schemas.UserSignupSchema): VALUES (%(email)s, 'owner', %(fullname)s,%(data)s) RETURNING user_id,email,role,name ), - au AS (INSERT - INTO public.basic_authentication (user_id, password) + au AS ( + INSERT INTO public.basic_authentication (user_id, password) VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12))) ) INSERT INTO public.projects (name, active) @@ -86,9 +70,9 @@ def create_step1(data: schemas.UserSignupSchema): with pg_client.PostgresClient() as cur: cur.execute(cur.mogrify(query, params)) - cur = cur.fetchone() - project_id = cur["project_id"] - api_key = cur["api_key"] + data = cur.fetchone() + project_id = data["project_id"] + api_key = data["api_key"] telemetry.new_client() created_at = TimeUTC.now() r = users.authenticate(email, password) @@ -106,7 +90,7 @@ def create_step1(data: schemas.UserSignupSchema): } c = { "tenantId": 1, - "name": company_name, + "name": organization_name, "apiKey": api_key, "remainingTrial": 14, "trialEnded": False, diff --git a/api/chalicelib/core/slack.py b/api/chalicelib/core/slack.py index 0bd715f5e..76bf40163 100644 --- a/api/chalicelib/core/slack.py +++ b/api/chalicelib/core/slack.py @@ -4,17 +4,6 @@ from decouple import config from chalicelib.core.collaboration_slack import Slack -def send(notification, destination): - if notification is None: - return - return Slack.send_text(tenant_id=notification["tenantId"], - webhook_id=destination, - text=notification["description"] \ - + f"\n<{config('SITE_URL')}{notification['buttonUrl']}|{notification['buttonText']}>", - title=notification["title"], - title_link=notification["buttonUrl"], ) - - def send_batch(notifications_list): if notifications_list is None or len(notifications_list) == 0: return diff --git a/api/chalicelib/core/socket_ios.py b/api/chalicelib/core/socket_ios.py index 50e4d025c..15e16ec0b 100644 --- a/api/chalicelib/core/socket_ios.py +++ b/api/chalicelib/core/socket_ios.py @@ -7,7 +7,7 @@ def start_replay(project_id, session_id, device, os_version, mob_url): r = requests.post(config("IOS_MIDDLEWARE") + "/replay", json={ "projectId": project_id, "projectKey": projects.get_project_key(project_id), - "sessionId": session_id, + "session_id": session_id, "device": device, "osVersion": os_version, "mobUrl": mob_url diff --git a/api/chalicelib/core/sourcemaps.py b/api/chalicelib/core/sourcemaps.py index 8714b9ee2..89df77926 100644 --- a/api/chalicelib/core/sourcemaps.py +++ b/api/chalicelib/core/sourcemaps.py @@ -1,11 +1,11 @@ -from decouple import config -from chalicelib.utils import helper - -from chalicelib.utils import s3 import hashlib from urllib.parse import urlparse +import requests +from decouple import config + from chalicelib.core import sourcemaps_parser +from chalicelib.utils import s3 def __get_key(project_id, url): @@ -54,7 +54,8 @@ def __frame_is_valid(f): def __format_frame(f): f["context"] = [] # no context by default - if "source" in f: f.pop("source") + if "source" in f: + f.pop("source") url = f.pop("fileName") f["absPath"] = url f["filename"] = urlparse(url).path @@ -73,6 +74,16 @@ def format_payload(p, truncate_to_first=False): return [] +def url_exists(url): + try: + r = requests.head(url, allow_redirects=False) + return r.status_code == 200 and "text/html" not in r.headers.get("Content-Type", "") + except Exception as e: + print(f"!! Issue checking if URL exists: {url}") + print(e) + return False + + def get_traces_group(project_id, payload): frames = format_payload(payload) @@ -80,25 +91,44 @@ def get_traces_group(project_id, payload): payloads = {} all_exists = True for i, u in enumerate(frames): - key = __get_key(project_id, u["absPath"]) # use filename instead? + file_exists_in_bucket = False + file_exists_in_server = False + file_url = u["absPath"] + key = __get_key(project_id, file_url) # use filename instead? + params_idx = file_url.find("?") + if file_url and len(file_url) > 0 \ + and not (file_url[:params_idx] if params_idx > -1 else file_url).endswith(".js"): + print(f"{u['absPath']} sourcemap is not a JS file") + payloads[key] = None + if key not in payloads: - file_exists = s3.exists(config('sourcemaps_bucket'), key) - all_exists = all_exists and file_exists - if not file_exists: - print(f"{u['absPath']} sourcemap (key '{key}') doesn't exist in S3") + file_exists_in_bucket = len(file_url) > 0 and s3.exists(config('sourcemaps_bucket'), key) + if len(file_url) > 0 and not file_exists_in_bucket: + print(f"{u['absPath']} sourcemap (key '{key}') doesn't exist in S3 looking in server") + if not file_url.endswith(".map"): + file_url += '.map' + file_exists_in_server = url_exists(file_url) + file_exists_in_bucket = file_exists_in_server + all_exists = all_exists and file_exists_in_bucket + if not file_exists_in_bucket and not file_exists_in_server: + print(f"{u['absPath']} sourcemap (key '{key}') doesn't exist in S3 nor server") payloads[key] = None else: payloads[key] = [] results[i] = dict(u) results[i]["frame"] = dict(u) if payloads[key] is not None: - payloads[key].append({"resultIndex": i, + payloads[key].append({"resultIndex": i, "frame": dict(u), "URL": file_url, "position": {"line": u["lineNo"], "column": u["colNo"]}, - "frame": dict(u)}) + "isURL": file_exists_in_server}) + for key in payloads.keys(): if payloads[key] is None: continue - key_results = sourcemaps_parser.get_original_trace(key=key, positions=[o["position"] for o in payloads[key]]) + key_results = sourcemaps_parser.get_original_trace( + key=payloads[key][0]["URL"] if payloads[key][0]["isURL"] else key, + positions=[o["position"] for o in payloads[key]], + is_url=payloads[key][0]["isURL"]) if key_results is None: all_exists = False continue @@ -123,16 +153,17 @@ MAX_COLUMN_OFFSET = 60 def fetch_missed_contexts(frames): source_cache = {} for i in range(len(frames)): - if len(frames[i]["context"]) != 0: + if frames[i] and frames[i].get("context") and len(frames[i]["context"]) > 0: continue - if frames[i]["frame"]["absPath"] in source_cache: - file = source_cache[frames[i]["frame"]["absPath"]] + file_abs_path = frames[i]["frame"]["absPath"] + if file_abs_path in source_cache: + file = source_cache[file_abs_path] else: - file = s3.get_file(config('js_cache_bucket'), get_js_cache_path(frames[i]["frame"]["absPath"])) + file_path = get_js_cache_path(file_abs_path) + file = s3.get_file(config('js_cache_bucket'), file_path) if file is None: - print( - f"File {get_js_cache_path(frames[i]['frame']['absPath'])} not found in {config('js_cache_bucket')}") - source_cache[frames[i]["frame"]["absPath"]] = file + print(f"Missing abs_path: {file_abs_path}, file {file_path} not found in {config('js_cache_bucket')}") + source_cache[file_abs_path] = file if file is None: continue lines = file.split("\n") diff --git a/api/chalicelib/core/sourcemaps_parser.py b/api/chalicelib/core/sourcemaps_parser.py index c8918cace..df9dcef1d 100644 --- a/api/chalicelib/core/sourcemaps_parser.py +++ b/api/chalicelib/core/sourcemaps_parser.py @@ -11,14 +11,14 @@ if '%s' in SMR_URL: SMR_URL = SMR_URL % "smr" -def get_original_trace(key, positions): +def get_original_trace(key, positions, is_url=False): payload = { "key": key, "positions": positions, "padding": 5, - "bucket": config('sourcemaps_bucket') + "bucket": config('sourcemaps_bucket'), + "isURL": is_url } - try: r = requests.post(SMR_URL, json=payload, timeout=config("sourcemapTimeout", cast=int, default=5)) if r.status_code != 200: diff --git a/api/chalicelib/core/telemetry.py b/api/chalicelib/core/telemetry.py index 8098c9cd7..2996ace3e 100644 --- a/api/chalicelib/core/telemetry.py +++ b/api/chalicelib/core/telemetry.py @@ -20,15 +20,19 @@ def process_data(data): def compute(): - with pg_client.PostgresClient() as cur: + with pg_client.PostgresClient(long_query=True) as cur: cur.execute( f"""UPDATE public.tenants SET t_integrations = COALESCE((SELECT COUNT(DISTINCT provider) FROM public.integrations) + (SELECT COUNT(*) FROM public.webhooks WHERE type = 'slack') + (SELECT COUNT(*) FROM public.jira_cloud), 0), t_projects=COALESCE((SELECT COUNT(*) FROM public.projects WHERE deleted_at ISNULL), 0), - t_sessions=COALESCE((SELECT COUNT(*) FROM public.sessions), 0), - t_users=COALESCE((SELECT COUNT(*) FROM public.users WHERE deleted_at ISNULL), 0) + t_sessions=t_sessions + COALESCE((SELECT COUNT(*) + FROM public.sessions + WHERE start_ts >= (SELECT last_telemetry FROM tenants) + AND start_ts <=CAST(EXTRACT(epoch FROM date_trunc('day', now())) * 1000 AS BIGINT)), 0), + t_users=COALESCE((SELECT COUNT(*) FROM public.users WHERE deleted_at ISNULL), 0), + last_telemetry=CAST(EXTRACT(epoch FROM date_trunc('day', now())) * 1000 AS BIGINT) RETURNING name,t_integrations,t_projects,t_sessions,t_users,tenant_key,opt_out, (SELECT openreplay_version()) AS version_number,(SELECT email FROM public.users WHERE role = 'owner' LIMIT 1);""" ) @@ -39,8 +43,8 @@ def compute(): def new_client(): with pg_client.PostgresClient() as cur: cur.execute( - f"""SELECT *, - (SELECT email FROM public.users WHERE role='owner' LIMIT 1) AS email + f"""SELECT *, openreplay_version() AS version_number, + (SELECT email FROM public.users WHERE role='owner' LIMIT 1) AS email FROM public.tenants LIMIT 1;""") data = cur.fetchone() diff --git a/api/chalicelib/core/tenants.py b/api/chalicelib/core/tenants.py index e5b8cc63c..f61456de5 100644 --- a/api/chalicelib/core/tenants.py +++ b/api/chalicelib/core/tenants.py @@ -14,7 +14,7 @@ def get_by_tenant_id(tenant_id): api_key, created_at, '{license.EDITION}' AS edition, - version_number, + openreplay_version() AS version_number, opt_out FROM public.tenants LIMIT 1;""", diff --git a/api/chalicelib/core/users.py b/api/chalicelib/core/users.py index 0ea8ed594..94c9261ea 100644 --- a/api/chalicelib/core/users.py +++ b/api/chalicelib/core/users.py @@ -7,7 +7,7 @@ from fastapi import BackgroundTasks import schemas from chalicelib.core import authorizers, metadata, projects from chalicelib.core import tenants, assist -from chalicelib.utils import dev, email_helper +from chalicelib.utils import email_helper from chalicelib.utils import helper from chalicelib.utils import pg_client from chalicelib.utils.TimeUTC import TimeUTC @@ -194,14 +194,6 @@ def create_member(tenant_id, user_id, data, background_tasks: BackgroundTasks): new_member = create_new_member(email=data["email"], invitation_token=invitation_token, admin=data.get("admin", False), name=name) new_member["invitationLink"] = __get_invitation_link(new_member.pop("invitationToken")) - - # helper.async_post(config('email_basic') % 'member_invitation', - # { - # "email": data["email"], - # "invitationLink": new_member["invitationLink"], - # "clientId": tenants.get_by_tenant_id(tenant_id)["name"], - # "senderName": admin["name"] - # }) background_tasks.add_task(email_helper.send_team_invitation, **{ "recipient": data["email"], "invitation_link": new_member["invitationLink"], @@ -259,9 +251,8 @@ def generate_new_api_key(user_id): cur.mogrify( f"""UPDATE public.users SET api_key=generate_api_key(20) - WHERE - users.user_id = %(userId)s - AND deleted_at IS NULL + WHERE users.user_id = %(userId)s + AND deleted_at IS NULL RETURNING api_key;""", {"userId": user_id}) ) @@ -302,6 +293,39 @@ def edit(user_id_to_update, tenant_id, changes: schemas.EditUserSchema, editor_i return {"data": user} +def edit_member(user_id_to_update, tenant_id, changes: schemas.EditUserSchema, editor_id): + user = get_member(user_id=user_id_to_update, tenant_id=tenant_id) + if editor_id != user_id_to_update or changes.admin is not None and changes.admin != user["admin"]: + admin = get(tenant_id=tenant_id, user_id=editor_id) + if not admin["superAdmin"] and not admin["admin"]: + return {"errors": ["unauthorized"]} + _changes = {} + if editor_id == user_id_to_update: + if changes.admin is not None: + if user["superAdmin"]: + changes.admin = None + elif changes.admin != user["admin"]: + return {"errors": ["cannot change your own role"]} + + if changes.email is not None and changes.email != user["email"]: + if email_exists(changes.email): + return {"errors": ["email already exists."]} + if get_deleted_user_by_email(changes.email) is not None: + return {"errors": ["email previously deleted."]} + _changes["email"] = changes.email + + if changes.name is not None and len(changes.name) > 0: + _changes["name"] = changes.name + + if changes.admin is not None: + _changes["role"] = "admin" if changes.admin else "member" + + if len(_changes.keys()) > 0: + update(tenant_id=tenant_id, user_id=user_id_to_update, changes=_changes) + return {"data": get_member(user_id=user_id_to_update, tenant_id=tenant_id)} + return {"data": user} + + def get_by_email_only(email): with pg_client.PostgresClient() as cur: cur.execute( @@ -314,15 +338,16 @@ def get_by_email_only(email): users.name, (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, - (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member + (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, + TRUE AS has_password FROM public.users LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id - WHERE - users.email = %(email)s - AND users.deleted_at IS NULL;""", + WHERE users.email = %(email)s + AND users.deleted_at IS NULL + LIMIT 1;""", {"email": email}) ) - r = cur.fetchall() - return helper.list_to_camel_case(r) + r = cur.fetchone() + return helper.dict_to_camel_case(r) def get_by_email_reset(email, reset_token): @@ -349,11 +374,44 @@ def get_by_email_reset(email, reset_token): return helper.dict_to_camel_case(r) +def get_member(tenant_id, user_id): + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify( + f"""SELECT + users.user_id, + users.email, + users.role, + users.name, + users.created_at, + (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, + (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, + (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, + DATE_PART('day',timezone('utc'::text, now()) \ + - COALESCE(basic_authentication.invited_at,'2000-01-01'::timestamp ))>=1 AS expired_invitation, + basic_authentication.password IS NOT NULL AS joined, + invitation_token + FROM public.users LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id + WHERE users.deleted_at IS NULL AND users.user_id=%(user_id)s + ORDER BY name, user_id""", + {"user_id": user_id}) + ) + u = helper.dict_to_camel_case(cur.fetchone()) + if u: + u["createdAt"] = TimeUTC.datetime_to_timestamp(u["createdAt"]) + if u["invitationToken"]: + u["invitationLink"] = __get_invitation_link(u.pop("invitationToken")) + else: + u["invitationLink"] = None + + return u + + def get_members(tenant_id): with pg_client.PostgresClient() as cur: cur.execute( f"""SELECT - users.user_id AS id, + users.user_id, users.email, users.role, users.name, @@ -367,7 +425,7 @@ def get_members(tenant_id): invitation_token FROM public.users LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id WHERE users.deleted_at IS NULL - ORDER BY name, id""" + ORDER BY name, user_id""" ) r = cur.fetchall() if len(r): @@ -424,8 +482,8 @@ def change_password(tenant_id, user_id, email, old_password, new_password): changes = {"password": new_password} user = update(tenant_id=tenant_id, user_id=user_id, changes=changes) r = authenticate(user['email'], new_password) - tenant_id = r.pop("tenantId") + tenant_id = r.pop("tenantId") r["limits"] = { "teamMember": -1, "projects": -1, @@ -452,8 +510,8 @@ def set_password_invitation(user_id, new_password): "changePwdExpireAt": None, "changePwdToken": None} user = update(tenant_id=-1, user_id=user_id, changes=changes) r = authenticate(user['email'], new_password) - tenant_id = r.pop("tenantId") + tenant_id = r.pop("tenantId") r["limits"] = { "teamMember": -1, "projects": -1, @@ -552,7 +610,19 @@ def auth_exists(user_id, tenant_id, jwt_iat, jwt_aud): ) -def authenticate(email, password, for_change_password=False, for_plugin=False): +def change_jwt_iat(user_id): + with pg_client.PostgresClient() as cur: + query = cur.mogrify( + f"""UPDATE public.users + SET jwt_iat = timezone('utc'::text, now()) + WHERE user_id = %(user_id)s + RETURNING jwt_iat;""", + {"user_id": user_id}) + cur.execute(query) + return cur.fetchone().get("jwt_iat") + + +def authenticate(email, password, for_change_password=False): with pg_client.PostgresClient() as cur: query = cur.mogrify( f"""SELECT @@ -573,22 +643,16 @@ def authenticate(email, password, for_change_password=False, for_plugin=False): cur.execute(query) r = cur.fetchone() - if r is not None: - if for_change_password: - return True - r = helper.dict_to_camel_case(r) - query = cur.mogrify( - f"""UPDATE public.users - SET jwt_iat = timezone('utc'::text, now()) - WHERE user_id = %(user_id)s - RETURNING jwt_iat;""", - {"user_id": r["userId"]}) - cur.execute(query) - return { - "jwt": authorizers.generate_jwt(r['userId'], r['tenantId'], - TimeUTC.datetime_to_timestamp(cur.fetchone()["jwt_iat"]), - aud=f"plugin:{helper.get_stage_name()}" if for_plugin else f"front:{helper.get_stage_name()}"), - "email": email, - **r - } + if r is not None: + if for_change_password: + return True + r = helper.dict_to_camel_case(r) + jwt_iat = change_jwt_iat(r['userId']) + return { + "jwt": authorizers.generate_jwt(r['userId'], r['tenantId'], + TimeUTC.datetime_to_timestamp(jwt_iat), + aud=f"front:{helper.get_stage_name()}"), + "email": email, + **r + } return None diff --git a/api/chalicelib/core/webhook.py b/api/chalicelib/core/webhook.py index d0b3e2adc..d74271d58 100644 --- a/api/chalicelib/core/webhook.py +++ b/api/chalicelib/core/webhook.py @@ -10,8 +10,7 @@ def get_by_id(webhook_id): with pg_client.PostgresClient() as cur: cur.execute( cur.mogrify("""\ - SELECT - w.* + SELECT w.* FROM public.webhooks AS w where w.webhook_id =%(webhook_id)s AND deleted_at ISNULL;""", {"webhook_id": webhook_id}) @@ -161,8 +160,8 @@ def __trigger(hook, data): r = requests.post(url=hook["endpoint"], json=data, headers=headers) if r.status_code != 200: - logging.error("=======> webhook: something went wrong") - logging.error(r) + logging.error("=======> webhook: something went wrong for:") + logging.error(hook) logging.error(r.status_code) logging.error(r.text) return diff --git a/api/chalicelib/utils/github_client_v3.py b/api/chalicelib/utils/github_client_v3.py index 692e878ae..650aeb4fe 100644 --- a/api/chalicelib/utils/github_client_v3.py +++ b/api/chalicelib/utils/github_client_v3.py @@ -1,6 +1,9 @@ import requests from datetime import datetime +from fastapi import HTTPException +from starlette import status + class github_formatters: @@ -120,9 +123,9 @@ class githubV3Request: pages = get_response_links(response) result = response.json() if response.status_code != 200: - print("!-------- error") + print(f"=>GITHUB Exception") print(result) - raise Exception(result["message"]) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"GITHUB: {result['message']}") if isinstance(result, dict): return result results += result diff --git a/api/chalicelib/utils/helper.py b/api/chalicelib/utils/helper.py index b04b8aa43..7639f1950 100644 --- a/api/chalicelib/utils/helper.py +++ b/api/chalicelib/utils/helper.py @@ -4,52 +4,18 @@ import re import string from typing import Union -import requests +from decouple import config import schemas from chalicelib.utils.TimeUTC import TimeUTC -local_prefix = 'local-' -from decouple import config - - -def get_version_number(): - return config("version") - def get_stage_name(): - stage = config("stage") - return stage[len(local_prefix):] if stage.startswith(local_prefix) else stage + return "OpenReplay" -def is_production(): - return get_stage_name() == "production" - - -def is_staging(): - return get_stage_name() == "staging" - - -def is_onprem(): - return not is_production() and not is_staging() - - -def is_local(): - return config("stage").startswith(local_prefix) - - -def generate_salt(): - return "".join(random.choices(string.hexdigits, k=36)) - - -def unique_ordered_list(array): - uniq = [] - [uniq.append(x) for x in array if x not in uniq] - return uniq - - -def unique_unordered_list(array): - return list(set(array)) +def random_string(length=36): + return "".join(random.choices(string.hexdigits, k=length)) def list_to_camel_case(items, flatten=False): @@ -130,29 +96,11 @@ def key_to_snake_case(name, delimiter='_', split_number=False): TRACK_TIME = True -def __sbool_to_bool(value): - if value is None or not isinstance(value, str): - return False - return value.lower() in ["true", "yes", "1"] - - def allow_captcha(): return config("captcha_server", default=None) is not None and config("captcha_key", default=None) is not None \ and len(config("captcha_server")) > 0 and len(config("captcha_key")) > 0 -def allow_sentry(): - return config("sentryURL", default=None) is not None and len(config("sentryURL")) > 0 - - -def async_post(endpoint, data): - data["auth"] = config("async_Token") - try: - requests.post(endpoint, timeout=1, json=data) - except requests.exceptions.ReadTimeout: - pass - - def string_to_sql_like(value): value = re.sub(' +', ' ', value) value = value.replace("*", "%") @@ -222,54 +170,11 @@ def values_for_operator(value: Union[str, list], op: schemas.SearchEventOperator return value -def is_valid_email(email): - return re.match(r"[^@]+@[^@]+\.[^@]+", email) is not None - - -def is_valid_http_url(url): - regex = re.compile( - r'^(?:http|ftp)s?://' # http:// or https:// - r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... - r'localhost|' # localhost... - r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip - r'(?::\d+)?' # optional port - r'(?:/?|[/?]\S+)$', re.IGNORECASE) - - return re.match(regex, url) is not None - - -def is_valid_url(url): - regex = re.compile( - # r'^(?:http|ftp)s?://' # http:// or https:// - r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... - r'localhost|' # localhost... - r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip - r'(?::\d+)?' # optional port - r'(?:/?|[/?]\S+)$', re.IGNORECASE) - - return re.match(regex, url) is not None - - -def is_alphabet_space(word): - r = re.compile("^[a-zA-Z ]*$") - return r.match(word) is not None - - -def is_alphabet_latin_space(word): - r = re.compile("^[a-zA-Z\u00C0-\u00D6\u00D8-\u00f6\u00f8-\u00ff\s ]*$") - return r.match(word) is not None - - def is_alphabet_space_dash(word): r = re.compile("^[a-zA-Z -]*$") return r.match(word) is not None -def is_alphanumeric_space(word): - r = re.compile("^[a-zA-Z0-9._\- ]*$") - return r.match(word) is not None - - def merge_lists_by_key(l1, l2, key): merged = {} for item in l1 + l2: @@ -322,9 +227,6 @@ def explode_widget(data, key=None): return result -TEMP_PATH = "./" if is_local() else "/tmp/" - - def get_issue_title(issue_type): return {'click_rage': "Click Rage", 'dead_click': "Dead Click", diff --git a/api/chalicelib/utils/jira_client.py b/api/chalicelib/utils/jira_client.py index 4306cfab2..a820d4aa9 100644 --- a/api/chalicelib/utils/jira_client.py +++ b/api/chalicelib/utils/jira_client.py @@ -35,7 +35,7 @@ class JiraManager: if (e.status_code // 100) == 4 and self.retries > 0: time.sleep(1) return self.get_projects() - print(f"=>Exception {e.text}") + print(f"=>JIRA Exception {e.text}") raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"JIRA: {e.text}") projects_dict_list = [] for project in projects: diff --git a/api/chalicelib/utils/pg_client.py b/api/chalicelib/utils/pg_client.py index 8b9001649..69a5b5a8b 100644 --- a/api/chalicelib/utils/pg_client.py +++ b/api/chalicelib/utils/pg_client.py @@ -17,10 +17,8 @@ _PG_CONFIG = {"host": config("pg_host"), "port": config("pg_port", cast=int), "application_name": config("APP_NAME", default="PY")} PG_CONFIG = dict(_PG_CONFIG) -if config("pg_timeout", cast=int, default=0) > 0: - PG_CONFIG["options"] = f"-c statement_timeout={config('pg_timeout', cast=int) * 1000}" - -logging.info(f">PG_POOL:{config('PG_POOL', default=None)}") +if config("PG_TIMEOUT", cast=int, default=0) > 0: + PG_CONFIG["options"] = f"-c statement_timeout={config('PG_TIMEOUT', cast=int) * 1000}" class ORThreadedConnectionPool(psycopg2.pool.ThreadedConnectionPool): @@ -67,8 +65,8 @@ def make_pool(): except (Exception, psycopg2.DatabaseError) as error: logging.error("Error while closing all connexions to PostgreSQL", error) try: - postgreSQL_pool = ORThreadedConnectionPool(config("pg_minconn", cast=int, default=20), - config("pg_maxconn", cast=int, default=80), + postgreSQL_pool = ORThreadedConnectionPool(config("PG_MINCONN", cast=int, default=20), + config("PG_MAXCONN", cast=int, default=80), **PG_CONFIG) if (postgreSQL_pool): logging.info("Connection pool created successfully") @@ -83,10 +81,6 @@ def make_pool(): raise error -if config('PG_POOL', cast=bool, default=True): - make_pool() - - class PostgresClient: connection = None cursor = None @@ -109,7 +103,7 @@ class PostgresClient: elif not config('PG_POOL', cast=bool, default=True): single_config = dict(_PG_CONFIG) single_config["application_name"] += "-NOPOOL" - single_config["options"] = f"-c statement_timeout={config('pg_timeout', cast=int, default=3 * 60) * 1000}" + single_config["options"] = f"-c statement_timeout={config('PG_TIMEOUT', cast=int, default=30) * 1000}" self.connection = psycopg2.connect(**single_config) else: self.connection = postgreSQL_pool.getconn() @@ -117,6 +111,7 @@ class PostgresClient: def __enter__(self): if self.cursor is None: self.cursor = self.connection.cursor(cursor_factory=psycopg2.extras.RealDictCursor) + self.cursor.recreate = self.recreate_cursor return self.cursor def __exit__(self, *args): @@ -141,6 +136,31 @@ class PostgresClient: and not self.unlimited_query: postgreSQL_pool.putconn(self.connection) + def recreate_cursor(self, rollback=False): + if rollback: + try: + self.connection.rollback() + except Exception as error: + logging.error("Error while rollbacking connection for recreation", error) + try: + self.cursor.close() + except Exception as error: + logging.error("Error while closing cursor for recreation", error) + self.cursor = None + return self.__enter__() -def close(): - pass + +async def init(): + logging.info(f">PG_POOL:{config('PG_POOL', default=None)}") + if config('PG_POOL', cast=bool, default=True): + make_pool() + + +async def terminate(): + global postgreSQL_pool + if postgreSQL_pool is not None: + try: + postgreSQL_pool.closeall() + logging.info("Closed all connexions to PostgreSQL") + except (Exception, psycopg2.DatabaseError) as error: + logging.error("Error while closing all connexions to PostgreSQL", error) diff --git a/api/chalicelib/utils/s3.py b/api/chalicelib/utils/s3.py index f3c580e90..5458c8f14 100644 --- a/api/chalicelib/utils/s3.py +++ b/api/chalicelib/utils/s3.py @@ -70,7 +70,6 @@ def get_file(source_bucket, source_key): ) except ClientError as ex: if ex.response['Error']['Code'] == 'NoSuchKey': - print(f'======> No object found - returning None for \nbucket:{source_bucket}\nkey:{source_key}') return None else: raise ex diff --git a/api/db_changes.sql b/api/db_changes.sql deleted file mode 100644 index 155f10278..000000000 --- a/api/db_changes.sql +++ /dev/null @@ -1,3 +0,0 @@ -BEGIN; -CREATE INDEX pages_ttfb_idx ON events.pages (ttfb) WHERE ttfb > 0; -COMMIT; \ No newline at end of file diff --git a/api/entrypoint.sh b/api/entrypoint.sh index 7342426c2..e140268ef 100755 --- a/api/entrypoint.sh +++ b/api/entrypoint.sh @@ -1,5 +1,3 @@ #!/bin/sh -cd sourcemap-reader -nohup npm start & -cd .. + uvicorn app:app --host 0.0.0.0 --port $LISTEN_PORT --reload --proxy-headers diff --git a/api/entrypoint_alerts.sh b/api/entrypoint_alerts.sh index 4c9a66672..dedfa102b 100755 --- a/api/entrypoint_alerts.sh +++ b/api/entrypoint_alerts.sh @@ -1,3 +1,3 @@ #!/bin/sh - +export ASSIST_KEY=ignore uvicorn app:app --host 0.0.0.0 --port $LISTEN_PORT --reload diff --git a/api/env.default b/api/env.default index c4388c7d5..3ee65e89c 100644 --- a/api/env.default +++ b/api/env.default @@ -12,19 +12,14 @@ S3_KEY= S3_SECRET= SITE_URL= announcement_url= -async_Token= captcha_key= captcha_server= change_password_link=/reset-password?invitation=%s&&pass=%s -email_basic=http://127.0.0.1:8000/async/basic/%s -email_signup=http://127.0.0.1:8000/async/email_signup/%s invitation_link=/api/users/invitation?token=%s -isEE=false -isFOS=true js_cache_bucket=sessions-assets jwt_algorithm=HS512 -jwt_exp_delta_seconds=2592000 -jwt_issuer=openreplay-default-foss +JWT_EXPIRATION=2592000 +JWT_ISSUER=openreplay-oss jwt_secret="SET A RANDOM STRING HERE" ASSIST_URL=http://assist-openreplay.app.svc.cluster.local:9001/assist/%s assist=/sockets-live @@ -34,18 +29,25 @@ pg_host=postgresql.db.svc.cluster.local pg_password=asayerPostgres pg_port=5432 pg_user=postgres -pg_timeout=30 -pg_minconn=20 -pg_maxconn=50 +PG_TIMEOUT=30 +PG_MINCONN=20 +PG_MAXCONN=50 PG_RETRY_MAX=50 PG_RETRY_INTERVAL=2 PG_POOL=true -put_S3_TTL=20 -sentryURL= sessions_bucket=mobs sessions_region=us-east-1 sourcemaps_bucket=sourcemaps -sourcemaps_reader=http://127.0.0.1:9000/sourcemaps/%s/sourcemaps -stage=default-foss +sourcemaps_reader=http://sourcemaps-reader-openreplay.app.svc.cluster.local:9000/sourcemaps/%s/sourcemaps +STAGE=default-foss version_number=1.4.0 -FS_DIR=/mnt/efs \ No newline at end of file +FS_DIR=/mnt/efs +EFS_SESSION_MOB_PATTERN=%(sessionId)s +EFS_DEVTOOLS_MOB_PATTERN=%(sessionId)sdevtools +SESSION_MOB_PATTERN_S=%(sessionId)s/dom.mobs +SESSION_MOB_PATTERN_E=%(sessionId)s/dom.mobe +DEVTOOLS_MOB_PATTERN=%(sessionId)s/devtools.mob +PRESIGNED_URL_EXPIRATION=3600 +ASSIST_JWT_EXPIRATION=144000 +ASSIST_JWT_SECRET= +PYTHONUNBUFFERED=1 \ No newline at end of file diff --git a/api/requirements-alerts.txt b/api/requirements-alerts.txt index fc141eb09..ff36f3099 100644 --- a/api/requirements-alerts.txt +++ b/api/requirements-alerts.txt @@ -1,15 +1,15 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 -psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +urllib3==1.26.12 +boto3==1.26.14 +pyjwt==2.6.0 +psycopg2-binary==2.9.5 +elasticsearch==8.5.1 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.87.0 +uvicorn[standard]==0.20.0 python-decouple==3.6 -pydantic[email]==1.9.2 -apscheduler==3.9.1 \ No newline at end of file +pydantic[email]==1.10.2 +apscheduler==3.9.1.post1 \ No newline at end of file diff --git a/api/requirements.txt b/api/requirements.txt index fc141eb09..ff36f3099 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -1,15 +1,15 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 -psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +urllib3==1.26.12 +boto3==1.26.14 +pyjwt==2.6.0 +psycopg2-binary==2.9.5 +elasticsearch==8.5.1 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.87.0 +uvicorn[standard]==0.20.0 python-decouple==3.6 -pydantic[email]==1.9.2 -apscheduler==3.9.1 \ No newline at end of file +pydantic[email]==1.10.2 +apscheduler==3.9.1.post1 \ No newline at end of file diff --git a/api/routers/base.py b/api/routers/base.py index 5c665b2d1..09821e93e 100644 --- a/api/routers/base.py +++ b/api/routers/base.py @@ -6,9 +6,11 @@ from auth.auth_project import ProjectAuthorizer from or_dependencies import ORRoute -def get_routers() -> (APIRouter, APIRouter, APIRouter): +def get_routers(extra_dependencies=[]) -> (APIRouter, APIRouter, APIRouter): public_app = APIRouter(route_class=ORRoute) - app = APIRouter(dependencies=[Depends(JWTAuth()), Depends(ProjectAuthorizer("projectId"))], route_class=ORRoute) - app_apikey = APIRouter(dependencies=[Depends(APIKeyAuth()), Depends(ProjectAuthorizer("projectKey"))], - route_class=ORRoute) + app = APIRouter(dependencies=[Depends(JWTAuth()), Depends(ProjectAuthorizer("projectId"))] + extra_dependencies, + route_class=ORRoute) + app_apikey = APIRouter( + dependencies=[Depends(APIKeyAuth()), Depends(ProjectAuthorizer("projectKey"))] + extra_dependencies, + route_class=ORRoute) return public_app, app, app_apikey diff --git a/api/routers/core.py b/api/routers/core.py index b3252e34a..7ee8364e7 100644 --- a/api/routers/core.py +++ b/api/routers/core.py @@ -1,22 +1,19 @@ from typing import Union from decouple import config -from fastapi import Depends, Body, BackgroundTasks, HTTPException -from fastapi.responses import FileResponse +from fastapi import Depends, Body, HTTPException from starlette import status import schemas from chalicelib.core import log_tool_rollbar, sourcemaps, events, sessions_assignments, projects, \ alerts, funnels, issues, integrations_manager, metadata, \ log_tool_elasticsearch, log_tool_datadog, \ - log_tool_stackdriver, reset_password, sessions_favorite, \ - log_tool_cloudwatch, log_tool_sentry, log_tool_sumologic, log_tools, errors, sessions, \ + log_tool_stackdriver, reset_password, log_tool_cloudwatch, log_tool_sentry, log_tool_sumologic, log_tools, sessions, \ log_tool_newrelic, announcements, log_tool_bugsnag, weekly_report, integration_jira_cloud, integration_github, \ - assist, heatmaps, mobile, signup, tenants, errors_viewed, boarding, notifications, webhook, users, \ - custom_metrics, saved_search, integrations_global, sessions_viewed, errors_favorite + assist, mobile, signup, tenants, boarding, notifications, webhook, users, \ + custom_metrics, saved_search, integrations_global from chalicelib.core.collaboration_slack import Slack -from chalicelib.utils import email_helper, helper, captcha -from chalicelib.utils.TimeUTC import TimeUTC +from chalicelib.utils import helper, captcha from or_dependencies import OR_context from routers.base import get_routers @@ -31,7 +28,7 @@ def login(data: schemas.UserLoginSchema = Body(...)): detail="Invalid captcha." ) - r = users.authenticate(data.email, data.password, for_plugin=False) + r = users.authenticate(data.email, data.password) if r is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -59,85 +56,12 @@ def sessions_search(projectId: int, data: schemas.FlatSessionsSearchPayloadSchem return {'data': data} -@app.get('/{projectId}/sessions/{sessionId}', tags=["sessions"]) -@app.get('/{projectId}/sessions2/{sessionId}', tags=["sessions"]) -def get_session2(projectId: int, sessionId: Union[int, str], background_tasks: BackgroundTasks, - context: schemas.CurrentContext = Depends(OR_context)): - if isinstance(sessionId, str): - return {"errors": ["session not found"]} - data = sessions.get_by_id2_pg(project_id=projectId, session_id=sessionId, full_data=True, user_id=context.user_id, - include_fav_viewed=True, group_metadata=True) - if data is None: - return {"errors": ["session not found"]} - if data.get("inDB"): - background_tasks.add_task(sessions_viewed.view_session, project_id=projectId, user_id=context.user_id, - session_id=sessionId) - return { - 'data': data - } - - -@app.get('/{projectId}/sessions/{sessionId}/favorite', tags=["sessions"]) -@app.get('/{projectId}/sessions2/{sessionId}/favorite', tags=["sessions"]) -def add_remove_favorite_session2(projectId: int, sessionId: int, - context: schemas.CurrentContext = Depends(OR_context)): - return { - "data": sessions_favorite.favorite_session(project_id=projectId, user_id=context.user_id, - session_id=sessionId)} - - -@app.get('/{projectId}/sessions/{sessionId}/assign', tags=["sessions"]) -@app.get('/{projectId}/sessions2/{sessionId}/assign', tags=["sessions"]) -def assign_session(projectId: int, sessionId, context: schemas.CurrentContext = Depends(OR_context)): - data = sessions_assignments.get_by_session(project_id=projectId, session_id=sessionId, - tenant_id=context.tenant_id, - user_id=context.user_id) - if "errors" in data: - return data - return { - 'data': data - } - - -@app.get('/{projectId}/sessions/{sessionId}/errors/{errorId}/sourcemaps', tags=["sessions", "sourcemaps"]) -@app.get('/{projectId}/sessions2/{sessionId}/errors/{errorId}/sourcemaps', tags=["sessions", "sourcemaps"]) -def get_error_trace(projectId: int, sessionId: int, errorId: str, - context: schemas.CurrentContext = Depends(OR_context)): - data = errors.get_trace(project_id=projectId, error_id=errorId) - if "errors" in data: - return data - return { - 'data': data - } - - -@app.get('/{projectId}/sessions/{sessionId}/assign/{issueId}', tags=["sessions", "issueTracking"]) -@app.get('/{projectId}/sessions2/{sessionId}/assign/{issueId}', tags=["sessions", "issueTracking"]) -def assign_session(projectId: int, sessionId: int, issueId: str, - context: schemas.CurrentContext = Depends(OR_context)): - data = sessions_assignments.get(project_id=projectId, session_id=sessionId, assignment_id=issueId, - tenant_id=context.tenant_id, user_id=context.user_id) - if "errors" in data: - return data - return { - 'data': data - } - - -@app.post('/{projectId}/sessions/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"]) -@app.put('/{projectId}/sessions/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"]) -@app.post('/{projectId}/sessions2/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"]) -@app.put('/{projectId}/sessions2/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"]) -def comment_assignment(projectId: int, sessionId: int, issueId: str, data: schemas.CommentAssignmentSchema = Body(...), +@app.post('/{projectId}/sessions/search/ids', tags=["sessions"]) +@app.post('/{projectId}/sessions/search2/ids', tags=["sessions"]) +def session_ids_search(projectId: int, data: schemas.FlatSessionsSearchPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): - data = sessions_assignments.comment(tenant_id=context.tenant_id, project_id=projectId, - session_id=sessionId, assignment_id=issueId, - user_id=context.user_id, message=data.message) - if "errors" in data.keys(): - return data - return { - 'data': data - } + data = sessions.search_sessions(data=data, project_id=projectId, user_id=context.user_id, ids_only=True) + return {'data': data} @app.get('/{projectId}/events/search', tags=["events"]) @@ -181,7 +105,6 @@ def get_integrations_status(projectId: int, context: schemas.CurrentContext = De @app.post('/{projectId}/integrations/{integration}/notify/{integrationId}/{source}/{sourceId}', tags=["integrations"]) -@app.put('/{projectId}/integrations/{integration}/notify/{integrationId}/{source}/{sourceId}', tags=["integrations"]) def integration_notify(projectId: int, integration: str, integrationId: int, source: str, sourceId: str, data: schemas.IntegrationNotificationSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): @@ -210,7 +133,6 @@ def get_sentry(projectId: int, context: schemas.CurrentContext = Depends(OR_cont @app.post('/{projectId}/integrations/sentry', tags=["integrations"]) -@app.put('/{projectId}/integrations/sentry', tags=["integrations"]) def add_edit_sentry(projectId: int, data: schemas.SentrySchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": log_tool_sentry.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())} @@ -237,7 +159,6 @@ def get_datadog(projectId: int, context: schemas.CurrentContext = Depends(OR_con @app.post('/{projectId}/integrations/datadog', tags=["integrations"]) -@app.put('/{projectId}/integrations/datadog', tags=["integrations"]) def add_edit_datadog(projectId: int, data: schemas.DatadogSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": log_tool_datadog.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())} @@ -259,7 +180,6 @@ def get_stackdriver(projectId: int, context: schemas.CurrentContext = Depends(OR @app.post('/{projectId}/integrations/stackdriver', tags=["integrations"]) -@app.put('/{projectId}/integrations/stackdriver', tags=["integrations"]) def add_edit_stackdriver(projectId: int, data: schemas.StackdriverSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": log_tool_stackdriver.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())} @@ -281,7 +201,6 @@ def get_newrelic(projectId: int, context: schemas.CurrentContext = Depends(OR_co @app.post('/{projectId}/integrations/newrelic', tags=["integrations"]) -@app.put('/{projectId}/integrations/newrelic', tags=["integrations"]) def add_edit_newrelic(projectId: int, data: schemas.NewrelicSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": log_tool_newrelic.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())} @@ -303,7 +222,6 @@ def get_rollbar(projectId: int, context: schemas.CurrentContext = Depends(OR_con @app.post('/{projectId}/integrations/rollbar', tags=["integrations"]) -@app.put('/{projectId}/integrations/rollbar', tags=["integrations"]) def add_edit_rollbar(projectId: int, data: schemas.RollbarSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": log_tool_rollbar.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())} @@ -331,7 +249,6 @@ def get_bugsnag(projectId: int, context: schemas.CurrentContext = Depends(OR_con @app.post('/{projectId}/integrations/bugsnag', tags=["integrations"]) -@app.put('/{projectId}/integrations/bugsnag', tags=["integrations"]) def add_edit_bugsnag(projectId: int, data: schemas.BugsnagSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": log_tool_bugsnag.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())} @@ -361,7 +278,6 @@ def get_cloudwatch(projectId: int, context: schemas.CurrentContext = Depends(OR_ @app.post('/{projectId}/integrations/cloudwatch', tags=["integrations"]) -@app.put('/{projectId}/integrations/cloudwatch', tags=["integrations"]) def add_edit_cloudwatch(projectId: int, data: schemas.CloudwatchSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": log_tool_cloudwatch.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())} @@ -389,7 +305,6 @@ def test_elasticsearch_connection(data: schemas.ElasticsearchBasicSchema = Body( @app.post('/{projectId}/integrations/elasticsearch', tags=["integrations"]) -@app.put('/{projectId}/integrations/elasticsearch', tags=["integrations"]) def add_edit_elasticsearch(projectId: int, data: schemas.ElasticsearchSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return { @@ -412,7 +327,6 @@ def get_sumologic(projectId: int, context: schemas.CurrentContext = Depends(OR_c @app.post('/{projectId}/integrations/sumologic', tags=["integrations"]) -@app.put('/{projectId}/integrations/sumologic', tags=["integrations"]) def add_edit_sumologic(projectId: int, data: schemas.SumologicSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": log_tool_sumologic.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())} @@ -453,7 +367,6 @@ def get_integration_status_github(context: schemas.CurrentContext = Depends(OR_c @app.post('/integrations/jira', tags=["integrations"]) -@app.put('/integrations/jira', tags=["integrations"]) def add_edit_jira_cloud(data: schemas.JiraSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): if not data.url.endswith('atlassian.net'): @@ -467,7 +380,6 @@ def add_edit_jira_cloud(data: schemas.JiraSchema = Body(...), @app.post('/integrations/github', tags=["integrations"]) -@app.put('/integrations/github', tags=["integrations"]) def add_edit_github(data: schemas.GithubSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): error, integration = integrations_manager.get_integration(tool=integration_github.PROVIDER, @@ -541,8 +453,7 @@ def get_all_assignments(projectId: int, context: schemas.CurrentContext = Depend } -@app.post('/{projectId}/sessions2/{sessionId}/assign/projects/{integrationProjectId}', tags=["assignment"]) -@app.put('/{projectId}/sessions2/{sessionId}/assign/projects/{integrationProjectId}', tags=["assignment"]) +@app.post('/{projectId}/sessions/{sessionId}/assign/projects/{integrationProjectId}', tags=["assignment"]) def create_issue_assignment(projectId: int, sessionId: int, integrationProjectId, data: schemas.AssignmentSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): @@ -565,14 +476,12 @@ def get_gdpr(projectId: int, context: schemas.CurrentContext = Depends(OR_contex @app.post('/{projectId}/gdpr', tags=["projects", "gdpr"]) -@app.put('/{projectId}/gdpr', tags=["projects", "gdpr"]) def edit_gdpr(projectId: int, data: schemas.GdprSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": projects.edit_gdpr(project_id=projectId, gdpr=data.dict())} @public_app.post('/password/reset-link', tags=["reset password"]) -@public_app.put('/password/reset-link', tags=["reset password"]) def reset_password_handler(data: schemas.ForgetPasswordPayloadSchema = Body(...)): if len(data.email) < 5: return {"errors": ["please provide a valid email address"]} @@ -585,21 +494,18 @@ def get_metadata(projectId: int, context: schemas.CurrentContext = Depends(OR_co @app.post('/{projectId}/metadata/list', tags=["metadata"]) -@app.put('/{projectId}/metadata/list', tags=["metadata"]) def add_edit_delete_metadata(projectId: int, data: schemas.MetadataListSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return metadata.add_edit_delete(tenant_id=context.tenant_id, project_id=projectId, new_metas=data.list) @app.post('/{projectId}/metadata', tags=["metadata"]) -@app.put('/{projectId}/metadata', tags=["metadata"]) def add_metadata(projectId: int, data: schemas.MetadataBasicSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return metadata.add(tenant_id=context.tenant_id, project_id=projectId, new_name=data.key) @app.post('/{projectId}/metadata/{index}', tags=["metadata"]) -@app.put('/{projectId}/metadata/{index}', tags=["metadata"]) def edit_metadata(projectId: int, index: int, data: schemas.MetadataBasicSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return metadata.edit(tenant_id=context.tenant_id, project_id=projectId, index=index, @@ -627,28 +533,12 @@ def search_integrations(projectId: int, context: schemas.CurrentContext = Depend return log_tools.search(project_id=projectId) -@public_app.post('/async/email_assignment', tags=["async mail"]) -def async_send_signup_emails(data: schemas.EmailPayloadSchema = Body(...)): - if data.auth != config("async_Token"): - return {} - email_helper.send_assign_session(recipient=data.email, link=data.link, message=data.message) - - -# @public_app.post('/async/basic/member_invitation', tags=["async mail"]) -# def async_basic_emails(data: schemas.MemberInvitationPayloadSchema = Body(...)): -# if data.auth != config("async_Token"): -# return {} -# email_helper.send_team_invitation(recipient=data.email, invitation_link=data.invitation_link, -# client_id=data.client_id, sender_name=data.sender_name) - - @app.get('/{projectId}/sample_rate', tags=["projects"]) def get_capture_status(projectId: int, context: schemas.CurrentContext = Depends(OR_context)): return {"data": projects.get_capture_status(project_id=projectId)} @app.post('/{projectId}/sample_rate', tags=["projects"]) -@app.put('/{projectId}/sample_rate', tags=["projects"]) def update_capture_status(projectId: int, data: schemas.SampleRateSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": projects.update_capture_status(project_id=projectId, changes=data.dict())} @@ -664,20 +554,12 @@ def get_all_announcements(context: schemas.CurrentContext = Depends(OR_context)) return {"data": announcements.view(user_id=context.user_id)} -@app.post('/{projectId}/errors/merge', tags=["errors"]) -def errors_merge(projectId: int, data: schemas.ErrorIdsPayloadSchema = Body(...), - context: schemas.CurrentContext = Depends(OR_context)): - data = errors.merge(error_ids=data.errors) - return data - - @app.get('/show_banner', tags=["banner"]) def errors_merge(context: schemas.CurrentContext = Depends(OR_context)): return {"data": False} @app.post('/{projectId}/alerts', tags=["alerts"]) -@app.put('/{projectId}/alerts', tags=["alerts"]) def create_alert(projectId: int, data: schemas.AlertSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return alerts.create(projectId, data) @@ -700,7 +582,6 @@ def get_alert(projectId: int, alertId: int, context: schemas.CurrentContext = De @app.post('/{projectId}/alerts/{alertId}', tags=["alerts"]) -@app.put('/{projectId}/alerts/{alertId}', tags=["alerts"]) def update_alert(projectId: int, alertId: int, data: schemas.AlertSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return alerts.update(alertId, data) @@ -712,7 +593,6 @@ def delete_alert(projectId: int, alertId: int, context: schemas.CurrentContext = @app.post('/{projectId}/funnels', tags=["funnels"]) -@app.put('/{projectId}/funnels', tags=["funnels"]) def add_funnel(projectId: int, data: schemas.FunnelSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return funnels.create(project_id=projectId, @@ -756,7 +636,6 @@ def get_funnel_insights(projectId: int, funnelId: int, rangeValue: str = None, s @app.post('/{projectId}/funnels/{funnelId}/insights', tags=["funnels"]) -@app.put('/{projectId}/funnels/{funnelId}/insights', tags=["funnels"]) def get_funnel_insights_on_the_fly(projectId: int, funnelId: int, data: schemas.FunnelInsightsPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return funnels.get_top_insights_on_the_fly(funnel_id=funnelId, user_id=context.user_id, project_id=projectId, @@ -771,7 +650,6 @@ def get_funnel_issues(projectId: int, funnelId, rangeValue: str = None, startDat @app.post('/{projectId}/funnels/{funnelId}/issues', tags=["funnels"]) -@app.put('/{projectId}/funnels/{funnelId}/issues', tags=["funnels"]) def get_funnel_issues_on_the_fly(projectId: int, funnelId: int, data: schemas.FunnelSearchPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": funnels.get_issues_on_the_fly(funnel_id=funnelId, user_id=context.user_id, project_id=projectId, @@ -788,7 +666,6 @@ def get_funnel_sessions(projectId: int, funnelId: int, rangeValue: str = None, s @app.post('/{projectId}/funnels/{funnelId}/sessions', tags=["funnels"]) -@app.put('/{projectId}/funnels/{funnelId}/sessions', tags=["funnels"]) def get_funnel_sessions_on_the_fly(projectId: int, funnelId: int, data: schemas.FunnelSearchPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": funnels.get_sessions_on_the_fly(funnel_id=funnelId, user_id=context.user_id, project_id=projectId, @@ -808,7 +685,6 @@ def get_funnel_issue_sessions(projectId: int, issueId: str, startDate: int = Non @app.post('/{projectId}/funnels/{funnelId}/issues/{issueId}/sessions', tags=["funnels"]) -@app.put('/{projectId}/funnels/{funnelId}/issues/{issueId}/sessions', tags=["funnels"]) def get_funnel_issue_sessions(projectId: int, funnelId: int, issueId: str, data: schemas.FunnelSearchPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): @@ -832,7 +708,6 @@ def get_funnel(projectId: int, funnelId: int, context: schemas.CurrentContext = @app.post('/{projectId}/funnels/{funnelId}', tags=["funnels"]) -@app.put('/{projectId}/funnels/{funnelId}', tags=["funnels"]) def edit_funnel(projectId: int, funnelId: int, data: schemas.UpdateFunnelSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return funnels.update(funnel_id=funnelId, @@ -865,7 +740,6 @@ def get_weekly_report_config(context: schemas.CurrentContext = Depends(OR_contex @app.post('/config/weekly_report', tags=["weekly report config"]) -@app.put('/config/weekly_report', tags=["weekly report config"]) def edit_weekly_report_config(data: schemas.WeeklyReportConfigSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": weekly_report.edit_config(user_id=context.user_id, weekly_report=data.weekly_report)} @@ -894,58 +768,24 @@ def sessions_live(projectId: int, data: schemas.LiveSessionsSearchPayloadSchema return {'data': data} -@app.get('/{projectId}/assist/sessions/{sessionId}', tags=["assist"]) -def get_live_session(projectId: int, sessionId: str, background_tasks: BackgroundTasks, - context: schemas.CurrentContext = Depends(OR_context)): - data = assist.get_live_session_by_id(project_id=projectId, session_id=sessionId) - if data is None: - data = sessions.get_by_id2_pg(project_id=projectId, session_id=sessionId, full_data=True, - user_id=context.user_id, include_fav_viewed=True, group_metadata=True, live=False) - if data is None: - return {"errors": ["session not found"]} - if data.get("inDB"): - background_tasks.add_task(sessions_viewed.view_session, project_id=projectId, - user_id=context.user_id, session_id=sessionId) - return {'data': data} - - -@app.get('/{projectId}/unprocessed/{sessionId}', tags=["assist"]) -@app.get('/{projectId}/assist/sessions/{sessionId}/replay', tags=["assist"]) -def get_live_session_replay_file(projectId: int, sessionId: str, - context: schemas.CurrentContext = Depends(OR_context)): - path = assist.get_raw_mob_by_id(project_id=projectId, session_id=sessionId) - if path is None: - return {"errors": ["Replay file not found"]} - - return FileResponse(path=path, media_type="application/octet-stream") - - -@app.post('/{projectId}/heatmaps/url', tags=["heatmaps"]) -def get_heatmaps_by_url(projectId: int, data: schemas.GetHeatmapPayloadSchema = Body(...), - context: schemas.CurrentContext = Depends(OR_context)): - return {"data": heatmaps.get_by_url(project_id=projectId, data=data.dict())} - - @app.post('/{projectId}/mobile/{sessionId}/urls', tags=['mobile']) def mobile_signe(projectId: int, sessionId: int, data: schemas.MobileSignPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": mobile.sign_keys(project_id=projectId, session_id=sessionId, keys=data.keys)} -@public_app.put('/signup', tags=['signup']) @public_app.post('/signup', tags=['signup']) +@public_app.put('/signup', tags=['signup']) def signup_handler(data: schemas.UserSignupSchema = Body(...)): return signup.create_step1(data) @app.post('/projects', tags=['projects']) -@app.put('/projects', tags=['projects']) def create_project(data: schemas.CreateProjectSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return projects.create(tenant_id=context.tenant_id, user_id=context.user_id, data=data) -@app.post('/projects/{projectId}', tags=['projects']) @app.put('/projects/{projectId}', tags=['projects']) def edit_project(projectId: int, data: schemas.CreateProjectSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): @@ -964,74 +804,13 @@ def generate_new_tenant_token(context: schemas.CurrentContext = Depends(OR_conte } -@app.put('/client', tags=['client']) @app.post('/client', tags=['client']) +@app.put('/client', tags=['client']) def edit_client(data: schemas.UpdateTenantSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return tenants.update(tenant_id=context.tenant_id, user_id=context.user_id, data=data) -@app.post('/{projectId}/errors/search', tags=['errors']) -def errors_search(projectId: int, data: schemas.SearchErrorsSchema = Body(...), - context: schemas.CurrentContext = Depends(OR_context)): - return {"data": errors.search(data, projectId, user_id=context.user_id)} - - -@app.get('/{projectId}/errors/stats', tags=['errors']) -def errors_stats(projectId: int, startTimestamp: int, endTimestamp: int, - context: schemas.CurrentContext = Depends(OR_context)): - return errors.stats(projectId, user_id=context.user_id, startTimestamp=startTimestamp, endTimestamp=endTimestamp) - - -@app.get('/{projectId}/errors/{errorId}', tags=['errors']) -def errors_get_details(projectId: int, errorId: str, background_tasks: BackgroundTasks, density24: int = 24, - density30: int = 30, - context: schemas.CurrentContext = Depends(OR_context)): - data = errors.get_details(project_id=projectId, user_id=context.user_id, error_id=errorId, - **{"density24": density24, "density30": density30}) - if data.get("data") is not None: - background_tasks.add_task(errors_viewed.viewed_error, project_id=projectId, user_id=context.user_id, - error_id=errorId) - return data - - -@app.get('/{projectId}/errors/{errorId}/stats', tags=['errors']) -def errors_get_details_right_column(projectId: int, errorId: str, startDate: int = TimeUTC.now(-7), - endDate: int = TimeUTC.now(), density: int = 7, - context: schemas.CurrentContext = Depends(OR_context)): - data = errors.get_details_chart(project_id=projectId, user_id=context.user_id, error_id=errorId, - **{"startDate": startDate, "endDate": endDate, "density": density}) - return data - - -@app.get('/{projectId}/errors/{errorId}/sourcemaps', tags=['errors']) -def errors_get_details_sourcemaps(projectId: int, errorId: str, - context: schemas.CurrentContext = Depends(OR_context)): - data = errors.get_trace(project_id=projectId, error_id=errorId) - if "errors" in data: - return data - return { - 'data': data - } - - -@app.get('/{projectId}/errors/{errorId}/{action}', tags=["errors"]) -def add_remove_favorite_error(projectId: int, errorId: str, action: str, startDate: int = TimeUTC.now(-7), - endDate: int = TimeUTC.now(), context: schemas.CurrentContext = Depends(OR_context)): - if action == "favorite": - return errors_favorite.favorite_error(project_id=projectId, user_id=context.user_id, error_id=errorId) - elif action == "sessions": - start_date = startDate - end_date = endDate - return { - "data": errors.get_sessions(project_id=projectId, user_id=context.user_id, error_id=errorId, - start_date=start_date, end_date=end_date)} - elif action in list(errors.ACTION_STATE.keys()): - return errors.change_state(project_id=projectId, user_id=context.user_id, error_id=errorId, action=action) - else: - return {"errors": ["undefined action"]} - - @app.get('/notifications', tags=['notifications']) def get_notifications(context: schemas.CurrentContext = Depends(OR_context)): return {"data": notifications.get_all(tenant_id=context.tenant_id, user_id=context.user_id)} @@ -1048,7 +827,6 @@ def view_notifications(notificationId: int, context: schemas.CurrentContext = De @app.post('/notifications/view', tags=['notifications']) -@app.put('/notifications/view', tags=['notifications']) def batch_view_notifications(data: schemas.NotificationsViewSchema, context: schemas.CurrentContext = Depends(OR_context)): return {"data": notifications.view_notification(notification_ids=data.ids, @@ -1058,14 +836,6 @@ def batch_view_notifications(data: schemas.NotificationsViewSchema, tenant_id=context.tenant_id)} -@public_app.post('/notifications', tags=['notifications']) -@public_app.put('/notifications', tags=['notifications']) -def create_notifications(data: schemas.CreateNotificationSchema): - if data.token != config("async_Token"): - return {"errors": ["missing token"]} - return notifications.create(data.notifications) - - @app.get('/boarding', tags=['boarding']) def get_boarding_state(context: schemas.CurrentContext = Depends(OR_context)): return {"data": boarding.get_state(tenant_id=context.tenant_id)} @@ -1106,7 +876,6 @@ def delete_slack_integration(integrationId: int, context: schemas.CurrentContext return webhook.delete(context.tenant_id, integrationId) -@app.post('/webhooks', tags=["webhooks"]) @app.put('/webhooks', tags=["webhooks"]) def add_edit_webhook(data: schemas.CreateEditWebhookSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): @@ -1144,7 +913,6 @@ def generate_new_user_token(context: schemas.CurrentContext = Depends(OR_context @app.post('/account/password', tags=["account"]) -@app.put('/account/password', tags=["account"]) def change_client_password(data: schemas.EditUserPasswordSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return users.change_password(email=context.email, old_password=data.old_password, @@ -1153,7 +921,6 @@ def change_client_password(data: schemas.EditUserPasswordSchema = Body(...), @app.post('/{projectId}/saved_search', tags=["savedSearch"]) -@app.put('/{projectId}/saved_search', tags=["savedSearch"]) def add_saved_search(projectId: int, data: schemas.SavedSearchSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return saved_search.create(project_id=projectId, user_id=context.user_id, data=data) @@ -1170,7 +937,6 @@ def get_saved_search(projectId: int, search_id: int, context: schemas.CurrentCon @app.post('/{projectId}/saved_search/{search_id}', tags=["savedSearch"]) -@app.put('/{projectId}/saved_search/{search_id}', tags=["savedSearch"]) def update_saved_search(projectId: int, search_id: int, data: schemas.SavedSearchSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return {"data": saved_search.update(user_id=context.user_id, search_id=search_id, data=data, project_id=projectId)} diff --git a/api/routers/core_dynamic.py b/api/routers/core_dynamic.py index d37a56728..c9c9c40c8 100644 --- a/api/routers/core_dynamic.py +++ b/api/routers/core_dynamic.py @@ -1,16 +1,18 @@ -from typing import Optional +from typing import Optional, Union from decouple import config from fastapi import Body, Depends, BackgroundTasks -from starlette.responses import RedirectResponse +from starlette.responses import RedirectResponse, FileResponse import schemas -from chalicelib.core import integrations_manager -from chalicelib.core import sessions +from chalicelib.core import sessions, errors, errors_viewed, errors_favorite, sessions_assignments, heatmaps, \ + sessions_favorite, assist, sessions_notes +from chalicelib.core import sessions_viewed from chalicelib.core import tenants, users, projects, license from chalicelib.core import webhook from chalicelib.core.collaboration_slack import Slack from chalicelib.utils import helper +from chalicelib.utils.TimeUTC import TimeUTC from or_dependencies import OR_context from routers.base import get_routers @@ -44,7 +46,6 @@ def get_account(context: schemas.CurrentContext = Depends(OR_context)): @app.post('/account', tags=["account"]) -@app.put('/account', tags=["account"]) def edit_account(data: schemas.EditUserSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return users.edit(tenant_id=context.tenant_id, user_id_to_update=context.user_id, changes=data, @@ -68,8 +69,8 @@ def get_project(projectId: int, context: schemas.CurrentContext = Depends(OR_con return {"data": data} -@app.put('/integrations/slack', tags=['integrations']) @app.post('/integrations/slack', tags=['integrations']) +@app.put('/integrations/slack', tags=['integrations']) def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentContext = Depends(OR_context)): n = Slack.add_channel(tenant_id=context.tenant_id, url=data.url, name=data.name) if n is None: @@ -79,7 +80,6 @@ def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentConte return {"data": n} -@app.put('/integrations/slack/{integrationId}', tags=['integrations']) @app.post('/integrations/slack/{integrationId}', tags=['integrations']) def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): @@ -96,7 +96,6 @@ def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = B @app.post('/client/members', tags=["client"]) -@app.put('/client/members', tags=["client"]) def add_member(background_tasks: BackgroundTasks, data: schemas.CreateMemberSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return users.create_member(tenant_id=context.tenant_id, user_id=context.user_id, data=data.dict(), @@ -121,7 +120,6 @@ def process_invitation_link(token: str): @public_app.post('/password/reset', tags=["users"]) -@public_app.put('/password/reset', tags=["users"]) def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema = Body(...)): if data is None or len(data.invitation) < 64 or len(data.passphrase) < 8: return {"errors": ["please provide a valid invitation & pass"]} @@ -135,11 +133,10 @@ def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema = @app.put('/client/members/{memberId}', tags=["client"]) -@app.post('/client/members/{memberId}', tags=["client"]) def edit_member(memberId: int, data: schemas.EditMemberSchema, context: schemas.CurrentContext = Depends(OR_context)): - return users.edit(tenant_id=context.tenant_id, editor_id=context.user_id, changes=data, - user_id_to_update=memberId) + return users.edit_member(tenant_id=context.tenant_id, editor_id=context.user_id, changes=data, + user_id_to_update=memberId) @app.get('/metadata/session_search', tags=["metadata"]) @@ -165,3 +162,257 @@ def get_general_stats(): def get_projects(context: schemas.CurrentContext = Depends(OR_context)): return {"data": projects.get_projects(tenant_id=context.tenant_id, recording_state=True, gdpr=True, recorded=True, stack_integrations=True)} + + +@app.get('/{projectId}/sessions/{sessionId}', tags=["sessions"]) +def get_session(projectId: int, sessionId: Union[int, str], background_tasks: BackgroundTasks, + context: schemas.CurrentContext = Depends(OR_context)): + if isinstance(sessionId, str): + return {"errors": ["session not found"]} + data = sessions.get_by_id2_pg(project_id=projectId, session_id=sessionId, full_data=True, + include_fav_viewed=True, group_metadata=True, context=context) + if data is None: + return {"errors": ["session not found"]} + if data.get("inDB"): + background_tasks.add_task(sessions_viewed.view_session, project_id=projectId, user_id=context.user_id, + session_id=sessionId) + return { + 'data': data + } + + +@app.get('/{projectId}/sessions/{sessionId}/errors/{errorId}/sourcemaps', tags=["sessions", "sourcemaps"]) +def get_error_trace(projectId: int, sessionId: int, errorId: str, + context: schemas.CurrentContext = Depends(OR_context)): + data = errors.get_trace(project_id=projectId, error_id=errorId) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.post('/{projectId}/errors/search', tags=['errors']) +def errors_search(projectId: int, data: schemas.SearchErrorsSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return {"data": errors.search(data, projectId, user_id=context.user_id)} + + +@app.get('/{projectId}/errors/stats', tags=['errors']) +def errors_stats(projectId: int, startTimestamp: int, endTimestamp: int, + context: schemas.CurrentContext = Depends(OR_context)): + return errors.stats(projectId, user_id=context.user_id, startTimestamp=startTimestamp, endTimestamp=endTimestamp) + + +@app.get('/{projectId}/errors/{errorId}', tags=['errors']) +def errors_get_details(projectId: int, errorId: str, background_tasks: BackgroundTasks, density24: int = 24, + density30: int = 30, context: schemas.CurrentContext = Depends(OR_context)): + data = errors.get_details(project_id=projectId, user_id=context.user_id, error_id=errorId, + **{"density24": density24, "density30": density30}) + if data.get("data") is not None: + background_tasks.add_task(errors_viewed.viewed_error, project_id=projectId, user_id=context.user_id, + error_id=errorId) + return data + + +@app.get('/{projectId}/errors/{errorId}/stats', tags=['errors']) +def errors_get_details_right_column(projectId: int, errorId: str, startDate: int = TimeUTC.now(-7), + endDate: int = TimeUTC.now(), density: int = 7, + context: schemas.CurrentContext = Depends(OR_context)): + data = errors.get_details_chart(project_id=projectId, user_id=context.user_id, error_id=errorId, + **{"startDate": startDate, "endDate": endDate, "density": density}) + return data + + +@app.get('/{projectId}/errors/{errorId}/sourcemaps', tags=['errors']) +def errors_get_details_sourcemaps(projectId: int, errorId: str, + context: schemas.CurrentContext = Depends(OR_context)): + data = errors.get_trace(project_id=projectId, error_id=errorId) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.get('/{projectId}/errors/{errorId}/{action}', tags=["errors"]) +def add_remove_favorite_error(projectId: int, errorId: str, action: str, startDate: int = TimeUTC.now(-7), + endDate: int = TimeUTC.now(), context: schemas.CurrentContext = Depends(OR_context)): + if action == "favorite": + return errors_favorite.favorite_error(project_id=projectId, user_id=context.user_id, error_id=errorId) + elif action == "sessions": + start_date = startDate + end_date = endDate + return { + "data": errors.get_sessions(project_id=projectId, user_id=context.user_id, error_id=errorId, + start_date=start_date, end_date=end_date)} + elif action in list(errors.ACTION_STATE.keys()): + return errors.change_state(project_id=projectId, user_id=context.user_id, error_id=errorId, action=action) + else: + return {"errors": ["undefined action"]} + + +@app.get('/{projectId}/assist/sessions/{sessionId}', tags=["assist"]) +def get_live_session(projectId: int, sessionId: str, background_tasks: BackgroundTasks, + context: schemas.CurrentContext = Depends(OR_context)): + data = assist.get_live_session_by_id(project_id=projectId, session_id=sessionId) + if data is None: + data = sessions.get_by_id2_pg(context=context, project_id=projectId, session_id=sessionId, + full_data=True, include_fav_viewed=True, group_metadata=True, live=False) + if data is None: + return {"errors": ["session not found"]} + if data.get("inDB"): + background_tasks.add_task(sessions_viewed.view_session, project_id=projectId, + user_id=context.user_id, session_id=sessionId) + return {'data': data} + + +@app.get('/{projectId}/unprocessed/{sessionId}/dom.mob', tags=["assist"]) +def get_live_session_replay_file(projectId: int, sessionId: Union[int, str], + context: schemas.CurrentContext = Depends(OR_context)): + not_found = {"errors": ["Replay file not found"]} + if isinstance(sessionId, str): + print(f"{sessionId} not a valid number.") + return not_found + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in DB.") + if not assist.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in Assist.") + return not_found + + path = assist.get_raw_mob_by_id(project_id=projectId, session_id=sessionId) + if path is None: + return not_found + + return FileResponse(path=path, media_type="application/octet-stream") + + +@app.get('/{projectId}/unprocessed/{sessionId}/devtools.mob', tags=["assist"]) +def get_live_session_devtools_file(projectId: int, sessionId: Union[int, str], + context: schemas.CurrentContext = Depends(OR_context)): + not_found = {"errors": ["Devtools file not found"]} + if isinstance(sessionId, str): + print(f"{sessionId} not a valid number.") + return not_found + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in DB.") + if not assist.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in Assist.") + return not_found + + path = assist.get_raw_devtools_by_id(project_id=projectId, session_id=sessionId) + if path is None: + return {"errors": ["Devtools file not found"]} + + return FileResponse(path=path, media_type="application/octet-stream") + + +@app.post('/{projectId}/heatmaps/url', tags=["heatmaps"]) +def get_heatmaps_by_url(projectId: int, data: schemas.GetHeatmapPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return {"data": heatmaps.get_by_url(project_id=projectId, data=data.dict())} + + +@app.get('/{projectId}/sessions/{sessionId}/favorite', tags=["sessions"]) +def add_remove_favorite_session2(projectId: int, sessionId: int, + context: schemas.CurrentContext = Depends(OR_context)): + return { + "data": sessions_favorite.favorite_session(context=context, project_id=projectId, session_id=sessionId)} + + +@app.get('/{projectId}/sessions/{sessionId}/assign', tags=["sessions"]) +def assign_session(projectId: int, sessionId, context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_assignments.get_by_session(project_id=projectId, session_id=sessionId, + tenant_id=context.tenant_id, + user_id=context.user_id) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.get('/{projectId}/sessions/{sessionId}/assign/{issueId}', tags=["sessions", "issueTracking"]) +def assign_session(projectId: int, sessionId: int, issueId: str, + context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_assignments.get(project_id=projectId, session_id=sessionId, assignment_id=issueId, + tenant_id=context.tenant_id, user_id=context.user_id) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.post('/{projectId}/sessions/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"]) +def comment_assignment(projectId: int, sessionId: int, issueId: str, data: schemas.CommentAssignmentSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_assignments.comment(tenant_id=context.tenant_id, project_id=projectId, + session_id=sessionId, assignment_id=issueId, + user_id=context.user_id, message=data.message) + if "errors" in data.keys(): + return data + return { + 'data': data + } + + +@app.post('/{projectId}/sessions/{sessionId}/notes', tags=["sessions", "notes"]) +def create_note(projectId: int, sessionId: int, data: schemas.SessionNoteSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + return {"errors": ["Session not found"]} + data = sessions_notes.create(tenant_id=context.tenant_id, project_id=projectId, + session_id=sessionId, user_id=context.user_id, data=data) + if "errors" in data.keys(): + return data + return { + 'data': data + } + + +@app.get('/{projectId}/sessions/{sessionId}/notes', tags=["sessions", "notes"]) +def get_session_notes(projectId: int, sessionId: int, context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_notes.get_session_notes(tenant_id=context.tenant_id, project_id=projectId, + session_id=sessionId, user_id=context.user_id) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.post('/{projectId}/notes/{noteId}', tags=["sessions", "notes"]) +def edit_note(projectId: int, noteId: int, data: schemas.SessionUpdateNoteSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_notes.edit(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id, + note_id=noteId, data=data) + if "errors" in data.keys(): + return data + return { + 'data': data + } + + +@app.delete('/{projectId}/notes/{noteId}', tags=["sessions", "notes"]) +def delete_note(projectId: int, noteId: int, context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_notes.delete(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id, + note_id=noteId) + return data + + +@app.get('/{projectId}/notes/{noteId}/slack/{webhookId}', tags=["sessions", "notes"]) +def share_note_to_slack(projectId: int, noteId: int, webhookId: int, + context: schemas.CurrentContext = Depends(OR_context)): + return sessions_notes.share_to_slack(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id, + note_id=noteId, webhook_id=webhookId) + + +@app.post('/{projectId}/notes', tags=["sessions", "notes"]) +def get_all_notes(projectId: int, data: schemas.SearchNoteSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_notes.get_all_notes_by_project_id(tenant_id=context.tenant_id, project_id=projectId, + user_id=context.user_id, data=data) + if "errors" in data: + return data + return {'data': data} diff --git a/api/schemas.py b/api/schemas.py index f6dc8b34b..7e990bcb8 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -28,7 +28,6 @@ class UserLoginSchema(_Grecaptcha): class UserSignupSchema(UserLoginSchema): fullname: str = Field(...) organizationName: str = Field(...) - projectName: str = Field(default="my first project") class Config: alias_generator = attribute_to_camel_case @@ -875,14 +874,14 @@ class TryCustomMetricsPayloadSchema(CustomMetricChartPayloadSchema): class CustomMetricsConfigSchema(BaseModel): - col: Optional[int] = Field(default=2) + col: Optional[int] = Field(...) row: Optional[int] = Field(default=2) position: Optional[int] = Field(default=0) class CreateCustomMetricsSchema(TryCustomMetricsPayloadSchema): series: List[CustomMetricCreateSeriesSchema] = Field(..., min_items=1) - config: CustomMetricsConfigSchema = Field(default=CustomMetricsConfigSchema()) + config: CustomMetricsConfigSchema = Field(...) @root_validator(pre=True) def transform_series(cls, values): @@ -1084,3 +1083,41 @@ class IntegrationType(str, Enum): stackdriver = "STACKDRIVER" cloudwatch = "CLOUDWATCH" newrelic = "NEWRELIC" + + +class SearchNoteSchema(_PaginatedSchema): + sort: str = Field(default="createdAt") + order: SortOrderType = Field(default=SortOrderType.desc) + tags: Optional[List[str]] = Field(default=[]) + shared_only: bool = Field(default=False) + mine_only: bool = Field(default=False) + + class Config: + alias_generator = attribute_to_camel_case + + +class SessionNoteSchema(BaseModel): + message: str = Field(..., min_length=2) + tag: Optional[str] = Field(default=None) + timestamp: int = Field(default=-1) + is_public: bool = Field(default=False) + + class Config: + alias_generator = attribute_to_camel_case + + +class SessionUpdateNoteSchema(SessionNoteSchema): + message: Optional[str] = Field(default=None, min_length=2) + timestamp: Optional[int] = Field(default=None, ge=-1) + is_public: Optional[bool] = Field(default=None) + + @root_validator + def validator(cls, values): + assert len(values.keys()) > 0, "at least 1 attribute should be provided for update" + c = 0 + for v in values.values(): + if v is not None and (not isinstance(v, str) or len(v) > 0): + c += 1 + break + assert c > 0, "at least 1 value should be provided for update" + return values diff --git a/backend/Dockerfile b/backend/Dockerfile index 4e0064e9d..0d7cad075 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,6 +1,6 @@ FROM golang:1.18-alpine3.15 AS prepare -RUN apk add --no-cache git openssh openssl-dev pkgconf gcc g++ make libc-dev bash +RUN apk add --no-cache git openssh openssl-dev pkgconf gcc g++ make libc-dev bash librdkafka-dev cyrus-sasl cyrus-sasl-gssapiv2 krb5 WORKDIR /root @@ -15,11 +15,11 @@ COPY pkg pkg COPY internal internal ARG SERVICE_NAME -RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o service -tags musl openreplay/backend/cmd/$SERVICE_NAME +RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o service -tags dynamic openreplay/backend/cmd/$SERVICE_NAME FROM alpine AS entrypoint -RUN apk add --no-cache ca-certificates +RUN apk add --no-cache ca-certificates librdkafka-dev cyrus-sasl cyrus-sasl-gssapiv2 krb5 RUN adduser -u 1001 openreplay -D ENV TZ=UTC \ @@ -29,6 +29,18 @@ ENV TZ=UTC \ UAPARSER_FILE=/home/openreplay/regexes.yaml \ HTTP_PORT=8080 \ KAFKA_USE_SSL=true \ + # KAFKA_USE_KERBEROS should be set true if you wish to use Kerberos auth for Kafka + KAFKA_USE_KERBEROS=false \ + # KERBEROS_SERVICE_NAME is the primary name of the Brokers configured in the Broker JAAS file + KERBEROS_SERVICE_NAME="" \ + # KERBEROS_PRINCIPAL is this client's principal name + KERBEROS_PRINCIPAL="" \ + # KERBEROS_PRINCIPAL is the absolute path to the keytab to be used for authentication + KERBEROS_KEYTAB_LOCATION="" \ + # KAFKA_SSL_KEY is the absolute path to the CA cert for verifying the broker's key + KAFKA_SSL_KEY="" \ + # KAFKA_SSL_CERT is a CA cert string (PEM format) for verifying the broker's key + KAFKA_SSL_CERT="" \ KAFKA_MAX_POLL_INTERVAL_MS=400000 \ REDIS_STREAMS_MAX_LEN=10000 \ TOPIC_RAW_WEB=raw \ diff --git a/backend/Dockerfile.bundle b/backend/Dockerfile.bundle index 407a7b9d8..19c3b325c 100644 --- a/backend/Dockerfile.bundle +++ b/backend/Dockerfile.bundle @@ -1,6 +1,6 @@ FROM golang:1.18-alpine3.15 AS prepare -RUN apk add --no-cache git openssh openssl-dev pkgconf gcc g++ make libc-dev bash +RUN apk add --no-cache git openssh openssl-dev pkgconf gcc g++ make libc-dev bash librdkafka-dev cyrus-sasl-gssapi cyrus-sasl-devel WORKDIR /root @@ -14,11 +14,11 @@ COPY cmd cmd COPY pkg pkg COPY internal internal -RUN for name in assets db ender http integrations sink storage;do CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o bin/$name -tags musl openreplay/backend/cmd/$name; done +RUN for name in assets db ender http integrations sink storage;do CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o bin/$name -tags dynamic openreplay/backend/cmd/$name; done FROM alpine AS entrypoint #FROM pygmy/alpine-tini:latest -RUN apk add --no-cache ca-certificates +RUN apk add --no-cache ca-certificates librdkafka-dev cyrus-sasl-gssapi cyrus-sasl-devel pkgconf ENV TZ=UTC \ FS_ULIMIT=1000 \ @@ -28,6 +28,18 @@ ENV TZ=UTC \ HTTP_PORT=80 \ BEACON_SIZE_LIMIT=7000000 \ KAFKA_USE_SSL=true \ + # KAFKA_USE_KERBEROS should be set true if you wish to use Kerberos auth for Kafka + KAFKA_USE_KERBEROS=false \ + # KERBEROS_SERVICE_NAME is the primary name of the Brokers configured in the Broker JAAS file + KERBEROS_SERVICE_NAME="" \ + # KERBEROS_PRINCIPAL is this client's principal name + KERBEROS_PRINCIPAL="" \ + # KERBEROS_PRINCIPAL is the absolute path to the keytab to be used for authentication + KERBEROS_KEYTAB_LOCATION="" \ + # KAFKA_SSL_KEY is the absolute path to the CA cert for verifying the broker's key + KAFKA_SSL_KEY="" \ + # KAFKA_SSL_CERT is a CA cert string (PEM format) for verifying the broker's key + KAFKA_SSL_CERT="" \ KAFKA_MAX_POLL_INTERVAL_MS=400000 \ REDIS_STREAMS_MAX_LEN=3000 \ TOPIC_RAW_WEB=raw \ diff --git a/backend/build.sh b/backend/build.sh index d2a919d9a..073f540df 100755 --- a/backend/build.sh +++ b/backend/build.sh @@ -7,6 +7,7 @@ # Example # Usage: IMAGE_TAG=latest DOCKER_REPO=myDockerHubID bash build.sh +set -e git_sha1=${IMAGE_TAG:-$(git rev-parse HEAD)} ee="false" @@ -25,12 +26,17 @@ function build_service() { [[ $PUSH_IMAGE -eq 1 ]] && { docker push ${DOCKER_REPO:-'local'}/$image:${git_sha1} } + echo "Build completed for $image" return } function build_api(){ - cp -R ../backend ../_backend - cd ../_backend + destination="_backend" + [[ $1 == "ee" ]] && { + destination="_backend_ee" + } + cp -R ../backend ../${destination} + cd ../${destination} # Copy enterprise code [[ $1 == "ee" ]] && { cp -r ../ee/backend/* ./ @@ -38,6 +44,8 @@ function build_api(){ } [[ $2 != "" ]] && { build_service $2 + cd ../backend + rm -rf ../${destination} return } for image in $(ls cmd); @@ -46,7 +54,7 @@ function build_api(){ echo "::set-output name=image::${DOCKER_REPO:-'local'}/$image:${git_sha1}" done cd ../backend - rm -rf ../_backend + rm -rf ../${destination} echo "backend build completed" } diff --git a/backend/cmd/assets/file b/backend/cmd/assets/file deleted file mode 100644 index f0018a2e8..000000000 --- a/backend/cmd/assets/file +++ /dev/null @@ -1 +0,0 @@ -GROUP_CACHE=from_file \ No newline at end of file diff --git a/backend/cmd/assets/main.go b/backend/cmd/assets/main.go index b81ff9b5a..220300e74 100644 --- a/backend/cmd/assets/main.go +++ b/backend/cmd/assets/main.go @@ -3,7 +3,6 @@ package main import ( "context" "log" - "openreplay/backend/pkg/queue/types" "os" "os/signal" "syscall" @@ -31,40 +30,28 @@ func main() { log.Printf("can't create assets_total metric: %s", err) } - consumer := queue.NewMessageConsumer( + msgHandler := func(msg messages.Message) { + switch m := msg.(type) { + case *messages.AssetCache: + cacher.CacheURL(m.SessionID(), m.URL) + totalAssets.Add(context.Background(), 1) + // TODO: connect to "raw" topic in order to listen for JSException + case *messages.JSException: + sourceList, err := assets.ExtractJSExceptionSources(&m.Payload) + if err != nil { + log.Printf("Error on source extraction: %v", err) + return + } + for _, source := range sourceList { + cacher.CacheJSFile(source) + } + } + } + + msgConsumer := queue.NewConsumer( cfg.GroupCache, []string{cfg.TopicCache}, - func(sessionID uint64, iter messages.Iterator, meta *types.Meta) { - for iter.Next() { - if iter.Type() == messages.MsgAssetCache { - m := iter.Message().Decode() - if m == nil { - return - } - msg := m.(*messages.AssetCache) - cacher.CacheURL(sessionID, msg.URL) - totalAssets.Add(context.Background(), 1) - } else if iter.Type() == messages.MsgErrorEvent { - m := iter.Message().Decode() - if m == nil { - return - } - msg := m.(*messages.ErrorEvent) - if msg.Source != "js_exception" { - continue - } - sourceList, err := assets.ExtractJSExceptionSources(&msg.Payload) - if err != nil { - log.Printf("Error on source extraction: %v", err) - continue - } - for _, source := range sourceList { - cacher.CacheJSFile(source) - } - } - } - iter.Close() - }, + messages.NewMessageIterator(msgHandler, []int{messages.MsgAssetCache, messages.MsgJSException}, true), true, cfg.MessageSizeLimit, ) @@ -79,15 +66,18 @@ func main() { select { case sig := <-sigchan: log.Printf("Caught signal %v: terminating\n", sig) - consumer.Close() + cacher.Stop() + msgConsumer.Close() os.Exit(0) case err := <-cacher.Errors: log.Printf("Error while caching: %v", err) - // TODO: notify user case <-tick: cacher.UpdateTimeouts() default: - if err := consumer.ConsumeNext(); err != nil { + if !cacher.CanCache() { + continue + } + if err := msgConsumer.ConsumeNext(); err != nil { log.Fatalf("Error on consumption: %v", err) } } diff --git a/backend/cmd/db/main.go b/backend/cmd/db/main.go index a807cc253..c9916b03d 100644 --- a/backend/cmd/db/main.go +++ b/backend/cmd/db/main.go @@ -3,6 +3,7 @@ package main import ( "errors" "log" + types2 "openreplay/backend/pkg/db/types" "openreplay/backend/pkg/queue/types" "os" "os/signal" @@ -30,7 +31,8 @@ func main() { cfg := db.New() // Init database - pg := cache.NewPGCache(postgres.NewConn(cfg.Postgres, cfg.BatchQueueLimit, cfg.BatchSizeLimit, metrics), cfg.ProjectExpirationTimeoutMs) + pg := cache.NewPGCache( + postgres.NewConn(cfg.Postgres, cfg.BatchQueueLimit, cfg.BatchSizeLimit, metrics), cfg.ProjectExpirationTimeoutMs) defer pg.Close() // HandlersFabric returns the list of message handlers we want to be applied to each incoming message. @@ -45,10 +47,6 @@ func main() { // Create handler's aggregator builderMap := sessions.NewBuilderMap(handlersFabric) - keepMessage := func(tp int) bool { - return tp == messages.MsgMetadata || tp == messages.MsgIssueEvent || tp == messages.MsgSessionStart || tp == messages.MsgSessionEnd || tp == messages.MsgUserID || tp == messages.MsgUserAnonymousID || tp == messages.MsgCustomEvent || tp == messages.MsgClickEvent || tp == messages.MsgInputEvent || tp == messages.MsgPageEvent || tp == messages.MsgErrorEvent || tp == messages.MsgFetchEvent || tp == messages.MsgGraphQLEvent || tp == messages.MsgIntegrationEvent || tp == messages.MsgPerformanceTrackAggr || tp == messages.MsgResourceEvent || tp == messages.MsgLongTask || tp == messages.MsgJSException || tp == messages.MsgResourceTiming || tp == messages.MsgRawCustomEvent || tp == messages.MsgCustomIssue || tp == messages.MsgFetch || tp == messages.MsgGraphQL || tp == messages.MsgStateAction || tp == messages.MsgSetInputTarget || tp == messages.MsgSetInputValue || tp == messages.MsgCreateDocument || tp == messages.MsgMouseClick || tp == messages.MsgSetPageLocation || tp == messages.MsgPageLoadTiming || tp == messages.MsgPageRenderTiming - } - var producer types.Producer = nil if cfg.UseQuickwit { producer = queue.NewProducer(cfg.MessageSizeLimit, true) @@ -60,69 +58,74 @@ func main() { saver.InitStats() statsLogger := logger.NewQueueStats(cfg.LoggerTimeout) + msgFilter := []int{messages.MsgMetadata, messages.MsgIssueEvent, messages.MsgSessionStart, messages.MsgSessionEnd, + messages.MsgUserID, messages.MsgUserAnonymousID, messages.MsgClickEvent, + messages.MsgIntegrationEvent, messages.MsgPerformanceTrackAggr, + messages.MsgJSException, messages.MsgResourceTiming, + messages.MsgRawCustomEvent, messages.MsgCustomIssue, messages.MsgFetch, messages.MsgGraphQL, + messages.MsgStateAction, messages.MsgSetInputTarget, messages.MsgSetInputValue, messages.MsgCreateDocument, + messages.MsgMouseClick, messages.MsgSetPageLocation, messages.MsgPageLoadTiming, messages.MsgPageRenderTiming} + // Handler logic - handler := func(sessionID uint64, iter messages.Iterator, meta *types.Meta) { - statsLogger.Collect(sessionID, meta) + msgHandler := func(msg messages.Message) { + statsLogger.Collect(msg) - for iter.Next() { - if !keepMessage(iter.Type()) { - continue + // Just save session data into db without additional checks + if err := saver.InsertMessage(msg); err != nil { + if !postgres.IsPkeyViolation(err) { + log.Printf("Message Insertion Error %v, SessionID: %v, Message: %v", err, msg.SessionID(), msg) } - msg := iter.Message().Decode() - if msg == nil { - return - } - - // Just save session data into db without additional checks - if err := saver.InsertMessage(sessionID, msg); err != nil { - if !postgres.IsPkeyViolation(err) { - log.Printf("Message Insertion Error %v, SessionID: %v, Message: %v", err, sessionID, msg) - } - return - } - - session, err := pg.GetSession(sessionID) - if session == nil { - if err != nil && !errors.Is(err, cache.NilSessionInCacheError) { - log.Printf("Error on session retrieving from cache: %v, SessionID: %v, Message: %v", err, sessionID, msg) - } - return - } - - // Save statistics to db - err = saver.InsertStats(session, msg) - if err != nil { - log.Printf("Stats Insertion Error %v; Session: %v, Message: %v", err, session, msg) - } - - // Handle heuristics and save to temporary queue in memory - builderMap.HandleMessage(sessionID, msg, msg.Meta().Index) - - // Process saved heuristics messages as usual messages above in the code - builderMap.IterateSessionReadyMessages(sessionID, func(msg messages.Message) { - if err := saver.InsertMessage(sessionID, msg); err != nil { - if !postgres.IsPkeyViolation(err) { - log.Printf("Message Insertion Error %v; Session: %v, Message %v", err, session, msg) - } - return - } - - if err := saver.InsertStats(session, msg); err != nil { - log.Printf("Stats Insertion Error %v; Session: %v, Message %v", err, session, msg) - } - }) + return } - iter.Close() + + var ( + session *types2.Session + err error + ) + if msg.TypeID() == messages.MsgSessionEnd { + session, err = pg.GetSession(msg.SessionID()) + } else { + session, err = pg.Cache.GetSession(msg.SessionID()) + } + if session == nil { + if err != nil && !errors.Is(err, cache.NilSessionInCacheError) { + log.Printf("Error on session retrieving from cache: %v, SessionID: %v, Message: %v", err, msg.SessionID(), msg) + } + return + } + + // Save statistics to db + err = saver.InsertStats(session, msg) + if err != nil { + log.Printf("Stats Insertion Error %v; Session: %v, Message: %v", err, session, msg) + } + + // Handle heuristics and save to temporary queue in memory + builderMap.HandleMessage(msg) + + // Process saved heuristics messages as usual messages above in the code + builderMap.IterateSessionReadyMessages(msg.SessionID(), func(msg messages.Message) { + if err := saver.InsertMessage(msg); err != nil { + if !postgres.IsPkeyViolation(err) { + log.Printf("Message Insertion Error %v; Session: %v, Message %v", err, session, msg) + } + return + } + + if err := saver.InsertStats(session, msg); err != nil { + log.Printf("Stats Insertion Error %v; Session: %v, Message %v", err, session, msg) + } + }) } // Init consumer - consumer := queue.NewMessageConsumer( + consumer := queue.NewConsumer( cfg.GroupDB, []string{ cfg.TopicRawWeb, cfg.TopicAnalytics, }, - handler, + messages.NewMessageIterator(msgHandler, msgFilter, true), false, cfg.MessageSizeLimit, ) @@ -133,33 +136,36 @@ func main() { signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) commitTick := time.Tick(cfg.CommitBatchTimeout) + + // Send collected batches to db + commitDBUpdates := func() { + start := time.Now() + pg.CommitBatches() + pgDur := time.Now().Sub(start).Milliseconds() + + start = time.Now() + if err := saver.CommitStats(); err != nil { + log.Printf("Error on stats commit: %v", err) + } + chDur := time.Now().Sub(start).Milliseconds() + log.Printf("commit duration(ms), pg: %d, ch: %d", pgDur, chDur) + + if err := consumer.Commit(); err != nil { + log.Printf("Error on consumer commit: %v", err) + } + } for { select { case sig := <-sigchan: - log.Printf("Caught signal %v: terminating\n", sig) + log.Printf("Caught signal %s: terminating\n", sig.String()) + commitDBUpdates() consumer.Close() os.Exit(0) case <-commitTick: - // Send collected batches to db - start := time.Now() - pg.CommitBatches() - pgDur := time.Now().Sub(start).Milliseconds() - - start = time.Now() - if err := saver.CommitStats(consumer.HasFirstPartition()); err != nil { - log.Printf("Error on stats commit: %v", err) - } - chDur := time.Now().Sub(start).Milliseconds() - log.Printf("commit duration(ms), pg: %d, ch: %d", pgDur, chDur) - - // TODO: use commit worker to save time each tick - if err := consumer.Commit(); err != nil { - log.Printf("Error on consumer commit: %v", err) - } + commitDBUpdates() default: // Handle new message from queue - err := consumer.ConsumeNext() - if err != nil { + if err := consumer.ConsumeNext(); err != nil { log.Fatalf("Error on consumption: %v", err) } } diff --git a/backend/cmd/db/values.yaml b/backend/cmd/db/values.yaml deleted file mode 100644 index 2c0f0e7f3..000000000 --- a/backend/cmd/db/values.yaml +++ /dev/null @@ -1,92 +0,0 @@ -chalice: - env: - jwt_secret: SetARandomStringHere -clickhouse: - enabled: false -fromVersion: v1.6.0 -global: - domainName: openreplay.local - email: - emailFrom: OpenReplay - emailHost: "" - emailPassword: "" - emailPort: "587" - emailSslCert: "" - emailSslKey: "" - emailUseSsl: "false" - emailUseTls: "true" - emailUser: "" - enterpriseEditionLicense: "" - ingress: - controller: - config: - enable-real-ip: true - force-ssl-redirect: false - max-worker-connections: 0 - proxy-body-size: 10m - ssl-redirect: false - extraArgs: - default-ssl-certificate: app/openreplay-ssl - ingressClass: openreplay - ingressClassResource: - name: openreplay - service: - externalTrafficPolicy: Local - kafka: - kafkaHost: kafka.db.svc.cluster.local - kafkaPort: "9092" - kafkaUseSsl: "false" - zookeeperHost: databases-zookeeper.svc.cluster.local - zookeeperNonTLSPort: 2181 - postgresql: - postgresqlDatabase: postgres - postgresqlHost: postgresql.db.svc.cluster.local - postgresqlPassword: changeMePassword - postgresqlPort: "5432" - postgresqlUser: postgres - redis: - redisHost: redis-master.db.svc.cluster.local - redisPort: "6379" - s3: - accessKey: changeMeMinioAccessKey - assetsBucket: sessions-assets - endpoint: http://minio.db.svc.cluster.local:9000 - recordingsBucket: mobs - region: us-east-1 - secretKey: changeMeMinioPassword - sourcemapsBucket: sourcemaps -ingress-nginx: - controller: - config: - enable-real-ip: true - force-ssl-redirect: false - max-worker-connections: 0 - proxy-body-size: 10m - ssl-redirect: false - extraArgs: - default-ssl-certificate: app/openreplay-ssl - ingressClass: openreplay - ingressClassResource: - name: openreplay - service: - externalTrafficPolicy: Local -kafka: - kafkaHost: kafka.db.svc.cluster.local - kafkaPort: "9092" - kafkaUseSsl: "false" - zookeeperHost: databases-zookeeper.svc.cluster.local - zookeeperNonTLSPort: 2181 -minio: - global: - minio: - accessKey: changeMeMinioAccessKey - secretKey: changeMeMinioPassword -postgresql: - postgresqlDatabase: postgres - postgresqlHost: postgresql.db.svc.cluster.local - postgresqlPassword: changeMePassword - postgresqlPort: "5432" - postgresqlUser: postgres -redis: - redisHost: redis-master.db.svc.cluster.local - redisPort: "6379" diff --git a/backend/cmd/ender/main.go b/backend/cmd/ender/main.go index a2dafa689..913629f0e 100644 --- a/backend/cmd/ender/main.go +++ b/backend/cmd/ender/main.go @@ -2,7 +2,7 @@ package main import ( "log" - "openreplay/backend/pkg/queue/types" + "openreplay/backend/internal/storage" "os" "os/signal" "syscall" @@ -20,42 +20,27 @@ import ( ) func main() { - metrics := monitoring.New("ender") - log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) - - // Load service configuration + metrics := monitoring.New("ender") cfg := ender.New() pg := cache.NewPGCache(postgres.NewConn(cfg.Postgres, 0, 0, metrics), cfg.ProjectExpirationTimeoutMs) defer pg.Close() - // Init all modules - statsLogger := logger.NewQueueStats(cfg.LoggerTimeout) - sessions, err := sessionender.New(metrics, intervals.EVENTS_SESSION_END_TIMEOUT, cfg.PartitionsNumber) + sessions, err := sessionender.New(metrics, intervals.EVENTS_SESSION_END_TIMEOUT, cfg.PartitionsNumber, logger.NewQueueStats(cfg.LoggerTimeout)) if err != nil { log.Printf("can't init ender service: %s", err) return } + producer := queue.NewProducer(cfg.MessageSizeLimit, true) - consumer := queue.NewMessageConsumer( + consumer := queue.NewConsumer( cfg.GroupEnder, - []string{ - cfg.TopicRawWeb, - }, - func(sessionID uint64, iter messages.Iterator, meta *types.Meta) { - for iter.Next() { - if iter.Type() == messages.MsgSessionStart || iter.Type() == messages.MsgSessionEnd { - continue - } - if iter.Message().Meta().Timestamp == 0 { - log.Printf("ZERO TS, sessID: %d, msgType: %d", sessionID, iter.Type()) - } - statsLogger.Collect(sessionID, meta) - sessions.UpdateSession(sessionID, meta.Timestamp, iter.Message().Meta().Timestamp) - } - iter.Close() - }, + []string{cfg.TopicRawWeb}, + messages.NewMessageIterator( + func(msg messages.Message) { sessions.UpdateSession(msg) }, + []int{messages.MsgTimestamp}, + false), false, cfg.MessageSizeLimit, ) @@ -94,7 +79,16 @@ func main() { currDuration, newDuration) return true } - if err := producer.Produce(cfg.TopicRawWeb, sessionID, messages.Encode(msg)); err != nil { + if cfg.UseEncryption { + if key := storage.GenerateEncryptionKey(); key != nil { + if err := pg.InsertSessionEncryptionKey(sessionID, key); err != nil { + log.Printf("can't save session encryption key: %s, session will not be encrypted", err) + } else { + msg.EncryptionKey = string(key) + } + } + } + if err := producer.Produce(cfg.TopicRawWeb, sessionID, msg.Encode()); err != nil { log.Printf("can't send sessionEnd to topic: %s; sessID: %d", err, sessionID) return false } diff --git a/backend/cmd/heuristics/main.go b/backend/cmd/heuristics/main.go index be27a86bd..9e4804089 100644 --- a/backend/cmd/heuristics/main.go +++ b/backend/cmd/heuristics/main.go @@ -2,7 +2,6 @@ package main import ( "log" - "openreplay/backend/pkg/queue/types" "os" "os/signal" "syscall" @@ -47,25 +46,18 @@ func main() { // Init producer and consumer for data bus producer := queue.NewProducer(cfg.MessageSizeLimit, true) - consumer := queue.NewMessageConsumer( + + msgHandler := func(msg messages.Message) { + statsLogger.Collect(msg) + builderMap.HandleMessage(msg) + } + + consumer := queue.NewConsumer( cfg.GroupHeuristics, []string{ cfg.TopicRawWeb, }, - func(sessionID uint64, iter messages.Iterator, meta *types.Meta) { - var lastMessageID uint64 - for iter.Next() { - statsLogger.Collect(sessionID, meta) - msg := iter.Message().Decode() - if msg == nil { - log.Printf("failed batch, sess: %d, lastIndex: %d", sessionID, lastMessageID) - continue - } - lastMessageID = msg.Meta().Index - builderMap.HandleMessage(sessionID, msg, iter.Message().Meta().Index) - } - iter.Close() - }, + messages.NewMessageIterator(msgHandler, nil, true), false, cfg.MessageSizeLimit, ) @@ -86,7 +78,7 @@ func main() { os.Exit(0) case <-tick: builderMap.IterateReadyMessages(func(sessionID uint64, readyMsg messages.Message) { - producer.Produce(cfg.TopicAnalytics, sessionID, messages.Encode(readyMsg)) + producer.Produce(cfg.TopicAnalytics, sessionID, readyMsg.Encode()) }) producer.Flush(cfg.ProducerTimeout) consumer.Commit() diff --git a/backend/cmd/integrations/main.go b/backend/cmd/integrations/main.go index 86490c6ab..4f5a30dcf 100644 --- a/backend/cmd/integrations/main.go +++ b/backend/cmd/integrations/main.go @@ -13,12 +13,10 @@ import ( "openreplay/backend/pkg/db/postgres" "openreplay/backend/pkg/intervals" - "openreplay/backend/pkg/messages" "openreplay/backend/pkg/queue" "openreplay/backend/pkg/token" ) -// func main() { metrics := monitoring.New("integrations") @@ -84,7 +82,7 @@ func main() { } sessionID = sessData.ID } - producer.Produce(cfg.TopicAnalytics, sessionID, messages.Encode(event.IntegrationEvent)) + producer.Produce(cfg.TopicAnalytics, sessionID, event.IntegrationEvent.Encode()) case err := <-manager.Errors: log.Printf("Integration error: %v\n", err) case i := <-manager.RequestDataUpdates: diff --git a/backend/cmd/sink/main.go b/backend/cmd/sink/main.go index bd7fddf20..a7e2804c4 100644 --- a/backend/cmd/sink/main.go +++ b/backend/cmd/sink/main.go @@ -3,7 +3,6 @@ package main import ( "context" "log" - "openreplay/backend/pkg/queue/types" "os" "os/signal" "syscall" @@ -11,15 +10,18 @@ import ( "openreplay/backend/internal/config/sink" "openreplay/backend/internal/sink/assetscache" - "openreplay/backend/internal/sink/oswriter" + "openreplay/backend/internal/sink/sessionwriter" "openreplay/backend/internal/storage" - . "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/messages" "openreplay/backend/pkg/monitoring" + "openreplay/backend/pkg/pprof" "openreplay/backend/pkg/queue" "openreplay/backend/pkg/url/assets" ) func main() { + pprof.StartProfilingServer() + metrics := monitoring.New("sink") log.SetFlags(log.LstdFlags | log.LUTC | log.Llongfile) @@ -30,14 +32,15 @@ func main() { log.Fatalf("%v doesn't exist. %v", cfg.FsDir, err) } - writer := oswriter.NewWriter(cfg.FsUlimit, cfg.FsDir) + writer := sessionwriter.NewWriter(cfg.FsUlimit, cfg.FsDir, cfg.FileBuffer, cfg.SyncTimeout) producer := queue.NewProducer(cfg.MessageSizeLimit, true) defer producer.Close(cfg.ProducerCloseTimeout) rewriter := assets.NewRewriter(cfg.AssetsOrigin) - assetMessageHandler := assetscache.New(cfg, rewriter, producer) + assetMessageHandler := assetscache.New(cfg, rewriter, producer, metrics) counter := storage.NewLogCounter() + // Session message metrics totalMessages, err := metrics.RegisterCounter("messages_total") if err != nil { log.Printf("can't create messages_total metric: %s", err) @@ -51,64 +54,70 @@ func main() { log.Printf("can't create messages_size metric: %s", err) } - consumer := queue.NewMessageConsumer( + msgHandler := func(msg messages.Message) { + // [METRICS] Increase the number of processed messages + totalMessages.Add(context.Background(), 1) + + // Send SessionEnd trigger to storage service + if msg.TypeID() == messages.MsgSessionEnd { + if err := producer.Produce(cfg.TopicTrigger, msg.SessionID(), msg.Encode()); err != nil { + log.Printf("can't send SessionEnd to trigger topic: %s; sessID: %d", err, msg.SessionID()) + } + writer.Close(msg.SessionID()) + return + } + + // Process assets + if msg.TypeID() == messages.MsgSetNodeAttributeURLBased || + msg.TypeID() == messages.MsgSetCSSDataURLBased || + msg.TypeID() == messages.MsgCSSInsertRuleURLBased || + msg.TypeID() == messages.MsgAdoptedSSReplaceURLBased || + msg.TypeID() == messages.MsgAdoptedSSInsertRuleURLBased { + m := msg.Decode() + if m == nil { + log.Printf("assets decode err, info: %s", msg.Meta().Batch().Info()) + return + } + msg = assetMessageHandler.ParseAssets(m) + } + + // Filter message + if !messages.IsReplayerType(msg.TypeID()) { + return + } + + // If message timestamp is empty, use at least ts of session start + ts := msg.Meta().Timestamp + if ts == 0 { + log.Printf("zero ts; sessID: %d, msgType: %d", msg.SessionID(), msg.TypeID()) + } else { + // Log ts of last processed message + counter.Update(msg.SessionID(), time.UnixMilli(ts)) + } + + // Try to encode message to avoid null data inserts + data := msg.Encode() + if data == nil { + return + } + + // Write message to file + if err := writer.Write(msg); err != nil { + log.Printf("writer error: %s", err) + return + } + + // [METRICS] Increase the number of written to the files messages and the message size + messageSize.Record(context.Background(), float64(len(msg.Encode()))) + savedMessages.Add(context.Background(), 1) + } + + consumer := queue.NewConsumer( cfg.GroupSink, []string{ cfg.TopicRawWeb, }, - func(sessionID uint64, iter Iterator, meta *types.Meta) { - for iter.Next() { - // [METRICS] Increase the number of processed messages - totalMessages.Add(context.Background(), 1) - - // Send SessionEnd trigger to storage service - if iter.Type() == MsgSessionEnd { - if err := producer.Produce(cfg.TopicTrigger, sessionID, iter.Message().Encode()); err != nil { - log.Printf("can't send SessionEnd to trigger topic: %s; sessID: %d", err, sessionID) - } - continue - } - - msg := iter.Message() - // Process assets - if iter.Type() == MsgSetNodeAttributeURLBased || - iter.Type() == MsgSetCSSDataURLBased || - iter.Type() == MsgCSSInsertRuleURLBased || - iter.Type() == MsgAdoptedSSReplaceURLBased || - iter.Type() == MsgAdoptedSSInsertRuleURLBased { - m := msg.Decode() - if m == nil { - return - } - msg = assetMessageHandler.ParseAssets(sessionID, m) // TODO: filter type only once (use iterator inide or bring ParseAssets out here). - } - - // Filter message - if !IsReplayerType(msg.TypeID()) { - continue - } - - // If message timestamp is empty, use at least ts of session start - ts := msg.Meta().Timestamp - if ts == 0 { - log.Printf("zero ts; sessID: %d, msgType: %d", sessionID, iter.Type()) - } else { - // Log ts of last processed message - counter.Update(sessionID, time.UnixMilli(ts)) - } - - // Write encoded message with index to session file - data := msg.EncodeWithIndex() - if err := writer.Write(sessionID, data); err != nil { - log.Printf("Writer error: %v\n", err) - } - - // [METRICS] Increase the number of written to the files messages and the message size - messageSize.Record(context.Background(), float64(len(data))) - savedMessages.Add(context.Background(), 1) - } - iter.Close() - }, + messages.NewMessageIterator(msgHandler, nil, false), false, cfg.MessageSizeLimit, ) @@ -117,24 +126,27 @@ func main() { sigchan := make(chan os.Signal, 1) signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) - tick := time.Tick(30 * time.Second) + tick := time.Tick(10 * time.Second) + tickInfo := time.Tick(30 * time.Second) for { select { case sig := <-sigchan: log.Printf("Caught signal %v: terminating\n", sig) + // Sync and stop writer + writer.Stop() + // Commit and stop consumer if err := consumer.Commit(); err != nil { log.Printf("can't commit messages: %s", err) } consumer.Close() os.Exit(0) case <-tick: - if err := writer.SyncAll(); err != nil { - log.Fatalf("Sync error: %v\n", err) - } - counter.Print() if err := consumer.Commit(); err != nil { log.Printf("can't commit messages: %s", err) } + case <-tickInfo: + counter.Print() + log.Printf("writer: %s", writer.Info()) default: err := consumer.ConsumeNext() if err != nil { @@ -142,5 +154,4 @@ func main() { } } } - } diff --git a/backend/cmd/storage/main.go b/backend/cmd/storage/main.go index b3848c5de..07c6eec91 100644 --- a/backend/cmd/storage/main.go +++ b/backend/cmd/storage/main.go @@ -2,10 +2,8 @@ package main import ( "log" - "openreplay/backend/pkg/queue/types" "os" "os/signal" - "strconv" "syscall" "time" @@ -38,24 +36,24 @@ func main() { log.Fatalf("can't init sessionFinder module: %s", err) } - consumer := queue.NewMessageConsumer( + consumer := queue.NewConsumer( cfg.GroupStorage, []string{ cfg.TopicTrigger, }, - func(sessionID uint64, iter messages.Iterator, meta *types.Meta) { - for iter.Next() { - if iter.Type() == messages.MsgSessionEnd { - msg := iter.Message().Decode().(*messages.SessionEnd) - if err := srv.UploadKey(strconv.FormatUint(sessionID, 10), 5); err != nil { - log.Printf("can't find session: %d", sessionID) - sessionFinder.Find(sessionID, msg.Timestamp) - } - // Log timestamp of last processed session - counter.Update(sessionID, time.UnixMilli(meta.Timestamp)) + messages.NewMessageIterator( + func(msg messages.Message) { + sesEnd := msg.(*messages.SessionEnd) + if err := srv.UploadSessionFiles(sesEnd); err != nil { + log.Printf("can't find session: %d", msg.SessionID()) + sessionFinder.Find(msg.SessionID(), sesEnd.Timestamp) } - } - }, + // Log timestamp of last processed session + counter.Update(msg.SessionID(), time.UnixMilli(msg.Meta().Batch().Timestamp())) + }, + []int{messages.MsgSessionEnd}, + true, + ), true, cfg.MessageSizeLimit, ) diff --git a/backend/go.mod b/backend/go.mod index e38e304a1..b1046b08e 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( cloud.google.com/go/logging v1.4.2 github.com/ClickHouse/clickhouse-go/v2 v2.2.0 + github.com/Masterminds/semver v1.5.0 github.com/aws/aws-sdk-go v1.44.98 github.com/btcsuite/btcutil v1.0.2 github.com/elastic/go-elasticsearch/v7 v7.13.1 @@ -68,8 +69,8 @@ require ( golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/text v0.4.0 // indirect golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect diff --git a/backend/go.sum b/backend/go.sum index 681b2b9d4..fea2aa1a3 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -64,6 +64,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/ClickHouse/clickhouse-go/v2 v2.2.0 h1:dj00TDKY+xwuTJdbpspCSmTLFyWzRJerTHwaBxut1C0= github.com/ClickHouse/clickhouse-go/v2 v2.2.0/go.mod h1:8f2XZUi7XoeU+uPIytSi1cvx8fmJxi7vIgqpvYTF1+o= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -676,8 +678,9 @@ golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -688,8 +691,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 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= diff --git a/backend/internal/assets/cacher/cacher.go b/backend/internal/assets/cacher/cacher.go index 619c28c7c..b56c97d74 100644 --- a/backend/internal/assets/cacher/cacher.go +++ b/backend/internal/assets/cacher/cacher.go @@ -33,6 +33,11 @@ type cacher struct { sizeLimit int downloadedAssets syncfloat64.Counter requestHeaders map[string]string + workers *WorkerPool +} + +func (c *cacher) CanCache() bool { + return c.workers.CanAddTask() } func NewCacher(cfg *config.Config, metrics *monitoring.Metrics) *cacher { @@ -44,7 +49,7 @@ func NewCacher(cfg *config.Config, metrics *monitoring.Metrics) *cacher { if err != nil { log.Printf("can't create downloaded_assets metric: %s", err) } - return &cacher{ + c := &cacher{ timeoutMap: newTimeoutMap(), s3: storage.NewS3(cfg.AWSRegion, cfg.S3BucketAssets), httpClient: &http.Client{ @@ -60,47 +65,48 @@ func NewCacher(cfg *config.Config, metrics *monitoring.Metrics) *cacher { downloadedAssets: downloadedAssets, requestHeaders: cfg.AssetsRequestHeaders, } + c.workers = NewPool(64, c.CacheFile) + return c } -func (c *cacher) cacheURL(requestURL string, sessionID uint64, depth byte, urlContext string, isJS bool) { - var cachePath string - if isJS { - cachePath = assets.GetCachePathForJS(requestURL) - } else { - cachePath = assets.GetCachePathForAssets(sessionID, requestURL) - } - if c.timeoutMap.contains(cachePath) { - return - } - c.timeoutMap.add(cachePath) - crTime := c.s3.GetCreationTime(cachePath) - if crTime != nil && crTime.After(time.Now().Add(-MAX_STORAGE_TIME)) { // recently uploaded - return - } +func (c *cacher) CacheFile(task *Task) { + c.cacheURL(task) +} - req, _ := http.NewRequest("GET", requestURL, nil) - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0") +func (c *cacher) cacheURL(t *Task) { + t.retries-- + req, _ := http.NewRequest("GET", t.requestURL, nil) + if t.retries%2 == 0 { + req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0") + } for k, v := range c.requestHeaders { req.Header.Set(k, v) } res, err := c.httpClient.Do(req) if err != nil { - c.Errors <- errors.Wrap(err, urlContext) + c.Errors <- errors.Wrap(err, t.urlContext) return } defer res.Body.Close() if res.StatusCode >= 400 { - // TODO: retry - c.Errors <- errors.Wrap(fmt.Errorf("Status code is %v, ", res.StatusCode), urlContext) + printErr := true + // Retry 403 error + if res.StatusCode == 403 && t.retries > 0 { + c.workers.AddTask(t) + printErr = false + } + if printErr { + c.Errors <- errors.Wrap(fmt.Errorf("Status code is %v, ", res.StatusCode), t.urlContext) + } return } data, err := ioutil.ReadAll(io.LimitReader(res.Body, int64(c.sizeLimit+1))) if err != nil { - c.Errors <- errors.Wrap(err, urlContext) + c.Errors <- errors.Wrap(err, t.urlContext) return } if len(data) > c.sizeLimit { - c.Errors <- errors.Wrap(errors.New("Maximum size exceeded"), urlContext) + c.Errors <- errors.Wrap(errors.New("Maximum size exceeded"), t.urlContext) return } @@ -112,44 +118,94 @@ func (c *cacher) cacheURL(requestURL string, sessionID uint64, depth byte, urlCo strData := string(data) if isCSS { - strData = c.rewriter.RewriteCSS(sessionID, requestURL, strData) // TODO: one method for rewrite and return list + strData = c.rewriter.RewriteCSS(t.sessionID, t.requestURL, strData) // TODO: one method for rewrite and return list } // TODO: implement in streams - err = c.s3.Upload(strings.NewReader(strData), cachePath, contentType, false) + err = c.s3.Upload(strings.NewReader(strData), t.cachePath, contentType, false) if err != nil { - c.Errors <- errors.Wrap(err, urlContext) + c.Errors <- errors.Wrap(err, t.urlContext) return } c.downloadedAssets.Add(context.Background(), 1) if isCSS { - if depth > 0 { + if t.depth > 0 { for _, extractedURL := range assets.ExtractURLsFromCSS(string(data)) { - if fullURL, cachable := assets.GetFullCachableURL(requestURL, extractedURL); cachable { - go c.cacheURL(fullURL, sessionID, depth-1, urlContext+"\n -> "+fullURL, false) + if fullURL, cachable := assets.GetFullCachableURL(t.requestURL, extractedURL); cachable { + c.checkTask(&Task{ + requestURL: fullURL, + sessionID: t.sessionID, + depth: t.depth - 1, + urlContext: t.urlContext + "\n -> " + fullURL, + isJS: false, + retries: setRetries(), + }) } } if err != nil { - c.Errors <- errors.Wrap(err, urlContext) + c.Errors <- errors.Wrap(err, t.urlContext) return } } else { - c.Errors <- errors.Wrap(errors.New("Maximum recursion cache depth exceeded"), urlContext) + c.Errors <- errors.Wrap(errors.New("Maximum recursion cache depth exceeded"), t.urlContext) return } } return } +func (c *cacher) checkTask(newTask *Task) { + // check if file was recently uploaded + var cachePath string + if newTask.isJS { + cachePath = assets.GetCachePathForJS(newTask.requestURL) + } else { + cachePath = assets.GetCachePathForAssets(newTask.sessionID, newTask.requestURL) + } + if c.timeoutMap.contains(cachePath) { + return + } + c.timeoutMap.add(cachePath) + crTime := c.s3.GetCreationTime(cachePath) + if crTime != nil && crTime.After(time.Now().Add(-MAX_STORAGE_TIME)) { + return + } + // add new file in queue to download + newTask.cachePath = cachePath + c.workers.AddTask(newTask) +} + func (c *cacher) CacheJSFile(sourceURL string) { - go c.cacheURL(sourceURL, 0, 0, sourceURL, true) + c.checkTask(&Task{ + requestURL: sourceURL, + sessionID: 0, + depth: 0, + urlContext: sourceURL, + isJS: true, + retries: setRetries(), + }) } func (c *cacher) CacheURL(sessionID uint64, fullURL string) { - go c.cacheURL(fullURL, sessionID, MAX_CACHE_DEPTH, fullURL, false) + c.checkTask(&Task{ + requestURL: fullURL, + sessionID: sessionID, + depth: MAX_CACHE_DEPTH, + urlContext: fullURL, + isJS: false, + retries: setRetries(), + }) } func (c *cacher) UpdateTimeouts() { c.timeoutMap.deleteOutdated() } + +func (c *cacher) Stop() { + c.workers.Stop() +} + +func setRetries() int { + return 10 +} diff --git a/backend/internal/assets/cacher/pool.go b/backend/internal/assets/cacher/pool.go new file mode 100644 index 000000000..15ccb74b0 --- /dev/null +++ b/backend/internal/assets/cacher/pool.go @@ -0,0 +1,80 @@ +package cacher + +import ( + "log" + "sync" +) + +type Task struct { + requestURL string + sessionID uint64 + depth byte + urlContext string + isJS bool + cachePath string + retries int +} + +type WorkerPool struct { + tasks chan *Task + wg sync.WaitGroup + done chan struct{} + term sync.Once + size int + job Job +} + +func (p *WorkerPool) CanAddTask() bool { + if len(p.tasks) < cap(p.tasks) { + return true + } + return false +} + +type Job func(task *Task) + +func NewPool(size int, job Job) *WorkerPool { + newPool := &WorkerPool{ + tasks: make(chan *Task, 128), + done: make(chan struct{}), + size: size, + job: job, + } + newPool.init() + return newPool +} + +func (p *WorkerPool) init() { + p.wg.Add(p.size) + for i := 0; i < p.size; i++ { + go p.worker() + } +} + +func (p *WorkerPool) worker() { + for { + select { + case newTask := <-p.tasks: + p.job(newTask) + case <-p.done: + p.wg.Done() + return + } + } +} + +func (p *WorkerPool) AddTask(task *Task) { + if task.retries <= 0 { + return + } + p.tasks <- task +} + +func (p *WorkerPool) Stop() { + log.Printf("stopping workers") + p.term.Do(func() { + close(p.done) + }) + p.wg.Wait() + log.Printf("all workers have been stopped") +} diff --git a/backend/internal/config/configurator/configurator.go b/backend/internal/config/configurator/configurator.go index 3ffa8f7d7..1b459335d 100644 --- a/backend/internal/config/configurator/configurator.go +++ b/backend/internal/config/configurator/configurator.go @@ -17,9 +17,6 @@ import ( ) func readFile(path string) (map[string]string, error) { - if path == "" { - return nil, fmt.Errorf("file path is empty") - } file, err := os.Open(path) if err != nil { return nil, fmt.Errorf("can't open file: %s", err) @@ -33,13 +30,23 @@ func readFile(path string) (map[string]string, error) { res := make(map[string]string) lines := strings.Split(string(data), "\n") for _, line := range lines { + if len(line) == 0 { + continue + } env := strings.Split(line, "=") + if len(env) < 2 { + continue + } res[env[0]] = env[1] } return res, nil } func parseFile(a interface{}, path string) { + // Skip parsing process without logs if we don't have path to config file + if path == "" { + return + } envs, err := readFile(path) if err != nil { log.Printf("can't parse config file: %s", err) diff --git a/backend/internal/config/ender/config.go b/backend/internal/config/ender/config.go index 64c07eb7c..fb315acbe 100644 --- a/backend/internal/config/ender/config.go +++ b/backend/internal/config/ender/config.go @@ -14,6 +14,7 @@ type Config struct { TopicRawWeb string `env:"TOPIC_RAW_WEB,required"` ProducerTimeout int `env:"PRODUCER_TIMEOUT,default=2000"` PartitionsNumber int `env:"PARTITIONS_NUMBER,required"` + UseEncryption bool `env:"USE_ENCRYPTION,default=false"` } func New() *Config { diff --git a/backend/internal/config/sink/config.go b/backend/internal/config/sink/config.go index 215484082..1a2df142e 100644 --- a/backend/internal/config/sink/config.go +++ b/backend/internal/config/sink/config.go @@ -9,6 +9,8 @@ type Config struct { common.Config FsDir string `env:"FS_DIR,required"` FsUlimit uint16 `env:"FS_ULIMIT,required"` + FileBuffer int `env:"FILE_BUFFER,default=32768"` + SyncTimeout int `env:"SYNC_TIMEOUT,default=5"` GroupSink string `env:"GROUP_SINK,required"` TopicRawWeb string `env:"TOPIC_RAW_WEB,required"` TopicRawIOS string `env:"TOPIC_RAW_IOS,required"` @@ -17,6 +19,8 @@ type Config struct { CacheAssets bool `env:"CACHE_ASSETS,required"` AssetsOrigin string `env:"ASSETS_ORIGIN,required"` ProducerCloseTimeout int `env:"PRODUCER_CLOSE_TIMEOUT,default=15000"` + CacheThreshold int64 `env:"CACHE_THRESHOLD,default=5"` + CacheExpiration int64 `env:"CACHE_EXPIRATION,default=120"` } func New() *Config { diff --git a/backend/internal/config/storage/config.go b/backend/internal/config/storage/config.go index fdf29b7db..6083f0249 100644 --- a/backend/internal/config/storage/config.go +++ b/backend/internal/config/storage/config.go @@ -11,7 +11,6 @@ type Config struct { S3Region string `env:"AWS_REGION_WEB,required"` S3Bucket string `env:"S3_BUCKET_WEB,required"` FSDir string `env:"FS_DIR,required"` - FSCleanHRS int `env:"FS_CLEAN_HRS,required"` FileSplitSize int `env:"FILE_SPLIT_SIZE,required"` RetryTimeout time.Duration `env:"RETRY_TIMEOUT,default=2m"` GroupStorage string `env:"GROUP_STORAGE,required"` @@ -21,6 +20,7 @@ type Config struct { DeleteTimeout time.Duration `env:"DELETE_TIMEOUT,default=48h"` ProducerCloseTimeout int `env:"PRODUCER_CLOSE_TIMEOUT,default=15000"` UseFailover bool `env:"USE_FAILOVER,default=false"` + MaxFileSize int64 `env:"MAX_FILE_SIZE,default=524288000"` } func New() *Config { diff --git a/backend/internal/db/datasaver/messages.go b/backend/internal/db/datasaver/messages.go index 702c2f210..621659c6d 100644 --- a/backend/internal/db/datasaver/messages.go +++ b/backend/internal/db/datasaver/messages.go @@ -5,7 +5,8 @@ import ( . "openreplay/backend/pkg/messages" ) -func (mi *Saver) InsertMessage(sessionID uint64, msg Message) error { +func (mi *Saver) InsertMessage(msg Message) error { + sessionID := msg.SessionID() switch m := msg.(type) { // Common case *Metadata: @@ -37,23 +38,16 @@ func (mi *Saver) InsertMessage(sessionID uint64, msg Message) error { case *PageEvent: mi.sendToFTS(msg, sessionID) return mi.pg.InsertWebPageEvent(sessionID, m) - case *ErrorEvent: - return mi.pg.InsertWebErrorEvent(sessionID, m) case *FetchEvent: mi.sendToFTS(msg, sessionID) return mi.pg.InsertWebFetchEvent(sessionID, m) case *GraphQLEvent: mi.sendToFTS(msg, sessionID) return mi.pg.InsertWebGraphQLEvent(sessionID, m) + case *JSException: + return mi.pg.InsertWebJSException(m) case *IntegrationEvent: - return mi.pg.InsertWebErrorEvent(sessionID, &ErrorEvent{ - MessageID: m.Meta().Index, - Timestamp: m.Timestamp, - Source: m.Source, - Name: m.Name, - Message: m.Message, - Payload: m.Payload, - }) + return mi.pg.InsertWebIntegrationEvent(m) // IOS case *IOSSessionStart: diff --git a/backend/internal/db/datasaver/stats.go b/backend/internal/db/datasaver/stats.go index 17028ca5c..b523ecdbe 100644 --- a/backend/internal/db/datasaver/stats.go +++ b/backend/internal/db/datasaver/stats.go @@ -16,12 +16,10 @@ func (si *Saver) InsertStats(session *Session, msg Message) error { return si.pg.InsertWebStatsPerformance(session.SessionID, m) case *ResourceEvent: return si.pg.InsertWebStatsResourceEvent(session.SessionID, m) - case *LongTask: - return si.pg.InsertWebStatsLongtask(session.SessionID, m) } return nil } -func (si *Saver) CommitStats(optimize bool) error { +func (si *Saver) CommitStats() error { return nil } diff --git a/backend/internal/http/router/handlers-ios.go b/backend/internal/http/router/handlers-ios.go index 43fd0a7a9..e0fc73b6f 100644 --- a/backend/internal/http/router/handlers-ios.go +++ b/backend/internal/http/router/handlers-ios.go @@ -69,12 +69,12 @@ func (e *Router) startSessionHandlerIOS(w http.ResponseWriter, r *http.Request) } // TODO: if EXPIRED => send message for two sessions association expTime := startTime.Add(time.Duration(p.MaxSessionDuration) * time.Millisecond) - tokenData = &token.TokenData{sessionID, expTime.UnixMilli()} + tokenData = &token.TokenData{sessionID, 0, expTime.UnixMilli()} country := e.services.GeoIP.ExtractISOCodeFromHTTPRequest(r) // The difference with web is mostly here: - e.services.Producer.Produce(e.cfg.TopicRawIOS, tokenData.ID, Encode(&IOSSessionStart{ + sessStart := &IOSSessionStart{ Timestamp: req.Timestamp, ProjectID: uint64(p.ProjectID), TrackerVersion: req.TrackerVersion, @@ -85,7 +85,8 @@ func (e *Router) startSessionHandlerIOS(w http.ResponseWriter, r *http.Request) UserDevice: ios.MapIOSDevice(req.UserDevice), UserDeviceType: ios.GetIOSDeviceType(req.UserDevice), UserCountry: country, - })) + } + e.services.Producer.Produce(e.cfg.TopicRawIOS, tokenData.ID, sessStart.Encode()) } ResponseWithJSON(w, &StartIOSSessionResponse{ diff --git a/backend/internal/http/router/handlers-web.go b/backend/internal/http/router/handlers-web.go index 04728de4e..08c4c75c5 100644 --- a/backend/internal/http/router/handlers-web.go +++ b/backend/internal/http/router/handlers-web.go @@ -3,6 +3,7 @@ package router import ( "encoding/json" "errors" + "github.com/Masterminds/semver" "go.opentelemetry.io/otel/attribute" "io" "log" @@ -37,6 +38,22 @@ func (e *Router) readBody(w http.ResponseWriter, r *http.Request, limit int64) ( return bodyBytes, nil } +func getSessionTimestamp(req *StartSessionRequest, startTimeMili int64) (ts uint64) { + ts = uint64(req.Timestamp) + c, err := semver.NewConstraint(">=4.1.6") + if err != nil { + return + } + v, err := semver.NewVersion(req.TrackerVersion) + if err != nil { + return + } + if c.Check(v) { + return uint64(startTimeMili) + } + return +} + func (e *Router) startSessionHandlerWeb(w http.ResponseWriter, r *http.Request) { startTime := time.Now() @@ -91,17 +108,22 @@ func (e *Router) startSessionHandlerWeb(w http.ResponseWriter, r *http.Request) ResponseWithError(w, http.StatusForbidden, errors.New("browser not recognized")) return } - sessionID, err := e.services.Flaker.Compose(uint64(startTime.UnixMilli())) + startTimeMili := startTime.UnixMilli() + sessionID, err := e.services.Flaker.Compose(uint64(startTimeMili)) if err != nil { ResponseWithError(w, http.StatusInternalServerError, err) return } // TODO: if EXPIRED => send message for two sessions association expTime := startTime.Add(time.Duration(p.MaxSessionDuration) * time.Millisecond) - tokenData = &token.TokenData{ID: sessionID, ExpTime: expTime.UnixMilli()} + tokenData = &token.TokenData{ + ID: sessionID, + Delay: startTimeMili - req.Timestamp, + ExpTime: expTime.UnixMilli(), + } sessionStart := &SessionStart{ - Timestamp: req.Timestamp, + Timestamp: getSessionTimestamp(req, startTimeMili), ProjectID: uint64(p.ProjectID), TrackerVersion: req.TrackerVersion, RevID: req.RevID, @@ -125,7 +147,7 @@ func (e *Router) startSessionHandlerWeb(w http.ResponseWriter, r *http.Request) } // Send sessionStart message to kafka - if err := e.services.Producer.Produce(e.cfg.TopicRawWeb, tokenData.ID, Encode(sessionStart)); err != nil { + if err := e.services.Producer.Produce(e.cfg.TopicRawWeb, tokenData.ID, sessionStart.Encode()); err != nil { log.Printf("can't send session start: %s", err) } } @@ -137,6 +159,7 @@ func (e *Router) startSessionHandlerWeb(w http.ResponseWriter, r *http.Request) ProjectID: strconv.FormatUint(uint64(p.ProjectID), 10), BeaconSizeLimit: e.cfg.BeaconSizeLimit, StartTimestamp: int64(flakeid.ExtractTimestamp(tokenData.ID)), + Delay: tokenData.Delay, }) } diff --git a/backend/internal/http/router/model.go b/backend/internal/http/router/model.go index 42a500c06..b2ddfd9b4 100644 --- a/backend/internal/http/router/model.go +++ b/backend/internal/http/router/model.go @@ -4,7 +4,7 @@ type StartSessionRequest struct { Token string `json:"token"` UserUUID *string `json:"userUUID"` RevID string `json:"revID"` - Timestamp uint64 `json:"timestamp"` + Timestamp int64 `json:"timestamp"` TrackerVersion string `json:"trackerVersion"` IsSnippet bool `json:"isSnippet"` DeviceMemory uint64 `json:"deviceMemory"` diff --git a/backend/internal/sessionender/ender.go b/backend/internal/sessionender/ender.go index 2f8e1e1ba..dbd3eb901 100644 --- a/backend/internal/sessionender/ender.go +++ b/backend/internal/sessionender/ender.go @@ -5,6 +5,8 @@ import ( "fmt" "go.opentelemetry.io/otel/metric/instrument/syncfloat64" "log" + log2 "openreplay/backend/pkg/log" + "openreplay/backend/pkg/messages" "openreplay/backend/pkg/monitoring" "time" ) @@ -27,9 +29,10 @@ type SessionEnder struct { timeCtrl *timeController activeSessions syncfloat64.UpDownCounter totalSessions syncfloat64.Counter + stats log2.QueueStats } -func New(metrics *monitoring.Metrics, timeout int64, parts int) (*SessionEnder, error) { +func New(metrics *monitoring.Metrics, timeout int64, parts int, stats log2.QueueStats) (*SessionEnder, error) { if metrics == nil { return nil, fmt.Errorf("metrics module is empty") } @@ -48,24 +51,31 @@ func New(metrics *monitoring.Metrics, timeout int64, parts int) (*SessionEnder, timeCtrl: NewTimeController(parts), activeSessions: activeSessions, totalSessions: totalSessions, + stats: stats, }, nil } // UpdateSession save timestamp for new sessions and update for existing sessions -func (se *SessionEnder) UpdateSession(sessionID uint64, timestamp, msgTimestamp int64) { - localTS := time.Now().UnixMilli() - currTS := timestamp - if currTS == 0 { +func (se *SessionEnder) UpdateSession(msg messages.Message) { + se.stats.Collect(msg) + var ( + sessionID = msg.Meta().SessionID() + batchTimestamp = msg.Meta().Batch().Timestamp() + msgTimestamp = msg.Meta().Timestamp + localTimestamp = time.Now().UnixMilli() + ) + if batchTimestamp == 0 { log.Printf("got empty timestamp for sessionID: %d", sessionID) return } - se.timeCtrl.UpdateTime(sessionID, currTS) + se.timeCtrl.UpdateTime(sessionID, batchTimestamp) sess, ok := se.sessions[sessionID] if !ok { + // Register new session se.sessions[sessionID] = &session{ - lastTimestamp: currTS, // timestamp from message broker - lastUpdate: localTS, // local timestamp - lastUserTime: msgTimestamp, // last timestamp from user's machine + lastTimestamp: batchTimestamp, // timestamp from message broker + lastUpdate: localTimestamp, // local timestamp + lastUserTime: msgTimestamp, // last timestamp from user's machine isEnded: false, } se.activeSessions.Add(context.Background(), 1) @@ -77,9 +87,9 @@ func (se *SessionEnder) UpdateSession(sessionID uint64, timestamp, msgTimestamp sess.lastUserTime = msgTimestamp } // Keep information about the latest message for generating sessionEnd trigger - if currTS > sess.lastTimestamp { - sess.lastTimestamp = currTS - sess.lastUpdate = localTS + if batchTimestamp > sess.lastTimestamp { + sess.lastTimestamp = batchTimestamp + sess.lastUpdate = localTimestamp sess.isEnded = false } } diff --git a/backend/internal/sink/assetscache/assets.go b/backend/internal/sink/assetscache/assets.go index 8218af4e6..aa2dccbba 100644 --- a/backend/internal/sink/assetscache/assets.go +++ b/backend/internal/sink/assetscache/assets.go @@ -1,35 +1,111 @@ package assetscache import ( + "context" + "crypto/md5" + "go.opentelemetry.io/otel/metric/instrument/syncfloat64" + "io" "log" + "net/url" "openreplay/backend/internal/config/sink" "openreplay/backend/pkg/messages" + "openreplay/backend/pkg/monitoring" "openreplay/backend/pkg/queue/types" "openreplay/backend/pkg/url/assets" + "sync" + "time" ) -type AssetsCache struct { - cfg *sink.Config - rewriter *assets.Rewriter - producer types.Producer +type CachedAsset struct { + msg string + ts time.Time } -func New(cfg *sink.Config, rewriter *assets.Rewriter, producer types.Producer) *AssetsCache { - return &AssetsCache{ - cfg: cfg, - rewriter: rewriter, - producer: producer, +type AssetsCache struct { + mutex sync.RWMutex + cfg *sink.Config + rewriter *assets.Rewriter + producer types.Producer + cache map[string]*CachedAsset + totalAssets syncfloat64.Counter + cachedAssets syncfloat64.Counter + skippedAssets syncfloat64.Counter + assetSize syncfloat64.Histogram + assetDuration syncfloat64.Histogram +} + +func New(cfg *sink.Config, rewriter *assets.Rewriter, producer types.Producer, metrics *monitoring.Metrics) *AssetsCache { + // Assets metrics + totalAssets, err := metrics.RegisterCounter("assets_total") + if err != nil { + log.Printf("can't create assets_total metric: %s", err) + } + cachedAssets, err := metrics.RegisterCounter("assets_cached") + if err != nil { + log.Printf("can't create assets_cached metric: %s", err) + } + skippedAssets, err := metrics.RegisterCounter("assets_skipped") + if err != nil { + log.Printf("can't create assets_skipped metric: %s", err) + } + assetSize, err := metrics.RegisterHistogram("asset_size") + if err != nil { + log.Printf("can't create asset_size metric: %s", err) + } + assetDuration, err := metrics.RegisterHistogram("asset_duration") + if err != nil { + log.Printf("can't create asset_duration metric: %s", err) + } + assetsCache := &AssetsCache{ + cfg: cfg, + rewriter: rewriter, + producer: producer, + cache: make(map[string]*CachedAsset, 64), + totalAssets: totalAssets, + cachedAssets: cachedAssets, + skippedAssets: skippedAssets, + assetSize: assetSize, + assetDuration: assetDuration, + } + go assetsCache.cleaner() + return assetsCache +} + +func (e *AssetsCache) cleaner() { + cleanTick := time.Tick(time.Minute * 30) + for { + select { + case <-cleanTick: + e.clearCache() + } } } -func (e *AssetsCache) ParseAssets(sessID uint64, msg messages.Message) messages.Message { +func (e *AssetsCache) clearCache() { + e.mutex.Lock() + defer e.mutex.Unlock() + + now := time.Now() + cacheSize := len(e.cache) + deleted := 0 + + for id, cache := range e.cache { + if int64(now.Sub(cache.ts).Minutes()) > e.cfg.CacheExpiration { + deleted++ + delete(e.cache, id) + } + } + log.Printf("cache cleaner: deleted %d/%d assets", deleted, cacheSize) +} + +func (e *AssetsCache) ParseAssets(msg messages.Message) messages.Message { switch m := msg.(type) { case *messages.SetNodeAttributeURLBased: if m.Name == "src" || m.Name == "href" { newMsg := &messages.SetNodeAttribute{ ID: m.ID, Name: m.Name, - Value: e.handleURL(sessID, m.BaseURL, m.Value), + Value: e.handleURL(m.SessionID(), m.BaseURL, m.Value), } newMsg.SetMeta(msg.Meta()) return newMsg @@ -37,7 +113,7 @@ func (e *AssetsCache) ParseAssets(sessID uint64, msg messages.Message) messages. newMsg := &messages.SetNodeAttribute{ ID: m.ID, Name: m.Name, - Value: e.handleCSS(sessID, m.BaseURL, m.Value), + Value: e.handleCSS(m.SessionID(), m.BaseURL, m.Value), } newMsg.SetMeta(msg.Meta()) return newMsg @@ -45,7 +121,7 @@ func (e *AssetsCache) ParseAssets(sessID uint64, msg messages.Message) messages. case *messages.SetCSSDataURLBased: newMsg := &messages.SetCSSData{ ID: m.ID, - Data: e.handleCSS(sessID, m.BaseURL, m.Data), + Data: e.handleCSS(m.SessionID(), m.BaseURL, m.Data), } newMsg.SetMeta(msg.Meta()) return newMsg @@ -53,14 +129,14 @@ func (e *AssetsCache) ParseAssets(sessID uint64, msg messages.Message) messages. newMsg := &messages.CSSInsertRule{ ID: m.ID, Index: m.Index, - Rule: e.handleCSS(sessID, m.BaseURL, m.Rule), + Rule: e.handleCSS(m.SessionID(), m.BaseURL, m.Rule), } newMsg.SetMeta(msg.Meta()) return newMsg case *messages.AdoptedSSReplaceURLBased: newMsg := &messages.AdoptedSSReplace{ SheetID: m.SheetID, - Text: e.handleCSS(sessID, m.BaseURL, m.Text), + Text: e.handleCSS(m.SessionID(), m.BaseURL, m.Text), } newMsg.SetMeta(msg.Meta()) return newMsg @@ -68,7 +144,7 @@ func (e *AssetsCache) ParseAssets(sessID uint64, msg messages.Message) messages. newMsg := &messages.AdoptedSSInsertRule{ SheetID: m.SheetID, Index: m.Index, - Rule: e.handleCSS(sessID, m.BaseURL, m.Rule), + Rule: e.handleCSS(m.SessionID(), m.BaseURL, m.Rule), } newMsg.SetMeta(msg.Meta()) return newMsg @@ -78,10 +154,11 @@ func (e *AssetsCache) ParseAssets(sessID uint64, msg messages.Message) messages. func (e *AssetsCache) sendAssetForCache(sessionID uint64, baseURL string, relativeURL string) { if fullURL, cacheable := assets.GetFullCachableURL(baseURL, relativeURL); cacheable { + assetMessage := &messages.AssetCache{URL: fullURL} if err := e.producer.Produce( e.cfg.TopicCache, sessionID, - messages.Encode(&messages.AssetCache{URL: fullURL}), + assetMessage.Encode(), ); err != nil { log.Printf("can't send asset to cache topic, sessID: %d, err: %s", sessionID, err) } @@ -94,18 +171,72 @@ func (e *AssetsCache) sendAssetsForCacheFromCSS(sessionID uint64, baseURL string } } -func (e *AssetsCache) handleURL(sessionID uint64, baseURL string, url string) string { +func (e *AssetsCache) handleURL(sessionID uint64, baseURL string, urlVal string) string { if e.cfg.CacheAssets { - e.sendAssetForCache(sessionID, baseURL, url) - return e.rewriter.RewriteURL(sessionID, baseURL, url) + e.sendAssetForCache(sessionID, baseURL, urlVal) + return e.rewriter.RewriteURL(sessionID, baseURL, urlVal) + } else { + return assets.ResolveURL(baseURL, urlVal) } - return assets.ResolveURL(baseURL, url) } func (e *AssetsCache) handleCSS(sessionID uint64, baseURL string, css string) string { + ctx := context.Background() + e.totalAssets.Add(ctx, 1) + // Try to find asset in cache + h := md5.New() + // Cut first part of url (scheme + host) + u, err := url.Parse(baseURL) + if err != nil { + log.Printf("can't parse url: %s, err: %s", baseURL, err) + if e.cfg.CacheAssets { + e.sendAssetsForCacheFromCSS(sessionID, baseURL, css) + } + return e.getRewrittenCSS(sessionID, baseURL, css) + } + justUrl := u.Scheme + "://" + u.Host + "/" + // Calculate hash sum of url + css + io.WriteString(h, justUrl) + io.WriteString(h, css) + hash := string(h.Sum(nil)) + // Check the resulting hash in cache + e.mutex.RLock() + cachedAsset, ok := e.cache[hash] + e.mutex.RUnlock() + if ok { + if int64(time.Now().Sub(cachedAsset.ts).Minutes()) < e.cfg.CacheExpiration { + e.skippedAssets.Add(ctx, 1) + return cachedAsset.msg + } + } + // Send asset to download in assets service if e.cfg.CacheAssets { e.sendAssetsForCacheFromCSS(sessionID, baseURL, css) - return e.rewriter.RewriteCSS(sessionID, baseURL, css) } - return assets.ResolveCSS(baseURL, css) + // Rewrite asset + start := time.Now() + res := e.getRewrittenCSS(sessionID, baseURL, css) + duration := time.Now().Sub(start).Milliseconds() + e.assetSize.Record(ctx, float64(len(res))) + e.assetDuration.Record(ctx, float64(duration)) + // Save asset to cache if we spent more than threshold + if duration > e.cfg.CacheThreshold { + e.mutex.Lock() + e.cache[hash] = &CachedAsset{ + msg: res, + ts: time.Now(), + } + e.mutex.Unlock() + e.cachedAssets.Add(ctx, 1) + } + // Return rewritten asset + return res +} + +func (e *AssetsCache) getRewrittenCSS(sessionID uint64, url, css string) string { + if e.cfg.CacheAssets { + return e.rewriter.RewriteCSS(sessionID, url, css) + } else { + return assets.ResolveCSS(url, css) + } } diff --git a/backend/internal/sink/oswriter/oswriter.go b/backend/internal/sink/oswriter/oswriter.go deleted file mode 100644 index 4feb3e2aa..000000000 --- a/backend/internal/sink/oswriter/oswriter.go +++ /dev/null @@ -1,100 +0,0 @@ -package oswriter - -import ( - "math" - "os" - "strconv" - "time" -) - -type Writer struct { - ulimit int - dir string - files map[uint64]*os.File - atimes map[uint64]int64 -} - -func NewWriter(ulimit uint16, dir string) *Writer { - return &Writer{ - ulimit: int(ulimit), - dir: dir + "/", - files: make(map[uint64]*os.File), - atimes: make(map[uint64]int64), - } -} - -func (w *Writer) open(key uint64) (*os.File, error) { - file, ok := w.files[key] - if ok { - return file, nil - } - if len(w.atimes) == w.ulimit { - var m_k uint64 - var m_t int64 = math.MaxInt64 - for k, t := range w.atimes { - if t < m_t { - m_k = k - m_t = t - } - } - if err := w.Close(m_k); err != nil { - return nil, err - } - } - file, err := os.OpenFile(w.dir+strconv.FormatUint(key, 10), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) - if err != nil { - return nil, err - } - w.files[key] = file - w.atimes[key] = time.Now().Unix() - return file, nil -} - -func (w *Writer) Close(key uint64) error { - file := w.files[key] - if file == nil { - return nil - } - if err := file.Sync(); err != nil { - return err - } - if err := file.Close(); err != nil { - return err - } - delete(w.files, key) - delete(w.atimes, key) - return nil -} - -func (w *Writer) Write(key uint64, data []byte) error { - file, err := w.open(key) - if err != nil { - return err - } - // TODO: add check for the number of recorded bytes to file - _, err = file.Write(data) - return err -} - -func (w *Writer) SyncAll() error { - for _, file := range w.files { - if err := file.Sync(); err != nil { - return err - } - } - return nil -} - -func (w *Writer) CloseAll() error { - for _, file := range w.files { - if err := file.Sync(); err != nil { - return err - } - if err := file.Close(); err != nil { - return err - } - } - w.files = nil - w.atimes = nil - return nil -} diff --git a/backend/internal/sink/sessionwriter/file.go b/backend/internal/sink/sessionwriter/file.go new file mode 100644 index 000000000..1ad076d72 --- /dev/null +++ b/backend/internal/sink/sessionwriter/file.go @@ -0,0 +1,57 @@ +package sessionwriter + +import ( + "bufio" + "os" +) + +type File struct { + file *os.File + buffer *bufio.Writer + updated bool +} + +func NewFile(path string, bufSize int) (*File, error) { + file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + return nil, err + } + return &File{ + file: file, + buffer: bufio.NewWriterSize(file, bufSize), + updated: false, + }, nil +} + +func (f *File) Write(data []byte) error { + leftToWrite := len(data) + for leftToWrite > 0 { + writtenDown, err := f.buffer.Write(data) + if err != nil { + return err + } + leftToWrite -= writtenDown + } + f.updated = true + return nil +} + +func (f *File) Sync() error { + if !f.updated { + return nil + } + if err := f.buffer.Flush(); err != nil { + return err + } + if err := f.file.Sync(); err != nil { + return err + } + f.updated = false + return nil +} + +func (f *File) Close() error { + _ = f.buffer.Flush() + _ = f.file.Sync() + return f.file.Close() +} diff --git a/backend/internal/sink/sessionwriter/meta.go b/backend/internal/sink/sessionwriter/meta.go new file mode 100644 index 000000000..4fac56e50 --- /dev/null +++ b/backend/internal/sink/sessionwriter/meta.go @@ -0,0 +1,56 @@ +package sessionwriter + +import ( + "math" + "sync" + "time" +) + +type Meta struct { + limit int + lock *sync.Mutex + meta map[uint64]int64 +} + +func NewMeta(limit int) *Meta { + return &Meta{ + limit: limit, + lock: &sync.Mutex{}, + meta: make(map[uint64]int64, limit), + } +} + +func (m *Meta) Add(sid uint64) { + m.lock.Lock() + m.meta[sid] = time.Now().Unix() + m.lock.Unlock() +} + +func (m *Meta) Count() int { + m.lock.Lock() + defer m.lock.Unlock() + return len(m.meta) +} + +func (m *Meta) Delete(sid uint64) { + m.lock.Lock() + delete(m.meta, sid) + m.lock.Unlock() +} + +func (m *Meta) GetExtra() uint64 { + m.lock.Lock() + defer m.lock.Unlock() + if len(m.meta) >= m.limit { + var extraSessID uint64 + var minTimestamp int64 = math.MaxInt64 + for sessID, timestamp := range m.meta { + if timestamp < minTimestamp { + extraSessID = sessID + minTimestamp = timestamp + } + } + return extraSessID + } + return 0 +} diff --git a/backend/internal/sink/sessionwriter/session.go b/backend/internal/sink/sessionwriter/session.go new file mode 100644 index 000000000..8cf8881de --- /dev/null +++ b/backend/internal/sink/sessionwriter/session.go @@ -0,0 +1,96 @@ +package sessionwriter + +import ( + "encoding/binary" + "fmt" + "strconv" + "sync" + + "openreplay/backend/pkg/messages" +) + +type Session struct { + lock *sync.Mutex + dom *File + dev *File + index []byte + updated bool +} + +func NewSession(sessID uint64, workDir string, bufSize int) (*Session, error) { + if sessID == 0 { + return nil, fmt.Errorf("wrong session id") + } + filePath := workDir + strconv.FormatUint(sessID, 10) + + dom, err := NewFile(filePath, bufSize) + if err != nil { + return nil, err + } + dev, err := NewFile(filePath+"devtools", bufSize) + if err != nil { + dom.Close() + return nil, err + } + + return &Session{ + lock: &sync.Mutex{}, + dom: dom, + dev: dev, + index: make([]byte, 8), + updated: false, + }, nil +} + +func (s *Session) Write(msg messages.Message) error { + s.lock.Lock() + defer s.lock.Unlock() + + // Encode message index + binary.LittleEndian.PutUint64(s.index, msg.Meta().Index) + + // Write message to dom.mob file + if messages.IsDOMType(msg.TypeID()) { + // Write message index + if err := s.dom.Write(s.index); err != nil { + return err + } + // Write message body + if err := s.dom.Write(msg.Encode()); err != nil { + return err + } + } + s.updated = true + // Write message to dev.mob file + if !messages.IsDOMType(msg.TypeID()) || msg.TypeID() == messages.MsgTimestamp { + // Write message index + if err := s.dev.Write(s.index); err != nil { + return err + } + // Write message body + if err := s.dev.Write(msg.Encode()); err != nil { + return err + } + } + return nil +} + +func (s *Session) Sync() error { + s.lock.Lock() + defer s.lock.Unlock() + + if err := s.dom.Sync(); err != nil { + return err + } + return s.dev.Sync() +} + +func (s *Session) Close() error { + s.lock.Lock() + defer s.lock.Unlock() + + if err := s.dom.Close(); err != nil { + return err + } + return s.dev.Close() +} diff --git a/backend/internal/sink/sessionwriter/writer.go b/backend/internal/sink/sessionwriter/writer.go new file mode 100644 index 000000000..f2eb052c7 --- /dev/null +++ b/backend/internal/sink/sessionwriter/writer.go @@ -0,0 +1,122 @@ +package sessionwriter + +import ( + "fmt" + "log" + "sync" + "time" + + "openreplay/backend/pkg/messages" +) + +type SessionWriter struct { + filesLimit int + workingDir string + fileBuffer int + syncTimeout time.Duration + meta *Meta + sessions *sync.Map + done chan struct{} + stopped chan struct{} +} + +func NewWriter(filesLimit uint16, workingDir string, fileBuffer int, syncTimeout int) *SessionWriter { + w := &SessionWriter{ + filesLimit: int(filesLimit) / 2, // should divide by 2 because each session has 2 files + workingDir: workingDir + "/", + fileBuffer: fileBuffer, + syncTimeout: time.Duration(syncTimeout) * time.Second, + meta: NewMeta(int(filesLimit)), + sessions: &sync.Map{}, + done: make(chan struct{}), + stopped: make(chan struct{}), + } + go w.synchronizer() + return w +} + +func (w *SessionWriter) Write(msg messages.Message) (err error) { + var ( + sess *Session + sid = msg.SessionID() + ) + + // Load session + sessObj, ok := w.sessions.Load(sid) + if !ok { + // Create new session + sess, err = NewSession(sid, w.workingDir, w.fileBuffer) + if err != nil { + return fmt.Errorf("can't create session: %d, err: %s", sid, err) + } + + // Check opened sessions limit and close extra session if you need to + if extraSessID := w.meta.GetExtra(); extraSessID != 0 { + if err := w.Close(extraSessID); err != nil { + log.Printf("can't close session: %s", err) + } + } + + // Add created session + w.sessions.Store(sid, sess) + w.meta.Add(sid) + } else { + sess = sessObj.(*Session) + } + + // Write data to session + return sess.Write(msg) +} + +func (w *SessionWriter) sync(sid uint64) error { + sessObj, ok := w.sessions.Load(sid) + if !ok { + return fmt.Errorf("session: %d not found", sid) + } + sess := sessObj.(*Session) + return sess.Sync() +} + +func (w *SessionWriter) Close(sid uint64) error { + sessObj, ok := w.sessions.LoadAndDelete(sid) + if !ok { + return fmt.Errorf("session: %d not found", sid) + } + sess := sessObj.(*Session) + err := sess.Close() + w.meta.Delete(sid) + return err +} + +func (w *SessionWriter) Stop() { + w.done <- struct{}{} + <-w.stopped +} + +func (w *SessionWriter) Info() string { + return fmt.Sprintf("%d sessions", w.meta.Count()) +} + +func (w *SessionWriter) synchronizer() { + tick := time.Tick(w.syncTimeout) + for { + select { + case <-tick: + w.sessions.Range(func(sid, lockObj any) bool { + if err := w.sync(sid.(uint64)); err != nil { + log.Printf("can't sync file descriptor: %s", err) + } + return true + }) + case <-w.done: + w.sessions.Range(func(sid, lockObj any) bool { + if err := w.Close(sid.(uint64)); err != nil { + log.Printf("can't close file descriptor: %s", err) + } + return true + }) + w.stopped <- struct{}{} + return + } + } +} diff --git a/backend/internal/storage/encryptor.go b/backend/internal/storage/encryptor.go new file mode 100644 index 000000000..be835116c --- /dev/null +++ b/backend/internal/storage/encryptor.go @@ -0,0 +1,17 @@ +package storage + +import ( + "errors" +) + +func GenerateEncryptionKey() []byte { + return nil +} + +func EncryptData(data, fullKey []byte) ([]byte, error) { + return nil, errors.New("not supported") +} + +func DecryptData(data, fullKey []byte) ([]byte, error) { + return nil, errors.New("not supported") +} diff --git a/backend/internal/storage/storage.go b/backend/internal/storage/storage.go index 8d79468db..12a37183f 100644 --- a/backend/internal/storage/storage.go +++ b/backend/internal/storage/storage.go @@ -8,6 +8,7 @@ import ( "log" config "openreplay/backend/internal/config/storage" "openreplay/backend/pkg/flakeid" + "openreplay/backend/pkg/messages" "openreplay/backend/pkg/monitoring" "openreplay/backend/pkg/storage" "os" @@ -16,13 +17,16 @@ import ( ) type Storage struct { - cfg *config.Config - s3 *storage.S3 - startBytes []byte - totalSessions syncfloat64.Counter - sessionSize syncfloat64.Histogram - readingTime syncfloat64.Histogram - archivingTime syncfloat64.Histogram + cfg *config.Config + s3 *storage.S3 + startBytes []byte + + totalSessions syncfloat64.Counter + sessionDOMSize syncfloat64.Histogram + sessionDevtoolsSize syncfloat64.Histogram + readingDOMTime syncfloat64.Histogram + readingTime syncfloat64.Histogram + archivingTime syncfloat64.Histogram } func New(cfg *config.Config, s3 *storage.S3, metrics *monitoring.Metrics) (*Storage, error) { @@ -37,10 +41,14 @@ func New(cfg *config.Config, s3 *storage.S3, metrics *monitoring.Metrics) (*Stor if err != nil { log.Printf("can't create sessions_total metric: %s", err) } - sessionSize, err := metrics.RegisterHistogram("sessions_size") + sessionDOMSize, err := metrics.RegisterHistogram("sessions_size") if err != nil { log.Printf("can't create session_size metric: %s", err) } + sessionDevtoolsSize, err := metrics.RegisterHistogram("sessions_dt_size") + if err != nil { + log.Printf("can't create sessions_dt_size metric: %s", err) + } readingTime, err := metrics.RegisterHistogram("reading_duration") if err != nil { log.Printf("can't create reading_duration metric: %s", err) @@ -50,71 +58,177 @@ func New(cfg *config.Config, s3 *storage.S3, metrics *monitoring.Metrics) (*Stor log.Printf("can't create archiving_duration metric: %s", err) } return &Storage{ - cfg: cfg, - s3: s3, - startBytes: make([]byte, cfg.FileSplitSize), - totalSessions: totalSessions, - sessionSize: sessionSize, - readingTime: readingTime, - archivingTime: archivingTime, + cfg: cfg, + s3: s3, + startBytes: make([]byte, cfg.FileSplitSize), + totalSessions: totalSessions, + sessionDOMSize: sessionDOMSize, + sessionDevtoolsSize: sessionDevtoolsSize, + readingTime: readingTime, + archivingTime: archivingTime, }, nil } -func (s *Storage) UploadKey(key string, retryCount int) error { +func (s *Storage) UploadSessionFiles(msg *messages.SessionEnd) error { + if err := s.uploadKey(msg.SessionID(), "/dom.mob", true, 5, msg.EncryptionKey); err != nil { + return err + } + if err := s.uploadKey(msg.SessionID(), "/devtools.mob", false, 4, msg.EncryptionKey); err != nil { + log.Printf("can't find devtools for session: %d, err: %s", msg.SessionID(), err) + } + return nil +} + +// TODO: make a bit cleaner. +// TODO: Of course, I'll do! +func (s *Storage) uploadKey(sessID uint64, suffix string, shouldSplit bool, retryCount int, encryptionKey string) error { if retryCount <= 0 { return nil } - start := time.Now() - file, err := os.Open(s.cfg.FSDir + "/" + key) + fileName := strconv.FormatUint(sessID, 10) + mobFileName := fileName + if suffix == "/devtools.mob" { + mobFileName += "devtools" + } + filePath := s.cfg.FSDir + "/" + mobFileName + + // Check file size before download into memory + info, err := os.Stat(filePath) + if err == nil { + if info.Size() > s.cfg.MaxFileSize { + log.Printf("big file, size: %d, session: %d", info.Size(), sessID) + return nil + } + } + file, err := os.Open(filePath) if err != nil { - sessID, _ := strconv.ParseUint(key, 10, 64) return fmt.Errorf("File open error: %v; sessID: %s, part: %d, sessStart: %s\n", - err, key, sessID%16, + err, fileName, sessID%16, time.UnixMilli(int64(flakeid.ExtractTimestamp(sessID))), ) } defer file.Close() - nRead, err := file.Read(s.startBytes) - if err != nil { - sessID, _ := strconv.ParseUint(key, 10, 64) - log.Printf("File read error: %s; sessID: %s, part: %d, sessStart: %s", - err, - key, - sessID%16, - time.UnixMilli(int64(flakeid.ExtractTimestamp(sessID))), - ) - time.AfterFunc(s.cfg.RetryTimeout, func() { - s.UploadKey(key, retryCount-1) - }) - return nil - } - s.readingTime.Record(context.Background(), float64(time.Now().Sub(start).Milliseconds())) - - start = time.Now() - startReader := bytes.NewBuffer(s.startBytes[:nRead]) - if err := s.s3.Upload(s.gzipFile(startReader), key, "application/octet-stream", true); err != nil { - log.Fatalf("Storage: start upload failed. %v\n", err) - } - if nRead == s.cfg.FileSplitSize { - if err := s.s3.Upload(s.gzipFile(file), key+"e", "application/octet-stream", true); err != nil { - log.Fatalf("Storage: end upload failed. %v\n", err) - } - } - s.archivingTime.Record(context.Background(), float64(time.Now().Sub(start).Milliseconds())) - - // Save metrics - var fileSize float64 = 0 + var fileSize int64 = 0 fileInfo, err := file.Stat() if err != nil { log.Printf("can't get file info: %s", err) } else { - fileSize = float64(fileInfo.Size()) + fileSize = fileInfo.Size() + } + + var encryptedData []byte + fileName += suffix + if shouldSplit { + nRead, err := file.Read(s.startBytes) + if err != nil { + log.Printf("File read error: %s; sessID: %s, part: %d, sessStart: %s", + err, + fileName, + sessID%16, + time.UnixMilli(int64(flakeid.ExtractTimestamp(sessID))), + ) + time.AfterFunc(s.cfg.RetryTimeout, func() { + s.uploadKey(sessID, suffix, shouldSplit, retryCount-1, encryptionKey) + }) + return nil + } + s.readingTime.Record(context.Background(), float64(time.Now().Sub(start).Milliseconds())) + + start = time.Now() + // Encrypt session file if we have encryption key + if encryptionKey != "" { + encryptedData, err = EncryptData(s.startBytes[:nRead], []byte(encryptionKey)) + if err != nil { + log.Printf("can't encrypt data: %s", err) + encryptedData = s.startBytes[:nRead] + } + } else { + encryptedData = s.startBytes[:nRead] + } + // Compress and save to s3 + startReader := bytes.NewBuffer(encryptedData) + if err := s.s3.Upload(s.gzipFile(startReader), fileName+"s", "application/octet-stream", true); err != nil { + log.Fatalf("Storage: start upload failed. %v\n", err) + } + // TODO: fix possible error (if we read less then FileSplitSize) + if nRead == s.cfg.FileSplitSize { + restPartSize := fileSize - int64(nRead) + fileData := make([]byte, restPartSize) + nRead, err = file.Read(fileData) + if err != nil { + log.Printf("File read error: %s; sessID: %s, part: %d, sessStart: %s", + err, + fileName, + sessID%16, + time.UnixMilli(int64(flakeid.ExtractTimestamp(sessID))), + ) + return nil + } + if int64(nRead) != restPartSize { + log.Printf("can't read the rest part of file") + } + + // Encrypt session file if we have encryption key + if encryptionKey != "" { + encryptedData, err = EncryptData(fileData, []byte(encryptionKey)) + if err != nil { + log.Printf("can't encrypt data: %s", err) + encryptedData = fileData + } + } else { + encryptedData = fileData + } + // Compress and save to s3 + endReader := bytes.NewBuffer(encryptedData) + if err := s.s3.Upload(s.gzipFile(endReader), fileName+"e", "application/octet-stream", true); err != nil { + log.Fatalf("Storage: end upload failed. %v\n", err) + } + } + s.archivingTime.Record(context.Background(), float64(time.Now().Sub(start).Milliseconds())) + } else { + start = time.Now() + fileData := make([]byte, fileSize) + nRead, err := file.Read(fileData) + if err != nil { + log.Printf("File read error: %s; sessID: %s, part: %d, sessStart: %s", + err, + fileName, + sessID%16, + time.UnixMilli(int64(flakeid.ExtractTimestamp(sessID))), + ) + return nil + } + if int64(nRead) != fileSize { + log.Printf("can't read the rest part of file") + } + + // Encrypt session file if we have encryption key + if encryptionKey != "" { + encryptedData, err = EncryptData(fileData, []byte(encryptionKey)) + if err != nil { + log.Printf("can't encrypt data: %s", err) + encryptedData = fileData + } + } else { + encryptedData = fileData + } + endReader := bytes.NewBuffer(encryptedData) + if err := s.s3.Upload(s.gzipFile(endReader), fileName, "application/octet-stream", true); err != nil { + log.Fatalf("Storage: end upload failed. %v\n", err) + } + s.archivingTime.Record(context.Background(), float64(time.Now().Sub(start).Milliseconds())) + } + + // Save metrics + ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*200) + if shouldSplit { + s.totalSessions.Add(ctx, 1) + s.sessionDOMSize.Record(ctx, float64(fileSize)) + } else { + s.sessionDevtoolsSize.Record(ctx, float64(fileSize)) } - ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*200) - s.sessionSize.Record(ctx, fileSize) - s.totalSessions.Add(ctx, 1) return nil } diff --git a/backend/pkg/db/cache/cache.go b/backend/pkg/db/cache/cache.go new file mode 100644 index 000000000..99ec50724 --- /dev/null +++ b/backend/pkg/db/cache/cache.go @@ -0,0 +1,73 @@ +package cache + +import ( + "log" + "openreplay/backend/pkg/db/postgres" + "openreplay/backend/pkg/db/types" + "sync" + "time" +) + +type SessionMeta struct { + *types.Session + lastUse time.Time +} + +type ProjectMeta struct { + *types.Project + expirationTime time.Time +} + +type Cache interface { + SetSession(sess *types.Session) + HasSession(sessID uint64) bool + GetSession(sessID uint64) (*types.Session, error) + GetProject(projectID uint32) (*types.Project, error) + GetProjectByKey(projectKey string) (*types.Project, error) +} + +type cacheImpl struct { + conn *postgres.Conn + mutex sync.RWMutex + sessions map[uint64]*SessionMeta + projects map[uint32]*ProjectMeta + projectsByKeys sync.Map + projectExpirationTimeout time.Duration +} + +func NewCache(conn *postgres.Conn, projectExpirationTimeoutMs int64) Cache { + newCache := &cacheImpl{ + conn: conn, + sessions: make(map[uint64]*SessionMeta), + projects: make(map[uint32]*ProjectMeta), + projectExpirationTimeout: time.Duration(1000 * projectExpirationTimeoutMs), + } + go newCache.cleaner() + return newCache +} + +func (c *cacheImpl) cleaner() { + cleanTick := time.Tick(time.Minute * 5) + for { + select { + case <-cleanTick: + c.clearCache() + } + } +} + +func (c *cacheImpl) clearCache() { + c.mutex.Lock() + defer c.mutex.Unlock() + + now := time.Now() + cacheSize := len(c.sessions) + deleted := 0 + for id, sess := range c.sessions { + if now.Sub(sess.lastUse).Minutes() > 3 { + deleted++ + delete(c.sessions, id) + } + } + log.Printf("cache cleaner: deleted %d/%d sessions", deleted, cacheSize) +} diff --git a/backend/pkg/db/cache/messages-common.go b/backend/pkg/db/cache/messages-common.go index 41cdb1895..3fc52f395 100644 --- a/backend/pkg/db/cache/messages-common.go +++ b/backend/pkg/db/cache/messages-common.go @@ -4,23 +4,25 @@ import ( "log" . "openreplay/backend/pkg/messages" "time" - // . "openreplay/backend/pkg/db/types" ) func (c *PGCache) InsertSessionEnd(sessionID uint64, timestamp uint64) (uint64, error) { return c.Conn.InsertSessionEnd(sessionID, timestamp) } +func (c *PGCache) InsertSessionEncryptionKey(sessionID uint64, key []byte) error { + return c.Conn.InsertSessionEncryptionKey(sessionID, key) +} + func (c *PGCache) HandleSessionEnd(sessionID uint64) error { if err := c.Conn.HandleSessionEnd(sessionID); err != nil { log.Printf("can't handle session end: %s", err) } - c.DeleteSession(sessionID) return nil } func (c *PGCache) InsertIssueEvent(sessionID uint64, crash *IssueEvent) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -28,11 +30,11 @@ func (c *PGCache) InsertIssueEvent(sessionID uint64, crash *IssueEvent) error { } func (c *PGCache) InsertMetadata(sessionID uint64, metadata *Metadata) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } - project, err := c.GetProject(session.ProjectID) + project, err := c.Cache.GetProject(session.ProjectID) if err != nil { return err } diff --git a/backend/pkg/db/cache/messages-ios.go b/backend/pkg/db/cache/messages-ios.go index e0463c431..961b78dad 100644 --- a/backend/pkg/db/cache/messages-ios.go +++ b/backend/pkg/db/cache/messages-ios.go @@ -1,16 +1,16 @@ package cache import ( - "errors" + "fmt" . "openreplay/backend/pkg/db/types" . "openreplay/backend/pkg/messages" ) func (c *PGCache) InsertIOSSessionStart(sessionID uint64, s *IOSSessionStart) error { - if c.sessions[sessionID] != nil { - return errors.New("This session already in cache!") + if c.Cache.HasSession(sessionID) { + return fmt.Errorf("session %d already in cache", sessionID) } - c.sessions[sessionID] = &Session{ + newSess := &Session{ SessionID: sessionID, Platform: "ios", Timestamp: s.Timestamp, @@ -24,8 +24,10 @@ func (c *PGCache) InsertIOSSessionStart(sessionID uint64, s *IOSSessionStart) er UserCountry: s.UserCountry, UserDeviceType: s.UserDeviceType, } - if err := c.Conn.InsertSessionStart(sessionID, c.sessions[sessionID]); err != nil { - c.sessions[sessionID] = nil + c.Cache.SetSession(newSess) + if err := c.Conn.InsertSessionStart(sessionID, newSess); err != nil { + // don't know why? + c.Cache.SetSession(nil) return err } return nil @@ -40,7 +42,7 @@ func (c *PGCache) InsertIOSScreenEnter(sessionID uint64, screenEnter *IOSScreenE if err := c.Conn.InsertIOSScreenEnter(sessionID, screenEnter); err != nil { return err } - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -52,7 +54,7 @@ func (c *PGCache) InsertIOSClickEvent(sessionID uint64, clickEvent *IOSClickEven if err := c.Conn.InsertIOSClickEvent(sessionID, clickEvent); err != nil { return err } - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -64,7 +66,7 @@ func (c *PGCache) InsertIOSInputEvent(sessionID uint64, inputEvent *IOSInputEven if err := c.Conn.InsertIOSInputEvent(sessionID, inputEvent); err != nil { return err } - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -73,7 +75,7 @@ func (c *PGCache) InsertIOSInputEvent(sessionID uint64, inputEvent *IOSInputEven } func (c *PGCache) InsertIOSCrash(sessionID uint64, crash *IOSCrash) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } diff --git a/backend/pkg/db/cache/messages-web.go b/backend/pkg/db/cache/messages-web.go index 87098552b..931d1f639 100644 --- a/backend/pkg/db/cache/messages-web.go +++ b/backend/pkg/db/cache/messages-web.go @@ -1,7 +1,7 @@ package cache import ( - "errors" + "fmt" . "openreplay/backend/pkg/db/types" . "openreplay/backend/pkg/messages" ) @@ -31,10 +31,10 @@ func (c *PGCache) InsertWebSessionStart(sessionID uint64, s *SessionStart) error } func (c *PGCache) HandleWebSessionStart(sessionID uint64, s *SessionStart) error { - if c.sessions[sessionID] != nil { - return errors.New("This session already in cache!") + if c.Cache.HasSession(sessionID) { + return fmt.Errorf("session %d already in cache", sessionID) } - c.sessions[sessionID] = &Session{ + newSess := &Session{ SessionID: sessionID, Platform: "web", Timestamp: s.Timestamp, @@ -55,8 +55,10 @@ func (c *PGCache) HandleWebSessionStart(sessionID uint64, s *SessionStart) error UserDeviceHeapSize: s.UserDeviceHeapSize, UserID: &s.UserID, } - if err := c.Conn.HandleSessionStart(sessionID, c.sessions[sessionID]); err != nil { - c.sessions[sessionID] = nil + c.Cache.SetSession(newSess) + if err := c.Conn.HandleSessionStart(sessionID, newSess); err != nil { + // don't know why? + c.Cache.SetSession(nil) return err } return nil @@ -71,8 +73,14 @@ func (c *PGCache) HandleWebSessionEnd(sessionID uint64, e *SessionEnd) error { return c.HandleSessionEnd(sessionID) } +func (c *PGCache) InsertWebJSException(e *JSException) error { + return c.InsertWebErrorEvent(e.SessionID(), WrapJSException(e)) +} +func (c *PGCache) InsertWebIntegrationEvent(e *IntegrationEvent) error { + return c.InsertWebErrorEvent(e.SessionID(), WrapIntegrationEvent(e)) +} func (c *PGCache) InsertWebErrorEvent(sessionID uint64, e *ErrorEvent) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -84,7 +92,7 @@ func (c *PGCache) InsertWebErrorEvent(sessionID uint64, e *ErrorEvent) error { } func (c *PGCache) InsertSessionReferrer(sessionID uint64, referrer string) error { - _, err := c.GetSession(sessionID) + _, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -92,11 +100,11 @@ func (c *PGCache) InsertSessionReferrer(sessionID uint64, referrer string) error } func (c *PGCache) InsertWebFetchEvent(sessionID uint64, e *FetchEvent) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } - project, err := c.GetProject(session.ProjectID) + project, err := c.Cache.GetProject(session.ProjectID) if err != nil { return err } @@ -104,11 +112,11 @@ func (c *PGCache) InsertWebFetchEvent(sessionID uint64, e *FetchEvent) error { } func (c *PGCache) InsertWebGraphQLEvent(sessionID uint64, e *GraphQLEvent) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } - project, err := c.GetProject(session.ProjectID) + project, err := c.Cache.GetProject(session.ProjectID) if err != nil { return err } @@ -116,7 +124,7 @@ func (c *PGCache) InsertWebGraphQLEvent(sessionID uint64, e *GraphQLEvent) error } func (c *PGCache) InsertWebCustomEvent(sessionID uint64, e *CustomEvent) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -124,7 +132,7 @@ func (c *PGCache) InsertWebCustomEvent(sessionID uint64, e *CustomEvent) error { } func (c *PGCache) InsertWebUserID(sessionID uint64, userID *UserID) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -132,7 +140,7 @@ func (c *PGCache) InsertWebUserID(sessionID uint64, userID *UserID) error { } func (c *PGCache) InsertWebUserAnonymousID(sessionID uint64, userAnonymousID *UserAnonymousID) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -140,7 +148,7 @@ func (c *PGCache) InsertWebUserAnonymousID(sessionID uint64, userAnonymousID *Us } func (c *PGCache) InsertWebPageEvent(sessionID uint64, e *PageEvent) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -148,7 +156,7 @@ func (c *PGCache) InsertWebPageEvent(sessionID uint64, e *PageEvent) error { } func (c *PGCache) InsertWebClickEvent(sessionID uint64, e *ClickEvent) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } @@ -156,7 +164,7 @@ func (c *PGCache) InsertWebClickEvent(sessionID uint64, e *ClickEvent) error { } func (c *PGCache) InsertWebInputEvent(sessionID uint64, e *InputEvent) error { - session, err := c.GetSession(sessionID) + session, err := c.Cache.GetSession(sessionID) if err != nil { return err } diff --git a/backend/pkg/db/cache/pg-cache.go b/backend/pkg/db/cache/pg-cache.go index ca31bcd82..1b7a6710d 100644 --- a/backend/pkg/db/cache/pg-cache.go +++ b/backend/pkg/db/cache/pg-cache.go @@ -1,37 +1,20 @@ package cache import ( - "sync" - "time" - "openreplay/backend/pkg/db/postgres" - . "openreplay/backend/pkg/db/types" ) -type ProjectMeta struct { - *Project - expirationTime time.Time -} - -// !TODO: remove old sessions by timeout to avoid memleaks - -/* - * Cache layer around the stateless PG adapter -**/ type PGCache struct { *postgres.Conn - sessions map[uint64]*Session - projects map[uint32]*ProjectMeta - projectsByKeys sync.Map // map[string]*ProjectMeta - projectExpirationTimeout time.Duration + Cache Cache } -// TODO: create conn automatically -func NewPGCache(pgConn *postgres.Conn, projectExpirationTimeoutMs int64) *PGCache { +func NewPGCache(conn *postgres.Conn, projectExpirationTimeoutMs int64) *PGCache { + // Create in-memory cache layer for sessions and projects + c := NewCache(conn, projectExpirationTimeoutMs) + // Return PG wrapper with integrated cache layer return &PGCache{ - Conn: pgConn, - sessions: make(map[uint64]*Session), - projects: make(map[uint32]*ProjectMeta), - projectExpirationTimeout: time.Duration(1000 * projectExpirationTimeoutMs), + Conn: conn, + Cache: c, } } diff --git a/backend/pkg/db/cache/project.go b/backend/pkg/db/cache/project.go index 35d952302..60b868501 100644 --- a/backend/pkg/db/cache/project.go +++ b/backend/pkg/db/cache/project.go @@ -5,7 +5,7 @@ import ( "time" ) -func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) { +func (c *cacheImpl) GetProjectByKey(projectKey string) (*Project, error) { pmInterface, found := c.projectsByKeys.Load(projectKey) if found { if pm, ok := pmInterface.(*ProjectMeta); ok { @@ -15,7 +15,7 @@ func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) { } } - p, err := c.Conn.GetProjectByKey(projectKey) + p, err := c.conn.GetProjectByKey(projectKey) if err != nil { return nil, err } @@ -24,12 +24,12 @@ func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) { return p, nil } -func (c *PGCache) GetProject(projectID uint32) (*Project, error) { +func (c *cacheImpl) GetProject(projectID uint32) (*Project, error) { if c.projects[projectID] != nil && time.Now().Before(c.projects[projectID].expirationTime) { return c.projects[projectID].Project, nil } - p, err := c.Conn.GetProject(projectID) + p, err := c.conn.GetProject(projectID) if err != nil { return nil, err } diff --git a/backend/pkg/db/cache/session.go b/backend/pkg/db/cache/session.go index 89b8f89f8..f03f1e955 100644 --- a/backend/pkg/db/cache/session.go +++ b/backend/pkg/db/cache/session.go @@ -4,28 +4,48 @@ import ( "errors" "github.com/jackc/pgx/v4" . "openreplay/backend/pkg/db/types" + "time" ) var NilSessionInCacheError = errors.New("nil session in error") -func (c *PGCache) GetSession(sessionID uint64) (*Session, error) { - if s, inCache := c.sessions[sessionID]; inCache { - if s == nil { - return s, NilSessionInCacheError - } - return s, nil +func (c *cacheImpl) SetSession(sess *Session) { + c.mutex.Lock() + defer c.mutex.Unlock() + + if meta, ok := c.sessions[sess.SessionID]; ok { + meta.Session = sess + meta.lastUse = time.Now() + } else { + c.sessions[sess.SessionID] = &SessionMeta{sess, time.Now()} } - s, err := c.Conn.GetSession(sessionID) +} + +func (c *cacheImpl) HasSession(sessID uint64) bool { + c.mutex.RLock() + defer c.mutex.RUnlock() + + sess, ok := c.sessions[sessID] + return ok && sess.Session != nil +} + +func (c *cacheImpl) GetSession(sessionID uint64) (*Session, error) { + c.mutex.Lock() + defer c.mutex.Unlock() + + if s, inCache := c.sessions[sessionID]; inCache { + if s.Session == nil { + return nil, NilSessionInCacheError + } + return s.Session, nil + } + s, err := c.conn.GetSession(sessionID) if err == pgx.ErrNoRows { - c.sessions[sessionID] = nil + c.sessions[sessionID] = &SessionMeta{nil, time.Now()} } if err != nil { return nil, err } - c.sessions[sessionID] = s + c.sessions[sessionID] = &SessionMeta{s, time.Now()} return s, nil } - -func (c *PGCache) DeleteSession(sessionID uint64) { - delete(c.sessions, sessionID) -} diff --git a/backend/pkg/db/postgres/connector.go b/backend/pkg/db/postgres/connector.go index 63f42e25b..9e269fcc0 100644 --- a/backend/pkg/db/postgres/connector.go +++ b/backend/pkg/db/postgres/connector.go @@ -55,8 +55,7 @@ func NewConn(url string, queueLimit, sizeLimit int, metrics *monitoring.Metrics) } c, err := pgxpool.Connect(context.Background(), url) if err != nil { - log.Println(err) - log.Fatalln("pgxpool.Connect Error") + log.Fatalf("pgxpool.Connect err: %s", err) } conn := &Conn{ batches: make(map[uint64]*pgx.Batch), diff --git a/backend/pkg/db/postgres/helpers.go b/backend/pkg/db/postgres/helpers.go index 2d4c96e28..f3b96134b 100644 --- a/backend/pkg/db/postgres/helpers.go +++ b/backend/pkg/db/postgres/helpers.go @@ -1,6 +1,8 @@ package postgres import ( + "math" + "openreplay/backend/pkg/messages" ) @@ -33,3 +35,8 @@ func calcResponseTime(pe *messages.PageEvent) uint64 { } return 0 } + +// TODO: review message indexing (it is better to have lower values in db for faster search (int4/int2)) +func truncSqIdx(messageID uint64) uint32 { + return uint32(messageID % math.MaxInt32) +} diff --git a/backend/pkg/db/postgres/messages-common.go b/backend/pkg/db/postgres/messages-common.go index dbdedb02d..fca11ce88 100644 --- a/backend/pkg/db/postgres/messages-common.go +++ b/backend/pkg/db/postgres/messages-common.go @@ -82,6 +82,10 @@ func (conn *Conn) InsertSessionEnd(sessionID uint64, timestamp uint64) (uint64, return dur, nil } +func (conn *Conn) InsertSessionEncryptionKey(sessionID uint64, key []byte) error { + return conn.c.Exec(`UPDATE sessions SET file_key = $2 WHERE session_id = $1`, sessionID, string(key)) +} + func (conn *Conn) HandleSessionEnd(sessionID uint64) error { sqlRequest := ` UPDATE sessions @@ -91,22 +95,23 @@ func (conn *Conn) HandleSessionEnd(sessionID uint64) error { ELSE (COALESCE(ARRAY_AGG(DISTINCT ps.type), '{}'))::issue_type[] END - FROM events_common.issues - INNER JOIN issues AS ps USING (issue_id) - WHERE session_id = $1) - WHERE session_id = $1` + FROM events_common.issues + INNER JOIN issues AS ps USING (issue_id) + WHERE session_id = $1) + WHERE session_id = $1 + ` return conn.c.Exec(sqlRequest, sessionID) } -func (conn *Conn) InsertRequest(sessionID uint64, timestamp uint64, index uint64, url string, duration uint64, success bool) error { - if err := conn.requests.Append(sessionID, timestamp, getSqIdx(index), url, duration, success); err != nil { +func (conn *Conn) InsertRequest(sessionID uint64, timestamp uint64, index uint32, url string, duration uint64, success bool) error { + if err := conn.requests.Append(sessionID, timestamp, index, url, duration, success); err != nil { return fmt.Errorf("insert request in bulk err: %s", err) } return nil } -func (conn *Conn) InsertCustomEvent(sessionID uint64, timestamp uint64, index uint64, name string, payload string) error { - if err := conn.customEvents.Append(sessionID, timestamp, getSqIdx(index), name, payload); err != nil { +func (conn *Conn) InsertCustomEvent(sessionID uint64, timestamp uint64, index uint32, name string, payload string) error { + if err := conn.customEvents.Append(sessionID, timestamp, index, name, payload); err != nil { return fmt.Errorf("insert custom event in bulk err: %s", err) } return nil @@ -160,20 +165,16 @@ func (conn *Conn) InsertIssueEvent(sessionID uint64, projectID uint32, e *messag if *payload == "" || *payload == "{}" { payload = nil } - context := &e.Context - if *context == "" || *context == "{}" { - context = nil - } if err = tx.exec(` INSERT INTO issues ( - project_id, issue_id, type, context_string, context + project_id, issue_id, type, context_string ) (SELECT - project_id, $2, $3, $4, CAST($5 AS jsonb) + project_id, $2, $3, $4 FROM sessions WHERE session_id = $1 )ON CONFLICT DO NOTHING`, - sessionID, issueID, e.Type, e.ContextString, context, + sessionID, issueID, e.Type, e.ContextString, ); err != nil { return err } @@ -184,7 +185,7 @@ func (conn *Conn) InsertIssueEvent(sessionID uint64, projectID uint32, e *messag $1, $2, $3, $4, CAST($5 AS jsonb) )`, sessionID, issueID, e.Timestamp, - getSqIdx(e.MessageID), + truncSqIdx(e.MessageID), payload, ); err != nil { return err @@ -204,7 +205,7 @@ func (conn *Conn) InsertIssueEvent(sessionID uint64, projectID uint32, e *messag VALUES ($1, $2, $3, left($4, 2700), $5, 'error') `, - sessionID, getSqIdx(e.MessageID), e.Timestamp, e.ContextString, e.Payload, + sessionID, truncSqIdx(e.MessageID), e.Timestamp, e.ContextString, e.Payload, ); err != nil { return err } diff --git a/backend/pkg/db/postgres/messages-ios.go b/backend/pkg/db/postgres/messages-ios.go index d7b2f58f3..027cfc968 100644 --- a/backend/pkg/db/postgres/messages-ios.go +++ b/backend/pkg/db/postgres/messages-ios.go @@ -7,7 +7,7 @@ import ( ) func (conn *Conn) InsertIOSCustomEvent(sessionID uint64, e *messages.IOSCustomEvent) error { - err := conn.InsertCustomEvent(sessionID, e.Timestamp, e.Index, e.Name, e.Payload) + err := conn.InsertCustomEvent(sessionID, e.Timestamp, truncSqIdx(e.Index), e.Name, e.Payload) if err == nil { conn.insertAutocompleteValue(sessionID, 0, "CUSTOM_IOS", e.Name) } @@ -31,7 +31,7 @@ func (conn *Conn) InsertIOSUserAnonymousID(sessionID uint64, userAnonymousID *me } func (conn *Conn) InsertIOSNetworkCall(sessionID uint64, e *messages.IOSNetworkCall) error { - err := conn.InsertRequest(sessionID, e.Timestamp, e.Index, e.URL, e.Duration, e.Success) + err := conn.InsertRequest(sessionID, e.Timestamp, truncSqIdx(e.Index), e.URL, e.Duration, e.Success) if err == nil { conn.insertAutocompleteValue(sessionID, 0, "REQUEST_IOS", url.DiscardURLQuery(e.URL)) } diff --git a/backend/pkg/db/postgres/messages-web-stats.go b/backend/pkg/db/postgres/messages-web-stats.go index 396f2e74d..719fe0d61 100644 --- a/backend/pkg/db/postgres/messages-web-stats.go +++ b/backend/pkg/db/postgres/messages-web-stats.go @@ -5,11 +5,6 @@ import ( "openreplay/backend/pkg/url" ) -func (conn *Conn) InsertWebStatsLongtask(sessionID uint64, l *LongTask) error { - return nil // Do we even use them? - // conn.exec(``); -} - func (conn *Conn) InsertWebStatsPerformance(sessionID uint64, p *PerformanceTrackAggr) error { timestamp := (p.TimestampEnd + p.TimestampStart) / 2 @@ -65,7 +60,7 @@ func (conn *Conn) InsertWebStatsResourceEvent(sessionID uint64, e *ResourceEvent urlQuery := url.DiscardURLQuery(e.URL) urlMethod := url.EnsureMethod(e.Method) conn.batchQueue(sessionID, sqlRequest, - sessionID, e.Timestamp, e.MessageID, + sessionID, e.Timestamp, truncSqIdx(e.MessageID), e.Type, e.URL, host, urlQuery, e.Success, e.Status, diff --git a/backend/pkg/db/postgres/messages-web.go b/backend/pkg/db/postgres/messages-web.go index 9758587b8..10cfad409 100644 --- a/backend/pkg/db/postgres/messages-web.go +++ b/backend/pkg/db/postgres/messages-web.go @@ -2,21 +2,15 @@ package postgres import ( "log" - "math" - "openreplay/backend/pkg/hashid" + "openreplay/backend/pkg/db/types" . "openreplay/backend/pkg/messages" "openreplay/backend/pkg/url" ) -// TODO: change messages and replace everywhere to e.Index -func getSqIdx(messageID uint64) uint { - return uint(messageID % math.MaxInt32) -} - func (conn *Conn) InsertWebCustomEvent(sessionID uint64, projectID uint32, e *CustomEvent) error { err := conn.InsertCustomEvent(sessionID, e.Timestamp, - e.MessageID, + truncSqIdx(e.MessageID), e.Name, e.Payload) if err == nil { conn.insertAutocompleteValue(sessionID, projectID, "CUSTOM", e.Name) @@ -46,7 +40,7 @@ func (conn *Conn) InsertWebPageEvent(sessionID uint64, projectID uint32, e *Page return err } // base_path is deprecated - if err = conn.webPageEvents.Append(sessionID, e.MessageID, e.Timestamp, e.Referrer, url.DiscardURLQuery(e.Referrer), + if err = conn.webPageEvents.Append(sessionID, truncSqIdx(e.MessageID), e.Timestamp, e.Referrer, url.DiscardURLQuery(e.Referrer), host, path, query, e.DomContentLoadedEventEnd, e.LoadEventEnd, e.ResponseEnd, e.FirstPaint, e.FirstContentfulPaint, e.SpeedIndex, e.VisuallyComplete, e.TimeToInteractive, calcResponseTime(e), calcDomBuildingTime(e)); err != nil { log.Printf("insert web page event in bulk err: %s", err) @@ -69,7 +63,7 @@ func (conn *Conn) InsertWebClickEvent(sessionID uint64, projectID uint32, e *Cli WHERE session_id = $1 AND timestamp <= $3 ORDER BY timestamp DESC LIMIT 1 ) ` - conn.batchQueue(sessionID, sqlRequest, sessionID, e.MessageID, e.Timestamp, e.Label, e.Selector) + conn.batchQueue(sessionID, sqlRequest, sessionID, truncSqIdx(e.MessageID), e.Timestamp, e.Label, e.Selector) // Accumulate session updates and exec inside batch with another sql commands conn.updateSessionEvents(sessionID, 1, 0) // Add new value set to autocomplete bulk @@ -85,7 +79,7 @@ func (conn *Conn) InsertWebInputEvent(sessionID uint64, projectID uint32, e *Inp if e.ValueMasked { value = nil } - if err := conn.webInputEvents.Append(sessionID, e.MessageID, e.Timestamp, value, e.Label); err != nil { + if err := conn.webInputEvents.Append(sessionID, truncSqIdx(e.MessageID), e.Timestamp, value, e.Label); err != nil { log.Printf("insert web input event err: %s", err) } conn.updateSessionEvents(sessionID, 1, 0) @@ -93,7 +87,7 @@ func (conn *Conn) InsertWebInputEvent(sessionID uint64, projectID uint32, e *Inp return nil } -func (conn *Conn) InsertWebErrorEvent(sessionID uint64, projectID uint32, e *ErrorEvent) (err error) { +func (conn *Conn) InsertWebErrorEvent(sessionID uint64, projectID uint32, e *types.ErrorEvent) (err error) { tx, err := conn.c.Begin() if err != nil { return err @@ -105,7 +99,7 @@ func (conn *Conn) InsertWebErrorEvent(sessionID uint64, projectID uint32, e *Err } } }() - errorID := hashid.WebErrorID(projectID, e) + errorID := e.ID(projectID) if err = tx.exec(` INSERT INTO errors @@ -123,7 +117,7 @@ func (conn *Conn) InsertWebErrorEvent(sessionID uint64, projectID uint32, e *Err VALUES ($1, $2, $3, $4) `, - sessionID, e.MessageID, e.Timestamp, errorID, + sessionID, truncSqIdx(e.MessageID), e.Timestamp, errorID, ); err != nil { return err } @@ -135,6 +129,18 @@ func (conn *Conn) InsertWebErrorEvent(sessionID uint64, projectID uint32, e *Err return err } err = tx.commit() + + // Insert tags + sqlRequest := ` + INSERT INTO public.errors_tags ( + session_id, message_id, error_id, key, value + ) VALUES ( + $1, $2, $3, $4, $5 + ) ON CONFLICT DO NOTHING` + for key, value := range e.Tags { + conn.batchQueue(sessionID, sqlRequest, sessionID, truncSqIdx(e.MessageID), errorID, key, value) + } + return } @@ -163,7 +169,7 @@ func (conn *Conn) InsertWebFetchEvent(sessionID uint64, projectID uint32, savePa $12, $13 ) ON CONFLICT DO NOTHING` conn.batchQueue(sessionID, sqlRequest, - sessionID, e.Timestamp, getSqIdx(e.MessageID), + sessionID, e.Timestamp, truncSqIdx(e.MessageID), e.URL, host, path, query, request, response, e.Status, url.EnsureMethod(e.Method), e.Duration, e.Status < 400, @@ -181,7 +187,7 @@ func (conn *Conn) InsertWebGraphQLEvent(sessionID uint64, projectID uint32, save request = &e.Variables response = &e.Response } - if err := conn.webGraphQLEvents.Append(sessionID, e.Timestamp, e.MessageID, e.OperationName, request, response); err != nil { + if err := conn.webGraphQLEvents.Append(sessionID, e.Timestamp, truncSqIdx(e.MessageID), e.OperationName, request, response); err != nil { log.Printf("insert web graphQL event err: %s", err) } conn.insertAutocompleteValue(sessionID, projectID, "GRAPHQL", e.OperationName) diff --git a/backend/pkg/db/types/error-event.go b/backend/pkg/db/types/error-event.go new file mode 100644 index 000000000..bef9abd99 --- /dev/null +++ b/backend/pkg/db/types/error-event.go @@ -0,0 +1,122 @@ +package types + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "hash/fnv" + "log" + "strconv" + + . "openreplay/backend/pkg/messages" +) + +const SOURCE_JS = "js_exception" + +type ErrorEvent struct { + MessageID uint64 + Timestamp uint64 + Source string + Name string + Message string + Payload string + Tags map[string]*string +} + +func unquote(s string) string { + if s[0] == '"' { + return s[1 : len(s)-1] + } + return s +} +func parseTags(tagsJSON string) (tags map[string]*string, err error) { + if len(tagsJSON) == 0 { + return nil, fmt.Errorf("empty tags") + } + if tagsJSON[0] == '[' { + var tagsArr []json.RawMessage + if err = json.Unmarshal([]byte(tagsJSON), &tagsArr); err != nil { + return + } + + tags = make(map[string]*string) + for _, keyBts := range tagsArr { + tags[unquote(string(keyBts))] = nil + } + } else if tagsJSON[0] == '{' { + var tagsObj map[string]json.RawMessage + if err = json.Unmarshal([]byte(tagsJSON), &tagsObj); err != nil { + return + } + + tags = make(map[string]*string) + for key, valBts := range tagsObj { + val := unquote(string(valBts)) + tags[key] = &val + } + } + return +} + +func WrapJSException(m *JSException) *ErrorEvent { + meta, err := parseTags(m.Metadata) + if err != nil { + log.Printf("Error on parsing Exception metadata: %v", err) + } + return &ErrorEvent{ + MessageID: m.Meta().Index, + Timestamp: uint64(m.Meta().Timestamp), + Source: SOURCE_JS, + Name: m.Name, + Message: m.Message, + Payload: m.Payload, + Tags: meta, + } +} + +func WrapIntegrationEvent(m *IntegrationEvent) *ErrorEvent { + return &ErrorEvent{ + MessageID: m.Meta().Index, // This will be always 0 here since it's coming from backend TODO: find another way to index + Timestamp: m.Timestamp, + Source: m.Source, + Name: m.Name, + Message: m.Message, + Payload: m.Payload, + } +} + +type stackFrame struct { + FileName string `json:"fileName"` + LineNo int `json:"lineNumber"` + ColNo int `json:"columnNumber"` +} + +func parseFirstFrame(payload string) (*stackFrame, error) { + var frames []*stackFrame + if err := json.Unmarshal([]byte(payload), &frames); err != nil { + return nil, err + } + if len(frames) == 0 { + return nil, nil + } + return frames[0], nil +} + +func (e *ErrorEvent) ID(projectID uint32) string { + hash := fnv.New128a() + hash.Write([]byte(e.Source)) + hash.Write([]byte(e.Name)) + hash.Write([]byte(e.Message)) + if e.Source == SOURCE_JS { + frame, err := parseFirstFrame(e.Payload) + if err != nil { + log.Printf("Can't parse stackframe ((( %v ))): %v", e.Payload, err) + } + if frame != nil { + hash.Write([]byte(frame.FileName)) + hash.Write([]byte(strconv.Itoa(frame.LineNo))) + hash.Write([]byte(strconv.Itoa(frame.ColNo))) + } + } + return strconv.FormatUint(uint64(projectID), 16) + hex.EncodeToString(hash.Sum(nil)) +} diff --git a/backend/pkg/db/types/session.go b/backend/pkg/db/types/session.go index 53fef410c..202eb9966 100644 --- a/backend/pkg/db/types/session.go +++ b/backend/pkg/db/types/session.go @@ -20,7 +20,7 @@ type Session struct { IssueTypes []string IssueScore int - UserID *string // pointer?? + UserID *string UserAnonymousID *string Metadata1 *string Metadata2 *string diff --git a/backend/pkg/handlers/custom/eventMapper.go b/backend/pkg/handlers/custom/eventMapper.go index f1bd4cafe..3280e7ebc 100644 --- a/backend/pkg/handlers/custom/eventMapper.go +++ b/backend/pkg/handlers/custom/eventMapper.go @@ -56,15 +56,6 @@ func (b *EventMapper) Handle(message Message, messageID uint64, timestamp uint64 Selector: msg.Selector, } } - case *JSException: - return &ErrorEvent{ - MessageID: messageID, - Timestamp: timestamp, - Source: "js_exception", - Name: msg.Name, - Message: msg.Message, - Payload: msg.Payload, - } case *ResourceTiming: return &ResourceEvent{ MessageID: messageID, diff --git a/backend/pkg/hashid/hashid.go b/backend/pkg/hashid/hashid.go index 8620b0e69..25ce11369 100644 --- a/backend/pkg/hashid/hashid.go +++ b/backend/pkg/hashid/hashid.go @@ -23,12 +23,3 @@ func IOSCrashID(projectID uint32, crash *messages.IOSCrash) string { hash.Write([]byte(crash.Stacktrace)) return strconv.FormatUint(uint64(projectID), 16) + hex.EncodeToString(hash.Sum(nil)) } - -func WebErrorID(projectID uint32, errorEvent *messages.ErrorEvent) string { - hash := fnv.New128a() - hash.Write([]byte(errorEvent.Source)) - hash.Write([]byte(errorEvent.Name)) - hash.Write([]byte(errorEvent.Message)) - hash.Write([]byte(errorEvent.Payload)) - return strconv.FormatUint(uint64(projectID), 16) + hex.EncodeToString(hash.Sum(nil)) -} diff --git a/backend/pkg/log/queue.go b/backend/pkg/log/queue.go index ced815bd2..e9ac5dc1f 100644 --- a/backend/pkg/log/queue.go +++ b/backend/pkg/log/queue.go @@ -5,8 +5,7 @@ import ( "log" "time" - "openreplay/backend/pkg/queue/types" - //"openreplay/backend/pkg/env" + "openreplay/backend/pkg/messages" ) type partitionStats struct { @@ -18,15 +17,15 @@ type partitionStats struct { } // Update partition statistic -func (prt *partitionStats) update(m *types.Meta) { - if prt.maxts < m.Timestamp { - prt.maxts = m.Timestamp +func (prt *partitionStats) update(m *messages.BatchInfo) { + if prt.maxts < m.Timestamp() { + prt.maxts = m.Timestamp() } - if prt.mints > m.Timestamp || prt.mints == 0 { - prt.mints = m.Timestamp + if prt.mints > m.Timestamp() || prt.mints == 0 { + prt.mints = m.Timestamp() } - prt.lastts = m.Timestamp - prt.lastID = m.ID + prt.lastts = m.Timestamp() + prt.lastID = m.ID() prt.count += 1 } @@ -35,6 +34,10 @@ type queueStats struct { tick <-chan time.Time } +type QueueStats interface { + Collect(msg messages.Message) +} + func NewQueueStats(sec int) *queueStats { return &queueStats{ prts: make(map[int32]*partitionStats), @@ -43,14 +46,14 @@ func NewQueueStats(sec int) *queueStats { } // Collect writes new data to partition statistic -func (qs *queueStats) Collect(sessionID uint64, m *types.Meta) { - prti := int32(sessionID % 16) // TODO use GetKeyPartition from kafka/key.go +func (qs *queueStats) Collect(msg messages.Message) { + prti := int32(msg.SessionID() % 16) // TODO use GetKeyPartition from kafka/key.go prt, ok := qs.prts[prti] if !ok { qs.prts[prti] = &partitionStats{} prt = qs.prts[prti] } - prt.update(m) + prt.update(msg.Meta().Batch()) select { case <-qs.tick: diff --git a/backend/pkg/messages/batch.go b/backend/pkg/messages/batch.go deleted file mode 100644 index 887e5ddb3..000000000 --- a/backend/pkg/messages/batch.go +++ /dev/null @@ -1,197 +0,0 @@ -package messages - -import ( - "bytes" - "io" - "log" - "strings" -) - -type Iterator interface { - Next() bool // Return true if we have next message - Type() int // Return type of the next message - Message() Message // Return raw or decoded message - Close() -} - -type iteratorImpl struct { - data *bytes.Reader - index uint64 - timestamp int64 - version uint64 - msgType uint64 - msgSize uint64 - canSkip bool - msg Message - url string -} - -func NewIterator(data []byte) Iterator { - return &iteratorImpl{ - data: bytes.NewReader(data), - } -} - -func (i *iteratorImpl) Next() bool { - if i.canSkip { - if _, err := i.data.Seek(int64(i.msgSize), io.SeekCurrent); err != nil { - log.Printf("seek err: %s", err) - return false - } - } - i.canSkip = false - - var err error - i.msgType, err = ReadUint(i.data) - if err != nil { - if err == io.EOF { - return false - } - log.Printf("can't read message type: %s", err) - return false - } - - if i.version > 0 && messageHasSize(i.msgType) { - // Read message size if it is a new protocol version - i.msgSize, err = ReadSize(i.data) - if err != nil { - log.Printf("can't read message size: %s", err) - return false - } - i.msg = &RawMessage{ - tp: i.msgType, - size: i.msgSize, - meta: &message{}, - reader: i.data, - skipped: &i.canSkip, - } - i.canSkip = true - } else { - i.msg, err = ReadMessage(i.msgType, i.data) - if err == io.EOF { - return false - } else if err != nil { - if strings.HasPrefix(err.Error(), "Unknown message code:") { - code := strings.TrimPrefix(err.Error(), "Unknown message code: ") - i.msg, err = DecodeExtraMessage(code, i.data) - if err != nil { - log.Printf("can't decode msg: %s", err) - return false - } - } else { - log.Printf("Batch Message decoding error on message with index %v, err: %s", i.index, err) - return false - } - } - i.msg = transformDeprecated(i.msg) - } - - // Process meta information - isBatchMeta := false - switch i.msgType { - case MsgBatchMetadata: - if i.index != 0 { // Might be several 0-0 BatchMeta in a row without an error though - log.Printf("Batch Metadata found at the end of the batch") - return false - } - msg := i.msg.Decode() - if msg == nil { - return false - } - m := msg.(*BatchMetadata) - i.index = m.PageNo<<32 + m.FirstIndex // 2^32 is the maximum count of messages per page (ha-ha) - i.timestamp = m.Timestamp - i.version = m.Version - i.url = m.Url - isBatchMeta = true - if i.version > 1 { - log.Printf("incorrect batch version, skip current batch") - return false - } - case MsgBatchMeta: // Is not required to be present in batch since IOS doesn't have it (though we might change it) - if i.index != 0 { // Might be several 0-0 BatchMeta in a row without an error though - log.Printf("Batch Meta found at the end of the batch") - return false - } - msg := i.msg.Decode() - if msg == nil { - return false - } - m := msg.(*BatchMeta) - i.index = m.PageNo<<32 + m.FirstIndex // 2^32 is the maximum count of messages per page (ha-ha) - i.timestamp = m.Timestamp - isBatchMeta = true - // continue readLoop - case MsgIOSBatchMeta: - if i.index != 0 { // Might be several 0-0 BatchMeta in a row without an error though - log.Printf("Batch Meta found at the end of the batch") - return false - } - msg := i.msg.Decode() - if msg == nil { - return false - } - m := msg.(*IOSBatchMeta) - i.index = m.FirstIndex - i.timestamp = int64(m.Timestamp) - isBatchMeta = true - // continue readLoop - case MsgTimestamp: - msg := i.msg.Decode() - if msg == nil { - return false - } - m := msg.(*Timestamp) - i.timestamp = int64(m.Timestamp) - // No skipping here for making it easy to encode back the same sequence of message - // continue readLoop - case MsgSessionStart: - msg := i.msg.Decode() - if msg == nil { - return false - } - m := msg.(*SessionStart) - i.timestamp = int64(m.Timestamp) - case MsgSessionEnd: - msg := i.msg.Decode() - if msg == nil { - return false - } - m := msg.(*SessionEnd) - i.timestamp = int64(m.Timestamp) - case MsgSetPageLocation: - msg := i.msg.Decode() - if msg == nil { - return false - } - m := msg.(*SetPageLocation) - i.url = m.URL - } - i.msg.Meta().Index = i.index - i.msg.Meta().Timestamp = i.timestamp - i.msg.Meta().Url = i.url - - if !isBatchMeta { // Without that indexes will be unique anyway, though shifted by 1 because BatchMeta is not counted in tracker - i.index++ - } - return true -} - -func (i *iteratorImpl) Type() int { - return int(i.msgType) -} - -func (i *iteratorImpl) Message() Message { - return i.msg -} - -func (i *iteratorImpl) Close() { - _, err := i.data.Seek(0, io.SeekEnd) - if err != nil { - log.Printf("can't set seek pointer at the end: %s", err) - } -} - -func messageHasSize(msgType uint64) bool { - return !(msgType == 80 || msgType == 81 || msgType == 82) -} diff --git a/backend/pkg/messages/extra.go b/backend/pkg/messages/extra.go deleted file mode 100644 index b2a57e2ad..000000000 --- a/backend/pkg/messages/extra.go +++ /dev/null @@ -1,56 +0,0 @@ -package messages - -import ( - "encoding/binary" - "fmt" - "io" -) - -type SessionSearch struct { - message - Timestamp uint64 - Partition uint64 -} - -func (msg *SessionSearch) Encode() []byte { - buf := make([]byte, 11) - buf[0] = 127 - p := 1 - p = WriteUint(msg.Timestamp, buf, p) - p = WriteUint(msg.Partition, buf, p) - return buf[:p] -} - -func (msg *SessionSearch) EncodeWithIndex() []byte { - encoded := msg.Encode() - if IsIOSType(msg.TypeID()) { - return encoded - } - data := make([]byte, len(encoded)+8) - copy(data[8:], encoded[:]) - binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index) - return data -} - -func (msg *SessionSearch) Decode() Message { - return msg -} - -func (msg *SessionSearch) TypeID() int { - return 127 -} - -func DecodeExtraMessage(code string, reader io.Reader) (Message, error) { - var err error - if code != "127" { - return nil, fmt.Errorf("unknown message code: %s", code) - } - msg := &SessionSearch{} - if msg.Timestamp, err = ReadUint(reader); err != nil { - return nil, fmt.Errorf("can't read message timestamp: %s", err) - } - if msg.Partition, err = ReadUint(reader); err != nil { - return nil, fmt.Errorf("can't read last partition: %s", err) - } - return msg, nil -} diff --git a/backend/pkg/messages/facade.go b/backend/pkg/messages/facade.go deleted file mode 100644 index ebc9e7983..000000000 --- a/backend/pkg/messages/facade.go +++ /dev/null @@ -1,5 +0,0 @@ -package messages - -func Encode(msg Message) []byte { - return msg.Encode() -} diff --git a/backend/pkg/messages/filters.go b/backend/pkg/messages/filters.go index e79d1d987..399c1863c 100644 --- a/backend/pkg/messages/filters.go +++ b/backend/pkg/messages/filters.go @@ -2,9 +2,13 @@ package messages func IsReplayerType(id int) bool { - return 0 == id || 4 == id || 5 == id || 6 == id || 7 == id || 8 == id || 9 == id || 10 == id || 11 == id || 12 == id || 13 == id || 14 == id || 15 == id || 16 == id || 18 == id || 19 == id || 20 == id || 22 == id || 37 == id || 38 == id || 39 == id || 40 == id || 41 == id || 44 == id || 45 == id || 46 == id || 47 == id || 48 == id || 49 == id || 54 == id || 55 == id || 59 == id || 60 == id || 61 == id || 67 == id || 69 == id || 70 == id || 71 == id || 72 == id || 73 == id || 74 == id || 75 == id || 76 == id || 77 == id || 79 == id || 90 == id || 93 == id || 96 == id || 100 == id || 102 == id || 103 == id || 105 == id + return 80 != id && 81 != id && 82 != id && 1 != id && 3 != id && 17 != id && 23 != id && 24 != id && 25 != id && 26 != id && 27 != id && 28 != id && 29 != id && 30 != id && 31 != id && 32 != id && 33 != id && 35 != id && 36 != id && 42 != id && 43 != id && 50 != id && 51 != id && 52 != id && 53 != id && 56 != id && 62 != id && 63 != id && 64 != id && 66 != id && 78 != id && 126 != id && 127 != id && 107 != id && 91 != id && 92 != id && 94 != id && 95 != id && 97 != id && 98 != id && 99 != id && 101 != id && 104 != id && 110 != id && 111 != id } func IsIOSType(id int) bool { return 107 == id || 90 == id || 91 == id || 92 == id || 93 == id || 94 == id || 95 == id || 96 == id || 97 == id || 98 == id || 99 == id || 100 == id || 101 == id || 102 == id || 103 == id || 104 == id || 105 == id || 110 == id || 111 == id } + +func IsDOMType(id int) bool { + return 0 == id || 4 == id || 5 == id || 6 == id || 7 == id || 8 == id || 9 == id || 10 == id || 11 == id || 12 == id || 13 == id || 14 == id || 15 == id || 16 == id || 18 == id || 19 == id || 20 == id || 37 == id || 38 == id || 49 == id || 54 == id || 55 == id || 57 == id || 58 == id || 59 == id || 60 == id || 61 == id || 67 == id || 69 == id || 70 == id || 71 == id || 72 == id || 73 == id || 74 == id || 75 == id || 76 == id || 77 == id || 90 == id || 93 == id || 96 == id || 100 == id || 102 == id || 103 == id || 105 == id +} diff --git a/backend/pkg/messages/iterator.go b/backend/pkg/messages/iterator.go new file mode 100644 index 000000000..7b7991b19 --- /dev/null +++ b/backend/pkg/messages/iterator.go @@ -0,0 +1,216 @@ +package messages + +import ( + "bytes" + "fmt" + "io" + "log" +) + +// MessageHandler processes one message using service logic +type MessageHandler func(Message) + +// MessageIterator iterates by all messages in batch +type MessageIterator interface { + Iterate(batchData []byte, batchInfo *BatchInfo) +} + +type messageIteratorImpl struct { + filter map[int]struct{} + preFilter map[int]struct{} + handler MessageHandler + autoDecode bool + version uint64 + size uint64 + canSkip bool + broken bool + messageInfo *message + batchInfo *BatchInfo +} + +func NewMessageIterator(messageHandler MessageHandler, messageFilter []int, autoDecode bool) MessageIterator { + iter := &messageIteratorImpl{handler: messageHandler, autoDecode: autoDecode} + if len(messageFilter) != 0 { + filter := make(map[int]struct{}, len(messageFilter)) + for _, msgType := range messageFilter { + filter[msgType] = struct{}{} + } + iter.filter = filter + } + iter.preFilter = map[int]struct{}{ + MsgBatchMetadata: {}, MsgBatchMeta: {}, MsgTimestamp: {}, + MsgSessionStart: {}, MsgSessionEnd: {}, MsgSetPageLocation: {}, + MsgSessionEndDeprecated: {}} + return iter +} + +func (i *messageIteratorImpl) prepareVars(batchInfo *BatchInfo) { + i.batchInfo = batchInfo + i.messageInfo = &message{batch: batchInfo} + i.version = 0 + i.canSkip = false + i.broken = false + i.size = 0 +} + +func (i *messageIteratorImpl) Iterate(batchData []byte, batchInfo *BatchInfo) { + // Prepare iterator before processing messages in batch + i.prepareVars(batchInfo) + + // Initialize batch reader + reader := bytes.NewReader(batchData) + + // Process until end of batch or parsing error + for { + // Increase message index (can be overwritten by batch info message) + i.messageInfo.Index++ + + if i.broken { + log.Printf("skipping broken batch, info: %s", i.batchInfo.Info()) + return + } + + if i.canSkip { + if _, err := reader.Seek(int64(i.size), io.SeekCurrent); err != nil { + log.Printf("can't skip message: %s, info: %s", err, i.batchInfo.Info()) + return + } + } + i.canSkip = false + + // Read message type + msgType, err := ReadUint(reader) + if err != nil { + if err != io.EOF { + log.Printf("can't read message type: %s, info: %s", err, i.batchInfo.Info()) + } + return + } + + var msg Message + // Read message body (and decode if protocol version less than 1) + if i.version > 0 && messageHasSize(msgType) { + // Read message size if it is a new protocol version + i.size, err = ReadSize(reader) + if err != nil { + log.Printf("can't read message size: %s, info: %s", err, i.batchInfo.Info()) + return + } + msg = &RawMessage{ + tp: msgType, + size: i.size, + reader: reader, + raw: batchData, + skipped: &i.canSkip, + broken: &i.broken, + meta: i.messageInfo, + } + i.canSkip = true + } else { + msg, err = ReadMessage(msgType, reader) + if err != nil { + if err != io.EOF { + log.Printf("can't read message body: %s, info: %s", err, i.batchInfo.Info()) + } + return + } + msg = transformDeprecated(msg) + } + + // Preprocess "system" messages + if _, ok := i.preFilter[msg.TypeID()]; ok { + msg = msg.Decode() + if msg == nil { + log.Printf("decode error, type: %d, info: %s", msgType, i.batchInfo.Info()) + return + } + if err := i.preprocessing(msg); err != nil { + log.Printf("message preprocessing err: %s", err) + return + } + } + + // Skip messages we don't have in filter + if i.filter != nil { + if _, ok := i.filter[msg.TypeID()]; !ok { + continue + } + } + + if i.autoDecode { + msg = msg.Decode() + if msg == nil { + log.Printf("decode error, type: %d, info: %s", msgType, i.batchInfo.Info()) + return + } + } + + // Set meta information for message + msg.Meta().SetMeta(i.messageInfo) + + // Process message + i.handler(msg) + } +} + +func (i *messageIteratorImpl) zeroTsLog(msgType string) { + log.Printf("zero timestamp in %s, info: %s", msgType, i.batchInfo.Info()) +} + +func (i *messageIteratorImpl) preprocessing(msg Message) error { + switch m := msg.(type) { + case *BatchMetadata: + if i.messageInfo.Index > 1 { // Might be several 0-0 BatchMeta in a row without an error though + return fmt.Errorf("batchMetadata found at the end of the batch, info: %s", i.batchInfo.Info()) + } + if m.Version > 1 { + return fmt.Errorf("incorrect batch version: %d, skip current batch, info: %s", i.version, i.batchInfo.Info()) + } + i.messageInfo.Index = m.PageNo<<32 + m.FirstIndex // 2^32 is the maximum count of messages per page (ha-ha) + i.messageInfo.Timestamp = m.Timestamp + if m.Timestamp == 0 { + i.zeroTsLog("BatchMetadata") + } + i.messageInfo.Url = m.Url + i.version = m.Version + i.batchInfo.version = m.Version + + case *BatchMeta: // Is not required to be present in batch since IOS doesn't have it (though we might change it) + if i.messageInfo.Index > 1 { // Might be several 0-0 BatchMeta in a row without an error though + return fmt.Errorf("batchMeta found at the end of the batch, info: %s", i.batchInfo.Info()) + } + i.messageInfo.Index = m.PageNo<<32 + m.FirstIndex // 2^32 is the maximum count of messages per page (ha-ha) + i.messageInfo.Timestamp = m.Timestamp + if m.Timestamp == 0 { + i.zeroTsLog("BatchMeta") + } + + case *Timestamp: + i.messageInfo.Timestamp = int64(m.Timestamp) + if m.Timestamp == 0 { + i.zeroTsLog("Timestamp") + } + + case *SessionStart: + i.messageInfo.Timestamp = int64(m.Timestamp) + if m.Timestamp == 0 { + i.zeroTsLog("SessionStart") + log.Printf("zero session start, project: %d, UA: %s, tracker: %s, info: %s", + m.ProjectID, m.UserAgent, m.TrackerVersion, i.batchInfo.Info()) + } + + case *SessionEnd: + i.messageInfo.Timestamp = int64(m.Timestamp) + if m.Timestamp == 0 { + i.zeroTsLog("SessionEnd") + } + + case *SetPageLocation: + i.messageInfo.Url = m.URL + } + return nil +} + +func messageHasSize(msgType uint64) bool { + return !(msgType == 80 || msgType == 81 || msgType == 82) +} diff --git a/backend/pkg/messages/legacy-message-transform.go b/backend/pkg/messages/legacy-message-transform.go index 3a42cdab0..5e2bd3ed7 100644 --- a/backend/pkg/messages/legacy-message-transform.go +++ b/backend/pkg/messages/legacy-message-transform.go @@ -2,13 +2,18 @@ package messages func transformDeprecated(msg Message) Message { switch m := msg.(type) { - case *MouseClickDepricated: - return &MouseClick{ - ID: m.ID, - HesitationTime: m.HesitationTime, - Label: m.Label, + case *JSExceptionDeprecated: + return &JSException{ + Name: m.Name, + Message: m.Message, + Payload: m.Payload, + Metadata: "{}", + } + case *SessionEndDeprecated: + return &SessionEnd{ + Timestamp: m.Timestamp, + EncryptionKey: "", } - default: - return msg } + return msg } diff --git a/backend/pkg/messages/message.go b/backend/pkg/messages/message.go index 16ab1920d..7bb2572eb 100644 --- a/backend/pkg/messages/message.go +++ b/backend/pkg/messages/message.go @@ -1,20 +1,6 @@ package messages -type message struct { - Timestamp int64 - Index uint64 - Url string -} - -func (m *message) Meta() *message { - return m -} - -func (m *message) SetMeta(origin *message) { - m.Timestamp = origin.Timestamp - m.Index = origin.Index - m.Url = origin.Url -} +import "fmt" type Message interface { Encode() []byte @@ -22,4 +8,74 @@ type Message interface { Decode() Message TypeID() int Meta() *message + SessionID() uint64 +} + +// BatchInfo represents common information for all messages inside data batch +type BatchInfo struct { + sessionID uint64 + id uint64 + topic string + partition uint64 + timestamp int64 + version uint64 +} + +func NewBatchInfo(sessID uint64, topic string, id, partition uint64, ts int64) *BatchInfo { + return &BatchInfo{ + sessionID: sessID, + id: id, + topic: topic, + partition: partition, + timestamp: ts, + } +} + +func (b *BatchInfo) SessionID() uint64 { + return b.sessionID +} + +func (b *BatchInfo) ID() uint64 { + return b.id +} + +func (b *BatchInfo) Timestamp() int64 { + return b.timestamp +} + +func (b *BatchInfo) Info() string { + return fmt.Sprintf("session: %d, partition: %d, offset: %d, ver: %d", b.sessionID, b.partition, b.id, b.version) +} + +type message struct { + Timestamp int64 + Index uint64 + Url string + batch *BatchInfo +} + +func (m *message) Batch() *BatchInfo { + return m.batch +} + +func (m *message) Meta() *message { + return m +} + +func (m *message) SetMeta(origin *message) { + m.batch = origin.batch + m.Timestamp = origin.Timestamp + m.Index = origin.Index + m.Url = origin.Url +} + +func (m *message) SessionID() uint64 { + return m.batch.sessionID +} + +func (m *message) SetSessionID(sessID uint64) { + if m.batch == nil { + m.batch = &BatchInfo{} + } + m.batch.sessionID = sessID } diff --git a/backend/pkg/messages/messages.go b/backend/pkg/messages/messages.go index 8cdb95722..138f8dcb7 100644 --- a/backend/pkg/messages/messages.go +++ b/backend/pkg/messages/messages.go @@ -14,7 +14,7 @@ const ( MsgSessionStart = 1 - MsgSessionEnd = 3 + MsgSessionEndDeprecated = 3 MsgSetPageLocation = 4 @@ -50,15 +50,13 @@ const ( MsgMouseMove = 20 - MsgMouseClickDepricated = 21 - MsgConsoleLog = 22 MsgPageLoadTiming = 23 MsgPageRenderTiming = 24 - MsgJSException = 25 + MsgJSExceptionDeprecated = 25 MsgIntegrationEvent = 26 @@ -76,8 +74,6 @@ const ( MsgClickEvent = 33 - MsgErrorEvent = 34 - MsgResourceEvent = 35 MsgCustomEvent = 36 @@ -122,6 +118,10 @@ const ( MsgPerformanceTrackAggr = 56 + MsgLoadFontFace = 57 + + MsgSetNodeFocus = 58 + MsgLongTask = 59 MsgSetNodeAttributeURLBased = 60 @@ -158,6 +158,12 @@ const ( MsgZustand = 79 + MsgJSException = 78 + + MsgSessionEnd = 126 + + MsgSessionSearch = 127 + MsgIOSBatchMeta = 107 MsgIOSSessionStart = 90 @@ -401,12 +407,12 @@ func (msg *SessionStart) TypeID() int { return 1 } -type SessionEnd struct { +type SessionEndDeprecated struct { message Timestamp uint64 } -func (msg *SessionEnd) Encode() []byte { +func (msg *SessionEndDeprecated) Encode() []byte { buf := make([]byte, 11) buf[0] = 3 p := 1 @@ -414,7 +420,7 @@ func (msg *SessionEnd) Encode() []byte { return buf[:p] } -func (msg *SessionEnd) EncodeWithIndex() []byte { +func (msg *SessionEndDeprecated) EncodeWithIndex() []byte { encoded := msg.Encode() if IsIOSType(msg.TypeID()) { return encoded @@ -425,11 +431,11 @@ func (msg *SessionEnd) EncodeWithIndex() []byte { return data } -func (msg *SessionEnd) Decode() Message { +func (msg *SessionEndDeprecated) Decode() Message { return msg } -func (msg *SessionEnd) TypeID() int { +func (msg *SessionEndDeprecated) TypeID() int { return 3 } @@ -1024,42 +1030,6 @@ func (msg *MouseMove) TypeID() int { return 20 } -type MouseClickDepricated struct { - message - ID uint64 - HesitationTime uint64 - Label string -} - -func (msg *MouseClickDepricated) Encode() []byte { - buf := make([]byte, 31+len(msg.Label)) - buf[0] = 21 - p := 1 - p = WriteUint(msg.ID, buf, p) - p = WriteUint(msg.HesitationTime, buf, p) - p = WriteString(msg.Label, buf, p) - return buf[:p] -} - -func (msg *MouseClickDepricated) EncodeWithIndex() []byte { - encoded := msg.Encode() - if IsIOSType(msg.TypeID()) { - return encoded - } - data := make([]byte, len(encoded)+8) - copy(data[8:], encoded[:]) - binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index) - return data -} - -func (msg *MouseClickDepricated) Decode() Message { - return msg -} - -func (msg *MouseClickDepricated) TypeID() int { - return 21 -} - type ConsoleLog struct { message Level string @@ -1178,14 +1148,14 @@ func (msg *PageRenderTiming) TypeID() int { return 24 } -type JSException struct { +type JSExceptionDeprecated struct { message Name string Message string Payload string } -func (msg *JSException) Encode() []byte { +func (msg *JSExceptionDeprecated) Encode() []byte { buf := make([]byte, 31+len(msg.Name)+len(msg.Message)+len(msg.Payload)) buf[0] = 25 p := 1 @@ -1195,7 +1165,7 @@ func (msg *JSException) Encode() []byte { return buf[:p] } -func (msg *JSException) EncodeWithIndex() []byte { +func (msg *JSExceptionDeprecated) EncodeWithIndex() []byte { encoded := msg.Encode() if IsIOSType(msg.TypeID()) { return encoded @@ -1206,11 +1176,11 @@ func (msg *JSException) EncodeWithIndex() []byte { return data } -func (msg *JSException) Decode() Message { +func (msg *JSExceptionDeprecated) Decode() Message { return msg } -func (msg *JSException) TypeID() int { +func (msg *JSExceptionDeprecated) TypeID() int { return 25 } @@ -1530,48 +1500,6 @@ func (msg *ClickEvent) TypeID() int { return 33 } -type ErrorEvent struct { - message - MessageID uint64 - Timestamp uint64 - Source string - Name string - Message string - Payload string -} - -func (msg *ErrorEvent) Encode() []byte { - buf := make([]byte, 61+len(msg.Source)+len(msg.Name)+len(msg.Message)+len(msg.Payload)) - buf[0] = 34 - p := 1 - p = WriteUint(msg.MessageID, buf, p) - p = WriteUint(msg.Timestamp, buf, p) - p = WriteString(msg.Source, buf, p) - p = WriteString(msg.Name, buf, p) - p = WriteString(msg.Message, buf, p) - p = WriteString(msg.Payload, buf, p) - return buf[:p] -} - -func (msg *ErrorEvent) EncodeWithIndex() []byte { - encoded := msg.Encode() - if IsIOSType(msg.TypeID()) { - return encoded - } - data := make([]byte, len(encoded)+8) - copy(data[8:], encoded[:]) - binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index) - return data -} - -func (msg *ErrorEvent) Decode() Message { - return msg -} - -func (msg *ErrorEvent) TypeID() int { - return 34 -} - type ResourceEvent struct { message MessageID uint64 @@ -2424,6 +2352,76 @@ func (msg *PerformanceTrackAggr) TypeID() int { return 56 } +type LoadFontFace struct { + message + ParentID uint64 + Family string + Source string + Descriptors string +} + +func (msg *LoadFontFace) Encode() []byte { + buf := make([]byte, 41+len(msg.Family)+len(msg.Source)+len(msg.Descriptors)) + buf[0] = 57 + p := 1 + p = WriteUint(msg.ParentID, buf, p) + p = WriteString(msg.Family, buf, p) + p = WriteString(msg.Source, buf, p) + p = WriteString(msg.Descriptors, buf, p) + return buf[:p] +} + +func (msg *LoadFontFace) EncodeWithIndex() []byte { + encoded := msg.Encode() + if IsIOSType(msg.TypeID()) { + return encoded + } + data := make([]byte, len(encoded)+8) + copy(data[8:], encoded[:]) + binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index) + return data +} + +func (msg *LoadFontFace) Decode() Message { + return msg +} + +func (msg *LoadFontFace) TypeID() int { + return 57 +} + +type SetNodeFocus struct { + message + ID int64 +} + +func (msg *SetNodeFocus) Encode() []byte { + buf := make([]byte, 11) + buf[0] = 58 + p := 1 + p = WriteInt(msg.ID, buf, p) + return buf[:p] +} + +func (msg *SetNodeFocus) EncodeWithIndex() []byte { + encoded := msg.Encode() + if IsIOSType(msg.TypeID()) { + return encoded + } + data := make([]byte, len(encoded)+8) + copy(data[8:], encoded[:]) + binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index) + return data +} + +func (msg *SetNodeFocus) Decode() Message { + return msg +} + +func (msg *SetNodeFocus) TypeID() int { + return 58 +} + type LongTask struct { message Timestamp uint64 @@ -3074,6 +3072,112 @@ func (msg *Zustand) TypeID() int { return 79 } +type JSException struct { + message + Name string + Message string + Payload string + Metadata string +} + +func (msg *JSException) Encode() []byte { + buf := make([]byte, 41+len(msg.Name)+len(msg.Message)+len(msg.Payload)+len(msg.Metadata)) + buf[0] = 78 + p := 1 + p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Message, buf, p) + p = WriteString(msg.Payload, buf, p) + p = WriteString(msg.Metadata, buf, p) + return buf[:p] +} + +func (msg *JSException) EncodeWithIndex() []byte { + encoded := msg.Encode() + if IsIOSType(msg.TypeID()) { + return encoded + } + data := make([]byte, len(encoded)+8) + copy(data[8:], encoded[:]) + binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index) + return data +} + +func (msg *JSException) Decode() Message { + return msg +} + +func (msg *JSException) TypeID() int { + return 78 +} + +type SessionEnd struct { + message + Timestamp uint64 + EncryptionKey string +} + +func (msg *SessionEnd) Encode() []byte { + buf := make([]byte, 21+len(msg.EncryptionKey)) + buf[0] = 126 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.EncryptionKey, buf, p) + return buf[:p] +} + +func (msg *SessionEnd) EncodeWithIndex() []byte { + encoded := msg.Encode() + if IsIOSType(msg.TypeID()) { + return encoded + } + data := make([]byte, len(encoded)+8) + copy(data[8:], encoded[:]) + binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index) + return data +} + +func (msg *SessionEnd) Decode() Message { + return msg +} + +func (msg *SessionEnd) TypeID() int { + return 126 +} + +type SessionSearch struct { + message + Timestamp uint64 + Partition uint64 +} + +func (msg *SessionSearch) Encode() []byte { + buf := make([]byte, 21) + buf[0] = 127 + p := 1 + p = WriteUint(msg.Timestamp, buf, p) + p = WriteUint(msg.Partition, buf, p) + return buf[:p] +} + +func (msg *SessionSearch) EncodeWithIndex() []byte { + encoded := msg.Encode() + if IsIOSType(msg.TypeID()) { + return encoded + } + data := make([]byte, len(encoded)+8) + copy(data[8:], encoded[:]) + binary.LittleEndian.PutUint64(data[0:], msg.Meta().Index) + return data +} + +func (msg *SessionSearch) Decode() Message { + return msg +} + +func (msg *SessionSearch) TypeID() int { + return 127 +} + type IOSBatchMeta struct { message Timestamp uint64 diff --git a/backend/pkg/messages/primitives.go b/backend/pkg/messages/primitives.go index eb65ae7b1..1d3d2410b 100644 --- a/backend/pkg/messages/primitives.go +++ b/backend/pkg/messages/primitives.go @@ -8,13 +8,17 @@ import ( "log" ) +var ( + one = []byte{0} + three = []byte{0, 0, 0} +) + func ReadByte(reader io.Reader) (byte, error) { - p := make([]byte, 1) - _, err := io.ReadFull(reader, p) + _, err := io.ReadFull(reader, one) if err != nil { return 0, err } - return p[0], nil + return one[0], nil } func ReadData(reader io.Reader) ([]byte, error) { @@ -156,8 +160,7 @@ func WriteSize(size uint64, buf []byte, p int) { } func ReadSize(reader io.Reader) (uint64, error) { - buf := make([]byte, 3) - n, err := io.ReadFull(reader, buf) + n, err := io.ReadFull(reader, three) if err != nil { return 0, err } @@ -165,7 +168,7 @@ func ReadSize(reader io.Reader) (uint64, error) { return 0, fmt.Errorf("read only %d of 3 size bytes", n) } var size uint64 - for i, b := range buf { + for i, b := range three { size += uint64(b) << (8 * i) } return size, nil diff --git a/backend/pkg/messages/raw.go b/backend/pkg/messages/raw.go index b9dba5de2..dbc71f4e6 100644 --- a/backend/pkg/messages/raw.go +++ b/backend/pkg/messages/raw.go @@ -13,30 +13,45 @@ type RawMessage struct { size uint64 data []byte reader *bytes.Reader + raw []byte meta *message encoded bool skipped *bool + broken *bool } func (m *RawMessage) Encode() []byte { if m.encoded { return m.data } - m.data = make([]byte, m.size+1) - m.data[0] = uint8(m.tp) - m.encoded = true - *m.skipped = false - _, err := io.ReadFull(m.reader, m.data[1:]) - if err != nil { - log.Printf("message encode err: %s", err) + // Try to avoid EOF error + if m.reader.Len() < int(m.size) { return nil } + // Get current batch position + currPos, err := m.reader.Seek(0, io.SeekCurrent) + if err != nil { + log.Printf("can't get current batch position: %s", err) + return nil + } + // "Move" message type + if currPos == 0 { + log.Printf("can't move message type, curr position = %d", currPos) + return nil + } + // Dirty hack to avoid extra memory allocation + m.raw[currPos-1] = uint8(m.tp) + m.data = m.raw[currPos-1 : currPos+int64(m.size)] + m.encoded = true return m.data } func (m *RawMessage) EncodeWithIndex() []byte { if !m.encoded { - m.Encode() + if m.Encode() == nil { + *m.broken = true + return nil + } } if IsIOSType(int(m.tp)) { return m.data @@ -49,13 +64,18 @@ func (m *RawMessage) EncodeWithIndex() []byte { func (m *RawMessage) Decode() Message { if !m.encoded { - m.Encode() + if m.Encode() == nil { + *m.broken = true + return nil + } } msg, err := ReadMessage(m.tp, bytes.NewReader(m.data[1:])) if err != nil { log.Printf("decode err: %s", err) + *m.broken = true return nil } + msg = transformDeprecated(msg) msg.Meta().SetMeta(m.meta) return msg } @@ -67,3 +87,10 @@ func (m *RawMessage) TypeID() int { func (m *RawMessage) Meta() *message { return m.meta } + +func (m *RawMessage) SessionID() uint64 { + if m.meta != nil { + return m.meta.SessionID() + } + return 0 +} diff --git a/backend/pkg/messages/read-message.go b/backend/pkg/messages/read-message.go index 1b0f579af..5988ebe62 100644 --- a/backend/pkg/messages/read-message.go +++ b/backend/pkg/messages/read-message.go @@ -117,9 +117,9 @@ func DecodeSessionStart(reader io.Reader) (Message, error) { return msg, err } -func DecodeSessionEnd(reader io.Reader) (Message, error) { +func DecodeSessionEndDeprecated(reader io.Reader) (Message, error) { var err error = nil - msg := &SessionEnd{} + msg := &SessionEndDeprecated{} if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } @@ -349,21 +349,6 @@ func DecodeMouseMove(reader io.Reader) (Message, error) { return msg, err } -func DecodeMouseClickDepricated(reader io.Reader) (Message, error) { - var err error = nil - msg := &MouseClickDepricated{} - if msg.ID, err = ReadUint(reader); err != nil { - return nil, err - } - if msg.HesitationTime, err = ReadUint(reader); err != nil { - return nil, err - } - if msg.Label, err = ReadString(reader); err != nil { - return nil, err - } - return msg, err -} - func DecodeConsoleLog(reader io.Reader) (Message, error) { var err error = nil msg := &ConsoleLog{} @@ -424,9 +409,9 @@ func DecodePageRenderTiming(reader io.Reader) (Message, error) { return msg, err } -func DecodeJSException(reader io.Reader) (Message, error) { +func DecodeJSExceptionDeprecated(reader io.Reader) (Message, error) { var err error = nil - msg := &JSException{} + msg := &JSExceptionDeprecated{} if msg.Name, err = ReadString(reader); err != nil { return nil, err } @@ -601,30 +586,6 @@ func DecodeClickEvent(reader io.Reader) (Message, error) { return msg, err } -func DecodeErrorEvent(reader io.Reader) (Message, error) { - var err error = nil - msg := &ErrorEvent{} - if msg.MessageID, err = ReadUint(reader); err != nil { - return nil, err - } - if msg.Timestamp, err = ReadUint(reader); err != nil { - return nil, err - } - if msg.Source, err = ReadString(reader); err != nil { - return nil, err - } - if msg.Name, err = ReadString(reader); err != nil { - return nil, err - } - if msg.Message, err = ReadString(reader); err != nil { - return nil, err - } - if msg.Payload, err = ReadString(reader); err != nil { - return nil, err - } - return msg, err -} - func DecodeResourceEvent(reader io.Reader) (Message, error) { var err error = nil msg := &ResourceEvent{} @@ -1045,6 +1006,33 @@ func DecodePerformanceTrackAggr(reader io.Reader) (Message, error) { return msg, err } +func DecodeLoadFontFace(reader io.Reader) (Message, error) { + var err error = nil + msg := &LoadFontFace{} + if msg.ParentID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Family, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Source, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Descriptors, err = ReadString(reader); err != nil { + return nil, err + } + return msg, err +} + +func DecodeSetNodeFocus(reader io.Reader) (Message, error) { + var err error = nil + msg := &SetNodeFocus{} + if msg.ID, err = ReadInt(reader); err != nil { + return nil, err + } + return msg, err +} + func DecodeLongTask(reader io.Reader) (Message, error) { var err error = nil msg := &LongTask{} @@ -1318,6 +1306,48 @@ func DecodeZustand(reader io.Reader) (Message, error) { return msg, err } +func DecodeJSException(reader io.Reader) (Message, error) { + var err error = nil + msg := &JSException{} + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Message, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Metadata, err = ReadString(reader); err != nil { + return nil, err + } + return msg, err +} + +func DecodeSessionEnd(reader io.Reader) (Message, error) { + var err error = nil + msg := &SessionEnd{} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.EncryptionKey, err = ReadString(reader); err != nil { + return nil, err + } + return msg, err +} + +func DecodeSessionSearch(reader io.Reader) (Message, error) { + var err error = nil + msg := &SessionSearch{} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Partition, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, err +} + func DecodeIOSBatchMeta(reader io.Reader) (Message, error) { var err error = nil msg := &IOSBatchMeta{} @@ -1739,7 +1769,7 @@ func ReadMessage(t uint64, reader io.Reader) (Message, error) { return DecodeSessionStart(reader) case 3: - return DecodeSessionEnd(reader) + return DecodeSessionEndDeprecated(reader) case 4: return DecodeSetPageLocation(reader) @@ -1792,9 +1822,6 @@ func ReadMessage(t uint64, reader io.Reader) (Message, error) { case 20: return DecodeMouseMove(reader) - case 21: - return DecodeMouseClickDepricated(reader) - case 22: return DecodeConsoleLog(reader) @@ -1805,7 +1832,7 @@ func ReadMessage(t uint64, reader io.Reader) (Message, error) { return DecodePageRenderTiming(reader) case 25: - return DecodeJSException(reader) + return DecodeJSExceptionDeprecated(reader) case 26: return DecodeIntegrationEvent(reader) @@ -1831,9 +1858,6 @@ func ReadMessage(t uint64, reader io.Reader) (Message, error) { case 33: return DecodeClickEvent(reader) - case 34: - return DecodeErrorEvent(reader) - case 35: return DecodeResourceEvent(reader) @@ -1900,6 +1924,12 @@ func ReadMessage(t uint64, reader io.Reader) (Message, error) { case 56: return DecodePerformanceTrackAggr(reader) + case 57: + return DecodeLoadFontFace(reader) + + case 58: + return DecodeSetNodeFocus(reader) + case 59: return DecodeLongTask(reader) @@ -1954,6 +1984,15 @@ func ReadMessage(t uint64, reader io.Reader) (Message, error) { case 79: return DecodeZustand(reader) + case 78: + return DecodeJSException(reader) + + case 126: + return DecodeSessionEnd(reader) + + case 127: + return DecodeSessionSearch(reader) + case 107: return DecodeIOSBatchMeta(reader) diff --git a/backend/pkg/queue/import.go b/backend/pkg/queue/import.go index d5daa1dd5..978798ce2 100644 --- a/backend/pkg/queue/import.go +++ b/backend/pkg/queue/import.go @@ -1,12 +1,13 @@ package queue import ( + "openreplay/backend/pkg/messages" "openreplay/backend/pkg/queue/types" "openreplay/backend/pkg/redisstream" ) -func NewConsumer(group string, topics []string, handler types.MessageHandler, _ bool, _ int) types.Consumer { - return redisstream.NewConsumer(group, topics, handler) +func NewConsumer(group string, topics []string, iterator messages.MessageIterator, _ bool, _ int) types.Consumer { + return redisstream.NewConsumer(group, topics, iterator) } func NewProducer(_ int, _ bool) types.Producer { diff --git a/backend/pkg/queue/messages.go b/backend/pkg/queue/messages.go deleted file mode 100644 index f52813492..000000000 --- a/backend/pkg/queue/messages.go +++ /dev/null @@ -1,12 +0,0 @@ -package queue - -import ( - "openreplay/backend/pkg/messages" - "openreplay/backend/pkg/queue/types" -) - -func NewMessageConsumer(group string, topics []string, handler types.RawMessageHandler, autoCommit bool, messageSizeLimit int) types.Consumer { - return NewConsumer(group, topics, func(sessionID uint64, value []byte, meta *types.Meta) { - handler(sessionID, messages.NewIterator(value), meta) - }, autoCommit, messageSizeLimit) -} diff --git a/backend/pkg/queue/types/types.go b/backend/pkg/queue/types/types.go index 0f196c608..48408ce10 100644 --- a/backend/pkg/queue/types/types.go +++ b/backend/pkg/queue/types/types.go @@ -1,30 +1,17 @@ package types -import ( - "openreplay/backend/pkg/messages" -) - +// Consumer reads batches of session data from queue (redis or kafka) type Consumer interface { ConsumeNext() error - Commit() error CommitBack(gap int64) error + Commit() error Close() - HasFirstPartition() bool } +// Producer sends batches of session data to queue (redis or kafka) type Producer interface { Produce(topic string, key uint64, value []byte) error ProduceToPartition(topic string, partition, key uint64, value []byte) error - Close(timeout int) Flush(timeout int) + Close(timeout int) } - -type Meta struct { - ID uint64 - Topic string - Timestamp int64 -} - -type MessageHandler func(uint64, []byte, *Meta) -type DecodedMessageHandler func(uint64, messages.Message, *Meta) -type RawMessageHandler func(uint64, messages.Iterator, *Meta) diff --git a/backend/pkg/redisstream/consumer.go b/backend/pkg/redisstream/consumer.go index bae70120d..228b2c7a0 100644 --- a/backend/pkg/redisstream/consumer.go +++ b/backend/pkg/redisstream/consumer.go @@ -3,6 +3,7 @@ package redisstream import ( "log" "net" + "openreplay/backend/pkg/messages" "sort" "strconv" "strings" @@ -10,8 +11,6 @@ import ( _redis "github.com/go-redis/redis" "github.com/pkg/errors" - - "openreplay/backend/pkg/queue/types" ) type idsInfo struct { @@ -21,16 +20,16 @@ type idsInfo struct { type streamPendingIDsMap map[string]*idsInfo type Consumer struct { - redis *_redis.Client - streams []string - group string - messageHandler types.MessageHandler - idsPending streamPendingIDsMap - lastTs int64 - autoCommit bool + redis *_redis.Client + streams []string + group string + messageIterator messages.MessageIterator + idsPending streamPendingIDsMap + lastTs int64 + autoCommit bool } -func NewConsumer(group string, streams []string, messageHandler types.MessageHandler) *Consumer { +func NewConsumer(group string, streams []string, messageIterator messages.MessageIterator) *Consumer { redis := getRedisClient() for _, stream := range streams { err := redis.XGroupCreateMkStream(stream, group, "0").Err() @@ -52,12 +51,12 @@ func NewConsumer(group string, streams []string, messageHandler types.MessageHan } return &Consumer{ - redis: redis, - messageHandler: messageHandler, - streams: streams, - group: group, - autoCommit: true, - idsPending: idsPending, + redis: redis, + messageIterator: messageIterator, + streams: streams, + group: group, + autoCommit: true, + idsPending: idsPending, } } @@ -102,11 +101,8 @@ func (c *Consumer) ConsumeNext() error { if idx > 0x1FFF { return errors.New("Too many messages per ms in redis") } - c.messageHandler(sessionID, []byte(valueString), &types.Meta{ - Topic: r.Stream, - Timestamp: int64(ts), - ID: ts<<13 | (idx & 0x1FFF), // Max: 4096 messages/ms for 69 years - }) + bID := ts<<13 | (idx & 0x1FFF) // Max: 4096 messages/ms for 69 years + c.messageIterator.Iterate([]byte(valueString), messages.NewBatchInfo(sessionID, r.Stream, bID, 0, int64(ts))) if c.autoCommit { if err = c.redis.XAck(r.Stream, c.group, m.ID).Err(); err != nil { return errors.Wrapf(err, "Acknoledgment error for messageID %v", m.ID) @@ -161,7 +157,3 @@ func (c *Consumer) CommitBack(gap int64) error { func (c *Consumer) Close() { // noop } - -func (c *Consumer) HasFirstPartition() bool { - return false -} diff --git a/backend/pkg/redisstream/redis.go b/backend/pkg/redisstream/redis.go index 7dba0b537..434099879 100644 --- a/backend/pkg/redisstream/redis.go +++ b/backend/pkg/redisstream/redis.go @@ -2,6 +2,7 @@ package redisstream import ( "log" + "regexp" "github.com/go-redis/redis" @@ -14,9 +15,20 @@ func getRedisClient() *redis.Client { if redisClient != nil { return redisClient } - redisClient = redis.NewClient(&redis.Options{ - Addr: env.String("REDIS_STRING"), - }) + + connectionString := env.String("REDIS_STRING") + + match, _ := regexp.MatchString("^[^:]+://", connectionString) + if !match { + connectionString = "redis://" + connectionString + } + + options, err := redis.ParseURL(connectionString) + if err != nil { + log.Fatalln(err) + } + + redisClient = redis.NewClient(options) if _, err := redisClient.Ping().Result(); err != nil { log.Fatalln(err) } diff --git a/backend/pkg/sessions/builder.go b/backend/pkg/sessions/builder.go index c9cb0b6dd..d21fd890a 100644 --- a/backend/pkg/sessions/builder.go +++ b/backend/pkg/sessions/builder.go @@ -66,6 +66,7 @@ func (b *builder) handleMessage(message Message, messageID uint64) { b.lastSystemTime = time.Now() for _, p := range b.processors { if rm := p.Handle(message, messageID, b.timestamp); rm != nil { + rm.Meta().SetMeta(message.Meta()) b.readyMsgs = append(b.readyMsgs, rm) } } diff --git a/backend/pkg/sessions/builderMap.go b/backend/pkg/sessions/builderMap.go index f26993c13..bdf8e8686 100644 --- a/backend/pkg/sessions/builderMap.go +++ b/backend/pkg/sessions/builderMap.go @@ -30,7 +30,9 @@ func (m *builderMap) GetBuilder(sessionID uint64) *builder { return b } -func (m *builderMap) HandleMessage(sessionID uint64, msg Message, messageID uint64) { +func (m *builderMap) HandleMessage(msg Message) { + sessionID := msg.SessionID() + messageID := msg.Meta().Index b := m.GetBuilder(sessionID) b.handleMessage(msg, messageID) } @@ -39,6 +41,7 @@ func (m *builderMap) iterateSessionReadyMessages(sessionID uint64, b *builder, i if b.ended || b.lastSystemTime.Add(FORCE_DELETE_TIMEOUT).Before(time.Now()) { for _, p := range b.processors { if rm := p.Build(); rm != nil { + rm.Meta().SetSessionID(sessionID) b.readyMsgs = append(b.readyMsgs, rm) } } diff --git a/backend/pkg/token/tokenizer.go b/backend/pkg/token/tokenizer.go index f61e1f145..dd45907a8 100644 --- a/backend/pkg/token/tokenizer.go +++ b/backend/pkg/token/tokenizer.go @@ -23,6 +23,7 @@ func NewTokenizer(secret string) *Tokenizer { type TokenData struct { ID uint64 + Delay int64 ExpTime int64 } @@ -34,6 +35,7 @@ func (tokenizer *Tokenizer) sign(body string) []byte { func (tokenizer *Tokenizer) Compose(d TokenData) string { body := strconv.FormatUint(d.ID, 36) + + "." + strconv.FormatInt(d.Delay, 36) + "." + strconv.FormatInt(d.ExpTime, 36) sign := base58.Encode(tokenizer.sign(body)) return body + "." + sign @@ -41,12 +43,12 @@ func (tokenizer *Tokenizer) Compose(d TokenData) string { func (tokenizer *Tokenizer) Parse(token string) (*TokenData, error) { data := strings.Split(token, ".") - if len(data) != 3 { + if len(data) != 4 { return nil, errors.New("wrong token format") } if !hmac.Equal( base58.Decode(data[len(data)-1]), - tokenizer.sign(data[0]+"."+data[1]), + tokenizer.sign(strings.Join(data[:len(data)-1], ".")), ) { return nil, errors.New("wrong token sign") } @@ -54,12 +56,16 @@ func (tokenizer *Tokenizer) Parse(token string) (*TokenData, error) { if err != nil { return nil, err } - expTime, err := strconv.ParseInt(data[1], 36, 64) + delay, err := strconv.ParseInt(data[1], 36, 64) + if err != nil { + return nil, err + } + expTime, err := strconv.ParseInt(data[2], 36, 64) if err != nil { return nil, err } if expTime <= time.Now().UnixMilli() { - return &TokenData{id, expTime}, EXPIRED + return &TokenData{id, delay, expTime}, EXPIRED } - return &TokenData{id, expTime}, nil + return &TokenData{id, delay, expTime}, nil } diff --git a/backend/pkg/url/assets/css.go b/backend/pkg/url/assets/css.go index dda8755d7..32603f058 100644 --- a/backend/pkg/url/assets/css.go +++ b/backend/pkg/url/assets/css.go @@ -66,12 +66,18 @@ func ResolveCSS(baseURL string, css string) string { css = rewriteLinks(css, func(rawurl string) string { return ResolveURL(baseURL, rawurl) }) - return strings.Replace(css, ":hover", ".-openreplay-hover", -1) + return rewritePseudoclasses(css) } func (r *Rewriter) RewriteCSS(sessionID uint64, baseurl string, css string) string { css = rewriteLinks(css, func(rawurl string) string { return r.RewriteURL(sessionID, baseurl, rawurl) }) - return strings.Replace(css, ":hover", ".-openreplay-hover", -1) + return rewritePseudoclasses(css) +} + +func rewritePseudoclasses(css string) string { + css = strings.Replace(css, ":hover", ".-openreplay-hover", -1) + css = strings.Replace(css, ":focus", ".-openreplay-focus", -1) + return css } diff --git a/ee/api/.gitignore b/ee/api/.gitignore index d25a4474d..ee23eb7ff 100644 --- a/ee/api/.gitignore +++ b/ee/api/.gitignore @@ -210,7 +210,6 @@ Pipfile /chalicelib/core/log_tool_sumologic.py /chalicelib/core/metadata.py /chalicelib/core/mobile.py -/chalicelib/core/sessions.py /chalicelib/core/sessions_assignments.py /chalicelib/core/sessions_metas.py /chalicelib/core/sessions_mobs.py @@ -242,24 +241,21 @@ Pipfile /routers/subs/__init__.py /routers/__init__.py /chalicelib/core/assist.py +/auth/__init__.py /auth/auth_apikey.py -/auth/auth_jwt.py /build.sh /routers/base.py /routers/core.py /routers/crons/core_crons.py -/routers/subs/dashboard.py /db_changes.sql -/Dockerfile.bundle +/Dockerfile_bundle /entrypoint.bundle.sh /chalicelib/core/heatmaps.py -/routers/subs/insights.py /schemas.py #exp /chalicelib/core/custom_metrics.py /chalicelib/core/performance_event.py /chalicelib/core/saved_search.py /app_alerts.py /build_alerts.sh -/routers/subs/metrics.py /routers/subs/v1_api.py #exp /chalicelib/core/dashboards.py diff --git a/ee/api/Dockerfile b/ee/api/Dockerfile index 1b23fc6d4..3c041511b 100644 --- a/ee/api/Dockerfile +++ b/ee/api/Dockerfile @@ -1,26 +1,20 @@ FROM python:3.10-alpine LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" -RUN apk add --no-cache build-base libressl libffi-dev libressl-dev libxslt-dev libxml2-dev xmlsec-dev xmlsec nodejs npm tini +RUN apk add --no-cache build-base libressl libffi-dev libressl-dev libxslt-dev libxml2-dev xmlsec-dev xmlsec tini ARG envarg ENV SOURCE_MAP_VERSION=0.7.4 \ APP_NAME=chalice \ LISTEN_PORT=8000 \ - MAPPING_WASM=/work/sourcemap-reader/mappings.wasm \ + PRIVATE_ENDPOINTS=false \ ENTERPRISE_BUILD=${envarg} -ADD https://unpkg.com/source-map@${SOURCE_MAP_VERSION}/lib/mappings.wasm /mappings.wasm - -WORKDIR /work_tmp -COPY requirements.txt /work_tmp/requirements.txt -RUN pip install --no-cache-dir --upgrade -r /work_tmp/requirements.txt -COPY sourcemap-reader/*.json /work_tmp/ -RUN cd /work_tmp && npm install - WORKDIR /work +COPY requirements.txt ./requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + COPY . . -RUN mv env.default .env && mv /work_tmp/node_modules sourcemap-reader/. \ - && mv /mappings.wasm ${MAPPING_WASM} && chmod 644 ${MAPPING_WASM} +RUN mv env.default .env RUN adduser -u 1001 openreplay -D USER 1001 diff --git a/ee/api/.dockerignore b/ee/api/Dockerfile.dockerignore similarity index 87% rename from ee/api/.dockerignore rename to ee/api/Dockerfile.dockerignore index 7d122d6cb..6a0bf2646 100644 --- a/ee/api/.dockerignore +++ b/ee/api/Dockerfile.dockerignore @@ -10,7 +10,5 @@ app_crons.py app_alerts.py requirements-crons.txt requirements-alerts.txt -build_crons.sh -build_alerts.sh entrypoint_crons.sh entrypoint_alerts.sh \ No newline at end of file diff --git a/ee/api/Dockerfile.alerts b/ee/api/Dockerfile_alerts similarity index 73% rename from ee/api/Dockerfile.alerts rename to ee/api/Dockerfile_alerts index 02bac9350..488b68207 100644 --- a/ee/api/Dockerfile.alerts +++ b/ee/api/Dockerfile_alerts @@ -4,15 +4,16 @@ LABEL Maintainer="KRAIEM Taha Yassine" RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=alerts \ - pg_minconn=1 \ - pg_maxconn=10 \ + PG_MINCONN=1 \ + PG_MAXCONN=10 \ LISTEN_PORT=8000 \ + PRIVATE_ENDPOINTS=true \ ENTERPRISE_BUILD=${envarg} -COPY requirements-alerts.txt /work_tmp/requirements.txt -RUN pip install --no-cache-dir --upgrade -r /work_tmp/requirements.txt - WORKDIR /work +COPY requirements-alerts.txt ./requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + COPY . . RUN mv env.default .env && mv app_alerts.py app.py && mv entrypoint_alerts.sh entrypoint.sh diff --git a/ee/api/Dockerfile.alerts.dockerignore b/ee/api/Dockerfile_alerts.dockerignore similarity index 88% rename from ee/api/Dockerfile.alerts.dockerignore rename to ee/api/Dockerfile_alerts.dockerignore index 1b8f57638..c9f6d4928 100644 --- a/ee/api/Dockerfile.alerts.dockerignore +++ b/ee/api/Dockerfile_alerts.dockerignore @@ -10,7 +10,5 @@ app.py app_crons.py requirements.txt requirements-crons.txt -build.sh -build_crons.sh entrypoint.sh entrypoint_crons.sh \ No newline at end of file diff --git a/ee/api/Dockerfile.crons b/ee/api/Dockerfile_crons similarity index 71% rename from ee/api/Dockerfile.crons rename to ee/api/Dockerfile_crons index 83b3085e0..40763542c 100644 --- a/ee/api/Dockerfile.crons +++ b/ee/api/Dockerfile_crons @@ -4,17 +4,17 @@ LABEL Maintainer="KRAIEM Taha Yassine" RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=crons \ - pg_minconn=2 \ - pg_maxconn=10 \ + PG_MINCONN=2 \ + PG_MAXCONN=10 \ + PRIVATE_ENDPOINTS=true \ ENTERPRISE_BUILD=${envarg} \ ACTION="" \ PG_POOL=false -WORKDIR /work_tmp -COPY requirements-crons.txt /work_tmp/requirements.txt -RUN pip install --no-cache-dir --upgrade -r /work_tmp/requirements.txt - WORKDIR /work +COPY requirements-crons.txt ./requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + COPY . . RUN mv env.default .env && mv entrypoint_crons.sh entrypoint.sh diff --git a/ee/api/Dockerfile.crons.dockerignore b/ee/api/Dockerfile_crons.dockerignore similarity index 88% rename from ee/api/Dockerfile.crons.dockerignore rename to ee/api/Dockerfile_crons.dockerignore index fa6ca7a65..0c6e79cda 100644 --- a/ee/api/Dockerfile.crons.dockerignore +++ b/ee/api/Dockerfile_crons.dockerignore @@ -10,7 +10,5 @@ app.py app_alerts.py requirements.txt requirements-alerts.txt -build.sh -build_alerts.sh entrypoint.sh entrypoint_alerts.sh \ No newline at end of file diff --git a/ee/api/app.py b/ee/api/app.py index ad9310f95..055706792 100644 --- a/ee/api/app.py +++ b/ee/api/app.py @@ -9,6 +9,7 @@ from fastapi.middleware.gzip import GZipMiddleware from starlette import status from starlette.responses import StreamingResponse, JSONResponse +from chalicelib.core import traces from chalicelib.utils import helper from chalicelib.utils import pg_client from routers import core, core_dynamic, ee, saml @@ -27,21 +28,14 @@ async def or_middleware(request: Request, call_next): if not unlock.is_valid(): return JSONResponse(content={"errors": ["expired license"]}, status_code=status.HTTP_403_FORBIDDEN) - global OR_SESSION_TOKEN - OR_SESSION_TOKEN = request.headers.get('vnd.openreplay.com.sid', request.headers.get('vnd.asayer.io.sid')) - try: - if helper.TRACK_TIME: - import time - now = int(time.time() * 1000) - response: StreamingResponse = await call_next(request) - if helper.TRACK_TIME: - now = int(time.time() * 1000) - now - if now > 500: - print(f"Execution time: {now} ms") - except Exception as e: - pg_client.close() - raise e - pg_client.close() + if helper.TRACK_TIME: + import time + now = int(time.time() * 1000) + response: StreamingResponse = await call_next(request) + if helper.TRACK_TIME: + now = int(time.time() * 1000) - now + if now > 500: + logging.info(f"Execution time: {now} ms") return response @@ -74,18 +68,41 @@ app.include_router(insights.app) app.include_router(v1_api.app_apikey) app.include_router(v1_api_ee.app_apikey) -app.queue_system = queue.Queue() +loglevel = config("LOGLEVEL", default=logging.INFO) +print(f">Loglevel set to: {loglevel}") +logging.basicConfig(level=loglevel) +ap_logger = logging.getLogger('apscheduler') +ap_logger.setLevel(loglevel) app.schedule = AsyncIOScheduler() -app.schedule.start() +app.queue_system = queue.Queue() -for job in core_crons.cron_jobs + core_dynamic_crons.cron_jobs: - app.schedule.add_job(id=job["func"].__name__, **job) -from chalicelib.core import traces -app.schedule.add_job(id="trace_worker", **traces.cron_jobs[0]) +@app.on_event("startup") +async def startup(): + logging.info(">>>>> starting up <<<<<") + await pg_client.init() + app.schedule.start() -for job in app.schedule.get_jobs(): - print({"Name": str(job.id), "Run Frequency": str(job.trigger), "Next Run": str(job.next_run_time)}) + for job in core_crons.cron_jobs + core_dynamic_crons.cron_jobs + traces.cron_jobs: + app.schedule.add_job(id=job["func"].__name__, **job) + + ap_logger.info(">Scheduled jobs:") + for job in app.schedule.get_jobs(): + ap_logger.info({"Name": str(job.id), "Run Frequency": str(job.trigger), "Next Run": str(job.next_run_time)}) + + +@app.on_event("shutdown") +async def shutdown(): + logging.info(">>>>> shutting down <<<<<") + app.schedule.shutdown(wait=True) + await traces.process_traces_queue() + await pg_client.terminate() + + +@app.get('/private/shutdown', tags=["private"]) +async def stop_server(): + logging.info("Requested shutdown") + await shutdown() + import os, signal + os.kill(1, signal.SIGTERM) -logging.basicConfig(level=config("LOGLEVEL", default=logging.INFO)) -logging.getLogger('apscheduler').setLevel(config("LOGLEVEL", default=logging.INFO)) diff --git a/ee/api/auth/auth_jwt.py b/ee/api/auth/auth_jwt.py new file mode 100644 index 000000000..477beba3d --- /dev/null +++ b/ee/api/auth/auth_jwt.py @@ -0,0 +1,60 @@ +from typing import Optional + +from fastapi import Request +from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials +from starlette import status +from starlette.exceptions import HTTPException + +from chalicelib.core import authorizers, users +import schemas_ee + + +class JWTAuth(HTTPBearer): + def __init__(self, auto_error: bool = True): + super(JWTAuth, self).__init__(auto_error=auto_error) + + async def __call__(self, request: Request) -> Optional[schemas_ee.CurrentContext]: + credentials: HTTPAuthorizationCredentials = await super(JWTAuth, self).__call__(request) + if credentials: + if not credentials.scheme == "Bearer": + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid authentication scheme.") + jwt_payload = authorizers.jwt_authorizer(credentials.scheme + " " + credentials.credentials) + auth_exists = jwt_payload is not None \ + and users.auth_exists(user_id=jwt_payload.get("userId", -1), + tenant_id=jwt_payload.get("tenantId", -1), + jwt_iat=jwt_payload.get("iat", 100), + jwt_aud=jwt_payload.get("aud", "")) + if jwt_payload is None \ + or jwt_payload.get("iat") is None or jwt_payload.get("aud") is None \ + or not auth_exists: + print("JWTAuth: Token issue") + if jwt_payload is not None: + print(jwt_payload) + print(f"JWTAuth: user_id={jwt_payload.get('userId')} tenant_id={jwt_payload.get('tenantId')}") + if jwt_payload is None: + print("JWTAuth: jwt_payload is None") + print(credentials.scheme + " " + credentials.credentials) + if jwt_payload is not None and jwt_payload.get("iat") is None: + print("JWTAuth: iat is None") + if jwt_payload is not None and jwt_payload.get("aud") is None: + print("JWTAuth: aud is None") + if jwt_payload is not None and not auth_exists: + print("JWTAuth: not users.auth_exists") + + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Invalid token or expired token.") + user = users.get(user_id=jwt_payload.get("userId", -1), tenant_id=jwt_payload.get("tenantId", -1)) + if user is None: + print("JWTAuth: User not found.") + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="User not found.") + jwt_payload["authorizer_identity"] = "jwt" + print(jwt_payload) + request.state.authorizer_identity = "jwt" + request.state.currentContext = schemas_ee.CurrentContext(tenant_id=jwt_payload.get("tenantId", -1), + user_id=jwt_payload.get("userId", -1), + email=user["email"], + permissions=user["permissions"]) + return request.state.currentContext + + else: + print("JWTAuth: Invalid authorization code.") + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid authorization code.") diff --git a/ee/api/build_crons.sh b/ee/api/build_crons.sh index 810c1b4b5..2f9d84a81 100644 --- a/ee/api/build_crons.sh +++ b/ee/api/build_crons.sh @@ -17,19 +17,20 @@ check_prereq() { [[ exit -eq 1 ]] && exit 1 } -function build_api(){ - cp -R ../api ../_crons - cd ../_crons +function build_crons(){ + destination="_crons_ee" + cp -R ../api ../${destination} + cd ../${destination} tag="" # Copy enterprise code cp -rf ../ee/api/* ./ envarg="default-ee" tag="ee-" - - docker build -f ./Dockerfile.crons --build-arg envarg=$envarg -t ${DOCKER_REPO:-'local'}/crons:${git_sha1} . + mv Dockerfile_crons.dockerignore .dockerignore + docker build -f ./Dockerfile_crons --build-arg envarg=$envarg -t ${DOCKER_REPO:-'local'}/crons:${git_sha1} . cd ../api - rm -rf ../_crons + rm -rf ../${destination} [[ $PUSH_IMAGE -eq 1 ]] && { docker push ${DOCKER_REPO:-'local'}/crons:${git_sha1} docker tag ${DOCKER_REPO:-'local'}/crons:${git_sha1} ${DOCKER_REPO:-'local'}/crons:${tag}latest @@ -39,4 +40,4 @@ function build_api(){ } check_prereq -build_api $1 +build_crons $1 diff --git a/ee/api/chalicelib/core/__init__.py b/ee/api/chalicelib/core/__init__.py index 550327129..41c437c93 100644 --- a/ee/api/chalicelib/core/__init__.py +++ b/ee/api/chalicelib/core/__init__.py @@ -18,7 +18,11 @@ else: if config("EXP_ERRORS_SEARCH", cast=bool, default=False): print(">>> Using experimental error search") + from . import errors as errors_legacy from . import errors_exp as errors + + if config("EXP_ERRORS_GET", cast=bool, default=False): + print(">>> Using experimental error get") else: from . import errors as errors diff --git a/ee/api/chalicelib/core/alerts_processor.py b/ee/api/chalicelib/core/alerts_processor.py index 0a8df1c02..326d17ffc 100644 --- a/ee/api/chalicelib/core/alerts_processor.py +++ b/ee/api/chalicelib/core/alerts_processor.py @@ -108,6 +108,7 @@ def Build(a): params = {"project_id": a["projectId"], "now": now} full_args = {} j_s = True + main_table = "" if a["seriesId"] is not None: a["filter"]["sort"] = "session_id" a["filter"]["order"] = schemas.SortOrderType.desc @@ -125,16 +126,16 @@ def Build(a): WHERE project_id = %(project_id)s {"AND " + colDef["condition"] if colDef.get("condition") is not None else ""}""" j_s = colDef.get("joinSessions", True) - + main_table = colDef["table"] + is_ss = main_table == "public.sessions" q = f"""SELECT coalesce(value,0) AS value, coalesce(value,0) {a["query"]["operator"]} {a["query"]["right"]} AS valid""" if a["detectionMethod"] == schemas.AlertDetectionMethod.threshold: if a["seriesId"] is not None: q += f""" FROM ({subQ}) AS stat""" else: - q += f""" FROM ({subQ} AND timestamp>=%(startDate)s AND timestamp<=%(now)s - {"AND sessions.start_ts >= %(startDate)s" if j_s else ""} - {"AND sessions.start_ts <= %(now)s" if j_s else ""}) AS stat""" + q += f""" FROM ({subQ} {"AND timestamp >= %(startDate)s AND timestamp <= %(now)s" if not is_ss else ""} + {"AND start_ts >= %(startDate)s AND start_ts <= %(now)s" if j_s else ""}) AS stat""" params = {**params, **full_args, "startDate": TimeUTC.now() - a["options"]["currentPeriod"] * 60 * 1000} else: if a["change"] == schemas.AlertDetectionType.change: @@ -147,13 +148,11 @@ def Build(a): "timestamp_sub2": TimeUTC.now() - 2 * a["options"]["currentPeriod"] * 60 * 1000} else: sub1 = f"""{subQ} AND timestamp>=%(startDate)s - AND datetime<=toDateTime(%(now)s/1000) - {"AND sessions.start_ts >= %(startDate)s" if j_s else ""} - {"AND sessions.start_ts <= %(now)s" if j_s else ""}""" + AND timestamp<=%(now)s + {"AND start_ts >= %(startDate)s AND start_ts <= %(now)s" if j_s else ""}""" params["startDate"] = TimeUTC.now() - a["options"]["currentPeriod"] * 60 * 1000 - sub2 = f"""{subQ} AND timestamp<%(startDate)s - AND timestamp>=%(timestamp_sub2)s - {"AND sessions.start_ts < %(startDate)s AND sessions.start_ts >= %(timestamp_sub2)s" if j_s else ""}""" + sub2 = f"""{subQ} {"AND timestamp < %(startDate)s AND timestamp >= %(timestamp_sub2)s" if not is_ss else ""} + {"AND start_ts < %(startDate)s AND start_ts >= %(timestamp_sub2)s" if j_s else ""}""" params["timestamp_sub2"] = TimeUTC.now() - 2 * a["options"]["currentPeriod"] * 60 * 1000 sub1 = f"SELECT (( {sub1} )-( {sub2} )) AS value" q += f" FROM ( {sub1} ) AS stat" @@ -169,13 +168,11 @@ def Build(a): - (a["options"]["currentPeriod"] + a["options"]["currentPeriod"]) \ * 60 * 1000} else: - sub1 = f"""{subQ} AND timestamp>=%(startDate)s AND timestamp<=%(now)s - {"AND sessions.start_ts >= %(startDate)s" if j_s else ""} - {"AND sessions.start_ts <= %(now)s" if j_s else ""}""" + sub1 = f"""{subQ} {"AND timestamp >= %(startDate)s AND timestamp <= %(now)s" if not is_ss else ""} + {"AND start_ts >= %(startDate)s AND start_ts <= %(now)s" if j_s else ""}""" params["startDate"] = TimeUTC.now() - a["options"]["currentPeriod"] * 60 * 1000 - sub2 = f"""{subQ} AND timestamp<%(startDate)s - AND timestamp>=%(timestamp_sub2)s - {"AND sessions.start_ts < %(startDate)s AND sessions.start_ts >= %(timestamp_sub2)s" if j_s else ""}""" + sub2 = f"""{subQ} {"AND timestamp < %(startDate)s AND timestamp >= %(timestamp_sub2)s" if not is_ss else ""} + {"AND start_ts < %(startDate)s AND start_ts >= %(timestamp_sub2)s" if j_s else ""}""" params["timestamp_sub2"] = TimeUTC.now() \ - (a["options"]["currentPeriod"] + a["options"]["currentPeriod"]) * 60 * 1000 sub1 = f"SELECT (({sub1})/NULLIF(({sub2}),0)-1)*100 AS value" @@ -190,21 +187,28 @@ def process(): with pg_client.PostgresClient() as cur: for alert in all_alerts: if can_check(alert): - logging.info(f"Querying alertId:{alert['alertId']} name: {alert['name']}") query, params = Build(alert) - query = cur.mogrify(query, params) + try: + query = cur.mogrify(query, params) + except Exception as e: + logging.error( + f"!!!Error while building alert query for alertId:{alert['alertId']} name: {alert['name']}") + logging.error(e) + continue logging.debug(alert) logging.debug(query) try: cur.execute(query) result = cur.fetchone() if result["valid"]: - logging.info("Valid alert, notifying users") + logging.info(f"Valid alert, notifying users, alertId:{alert['alertId']} name: {alert['name']}") notifications.append(generate_notification(alert, result)) except Exception as e: - logging.error(f"!!!Error while running alert query for alertId:{alert['alertId']}") - logging.error(str(e)) + logging.error( + f"!!!Error while running alert query for alertId:{alert['alertId']} name: {alert['name']}") logging.error(query) + logging.error(e) + cur = cur.recreate(rollback=True) if len(notifications) > 0: cur.execute( cur.mogrify(f"""UPDATE public.Alerts @@ -214,12 +218,22 @@ def process(): alerts.process_notifications(notifications) +def __format_value(x): + if x % 1 == 0: + x = int(x) + else: + x = round(x, 2) + return f"{x:,}" + + def generate_notification(alert, result): + left = __format_value(result['value']) + right = __format_value(alert['query']['right']) return { "alertId": alert["alertId"], "tenantId": alert["tenantId"], "title": alert["name"], - "description": f"has been triggered, {alert['query']['left']} = {round(result['value'], 2)} ({alert['query']['operator']} {alert['query']['right']}).", + "description": f"has been triggered, {alert['query']['left']} = {left} ({alert['query']['operator']} {right}).", "buttonText": "Check metrics for more details", "buttonUrl": f"/{alert['projectId']}/metrics", "imageUrl": None, diff --git a/ee/api/chalicelib/core/authorizers.py b/ee/api/chalicelib/core/authorizers.py index 5adf3e61a..363745f4b 100644 --- a/ee/api/chalicelib/core/authorizers.py +++ b/ee/api/chalicelib/core/authorizers.py @@ -16,7 +16,7 @@ def jwt_authorizer(token): token[1], config("jwt_secret"), algorithms=config("jwt_algorithm"), - audience=[f"plugin:{helper.get_stage_name()}", f"front:{helper.get_stage_name()}"] + audience=[f"front:{helper.get_stage_name()}"] ) except jwt.ExpiredSignatureError: print("! JWT Expired signature") @@ -43,9 +43,9 @@ def generate_jwt(id, tenant_id, iat, aud, exp=None): payload={ "userId": id, "tenantId": tenant_id, - "exp": iat // 1000 + int(config("jwt_exp_delta_seconds")) + TimeUTC.get_utc_offset() // 1000 \ - if exp is None else exp+ TimeUTC.get_utc_offset() // 1000, - "iss": config("jwt_issuer"), + "exp": exp + TimeUTC.get_utc_offset() // 1000 if exp is not None \ + else iat // 1000 + config("JWT_EXPIRATION", cast=int) + TimeUTC.get_utc_offset() // 1000, + "iss": config("JWT_ISSUER"), "iat": iat // 1000, "aud": aud }, diff --git a/ee/api/chalicelib/core/custom_metrics.py b/ee/api/chalicelib/core/custom_metrics.py index b925429f6..e871a5646 100644 --- a/ee/api/chalicelib/core/custom_metrics.py +++ b/ee/api/chalicelib/core/custom_metrics.py @@ -279,7 +279,8 @@ def update(metric_id, user_id, project_id, data: schemas.UpdateCustomMetricsSche params = {"metric_id": metric_id, "is_public": data.is_public, "name": data.name, "user_id": user_id, "project_id": project_id, "view_type": data.view_type, "metric_type": data.metric_type, "metric_of": data.metric_of, - "metric_value": data.metric_value, "metric_format": data.metric_format} + "metric_value": data.metric_value, "metric_format": data.metric_format, + "config": json.dumps(data.config.dict())} for i, s in enumerate(data.series): prefix = "u_" if s.index is None: @@ -329,7 +330,8 @@ def update(metric_id, user_id, project_id, data: schemas.UpdateCustomMetricsSche view_type= %(view_type)s, metric_type= %(metric_type)s, metric_of= %(metric_of)s, metric_value= %(metric_value)s, metric_format= %(metric_format)s, - edited_at = timezone('utc'::text, now()) + edited_at = timezone('utc'::text, now()), + default_config = %(config)s WHERE metric_id = %(metric_id)s AND project_id = %(project_id)s AND (user_id = %(user_id)s OR is_public) diff --git a/ee/api/chalicelib/core/dashboards.py b/ee/api/chalicelib/core/dashboards.py index d96356df1..25b1551d3 100644 --- a/ee/api/chalicelib/core/dashboards.py +++ b/ee/api/chalicelib/core/dashboards.py @@ -118,6 +118,8 @@ def get_dashboard(project_id, user_id, dashboard_id): for w in row["widgets"]: w["created_at"] = TimeUTC.datetime_to_timestamp(w["created_at"]) w["edited_at"] = TimeUTC.datetime_to_timestamp(w["edited_at"]) + w["config"]["col"] = w["default_config"]["col"] + w["config"]["row"] = w["default_config"]["row"] for s in w["series"]: s["created_at"] = TimeUTC.datetime_to_timestamp(s["created_at"]) return helper.dict_to_camel_case(row) diff --git a/ee/api/chalicelib/core/errors.py b/ee/api/chalicelib/core/errors.py index d50c6b54a..66c3a195d 100644 --- a/ee/api/chalicelib/core/errors.py +++ b/ee/api/chalicelib/core/errors.py @@ -90,6 +90,18 @@ def __process_tags(row): def get_details(project_id, error_id, user_id, **data): pg_sub_query24 = __get_basic_constraints(time_constraint=False, chart=True, step_size_name="step_size24") pg_sub_query24.append("error_id = %(error_id)s") + pg_sub_query30_session = __get_basic_constraints(time_constraint=True, chart=False, startTime_arg_name="startDate30", + endTime_arg_name="endDate30",project_key="sessions.project_id") + pg_sub_query30_session.append("sessions.start_ts >= %(startDate30)s") + pg_sub_query30_session.append("sessions.start_ts <= %(endDate30)s") + pg_sub_query30_session.append("error_id = %(error_id)s") + pg_sub_query30_err = __get_basic_constraints(time_constraint=True, chart=False, startTime_arg_name="startDate30", + endTime_arg_name="endDate30",project_key="errors.project_id") + pg_sub_query30_err.append("sessions.project_id = %(project_id)s") + pg_sub_query30_err.append("sessions.start_ts >= %(startDate30)s") + pg_sub_query30_err.append("sessions.start_ts <= %(endDate30)s") + pg_sub_query30_err.append("error_id = %(error_id)s") + pg_sub_query30_err.append("source ='js_exception'") pg_sub_query30 = __get_basic_constraints(time_constraint=False, chart=True, step_size_name="step_size30") pg_sub_query30.append("error_id = %(error_id)s") pg_basic_query = __get_basic_constraints(time_constraint=False) @@ -128,50 +140,49 @@ def get_details(project_id, error_id, user_id, **data): device_partition, country_partition, chart24, - chart30 + chart30, + custom_tags FROM (SELECT error_id, name, message, - COUNT(DISTINCT user_uuid) AS users, + COUNT(DISTINCT user_id) AS users, COUNT(DISTINCT session_id) AS sessions FROM public.errors INNER JOIN events.errors AS s_errors USING (error_id) INNER JOIN public.sessions USING (session_id) - WHERE error_id = %(error_id)s + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY error_id, name, message) AS details - INNER JOIN (SELECT error_id, - MAX(timestamp) AS last_occurrence, + INNER JOIN (SELECT MAX(timestamp) AS last_occurrence, MIN(timestamp) AS first_occurrence FROM events.errors WHERE error_id = %(error_id)s - GROUP BY error_id) AS time_details USING (error_id) - INNER JOIN (SELECT error_id, - session_id AS last_session_id, - user_os, - user_os_version, - user_browser, - user_browser_version, - user_device, - user_device_type, - user_uuid - FROM events.errors INNER JOIN public.sessions USING (session_id) + GROUP BY error_id) AS time_details ON (TRUE) + INNER JOIN (SELECT session_id AS last_session_id, + coalesce(custom_tags, '[]')::jsonb AS custom_tags + FROM events.errors + LEFT JOIN LATERAL ( + SELECT jsonb_agg(jsonb_build_object(errors_tags.key, errors_tags.value)) AS custom_tags + FROM errors_tags + WHERE errors_tags.error_id = %(error_id)s + AND errors_tags.session_id = errors.session_id + AND errors_tags.message_id = errors.message_id) AS errors_tags ON (TRUE) WHERE error_id = %(error_id)s ORDER BY errors.timestamp DESC - LIMIT 1) AS last_session_details USING (error_id) + LIMIT 1) AS last_session_details ON (TRUE) INNER JOIN (SELECT jsonb_agg(browser_details) AS browsers_partition FROM (SELECT * FROM (SELECT user_browser AS name, COUNT(session_id) AS count FROM events.errors INNER JOIN sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} GROUP BY user_browser ORDER BY count DESC) AS count_per_browser_query INNER JOIN LATERAL (SELECT JSONB_AGG(version_details) AS partition FROM (SELECT user_browser_version AS version, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} AND sessions.user_browser = count_per_browser_query.name GROUP BY user_browser_version ORDER BY count DESC) AS version_details @@ -181,13 +192,13 @@ def get_details(project_id, error_id, user_id, **data): FROM (SELECT user_os AS name, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} GROUP BY user_os ORDER BY count DESC) AS count_per_os_details INNER JOIN LATERAL (SELECT jsonb_agg(count_per_version_details) AS partition FROM (SELECT COALESCE(user_os_version,'unknown') AS version, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} AND sessions.user_os = count_per_os_details.name GROUP BY user_os_version ORDER BY count DESC) AS count_per_version_details @@ -198,7 +209,7 @@ def get_details(project_id, error_id, user_id, **data): FROM (SELECT user_device_type AS name, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} GROUP BY user_device_type ORDER BY count DESC) AS count_per_device_details INNER JOIN LATERAL (SELECT jsonb_agg(count_per_device_v_details) AS partition @@ -208,7 +219,7 @@ def get_details(project_id, error_id, user_id, **data): ELSE user_device END AS version, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} AND sessions.user_device_type = count_per_device_details.name GROUP BY user_device ORDER BY count DESC) AS count_per_device_v_details @@ -218,7 +229,7 @@ def get_details(project_id, error_id, user_id, **data): FROM (SELECT user_country AS name, COUNT(session_id) AS count FROM events.errors INNER JOIN public.sessions USING (session_id) - WHERE {" AND ".join(pg_basic_query)} + WHERE {" AND ".join(pg_sub_query30_session)} GROUP BY user_country ORDER BY count DESC) AS count_per_country_details) AS country_details ON (TRUE) INNER JOIN (SELECT jsonb_agg(chart_details) AS chart24 @@ -716,36 +727,6 @@ def __status_rank(status): }.get(status) -def merge(error_ids): - error_ids = list(set(error_ids)) - errors = get_batch(error_ids) - if len(error_ids) <= 1 or len(error_ids) > len(errors): - return {"errors": ["invalid list of ids"]} - error_ids = [e["errorId"] for e in errors] - parent_error_id = error_ids[0] - status = "unresolved" - for e in errors: - if __status_rank(status) < __status_rank(e["status"]): - status = e["status"] - if __status_rank(status) == MAX_RANK: - break - params = { - "error_ids": tuple(error_ids), - "parent_error_id": parent_error_id, - "status": status - } - with pg_client.PostgresClient() as cur: - query = cur.mogrify( - """UPDATE public.errors - SET parent_error_id = %(parent_error_id)s, status = %(status)s - WHERE error_id IN %(error_ids)s OR parent_error_id IN %(error_ids)s;""", - params) - cur.execute(query=query) - # row = cur.fetchone() - - return {"data": "success"} - - def format_first_stack_frame(error): error["stack"] = sourcemaps.format_payload(error.pop("payload"), truncate_to_first=True) for s in error["stack"]: diff --git a/ee/api/chalicelib/core/errors_exp.py b/ee/api/chalicelib/core/errors_exp.py index 7014a16e0..1fb201492 100644 --- a/ee/api/chalicelib/core/errors_exp.py +++ b/ee/api/chalicelib/core/errors_exp.py @@ -2,10 +2,12 @@ import json import schemas from chalicelib.core import metrics, metadata +from chalicelib.core import errors_legacy from chalicelib.core import sourcemaps, sessions from chalicelib.utils import ch_client, metrics_helper, exp_ch_helper from chalicelib.utils import pg_client, helper from chalicelib.utils.TimeUTC import TimeUTC +from decouple import config def _multiple_values(values, value_key="value"): @@ -113,6 +115,18 @@ def __flatten_sort_key_count_version(data, merge_nested=False): ] +def __transform_map_to_tag(data, key1, key2, requested_key): + result = [] + for i in data: + if requested_key == 0 and i.get(key1) is None and i.get(key2) is None: + result.append({"name": "all", "count": int(i.get("count"))}) + elif requested_key == 1 and i.get(key1) is not None and i.get(key2) is None: + result.append({"name": i.get(key1), "count": int(i.get("count"))}) + elif requested_key == 2 and i.get(key1) is not None and i.get(key2) is not None: + result.append({"name": i.get(key2), "count": int(i.get("count"))}) + return result + + def __flatten_sort_key_count(data): if data is None: return [] @@ -148,19 +162,85 @@ def __process_tags(row): ] -def get_details(project_id, error_id, user_id, **data): - # now=TimeUTC.now() +def __process_tags_map(row): + browsers_partition = row.pop("browsers_partition") + os_partition = row.pop("os_partition") + device_partition = row.pop("device_partition") + country_partition = row.pop("country_partition") + return [ + {"name": "browser", + "partitions": __transform_map_to_tag(data=browsers_partition, + key1="browser", + key2="browser_version", + requested_key=1)}, + {"name": "browser.ver", + "partitions": __transform_map_to_tag(data=browsers_partition, + key1="browser", + key2="browser_version", + requested_key=2)}, + {"name": "OS", + "partitions": __transform_map_to_tag(data=os_partition, + key1="os", + key2="os_version", + requested_key=1) + }, + {"name": "OS.ver", + "partitions": __transform_map_to_tag(data=os_partition, + key1="os", + key2="os_version", + requested_key=2)}, + {"name": "device.family", + "partitions": __transform_map_to_tag(data=device_partition, + key1="device_type", + key2="device", + requested_key=1)}, + {"name": "device", + "partitions": __transform_map_to_tag(data=device_partition, + key1="device_type", + key2="device", + requested_key=2)}, + {"name": "country", "partitions": __transform_map_to_tag(data=country_partition, + key1="country", + key2="", + requested_key=1)} + ] + + +def get_details_deprecated(project_id, error_id, user_id, **data): + if not config("EXP_ERRORS_GET", cast=bool, default=False): + return errors_legacy.get_details(project_id, error_id, user_id, **data) + + MAIN_SESSIONS_TABLE = exp_ch_helper.get_main_sessions_table(0) + MAIN_EVENTS_TABLE = exp_ch_helper.get_main_events_table(0) + MAIN_EVENTS_TABLE_24 = exp_ch_helper.get_main_events_table(TimeUTC.now()) + ch_sub_query24 = __get_basic_constraints(startTime_arg_name="startDate24", endTime_arg_name="endDate24") ch_sub_query24.append("error_id = %(error_id)s") - ch_sub_query30 = __get_basic_constraints(startTime_arg_name="startDate30", endTime_arg_name="endDate30") + pg_sub_query30_err = __get_basic_constraints(time_constraint=True, startTime_arg_name="startDate30", + endTime_arg_name="endDate30", project_key="errors.project_id", + table_name="errors") + pg_sub_query30_err.append("sessions.project_id = toUInt16(%(project_id)s)") + pg_sub_query30_err.append("sessions.datetime >= toDateTime(%(startDate30)s/1000)") + pg_sub_query30_err.append("sessions.datetime <= toDateTime(%(endDate30)s/1000)") + pg_sub_query30_err.append("error_id = %(error_id)s") + pg_sub_query30_err.append("source ='js_exception'") + ch_sub_query30 = __get_basic_constraints(startTime_arg_name="startDate30", endTime_arg_name="endDate30", + project_key="errors.project_id") ch_sub_query30.append("error_id = %(error_id)s") ch_basic_query = __get_basic_constraints(time_constraint=False) ch_basic_query.append("error_id = %(error_id)s") + ch_basic_query_session = ch_basic_query[:] + ch_basic_query_session.append("sessions.project_id = toUInt16(%(project_id)s)") with ch_client.ClickHouseClient() as ch: data["startDate24"] = TimeUTC.now(-1) data["endDate24"] = TimeUTC.now() data["startDate30"] = TimeUTC.now(-30) data["endDate30"] = TimeUTC.now() + # # TODO: remove time limits + # data["startDate24"] = 1650470729000 - 24 * 60 * 60 * 1000 + # data["endDate24"] = 1650470729000 + # data["startDate30"] = 1650470729000 - 30 * 60 * 60 * 1000 + # data["endDate30"] = 1650470729000 density24 = int(data.get("density24", 24)) step_size24 = __get_step_size(data["startDate24"], data["endDate24"], density24) density30 = int(data.get("density30", 30)) @@ -196,28 +276,27 @@ def get_details(project_id, error_id, user_id, **data): message, COUNT(DISTINCT user_uuid) AS users, COUNT(DISTINCT session_id) AS sessions - FROM errors - WHERE error_id = %(error_id)s + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY error_id, name, message) AS details INNER JOIN (SELECT error_id, - toUnixTimestamp(MAX(datetime)) * 1000 AS last_occurrence, - toUnixTimestamp(MIN(datetime)) * 1000 AS first_occurrence - FROM errors - WHERE error_id = %(error_id)s + toUnixTimestamp(max(datetime)) * 1000 AS last_occurrence, + toUnixTimestamp(min(datetime)) * 1000 AS first_occurrence + FROM {MAIN_EVENTS_TABLE} AS errors + WHERE {" AND ".join(ch_basic_query)} GROUP BY error_id) AS time_details ON details.error_id = time_details.error_id INNER JOIN (SELECT error_id, session_id AS last_session_id, user_os, user_os_version, user_browser, user_browser_version, user_device, user_device_type, user_uuid - FROM errors - WHERE error_id = %(error_id)s - ORDER BY datetime DESC + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(ch_basic_query_session)} + ORDER BY errors.datetime DESC LIMIT 1) AS last_session_details ON last_session_details.error_id = details.error_id - INNER JOIN (SELECT %(error_id)s AS error_id, - groupArray( - [[[user_browser]], [[toString(count_per_browser)]],versions_partition]) AS browsers_partition + INNER JOIN (SELECT %(error_id)s AS error_id, + groupArray([[[user_browser]], [[toString(count_per_browser)]],versions_partition]) AS browsers_partition FROM (SELECT user_browser, COUNT(session_id) AS count_per_browser - FROM errors - WHERE {" AND ".join(ch_basic_query)} + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY user_browser ORDER BY count_per_browser DESC) AS count_per_browser_query INNER JOIN (SELECT user_browser, @@ -225,63 +304,61 @@ def get_details(project_id, error_id, user_id, **data): FROM (SELECT user_browser, user_browser_version, COUNT(session_id) AS count_per_version - FROM errors - WHERE {" AND ".join(ch_basic_query)} + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY user_browser, user_browser_version ORDER BY count_per_version DESC) AS version_details GROUP BY user_browser ) AS browser_version_details USING (user_browser)) AS browser_details ON browser_details.error_id = details.error_id - INNER JOIN (SELECT %(error_id)s AS error_id, + INNER JOIN (SELECT %(error_id)s AS error_id, groupArray([[[user_os]], [[toString(count_per_os)]],versions_partition]) AS os_partition FROM (SELECT user_os, COUNT(session_id) AS count_per_os - FROM errors - WHERE {" AND ".join(ch_basic_query)} + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY user_os ORDER BY count_per_os DESC) AS count_per_os_details INNER JOIN (SELECT user_os, groupArray([user_os_version, toString(count_per_version)]) AS versions_partition FROM (SELECT user_os, user_os_version, COUNT(session_id) AS count_per_version - FROM errors - WHERE {" AND ".join(ch_basic_query)} + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY user_os, user_os_version ORDER BY count_per_version DESC) AS count_per_version_details GROUP BY user_os ) AS os_version_details USING (user_os)) AS os_details ON os_details.error_id = details.error_id - INNER JOIN (SELECT %(error_id)s AS error_id, - groupArray( - [[[toString(user_device_type)]], [[toString(count_per_device)]],versions_partition]) AS device_partition + INNER JOIN (SELECT %(error_id)s AS error_id, + groupArray([[[toString(user_device_type)]], [[toString(count_per_device)]],versions_partition]) AS device_partition FROM (SELECT user_device_type, COUNT(session_id) AS count_per_device - FROM errors - WHERE {" AND ".join(ch_basic_query)} + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY user_device_type ORDER BY count_per_device DESC) AS count_per_device_details INNER JOIN (SELECT user_device_type, groupArray([user_device, toString(count_per_device)]) AS versions_partition FROM (SELECT user_device_type, - COALESCE(user_device,'unknown') AS user_device, + coalesce(user_device,'unknown') AS user_device, COUNT(session_id) AS count_per_device - FROM errors - WHERE {" AND ".join(ch_basic_query)} + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY user_device_type, user_device ORDER BY count_per_device DESC) AS count_per_device_details GROUP BY user_device_type ) AS device_version_details USING (user_device_type)) AS device_details ON device_details.error_id = details.error_id - INNER JOIN (SELECT %(error_id)s AS error_id, - groupArray( - [[[toString(user_country)]], [[toString(count_per_country)]]]) AS country_partition + INNER JOIN (SELECT %(error_id)s AS error_id, + groupArray([[[toString(user_country)]], [[toString(count_per_country)]]]) AS country_partition FROM (SELECT user_country, COUNT(session_id) AS count_per_country - FROM errors - WHERE {" AND ".join(ch_basic_query)} + FROM {MAIN_EVENTS_TABLE} AS errors INNER JOIN {MAIN_SESSIONS_TABLE} AS sessions USING (session_id) + WHERE {" AND ".join(pg_sub_query30_err)} GROUP BY user_country ORDER BY count_per_country DESC) AS count_per_country_details) AS country_details ON country_details.error_id = details.error_id INNER JOIN (SELECT %(error_id)s AS error_id, groupArray([timestamp, count]) AS chart24 FROM (SELECT toUnixTimestamp(toStartOfInterval(datetime, INTERVAL %(step_size24)s second)) * 1000 AS timestamp, COUNT(DISTINCT session_id) AS count - FROM errors + FROM {MAIN_EVENTS_TABLE_24} AS errors WHERE {" AND ".join(ch_sub_query24)} GROUP BY timestamp ORDER BY timestamp) AS chart_details) AS chart_details24 @@ -289,14 +366,14 @@ def get_details(project_id, error_id, user_id, **data): INNER JOIN (SELECT %(error_id)s AS error_id, groupArray([timestamp, count]) AS chart30 FROM (SELECT toUnixTimestamp(toStartOfInterval(datetime, INTERVAL %(step_size30)s second)) * 1000 AS timestamp, COUNT(DISTINCT session_id) AS count - FROM errors + FROM {MAIN_EVENTS_TABLE} AS errors WHERE {" AND ".join(ch_sub_query30)} GROUP BY timestamp ORDER BY timestamp) AS chart_details) AS chart_details30 ON details.error_id = chart_details30.error_id;""" # print("--------------------") - # print(main_ch_query % params) + # print(ch.format(main_ch_query, params)) # print("--------------------") row = ch.execute(query=main_ch_query, params=params) if len(row) == 0: @@ -306,7 +383,7 @@ def get_details(project_id, error_id, user_id, **data): with pg_client.PostgresClient() as cur: query = cur.mogrify( f"""SELECT error_id, status, session_id, start_ts, - parent_error_id,session_id, user_anonymous_id, + parent_error_id, user_anonymous_id, user_id, user_uuid, user_browser, user_browser_version, user_os, user_os_version, user_device, payload, FALSE AS favorite, @@ -338,11 +415,208 @@ def get_details(project_id, error_id, user_id, **data): row["favorite"] = False row["viewed"] = False row["chart24"] = __rearrange_chart_details(start_at=data["startDate24"], end_at=data["endDate24"], - density=density24, - chart=row["chart24"]) + density=density24, chart=row["chart24"]) row["chart30"] = __rearrange_chart_details(start_at=data["startDate30"], end_at=data["endDate30"], - density=density30, - chart=row["chart30"]) + density=density30, chart=row["chart30"]) + return {"data": helper.dict_to_camel_case(row)} + + +def get_details(project_id, error_id, user_id, **data): + if not config("EXP_ERRORS_GET", cast=bool, default=False): + return errors_legacy.get_details(project_id, error_id, user_id, **data) + + MAIN_SESSIONS_TABLE = exp_ch_helper.get_main_sessions_table(0) + MAIN_ERR_SESS_TABLE = exp_ch_helper.get_main_js_errors_sessions_table(0) + MAIN_EVENTS_TABLE = exp_ch_helper.get_main_events_table(0) + MAIN_EVENTS_TABLE_24 = exp_ch_helper.get_main_events_table(TimeUTC.now()) + + ch_sub_query24 = __get_basic_constraints(startTime_arg_name="startDate24", endTime_arg_name="endDate24") + ch_sub_query24.append("error_id = %(error_id)s") + # pg_sub_query30_err = __get_basic_constraints(time_constraint=True, startTime_arg_name="startDate30", + # endTime_arg_name="endDate30", project_key="errors.project_id", + # table_name="errors") + # pg_sub_query30_err.append("sessions.project_id = toUInt16(%(project_id)s)") + # pg_sub_query30_err.append("sessions.datetime >= toDateTime(%(startDate30)s/1000)") + # pg_sub_query30_err.append("sessions.datetime <= toDateTime(%(endDate30)s/1000)") + # pg_sub_query30_err.append("error_id = %(error_id)s") + # pg_sub_query30_err.append("source ='js_exception'") + ch_sub_query30 = __get_basic_constraints(startTime_arg_name="startDate30", endTime_arg_name="endDate30", + project_key="errors.project_id") + ch_sub_query30.append("error_id = %(error_id)s") + ch_basic_query = __get_basic_constraints(time_constraint=False) + ch_basic_query.append("error_id = %(error_id)s") + # ch_basic_query_session = ch_basic_query[:] + # ch_basic_query_session.append("sessions.project_id = toUInt16(%(project_id)s)") + with ch_client.ClickHouseClient() as ch: + data["startDate24"] = TimeUTC.now(-1) + data["endDate24"] = TimeUTC.now() + data["startDate30"] = TimeUTC.now(-30) + data["endDate30"] = TimeUTC.now() + # # TODO: remove time limits + # data["startDate24"] = 1650470729000 - 24 * 60 * 60 * 1000 + # data["endDate24"] = 1650470729000 + # data["startDate30"] = 1650470729000 - 30 * 60 * 60 * 1000 + # data["endDate30"] = 1650470729000 + density24 = int(data.get("density24", 24)) + step_size24 = __get_step_size(data["startDate24"], data["endDate24"], density24) + density30 = int(data.get("density30", 30)) + step_size30 = __get_step_size(data["startDate30"], data["endDate30"], density30) + params = { + "startDate24": data['startDate24'], + "endDate24": data['endDate24'], + "startDate30": data['startDate30'], + "endDate30": data['endDate30'], + "project_id": project_id, + "userId": user_id, + "step_size24": step_size24, + "step_size30": step_size30, + "error_id": error_id} + + main_ch_query = f"""\ + WITH pre_processed AS (SELECT error_id, + name, + message, + session_id, + datetime, + user_id, + user_browser, + user_browser_version, + user_os, + user_os_version, + user_device_type, + user_device, + user_country, + error_tags_keys, + error_tags_values + FROM {MAIN_ERR_SESS_TABLE} AS errors + WHERE {" AND ".join(ch_basic_query)} + ) + SELECT %(error_id)s AS error_id, name, message,users, + first_occurrence,last_occurrence,last_session_id, + sessions,browsers_partition,os_partition,device_partition, + country_partition,chart24,chart30,custom_tags + FROM (SELECT error_id, + name, + message + FROM pre_processed + LIMIT 1) AS details + INNER JOIN (SELECT COUNT(DISTINCT user_id) AS users, + COUNT(DISTINCT session_id) AS sessions + FROM pre_processed + WHERE datetime >= toDateTime(%(startDate30)s / 1000) + AND datetime <= toDateTime(%(endDate30)s / 1000) + ) AS last_month_stats ON TRUE + INNER JOIN (SELECT toUnixTimestamp(max(datetime)) * 1000 AS last_occurrence, + toUnixTimestamp(min(datetime)) * 1000 AS first_occurrence + FROM pre_processed) AS time_details ON TRUE + INNER JOIN (SELECT session_id AS last_session_id, + arrayMap((key, value)->(map(key, value)), error_tags_keys, error_tags_values) AS custom_tags + FROM pre_processed + ORDER BY datetime DESC + LIMIT 1) AS last_session_details ON TRUE + INNER JOIN (SELECT groupArray(details) AS browsers_partition + FROM (SELECT COUNT(1) AS count, + coalesce(nullIf(user_browser,''),toNullable('unknown')) AS browser, + coalesce(nullIf(user_browser_version,''),toNullable('unknown')) AS browser_version, + map('browser', browser, + 'browser_version', browser_version, + 'count', toString(count)) AS details + FROM pre_processed + GROUP BY ROLLUP(browser, browser_version) + ORDER BY browser nulls first, browser_version nulls first, count DESC) AS mapped_browser_details + ) AS browser_details ON TRUE + INNER JOIN (SELECT groupArray(details) AS os_partition + FROM (SELECT COUNT(1) AS count, + coalesce(nullIf(user_os,''),toNullable('unknown')) AS os, + coalesce(nullIf(user_os_version,''),toNullable('unknown')) AS os_version, + map('os', os, + 'os_version', os_version, + 'count', toString(count)) AS details + FROM pre_processed + GROUP BY ROLLUP(os, os_version) + ORDER BY os nulls first, os_version nulls first, count DESC) AS mapped_os_details + ) AS os_details ON TRUE + INNER JOIN (SELECT groupArray(details) AS device_partition + FROM (SELECT COUNT(1) AS count, + coalesce(nullIf(user_device,''),toNullable('unknown')) AS user_device, + map('device_type', toString(user_device_type), + 'device', user_device, + 'count', toString(count)) AS details + FROM pre_processed + GROUP BY ROLLUP(user_device_type, user_device) + ORDER BY user_device_type nulls first, user_device nulls first, count DESC + ) AS count_per_device_details + ) AS mapped_device_details ON TRUE + INNER JOIN (SELECT groupArray(details) AS country_partition + FROM (SELECT COUNT(1) AS count, + map('country', toString(user_country), + 'count', toString(count)) AS details + FROM pre_processed + GROUP BY user_country + ORDER BY count DESC) AS count_per_country_details + ) AS mapped_country_details ON TRUE + INNER JOIN (SELECT groupArray(map('timestamp', timestamp, 'count', count)) AS chart24 + FROM (SELECT toUnixTimestamp(toStartOfInterval(datetime, INTERVAL 3756 second)) * + 1000 AS timestamp, + COUNT(DISTINCT session_id) AS count + FROM {MAIN_EVENTS_TABLE} AS errors + WHERE {" AND ".join(ch_sub_query24)} + GROUP BY timestamp + ORDER BY timestamp) AS chart_details + ) AS chart_details24 ON TRUE + INNER JOIN (SELECT groupArray(map('timestamp', timestamp, 'count', count)) AS chart30 + FROM (SELECT toUnixTimestamp(toStartOfInterval(datetime, INTERVAL 3724 second)) * + 1000 AS timestamp, + COUNT(DISTINCT session_id) AS count + FROM {MAIN_EVENTS_TABLE} AS errors + WHERE {" AND ".join(ch_sub_query30)} + GROUP BY timestamp + ORDER BY timestamp) AS chart_details + ) AS chart_details30 ON TRUE;""" + + # print("--------------------") + # print(ch.format(main_ch_query, params)) + # print("--------------------") + row = ch.execute(query=main_ch_query, params=params) + if len(row) == 0: + return {"errors": ["error not found"]} + row = row[0] + + row["tags"] = __process_tags_map(row) + + query = f"""SELECT session_id, toUnixTimestamp(datetime) * 1000 AS start_ts, + user_anonymous_id,user_id, user_uuid, user_browser, user_browser_version, + user_os, user_os_version, user_device, FALSE AS favorite, True AS viewed + FROM {MAIN_SESSIONS_TABLE} AS sessions + WHERE project_id = toUInt16(%(project_id)s) + AND session_id = %(session_id)s + ORDER BY datetime DESC + LIMIT 1;""" + params = {"project_id": project_id, "session_id": row["last_session_id"], "userId": user_id} + # print("--------------------") + # print(ch.format(query, params)) + # print("--------------------") + status = ch.execute(query=query, params=params) + + if status is not None: + status = status[0] + # row["stack"] = format_first_stack_frame(status).pop("stack") + # row["status"] = status.pop("status") + # row["parent_error_id"] = status.pop("parent_error_id") + row["favorite"] = status.pop("favorite") + row["viewed"] = status.pop("viewed") + row["last_hydrated_session"] = status + else: + # row["stack"] = [] + row["last_hydrated_session"] = None + # row["status"] = "untracked" + # row["parent_error_id"] = None + row["favorite"] = False + row["viewed"] = False + row["chart24"] = metrics.__complete_missing_steps(start_time=data["startDate24"], end_time=data["endDate24"], + density=density24, rows=row["chart24"], neutral={"count": 0}) + row["chart30"] = metrics.__complete_missing_steps(start_time=data["startDate30"], end_time=data["endDate30"], + density=density30, rows=row["chart30"], neutral={"count": 0}) return {"data": helper.dict_to_camel_case(row)} @@ -423,7 +697,7 @@ def get_details_chart(project_id, error_id, user_id, **data): INNER JOIN (SELECT user_device_type, groupArray([user_device, toString(count_per_device)]) AS versions_partition FROM (SELECT user_device_type, - COALESCE(user_device,'unknown') AS user_device, + coalesce(user_device,'unknown') AS user_device, COUNT(session_id) AS count_per_device FROM errors WHERE {" AND ".join(ch_sub_query)} @@ -463,13 +737,17 @@ def get_details_chart(project_id, error_id, user_id, **data): def __get_basic_constraints(platform=None, time_constraint=True, startTime_arg_name="startDate", - endTime_arg_name="endDate", type_condition=True): - ch_sub_query = ["project_id =toUInt32(%(project_id)s)"] + endTime_arg_name="endDate", type_condition=True, project_key="project_id", table_name=None): + ch_sub_query = [f"{project_key} =toUInt16(%(project_id)s)"] + if table_name is not None: + table_name = table_name + "." + else: + table_name = "" if type_condition: - ch_sub_query.append("event_type='ERROR'") + ch_sub_query.append(f"{table_name}event_type='ERROR'") if time_constraint: - ch_sub_query += [f"datetime >= toDateTime(%({startTime_arg_name})s/1000)", - f"datetime < toDateTime(%({endTime_arg_name})s/1000)"] + ch_sub_query += [f"{table_name}datetime >= toDateTime(%({startTime_arg_name})s/1000)", + f"{table_name}datetime < toDateTime(%({endTime_arg_name})s/1000)"] if platform == schemas.PlatformType.mobile: ch_sub_query.append("user_device_type = 'mobile'") elif platform == schemas.PlatformType.desktop: @@ -879,11 +1157,11 @@ def get_sessions(start_date, end_date, project_id, user_id, error_id): s.pages_count, s.errors_count, s.issue_types, - COALESCE((SELECT TRUE + coalesce((SELECT TRUE FROM public.user_favorite_sessions AS fs WHERE s.session_id = fs.session_id AND fs.user_id = %(userId)s LIMIT 1), FALSE) AS favorite, - COALESCE((SELECT TRUE + coalesce((SELECT TRUE FROM public.user_viewed_sessions AS fs WHERE s.session_id = fs.session_id AND fs.user_id = %(userId)s LIMIT 1), FALSE) AS viewed diff --git a/ee/api/chalicelib/core/metrics.py b/ee/api/chalicelib/core/metrics.py index 3861f48aa..2a2f6ee20 100644 --- a/ee/api/chalicelib/core/metrics.py +++ b/ee/api/chalicelib/core/metrics.py @@ -15,7 +15,7 @@ def __get_basic_constraints(table_name=None, time_constraint=True, round_start=F table_name += "." else: table_name = "" - ch_sub_query = [f"{table_name}{identifier} =toUInt32(%({identifier})s)"] + ch_sub_query = [f"{table_name}{identifier} =toUInt16(%({identifier})s)"] if time_constraint: if round_start: ch_sub_query.append( @@ -452,18 +452,18 @@ def get_slowest_images(project_id, startTimestamp=TimeUTC.now(delta_days=-1), ch_sub_query.append("resources.type = 'img'") ch_sub_query_chart = __get_basic_constraints(table_name="resources", round_start=True, data=args) ch_sub_query_chart.append("resources.type = 'img'") - ch_sub_query_chart.append("resources.url IN %(url)s") + ch_sub_query_chart.append("resources.url_hostpath IN %(url)s") meta_condition = __get_meta_constraint(args) ch_sub_query += meta_condition ch_sub_query_chart += meta_condition with ch_client.ClickHouseClient() as ch: - ch_query = f"""SELECT resources.url, + ch_query = f"""SELECT resources.url_hostpath AS url, COALESCE(avgOrNull(resources.duration),0) AS avg, COUNT(1) AS count FROM resources {"INNER JOIN sessions_metadata USING(session_id)" if len(meta_condition) > 0 else ""} WHERE {" AND ".join(ch_sub_query)} AND resources.duration>0 - GROUP BY resources.url ORDER BY avg DESC LIMIT 10;""" + GROUP BY resources.url_hostpath ORDER BY avg DESC LIMIT 10;""" params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, "endTimestamp": endTimestamp, **__get_constraint_values(args)} rows = ch.execute(query=ch_query, params=params) @@ -474,13 +474,13 @@ def get_slowest_images(project_id, startTimestamp=TimeUTC.now(delta_days=-1), urls = [row["url"] for row in rows] charts = {} - ch_query = f"""SELECT url, + ch_query = f"""SELECT url_hostpath AS url, toUnixTimestamp(toStartOfInterval(resources.datetime, INTERVAL %(step_size)s second ))*1000 AS timestamp, COALESCE(avgOrNull(resources.duration),0) AS avg FROM resources {"INNER JOIN sessions_metadata USING(session_id)" if len(meta_condition) > 0 else ""} WHERE {" AND ".join(ch_sub_query_chart)} AND resources.duration>0 - GROUP BY url, timestamp - ORDER BY url, timestamp;""" + GROUP BY url_hostpath, timestamp + ORDER BY url_hostpath, timestamp;""" params["url"] = urls u_rows = ch.execute(query=ch_query, params=params) for url in urls: @@ -526,13 +526,13 @@ def get_performance(project_id, startTimestamp=TimeUTC.now(delta_days=-1), endTi if resources and len(resources) > 0: for r in resources: if r["type"] == "IMG": - img_constraints.append(f"resources.url = %(val_{len(img_constraints)})s") + img_constraints.append(f"resources.url_hostpath = %(val_{len(img_constraints)})s") img_constraints_vals["val_" + str(len(img_constraints) - 1)] = r['value'] elif r["type"] == "LOCATION": location_constraints.append(f"pages.url_path = %(val_{len(location_constraints)})s") location_constraints_vals["val_" + str(len(location_constraints) - 1)] = r['value'] else: - request_constraints.append(f"resources.url = %(val_{len(request_constraints)})s") + request_constraints.append(f"resources.url_hostpath = %(val_{len(request_constraints)})s") request_constraints_vals["val_" + str(len(request_constraints) - 1)] = r['value'] params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, "endTimestamp": endTimestamp} @@ -638,7 +638,7 @@ def search(text, resource_type, project_id, performance=False, pages_only=False, if resource_type == "ALL" and not pages_only and not events_only: ch_sub_query.append("positionUTF8(url_hostpath,%(value)s)!=0") with ch_client.ClickHouseClient() as ch: - ch_query = f"""SELECT arrayJoin(arraySlice(arrayReverseSort(arrayDistinct(groupArray(url))), 1, 5)) AS value, + ch_query = f"""SELECT arrayJoin(arraySlice(arrayReverseSort(arrayDistinct(groupArray(url_hostpath))), 1, 5)) AS value, type AS key FROM resources WHERE {" AND ".join(ch_sub_query)} @@ -884,7 +884,7 @@ def get_resources_loading_time(project_id, startTimestamp=TimeUTC.now(delta_days if type is not None: ch_sub_query_chart.append(f"resources.type = '{__get_resource_db_type_from_type(type)}'") if url is not None: - ch_sub_query_chart.append(f"resources.url = %(value)s") + ch_sub_query_chart.append(f"resources.url_hostpath = %(value)s") meta_condition = __get_meta_constraint(args) ch_sub_query_chart += meta_condition ch_sub_query_chart.append("resources.duration>0") @@ -966,7 +966,7 @@ def get_slowest_resources(project_id, startTimestamp=TimeUTC.now(delta_days=-1), ch_sub_query_chart.append("isNotNull(resources.duration)") ch_sub_query_chart.append("resources.duration>0") with ch_client.ClickHouseClient() as ch: - ch_query = f"""SELECT any(url) AS url, any(type) AS type, + ch_query = f"""SELECT any(url_hostpath) AS url, any(type) AS type, splitByChar('/', resources.url_hostpath)[-1] AS name, COALESCE(avgOrNull(NULLIF(resources.duration,0)),0) AS avg FROM resources {"INNER JOIN sessions_metadata USING(session_id)" if len(meta_condition) > 0 else ""} @@ -2012,7 +2012,7 @@ def get_resources_by_party(project_id, startTimestamp=TimeUTC.now(delta_days=-1) ch_sub_query = __get_basic_constraints(table_name="resources", round_start=True, data=args) ch_sub_query.append("resources.success = 0") ch_sub_query.append("resources.type IN ('fetch','script')") - sch_sub_query = ["rs.project_id =toUInt32(%(project_id)s)", "rs.type IN ('fetch','script')"] + sch_sub_query = ["rs.project_id =toUInt16(%(project_id)s)", "rs.type IN ('fetch','script')"] meta_condition = __get_meta_constraint(args) ch_sub_query += meta_condition # sch_sub_query += meta_condition @@ -2179,7 +2179,7 @@ def get_performance_avg_image_load_time(ch, project_id, startTimestamp=TimeUTC.n if resources and len(resources) > 0: for r in resources: if r["type"] == "IMG": - img_constraints.append(f"resources.url = %(val_{len(img_constraints)})s") + img_constraints.append(f"resources.url_hostpath = %(val_{len(img_constraints)})s") img_constraints_vals["val_" + str(len(img_constraints) - 1)] = r['value'] params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, @@ -2254,7 +2254,7 @@ def get_performance_avg_request_load_time(ch, project_id, startTimestamp=TimeUTC if resources and len(resources) > 0: for r in resources: if r["type"] != "IMG" and r["type"] == "LOCATION": - request_constraints.append(f"resources.url = %(val_{len(request_constraints)})s") + request_constraints.append(f"resources.url_hostpath = %(val_{len(request_constraints)})s") request_constraints_vals["val_" + str(len(request_constraints) - 1)] = r['value'] params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, "endTimestamp": endTimestamp} diff --git a/ee/api/chalicelib/core/metrics_exp.py b/ee/api/chalicelib/core/metrics_exp.py index 04e180e93..c41676d4a 100644 --- a/ee/api/chalicelib/core/metrics_exp.py +++ b/ee/api/chalicelib/core/metrics_exp.py @@ -1,7 +1,7 @@ import math import schemas -from chalicelib.utils import pg_client, exp_ch_helper +from chalicelib.utils import exp_ch_helper from chalicelib.utils import args_transformer from chalicelib.utils import helper from chalicelib.utils.TimeUTC import TimeUTC @@ -462,18 +462,18 @@ def get_slowest_images(project_id, startTimestamp=TimeUTC.now(delta_days=-1), ch_sub_query_chart = __get_basic_constraints(table_name="resources", round_start=True, data=args) # ch_sub_query_chart.append("events.event_type='RESOURCE'") ch_sub_query_chart.append("resources.type = 'img'") - ch_sub_query_chart.append("resources.url IN %(url)s") + ch_sub_query_chart.append("resources.url_hostpath IN %(url)s") meta_condition = __get_meta_constraint(args) ch_sub_query += meta_condition ch_sub_query_chart += meta_condition with ch_client.ClickHouseClient() as ch: - ch_query = f"""SELECT resources.url, + ch_query = f"""SELECT resources.url_hostpath AS url, COALESCE(avgOrNull(resources.duration),0) AS avg, COUNT(1) AS count FROM {exp_ch_helper.get_main_resources_table(startTimestamp)} AS resources WHERE {" AND ".join(ch_sub_query)} AND resources.duration>0 - GROUP BY resources.url ORDER BY avg DESC LIMIT 10;""" + GROUP BY resources.url_hostpath ORDER BY avg DESC LIMIT 10;""" params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, "endTimestamp": endTimestamp, **__get_constraint_values(args)} rows = ch.execute(query=ch_query, params=params) @@ -484,13 +484,13 @@ def get_slowest_images(project_id, startTimestamp=TimeUTC.now(delta_days=-1), urls = [row["url"] for row in rows] charts = {} - ch_query = f"""SELECT url, + ch_query = f"""SELECT url_hostpath AS url, toUnixTimestamp(toStartOfInterval(resources.datetime, INTERVAL %(step_size)s second ))*1000 AS timestamp, COALESCE(avgOrNull(resources.duration),0) AS avg FROM {exp_ch_helper.get_main_resources_table(startTimestamp)} AS resources WHERE {" AND ".join(ch_sub_query_chart)} AND resources.duration>0 - GROUP BY url, timestamp - ORDER BY url, timestamp;""" + GROUP BY url_hostpath, timestamp + ORDER BY url_hostpath, timestamp;""" params["url"] = urls # print(ch.format(query=ch_query, params=params)) u_rows = ch.execute(query=ch_query, params=params) @@ -538,13 +538,13 @@ def get_performance(project_id, startTimestamp=TimeUTC.now(delta_days=-1), endTi if resources and len(resources) > 0: for r in resources: if r["type"] == "IMG": - img_constraints.append(f"resources.url = %(val_{len(img_constraints)})s") + img_constraints.append(f"resources.url_hostpath = %(val_{len(img_constraints)})s") img_constraints_vals["val_" + str(len(img_constraints) - 1)] = r['value'] elif r["type"] == "LOCATION": location_constraints.append(f"pages.url_path = %(val_{len(location_constraints)})s") location_constraints_vals["val_" + str(len(location_constraints) - 1)] = r['value'] else: - request_constraints.append(f"resources.url = %(val_{len(request_constraints)})s") + request_constraints.append(f"resources.url_hostpath = %(val_{len(request_constraints)})s") request_constraints_vals["val_" + str(len(request_constraints) - 1)] = r['value'] params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, "endTimestamp": endTimestamp} @@ -891,7 +891,7 @@ def get_resources_loading_time(project_id, startTimestamp=TimeUTC.now(delta_days if type is not None: ch_sub_query_chart.append(f"resources.type = '{__get_resource_db_type_from_type(type)}'") if url is not None: - ch_sub_query_chart.append(f"resources.url = %(value)s") + ch_sub_query_chart.append(f"resources.url_hostpath = %(value)s") meta_condition = __get_meta_constraint(args) ch_sub_query_chart += meta_condition ch_sub_query_chart.append("resources.duration>0") @@ -974,7 +974,7 @@ def get_slowest_resources(project_id, startTimestamp=TimeUTC.now(delta_days=-1), ch_sub_query_chart.append("isNotNull(resources.duration)") ch_sub_query_chart.append("resources.duration>0") with ch_client.ClickHouseClient() as ch: - ch_query = f"""SELECT any(url) AS url, any(type) AS type, name, + ch_query = f"""SELECT any(url_hostpath) AS url, any(type) AS type, name, COALESCE(avgOrNull(NULLIF(resources.duration,0)),0) AS avg FROM {exp_ch_helper.get_main_resources_table(startTimestamp)} AS resources WHERE {" AND ".join(ch_sub_query)} @@ -2185,7 +2185,7 @@ def get_performance_avg_image_load_time(ch, project_id, startTimestamp=TimeUTC.n if resources and len(resources) > 0: for r in resources: if r["type"] == "IMG": - img_constraints.append(f"resources.url = %(val_{len(img_constraints)})s") + img_constraints.append(f"resources.url_hostpath = %(val_{len(img_constraints)})s") img_constraints_vals["val_" + str(len(img_constraints) - 1)] = r['value'] params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, @@ -2260,7 +2260,7 @@ def get_performance_avg_request_load_time(ch, project_id, startTimestamp=TimeUTC if resources and len(resources) > 0: for r in resources: if r["type"] != "IMG" and r["type"] == "LOCATION": - request_constraints.append(f"resources.url = %(val_{len(request_constraints)})s") + request_constraints.append(f"resources.url_hostpath = %(val_{len(request_constraints)})s") request_constraints_vals["val_" + str(len(request_constraints) - 1)] = r['value'] params = {"step_size": step_size, "project_id": project_id, "startTimestamp": startTimestamp, "endTimestamp": endTimestamp} diff --git a/ee/api/chalicelib/core/permissions.py b/ee/api/chalicelib/core/permissions.py new file mode 100644 index 000000000..bcc30b891 --- /dev/null +++ b/ee/api/chalicelib/core/permissions.py @@ -0,0 +1,10 @@ +from fastapi.security import SecurityScopes + +import schemas_ee + + +def check(security_scopes: SecurityScopes, context: schemas_ee.CurrentContext): + for scope in security_scopes.scopes: + if scope not in context.permissions: + return False + return True diff --git a/ee/api/chalicelib/core/projects.py b/ee/api/chalicelib/core/projects.py index c5ab7c800..18d71914b 100644 --- a/ee/api/chalicelib/core/projects.py +++ b/ee/api/chalicelib/core/projects.py @@ -51,6 +51,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st AND users.deleted_at ISNULL AND users.tenant_id = %(tenant_id)s AND (roles.all_projects OR roles_projects.project_id = s.project_id) + LIMIT 1 ) AS role_project ON (TRUE)""" extra_projection = "" extra_join = "" @@ -86,22 +87,23 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st {"tenant_id": tenant_id, "user_id": user_id, "now": TimeUTC.now()}) cur.execute(query) rows = cur.fetchall() - # if recorded is requested, check if it was saved or computed if recorded: - for r in rows: + u_values = [] + params = {} + for i, r in enumerate(rows): if r["first_recorded_session_at"] is None: - extra_update = "" - if r["recorded"]: - extra_update = ", first_recorded_session_at=to_timestamp(%(first_recorded)s/1000)" - query = cur.mogrify(f"""UPDATE public.projects - SET sessions_last_check_at=(now() at time zone 'utc') - {extra_update} - WHERE project_id=%(project_id)s""", - {"project_id": r["project_id"], "first_recorded": r["first_recorded"]}) - cur.execute(query) + u_values.append(f"(%(project_id_{i})s,to_timestamp(%(first_recorded_{i})s/1000))") + params[f"project_id_{i}"] = r["project_id"] + params[f"first_recorded_{i}"] = r["first_recorded"] if r["recorded"] else None r.pop("first_recorded_session_at") r.pop("first_recorded") + if len(u_values) > 0: + query = cur.mogrify(f"""UPDATE public.projects + SET sessions_last_check_at=(now() at time zone 'utc'), first_recorded_session_at=u.first_recorded + FROM (VALUES {",".join(u_values)}) AS u(project_id,first_recorded) + WHERE projects.project_id=u.project_id;""", params) + cur.execute(query) if recording_state and len(rows) > 0: project_ids = [f'({r["project_id"]})' for r in rows] @@ -111,6 +113,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st WHERE sessions.start_ts >= %(startDate)s AND sessions.start_ts <= %(endDate)s GROUP BY project_id;""", {"startDate": TimeUTC.now(delta_days=-3), "endDate": TimeUTC.now(delta_days=1)}) + cur.execute(query=query) status = cur.fetchall() for r in rows: @@ -150,36 +153,6 @@ def get_project(tenant_id, project_id, include_last_session=False, include_gdpr= return helper.dict_to_camel_case(row) -def is_authorized(project_id, tenant_id, user_id=None): - if project_id is None or not str(project_id).isdigit(): - return False - with pg_client.PostgresClient() as cur: - role_query = """INNER JOIN LATERAL (SELECT 1 - FROM users - INNER JOIN roles USING (role_id) - LEFT JOIN roles_projects USING (role_id) - WHERE users.user_id = %(user_id)s - AND users.deleted_at ISNULL - AND users.tenant_id = %(tenant_id)s - AND (roles.all_projects OR roles_projects.project_id = %(project_id)s) - ) AS role_project ON (TRUE)""" - - query = cur.mogrify(f"""\ - SELECT project_id - FROM public.projects AS s - {role_query if user_id is not None else ""} - where s.tenant_id =%(tenant_id)s - AND s.project_id =%(project_id)s - AND s.deleted_at IS NULL - LIMIT 1;""", - {"tenant_id": tenant_id, "project_id": project_id, "user_id": user_id}) - cur.execute( - query=query - ) - row = cur.fetchone() - return row is not None - - def create(tenant_id, user_id, data: schemas.CreateProjectSchema, skip_authorization=False): if not skip_authorization: admin = users.get(user_id=user_id, tenant_id=tenant_id) @@ -198,17 +171,6 @@ def edit(tenant_id, user_id, project_id, data: schemas.CreateProjectSchema): changes={"name": data.name})} -def count_by_tenant(tenant_id): - with pg_client.PostgresClient() as cur: - cur.execute(cur.mogrify("""\ - SELECT - count(s.project_id) - FROM public.projects AS s - WHERE s.deleted_at IS NULL - AND tenant_id= %(tenant_id)s;""", {"tenant_id": tenant_id})) - return cur.fetchone()["count"] - - def delete(tenant_id, user_id, project_id): admin = users.get(user_id=user_id, tenant_id=tenant_id) @@ -227,6 +189,17 @@ def delete(tenant_id, user_id, project_id): return {"data": {"state": "success"}} +def count_by_tenant(tenant_id): + with pg_client.PostgresClient() as cur: + cur.execute(cur.mogrify("""\ + SELECT + count(s.project_id) + FROM public.projects AS s + WHERE s.deleted_at IS NULL + AND tenant_id= %(tenant_id)s;""", {"tenant_id": tenant_id})) + return cur.fetchone()["count"] + + def get_gdpr(project_id): with pg_client.PostgresClient() as cur: cur.execute( @@ -318,6 +291,16 @@ def update_capture_status(project_id, changes): return changes +def get_projects_ids(tenant_id): + with pg_client.PostgresClient() as cur: + cur.execute(cur.mogrify("""SELECT s.project_id + FROM public.projects AS s + WHERE tenant_id =%(tenant_id)s AND s.deleted_at IS NULL + ORDER BY s.project_id;""", {"tenant_id": tenant_id})) + rows = cur.fetchall() + return [r["project_id"] for r in rows] + + def get_project_by_key(tenant_id, project_key, include_last_session=False, include_gdpr=None): with pg_client.PostgresClient() as cur: query = cur.mogrify(f"""\ @@ -340,6 +323,36 @@ def get_project_by_key(tenant_id, project_key, include_last_session=False, inclu return helper.dict_to_camel_case(row) +def is_authorized(project_id, tenant_id, user_id=None): + if project_id is None or not str(project_id).isdigit(): + return False + with pg_client.PostgresClient() as cur: + role_query = """INNER JOIN LATERAL (SELECT 1 + FROM users + INNER JOIN roles USING (role_id) + LEFT JOIN roles_projects USING (role_id) + WHERE users.user_id = %(user_id)s + AND users.deleted_at ISNULL + AND users.tenant_id = %(tenant_id)s + AND (roles.all_projects OR roles_projects.project_id = %(project_id)s) + ) AS role_project ON (TRUE)""" + + query = cur.mogrify(f"""\ + SELECT project_id + FROM public.projects AS s + {role_query if user_id is not None else ""} + where s.tenant_id =%(tenant_id)s + AND s.project_id =%(project_id)s + AND s.deleted_at IS NULL + LIMIT 1;""", + {"tenant_id": tenant_id, "project_id": project_id, "user_id": user_id}) + cur.execute( + query=query + ) + row = cur.fetchone() + return row is not None + + def is_authorized_batch(project_ids, tenant_id): if project_ids is None or not len(project_ids): return False @@ -357,13 +370,3 @@ def is_authorized_batch(project_ids, tenant_id): ) rows = cur.fetchall() return [r["project_id"] for r in rows] - - -def get_projects_ids(tenant_id): - with pg_client.PostgresClient() as cur: - cur.execute(cur.mogrify("""SELECT s.project_id - FROM public.projects AS s - WHERE tenant_id =%(tenant_id)s AND s.deleted_at IS NULL - ORDER BY s.project_id;""", {"tenant_id": tenant_id})) - rows = cur.fetchall() - return [r["project_id"] for r in rows] diff --git a/ee/api/chalicelib/core/resources.py b/ee/api/chalicelib/core/resources.py index e5d7ee126..8bae47d10 100644 --- a/ee/api/chalicelib/core/resources.py +++ b/ee/api/chalicelib/core/resources.py @@ -26,7 +26,7 @@ def get_by_session_id(session_id, project_id, start_ts, duration): coalesce(status,if(success, 200, status)) AS status FROM resources WHERE session_id = toUInt64(%(session_id)s) - AND project_id = toUInt64(%(project_id)s) + AND project_id = toUInt16(%(project_id)s) AND datetime >= toDateTime(%(res_start_ts)s / 1000) AND datetime <= toDateTime(%(res_end_ts)s / 1000);""" params = {"session_id": session_id, "project_id": project_id, "start_ts": start_ts, "duration": duration, diff --git a/ee/api/chalicelib/core/sessions.py b/ee/api/chalicelib/core/sessions.py new file mode 100644 index 000000000..7d999fe6c --- /dev/null +++ b/ee/api/chalicelib/core/sessions.py @@ -0,0 +1,1272 @@ +from typing import List + +import schemas +import schemas_ee +from chalicelib.core import events, metadata, events_ios, \ + sessions_mobs, issues, projects, errors, resources, assist, performance_event, sessions_viewed, sessions_favorite, \ + sessions_devtool, sessions_notes +from chalicelib.utils import pg_client, helper, metrics_helper + +SESSION_PROJECTION_COLS = """s.project_id, +s.session_id::text AS session_id, +s.user_uuid, +s.user_id, +s.user_os, +s.user_browser, +s.user_device, +s.user_device_type, +s.user_country, +s.start_ts, +s.duration, +s.events_count, +s.pages_count, +s.errors_count, +s.user_anonymous_id, +s.platform, +s.issue_score, +to_jsonb(s.issue_types) AS issue_types, +favorite_sessions.session_id NOTNULL AS favorite, +COALESCE((SELECT TRUE + FROM public.user_viewed_sessions AS fs + WHERE s.session_id = fs.session_id + AND fs.user_id = %(userId)s LIMIT 1), FALSE) AS viewed """ + + +def __group_metadata(session, project_metadata): + meta = {} + for m in project_metadata.keys(): + if project_metadata[m] is not None and session.get(m) is not None: + meta[project_metadata[m]] = session[m] + session.pop(m) + return meta + + +def get_by_id2_pg(project_id, session_id, context: schemas_ee.CurrentContext, full_data=False, + include_fav_viewed=False, group_metadata=False, live=True): + with pg_client.PostgresClient() as cur: + extra_query = [] + if include_fav_viewed: + extra_query.append("""COALESCE((SELECT TRUE + FROM public.user_favorite_sessions AS fs + WHERE s.session_id = fs.session_id + AND fs.user_id = %(userId)s), FALSE) AS favorite""") + extra_query.append("""COALESCE((SELECT TRUE + FROM public.user_viewed_sessions AS fs + WHERE s.session_id = fs.session_id + AND fs.user_id = %(userId)s), FALSE) AS viewed""") + query = cur.mogrify( + f"""\ + SELECT + s.*, + s.session_id::text AS session_id, + (SELECT project_key FROM public.projects WHERE project_id = %(project_id)s LIMIT 1) AS project_key, + encode(file_key,'hex') AS file_key + {"," if len(extra_query) > 0 else ""}{",".join(extra_query)} + {(",json_build_object(" + ",".join([f"'{m}',p.{m}" for m in metadata._get_column_names()]) + ") AS project_metadata") if group_metadata else ''} + FROM public.sessions AS s {"INNER JOIN public.projects AS p USING (project_id)" if group_metadata else ""} + WHERE s.project_id = %(project_id)s + AND s.session_id = %(session_id)s;""", + {"project_id": project_id, "session_id": session_id, "userId": context.user_id} + ) + # print("===============") + # print(query) + cur.execute(query=query) + + data = cur.fetchone() + if data is not None: + data = helper.dict_to_camel_case(data) + if full_data: + if data["platform"] == 'ios': + data['events'] = events_ios.get_by_sessionId(project_id=project_id, session_id=session_id) + for e in data['events']: + if e["type"].endswith("_IOS"): + e["type"] = e["type"][:-len("_IOS")] + data['crashes'] = events_ios.get_crashes_by_session_id(session_id=session_id) + data['userEvents'] = events_ios.get_customs_by_sessionId(project_id=project_id, + session_id=session_id) + data['mobsUrl'] = sessions_mobs.get_ios(session_id=session_id) + else: + data['events'] = events.get_by_sessionId2_pg(project_id=project_id, session_id=session_id, + group_clickrage=True) + all_errors = events.get_errors_by_session_id(session_id=session_id, project_id=project_id) + data['stackEvents'] = [e for e in all_errors if e['source'] != "js_exception"] + # to keep only the first stack + # limit the number of errors to reduce the response-body size + data['errors'] = [errors.format_first_stack_frame(e) for e in all_errors + if e['source'] == "js_exception"][:500] + data['userEvents'] = events.get_customs_by_sessionId2_pg(project_id=project_id, + session_id=session_id) + data['domURL'] = sessions_mobs.get_urls(session_id=session_id, project_id=project_id) + data['mobsUrl'] = sessions_mobs.get_urls_depercated(session_id=session_id) + data['devtoolsURL'] = sessions_devtool.get_urls(session_id=session_id, project_id=project_id, + context=context) + data['resources'] = resources.get_by_session_id(session_id=session_id, project_id=project_id, + start_ts=data["startTs"], duration=data["duration"]) + + data['notes'] = sessions_notes.get_session_notes(tenant_id=context.tenant_id, project_id=project_id, + session_id=session_id, user_id=context.user_id) + data['metadata'] = __group_metadata(project_metadata=data.pop("projectMetadata"), session=data) + data['issues'] = issues.get_by_session_id(session_id=session_id, project_id=project_id) + data['live'] = live and assist.is_live(project_id=project_id, session_id=session_id, + project_key=data["projectKey"]) + data["inDB"] = True + return data + elif live: + return assist.get_live_session_by_id(project_id=project_id, session_id=session_id) + else: + return None + + +def __get_sql_operator(op: schemas.SearchEventOperator): + return { + schemas.SearchEventOperator._is: "=", + schemas.SearchEventOperator._is_any: "IN", + schemas.SearchEventOperator._on: "=", + schemas.SearchEventOperator._on_any: "IN", + schemas.SearchEventOperator._is_not: "!=", + schemas.SearchEventOperator._not_on: "!=", + schemas.SearchEventOperator._contains: "ILIKE", + schemas.SearchEventOperator._not_contains: "NOT ILIKE", + schemas.SearchEventOperator._starts_with: "ILIKE", + schemas.SearchEventOperator._ends_with: "ILIKE", + }.get(op, "=") + + +def __is_negation_operator(op: schemas.SearchEventOperator): + return op in [schemas.SearchEventOperator._is_not, + schemas.SearchEventOperator._not_on, + schemas.SearchEventOperator._not_contains] + + +def __reverse_sql_operator(op): + return "=" if op == "!=" else "!=" if op == "=" else "ILIKE" if op == "NOT ILIKE" else "NOT ILIKE" + + +def __get_sql_operator_multiple(op: schemas.SearchEventOperator): + return " IN " if op not in [schemas.SearchEventOperator._is_not, schemas.SearchEventOperator._not_on, + schemas.SearchEventOperator._not_contains] else " NOT IN " + + +def __get_sql_value_multiple(values): + if isinstance(values, tuple): + return values + return tuple(values) if isinstance(values, list) else (values,) + + +def _multiple_conditions(condition, values, value_key="value", is_not=False): + query = [] + for i in range(len(values)): + k = f"{value_key}_{i}" + query.append(condition.replace(value_key, k)) + return "(" + (" AND " if is_not else " OR ").join(query) + ")" + + +def _multiple_values(values, value_key="value"): + query_values = {} + if values is not None and isinstance(values, list): + for i in range(len(values)): + k = f"{value_key}_{i}" + query_values[k] = values[i] + return query_values + + +def _isAny_opreator(op: schemas.SearchEventOperator): + return op in [schemas.SearchEventOperator._on_any, schemas.SearchEventOperator._is_any] + + +def _isUndefined_operator(op: schemas.SearchEventOperator): + return op in [schemas.SearchEventOperator._is_undefined] + + +# This function executes the query and return result +def search_sessions(data: schemas.SessionsSearchPayloadSchema, project_id, user_id, errors_only=False, + error_status=schemas.ErrorStatus.all, count_only=False, issue=None, ids_only=False): + if data.bookmarked: + data.startDate, data.endDate = sessions_favorite.get_start_end_timestamp(project_id, user_id) + + full_args, query_part = search_query_parts(data=data, error_status=error_status, errors_only=errors_only, + favorite_only=data.bookmarked, issue=issue, project_id=project_id, + user_id=user_id) + if data.limit is not None and data.page is not None: + full_args["sessions_limit"] = data.limit + full_args["sessions_limit_s"] = (data.page - 1) * data.limit + full_args["sessions_limit_e"] = data.page * data.limit + else: + full_args["sessions_limit"] = 200 + full_args["sessions_limit_s"] = 1 + full_args["sessions_limit_e"] = 200 + + meta_keys = [] + with pg_client.PostgresClient() as cur: + if errors_only: + main_query = cur.mogrify(f"""SELECT DISTINCT er.error_id, + COALESCE((SELECT TRUE + FROM public.user_viewed_errors AS ve + WHERE er.error_id = ve.error_id + AND ve.user_id = %(userId)s LIMIT 1), FALSE) AS viewed + {query_part};""", full_args) + + elif count_only: + main_query = cur.mogrify(f"""SELECT COUNT(DISTINCT s.session_id) AS count_sessions, + COUNT(DISTINCT s.user_uuid) AS count_users + {query_part};""", full_args) + elif data.group_by_user: + g_sort = "count(full_sessions)" + if data.order is None: + data.order = schemas.SortOrderType.desc + else: + data.order = data.order.upper() + if data.sort is not None and data.sort != 'sessionsCount': + sort = helper.key_to_snake_case(data.sort) + g_sort = f"{'MIN' if data.order == schemas.SortOrderType.desc else 'MAX'}({sort})" + else: + sort = 'start_ts' + + meta_keys = metadata.get(project_id=project_id) + main_query = cur.mogrify(f"""SELECT COUNT(*) AS count, + COALESCE(JSONB_AGG(users_sessions) + FILTER (WHERE rn>%(sessions_limit_s)s AND rn<=%(sessions_limit_e)s), '[]'::JSONB) AS sessions + FROM (SELECT user_id, + count(full_sessions) AS user_sessions_count, + jsonb_agg(full_sessions) FILTER (WHERE rn <= 1) AS last_session, + MIN(full_sessions.start_ts) AS first_session_ts, + ROW_NUMBER() OVER (ORDER BY {g_sort} {data.order}) AS rn + FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY {sort} {data.order}) AS rn + FROM (SELECT DISTINCT ON(s.session_id) {SESSION_PROJECTION_COLS} + {"," if len(meta_keys) > 0 else ""}{",".join([f'metadata_{m["index"]}' for m in meta_keys])} + {query_part} + ) AS filtred_sessions + ) AS full_sessions + GROUP BY user_id + ) AS users_sessions;""", + full_args) + elif ids_only: + main_query = cur.mogrify(f"""SELECT DISTINCT ON(s.session_id) s.session_id + {query_part} + ORDER BY s.session_id desc + LIMIT %(sessions_limit)s OFFSET %(sessions_limit_s)s;""", + full_args) + else: + if data.order is None: + data.order = schemas.SortOrderType.desc + sort = 'session_id' + if data.sort is not None and data.sort != "session_id": + # sort += " " + data.order + "," + helper.key_to_snake_case(data.sort) + sort = helper.key_to_snake_case(data.sort) + meta_keys = metadata.get(project_id=project_id) + main_query = cur.mogrify(f"""SELECT COUNT(full_sessions) AS count, + COALESCE(JSONB_AGG(full_sessions) + FILTER (WHERE rn>%(sessions_limit_s)s AND rn<=%(sessions_limit_e)s), '[]'::JSONB) AS sessions + FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY {sort} {data.order}, issue_score DESC) AS rn + FROM (SELECT DISTINCT ON(s.session_id) {SESSION_PROJECTION_COLS} + {"," if len(meta_keys) > 0 else ""}{",".join([f'metadata_{m["index"]}' for m in meta_keys])} + {query_part} + ORDER BY s.session_id desc) AS filtred_sessions + ORDER BY {sort} {data.order}, issue_score DESC) AS full_sessions;""", + full_args) + # print("--------------------") + # print(main_query) + # print("--------------------") + try: + cur.execute(main_query) + except Exception as err: + print("--------- SESSIONS SEARCH QUERY EXCEPTION -----------") + print(main_query.decode('UTF-8')) + print("--------- PAYLOAD -----------") + print(data.json()) + print("--------------------") + raise err + if errors_only or ids_only: + return helper.list_to_camel_case(cur.fetchall()) + + sessions = cur.fetchone() + if count_only: + return helper.dict_to_camel_case(sessions) + + total = sessions["count"] + sessions = sessions["sessions"] + + if data.group_by_user: + for i, s in enumerate(sessions): + sessions[i] = {**s.pop("last_session")[0], **s} + sessions[i].pop("rn") + sessions[i]["metadata"] = {k["key"]: sessions[i][f'metadata_{k["index"]}'] for k in meta_keys \ + if sessions[i][f'metadata_{k["index"]}'] is not None} + else: + for i, s in enumerate(sessions): + sessions[i]["metadata"] = {k["key"]: sessions[i][f'metadata_{k["index"]}'] for k in meta_keys \ + if sessions[i][f'metadata_{k["index"]}'] is not None} + # if not data.group_by_user and data.sort is not None and data.sort != "session_id": + # sessions = sorted(sessions, key=lambda s: s[helper.key_to_snake_case(data.sort)], + # reverse=data.order.upper() == "DESC") + return { + 'total': total, + 'sessions': helper.list_to_camel_case(sessions) + } + + +def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, density: int, + view_type: schemas.MetricTimeseriesViewType, metric_type: schemas.MetricType, + metric_of: schemas.TableMetricOfType, metric_value: List): + step_size = int(metrics_helper.__get_step_size(endTimestamp=data.endDate, startTimestamp=data.startDate, + density=density, factor=1, decimal=True)) + extra_event = None + if metric_of == schemas.TableMetricOfType.visited_url: + extra_event = "events.pages" + elif metric_of == schemas.TableMetricOfType.issues and len(metric_value) > 0: + data.filters.append(schemas.SessionSearchFilterSchema(value=metric_value, type=schemas.FilterType.issue, + operator=schemas.SearchEventOperator._is)) + full_args, query_part = search_query_parts(data=data, error_status=None, errors_only=False, + favorite_only=False, issue=None, project_id=project_id, + user_id=None, extra_event=extra_event) + full_args["step_size"] = step_size + sessions = [] + with pg_client.PostgresClient() as cur: + if metric_type == schemas.MetricType.timeseries: + if view_type == schemas.MetricTimeseriesViewType.line_chart: + main_query = cur.mogrify(f"""WITH full_sessions AS (SELECT DISTINCT ON(s.session_id) s.session_id, s.start_ts + {query_part}) + SELECT generated_timestamp AS timestamp, + COUNT(s) AS count + FROM generate_series(%(startDate)s, %(endDate)s, %(step_size)s) AS generated_timestamp + LEFT JOIN LATERAL ( SELECT 1 AS s + FROM full_sessions + WHERE start_ts >= generated_timestamp + AND start_ts <= generated_timestamp + %(step_size)s) AS sessions ON (TRUE) + GROUP BY generated_timestamp + ORDER BY generated_timestamp;""", full_args) + else: + main_query = cur.mogrify(f"""SELECT count(DISTINCT s.session_id) AS count + {query_part};""", full_args) + + # print("--------------------") + # print(main_query) + # print("--------------------") + try: + cur.execute(main_query) + except Exception as err: + print("--------- SESSIONS-SERIES QUERY EXCEPTION -----------") + print(main_query.decode('UTF-8')) + print("--------- PAYLOAD -----------") + print(data.json()) + print("--------------------") + raise err + if view_type == schemas.MetricTimeseriesViewType.line_chart: + sessions = cur.fetchall() + else: + sessions = cur.fetchone()["count"] + elif metric_type == schemas.MetricType.table: + if isinstance(metric_of, schemas.TableMetricOfType): + main_col = "user_id" + extra_col = "" + extra_where = "" + pre_query = "" + if metric_of == schemas.TableMetricOfType.user_country: + main_col = "user_country" + elif metric_of == schemas.TableMetricOfType.user_device: + main_col = "user_device" + elif metric_of == schemas.TableMetricOfType.user_browser: + main_col = "user_browser" + elif metric_of == schemas.TableMetricOfType.issues: + main_col = "issue" + extra_col = f", UNNEST(s.issue_types) AS {main_col}" + if len(metric_value) > 0: + extra_where = [] + for i in range(len(metric_value)): + arg_name = f"selected_issue_{i}" + extra_where.append(f"{main_col} = %({arg_name})s") + full_args[arg_name] = metric_value[i] + extra_where = f"WHERE ({' OR '.join(extra_where)})" + elif metric_of == schemas.TableMetricOfType.visited_url: + main_col = "path" + extra_col = ", path" + main_query = cur.mogrify(f"""{pre_query} + SELECT COUNT(*) AS count, COALESCE(JSONB_AGG(users_sessions) FILTER ( WHERE rn <= 200 ), '[]'::JSONB) AS values + FROM (SELECT {main_col} AS name, + count(full_sessions) AS session_count, + ROW_NUMBER() OVER (ORDER BY count(full_sessions) DESC) AS rn + FROM (SELECT * + FROM (SELECT DISTINCT ON(s.session_id) s.session_id, s.user_uuid, + s.user_id, s.user_os, + s.user_browser, s.user_device, + s.user_device_type, s.user_country, s.issue_types{extra_col} + {query_part} + ORDER BY s.session_id desc) AS filtred_sessions + ) AS full_sessions + {extra_where} + GROUP BY {main_col} + ORDER BY session_count DESC) AS users_sessions;""", + full_args) + # print("--------------------") + # print(main_query) + # print("--------------------") + cur.execute(main_query) + sessions = cur.fetchone() + for s in sessions["values"]: + s.pop("rn") + sessions["values"] = helper.list_to_camel_case(sessions["values"]) + + return sessions + + +def __is_valid_event(is_any: bool, event: schemas._SessionSearchEventSchema): + return not (not is_any and len(event.value) == 0 and event.type not in [schemas.EventType.request_details, + schemas.EventType.graphql] \ + or event.type in [schemas.PerformanceEventType.location_dom_complete, + schemas.PerformanceEventType.location_largest_contentful_paint_time, + schemas.PerformanceEventType.location_ttfb, + schemas.PerformanceEventType.location_avg_cpu_load, + schemas.PerformanceEventType.location_avg_memory_usage + ] and (event.source is None or len(event.source) == 0) \ + or event.type in [schemas.EventType.request_details, schemas.EventType.graphql] and ( + event.filters is None or len(event.filters) == 0)) + + +# this function generates the query and return the generated-query with the dict of query arguments +def search_query_parts(data, error_status, errors_only, favorite_only, issue, project_id, user_id, extra_event=None): + ss_constraints = [] + full_args = {"project_id": project_id, "startDate": data.startDate, "endDate": data.endDate, + "projectId": project_id, "userId": user_id} + extra_constraints = [ + "s.project_id = %(project_id)s", + "s.duration IS NOT NULL" + ] + extra_from = "" + events_query_part = "" + if len(data.filters) > 0: + meta_keys = None + for i, f in enumerate(data.filters): + if not isinstance(f.value, list): + f.value = [f.value] + filter_type = f.type + f.value = helper.values_for_operator(value=f.value, op=f.operator) + f_k = f"f_value{i}" + full_args = {**full_args, **_multiple_values(f.value, value_key=f_k)} + op = __get_sql_operator(f.operator) \ + if filter_type not in [schemas.FilterType.events_count] else f.operator + is_any = _isAny_opreator(f.operator) + is_undefined = _isUndefined_operator(f.operator) + if not is_any and not is_undefined and len(f.value) == 0: + continue + is_not = False + if __is_negation_operator(f.operator): + is_not = True + if filter_type == schemas.FilterType.user_browser: + if is_any: + extra_constraints.append('s.user_browser IS NOT NULL') + ss_constraints.append('ms.user_browser IS NOT NULL') + else: + extra_constraints.append( + _multiple_conditions(f's.user_browser {op} %({f_k})s', f.value, is_not=is_not, value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f'ms.user_browser {op} %({f_k})s', f.value, is_not=is_not, value_key=f_k)) + + elif filter_type in [schemas.FilterType.user_os, schemas.FilterType.user_os_ios]: + if is_any: + extra_constraints.append('s.user_os IS NOT NULL') + ss_constraints.append('ms.user_os IS NOT NULL') + else: + extra_constraints.append( + _multiple_conditions(f's.user_os {op} %({f_k})s', f.value, is_not=is_not, value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f'ms.user_os {op} %({f_k})s', f.value, is_not=is_not, value_key=f_k)) + + elif filter_type in [schemas.FilterType.user_device, schemas.FilterType.user_device_ios]: + if is_any: + extra_constraints.append('s.user_device IS NOT NULL') + ss_constraints.append('ms.user_device IS NOT NULL') + else: + extra_constraints.append( + _multiple_conditions(f's.user_device {op} %({f_k})s', f.value, is_not=is_not, value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f'ms.user_device {op} %({f_k})s', f.value, is_not=is_not, value_key=f_k)) + + elif filter_type in [schemas.FilterType.user_country, schemas.FilterType.user_country_ios]: + if is_any: + extra_constraints.append('s.user_country IS NOT NULL') + ss_constraints.append('ms.user_country IS NOT NULL') + else: + extra_constraints.append( + _multiple_conditions(f's.user_country {op} %({f_k})s', f.value, is_not=is_not, value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f'ms.user_country {op} %({f_k})s', f.value, is_not=is_not, value_key=f_k)) + + elif filter_type in [schemas.FilterType.utm_source]: + if is_any: + extra_constraints.append('s.utm_source IS NOT NULL') + ss_constraints.append('ms.utm_source IS NOT NULL') + elif is_undefined: + extra_constraints.append('s.utm_source IS NULL') + ss_constraints.append('ms.utm_source IS NULL') + else: + extra_constraints.append( + _multiple_conditions(f's.utm_source {op} %({f_k})s::text', f.value, is_not=is_not, + value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f'ms.utm_source {op} %({f_k})s::text', f.value, is_not=is_not, + value_key=f_k)) + elif filter_type in [schemas.FilterType.utm_medium]: + if is_any: + extra_constraints.append('s.utm_medium IS NOT NULL') + ss_constraints.append('ms.utm_medium IS NOT NULL') + elif is_undefined: + extra_constraints.append('s.utm_medium IS NULL') + ss_constraints.append('ms.utm_medium IS NULL') + else: + extra_constraints.append( + _multiple_conditions(f's.utm_medium {op} %({f_k})s::text', f.value, is_not=is_not, + value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f'ms.utm_medium {op} %({f_k})s::text', f.value, is_not=is_not, + value_key=f_k)) + elif filter_type in [schemas.FilterType.utm_campaign]: + if is_any: + extra_constraints.append('s.utm_campaign IS NOT NULL') + ss_constraints.append('ms.utm_campaign IS NOT NULL') + elif is_undefined: + extra_constraints.append('s.utm_campaign IS NULL') + ss_constraints.append('ms.utm_campaign IS NULL') + else: + extra_constraints.append( + _multiple_conditions(f's.utm_campaign {op} %({f_k})s::text', f.value, is_not=is_not, + value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f'ms.utm_campaign {op} %({f_k})s::text', f.value, is_not=is_not, + value_key=f_k)) + + elif filter_type == schemas.FilterType.duration: + if len(f.value) > 0 and f.value[0] is not None: + extra_constraints.append("s.duration >= %(minDuration)s") + ss_constraints.append("ms.duration >= %(minDuration)s") + full_args["minDuration"] = f.value[0] + if len(f.value) > 1 and f.value[1] is not None and int(f.value[1]) > 0: + extra_constraints.append("s.duration <= %(maxDuration)s") + ss_constraints.append("ms.duration <= %(maxDuration)s") + full_args["maxDuration"] = f.value[1] + elif filter_type == schemas.FilterType.referrer: + # extra_from += f"INNER JOIN {events.event_type.LOCATION.table} AS p USING(session_id)" + if is_any: + extra_constraints.append('s.base_referrer IS NOT NULL') + else: + extra_constraints.append( + _multiple_conditions(f"s.base_referrer {op} %({f_k})s", f.value, is_not=is_not, value_key=f_k)) + elif filter_type == events.event_type.METADATA.ui_type: + # get metadata list only if you need it + if meta_keys is None: + meta_keys = metadata.get(project_id=project_id) + meta_keys = {m["key"]: m["index"] for m in meta_keys} + if f.source in meta_keys.keys(): + if is_any: + extra_constraints.append(f"s.{metadata.index_to_colname(meta_keys[f.source])} IS NOT NULL") + ss_constraints.append(f"ms.{metadata.index_to_colname(meta_keys[f.source])} IS NOT NULL") + elif is_undefined: + extra_constraints.append(f"s.{metadata.index_to_colname(meta_keys[f.source])} IS NULL") + ss_constraints.append(f"ms.{metadata.index_to_colname(meta_keys[f.source])} IS NULL") + else: + extra_constraints.append( + _multiple_conditions( + f"s.{metadata.index_to_colname(meta_keys[f.source])} {op} %({f_k})s::text", + f.value, is_not=is_not, value_key=f_k)) + ss_constraints.append( + _multiple_conditions( + f"ms.{metadata.index_to_colname(meta_keys[f.source])} {op} %({f_k})s::text", + f.value, is_not=is_not, value_key=f_k)) + elif filter_type in [schemas.FilterType.user_id, schemas.FilterType.user_id_ios]: + if is_any: + extra_constraints.append('s.user_id IS NOT NULL') + ss_constraints.append('ms.user_id IS NOT NULL') + elif is_undefined: + extra_constraints.append('s.user_id IS NULL') + ss_constraints.append('ms.user_id IS NULL') + else: + extra_constraints.append( + _multiple_conditions(f"s.user_id {op} %({f_k})s::text", f.value, is_not=is_not, value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f"ms.user_id {op} %({f_k})s::text", f.value, is_not=is_not, value_key=f_k)) + elif filter_type in [schemas.FilterType.user_anonymous_id, + schemas.FilterType.user_anonymous_id_ios]: + if is_any: + extra_constraints.append('s.user_anonymous_id IS NOT NULL') + ss_constraints.append('ms.user_anonymous_id IS NOT NULL') + elif is_undefined: + extra_constraints.append('s.user_anonymous_id IS NULL') + ss_constraints.append('ms.user_anonymous_id IS NULL') + else: + extra_constraints.append( + _multiple_conditions(f"s.user_anonymous_id {op} %({f_k})s::text", f.value, is_not=is_not, + value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f"ms.user_anonymous_id {op} %({f_k})s::text", f.value, is_not=is_not, + value_key=f_k)) + elif filter_type in [schemas.FilterType.rev_id, schemas.FilterType.rev_id_ios]: + if is_any: + extra_constraints.append('s.rev_id IS NOT NULL') + ss_constraints.append('ms.rev_id IS NOT NULL') + elif is_undefined: + extra_constraints.append('s.rev_id IS NULL') + ss_constraints.append('ms.rev_id IS NULL') + else: + extra_constraints.append( + _multiple_conditions(f"s.rev_id {op} %({f_k})s::text", f.value, is_not=is_not, value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f"ms.rev_id {op} %({f_k})s::text", f.value, is_not=is_not, value_key=f_k)) + elif filter_type == schemas.FilterType.platform: + # op = __get_sql_operator(f.operator) + extra_constraints.append( + _multiple_conditions(f"s.user_device_type {op} %({f_k})s", f.value, is_not=is_not, + value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f"ms.user_device_type {op} %({f_k})s", f.value, is_not=is_not, + value_key=f_k)) + elif filter_type == schemas.FilterType.issue: + if is_any: + extra_constraints.append("array_length(s.issue_types, 1) > 0") + ss_constraints.append("array_length(ms.issue_types, 1) > 0") + else: + extra_constraints.append( + _multiple_conditions(f"%({f_k})s {op} ANY (s.issue_types)", f.value, is_not=is_not, + value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f"%({f_k})s {op} ANY (ms.issue_types)", f.value, is_not=is_not, + value_key=f_k)) + elif filter_type == schemas.FilterType.events_count: + extra_constraints.append( + _multiple_conditions(f"s.events_count {op} %({f_k})s", f.value, is_not=is_not, + value_key=f_k)) + ss_constraints.append( + _multiple_conditions(f"ms.events_count {op} %({f_k})s", f.value, is_not=is_not, + value_key=f_k)) + # --------------------------------------------------------------------------- + if len(data.events) > 0: + valid_events_count = 0 + for event in data.events: + is_any = _isAny_opreator(event.operator) + if not isinstance(event.value, list): + event.value = [event.value] + if __is_valid_event(is_any=is_any, event=event): + valid_events_count += 1 + events_query_from = [] + event_index = 0 + or_events = data.events_order == schemas.SearchEventOrder._or + # events_joiner = " FULL JOIN " if or_events else " INNER JOIN LATERAL " + events_joiner = " UNION " if or_events else " INNER JOIN LATERAL " + for i, event in enumerate(data.events): + event_type = event.type + is_any = _isAny_opreator(event.operator) + if not isinstance(event.value, list): + event.value = [event.value] + if not __is_valid_event(is_any=is_any, event=event): + continue + op = __get_sql_operator(event.operator) + is_not = False + if __is_negation_operator(event.operator): + is_not = True + op = __reverse_sql_operator(op) + if event_index == 0 or or_events: + event_from = "%s INNER JOIN public.sessions AS ms USING (session_id)" + event_where = ["ms.project_id = %(projectId)s", "main.timestamp >= %(startDate)s", + "main.timestamp <= %(endDate)s", "ms.start_ts >= %(startDate)s", + "ms.start_ts <= %(endDate)s", "ms.duration IS NOT NULL"] + if favorite_only and not errors_only: + event_from += "INNER JOIN public.user_favorite_sessions AS fs USING(session_id)" + event_where.append("fs.user_id = %(userId)s") + else: + event_from = "%s" + event_where = ["main.timestamp >= %(startDate)s", "main.timestamp <= %(endDate)s", + "main.session_id=event_0.session_id"] + if data.events_order == schemas.SearchEventOrder._then: + event_where.append(f"event_{event_index - 1}.timestamp <= main.timestamp") + e_k = f"e_value{i}" + s_k = e_k + "_source" + if event.type != schemas.PerformanceEventType.time_between_events: + event.value = helper.values_for_operator(value=event.value, op=event.operator) + full_args = {**full_args, + **_multiple_values(event.value, value_key=e_k), + **_multiple_values(event.source, value_key=s_k)} + + if event_type == events.event_type.CLICK.ui_type: + event_from = event_from % f"{events.event_type.CLICK.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.CLICK.column} {op} %({e_k})s", event.value, + value_key=e_k)) + + elif event_type == events.event_type.INPUT.ui_type: + event_from = event_from % f"{events.event_type.INPUT.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.INPUT.column} {op} %({e_k})s", event.value, + value_key=e_k)) + if event.source is not None and len(event.source) > 0: + event_where.append(_multiple_conditions(f"main.value ILIKE %(custom{i})s", event.source, + value_key=f"custom{i}")) + full_args = {**full_args, **_multiple_values(event.source, value_key=f"custom{i}")} + + elif event_type == events.event_type.LOCATION.ui_type: + event_from = event_from % f"{events.event_type.LOCATION.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.LOCATION.column} {op} %({e_k})s", + event.value, value_key=e_k)) + elif event_type == events.event_type.CUSTOM.ui_type: + event_from = event_from % f"{events.event_type.CUSTOM.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.CUSTOM.column} {op} %({e_k})s", event.value, + value_key=e_k)) + elif event_type == events.event_type.REQUEST.ui_type: + event_from = event_from % f"{events.event_type.REQUEST.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.REQUEST.column} {op} %({e_k})s", event.value, + value_key=e_k)) + # elif event_type == events.event_type.GRAPHQL.ui_type: + # event_from = event_from % f"{events.event_type.GRAPHQL.table} AS main " + # if not is_any: + # event_where.append( + # _multiple_conditions(f"main.{events.event_type.GRAPHQL.column} {op} %({e_k})s", event.value, + # value_key=e_k)) + elif event_type == events.event_type.STATEACTION.ui_type: + event_from = event_from % f"{events.event_type.STATEACTION.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.STATEACTION.column} {op} %({e_k})s", + event.value, value_key=e_k)) + elif event_type == events.event_type.ERROR.ui_type: + event_from = event_from % f"{events.event_type.ERROR.table} AS main INNER JOIN public.errors AS main1 USING(error_id)" + event.source = list(set(event.source)) + if not is_any and event.value not in [None, "*", ""]: + event_where.append( + _multiple_conditions(f"(main1.message {op} %({e_k})s OR main1.name {op} %({e_k})s)", + event.value, value_key=e_k)) + if len(event.source) > 0 and event.source[0] not in [None, "*", ""]: + event_where.append(_multiple_conditions(f"main1.source = %({s_k})s", event.source, value_key=s_k)) + + + # ----- IOS + elif event_type == events.event_type.CLICK_IOS.ui_type: + event_from = event_from % f"{events.event_type.CLICK_IOS.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.CLICK_IOS.column} {op} %({e_k})s", + event.value, value_key=e_k)) + + elif event_type == events.event_type.INPUT_IOS.ui_type: + event_from = event_from % f"{events.event_type.INPUT_IOS.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.INPUT_IOS.column} {op} %({e_k})s", + event.value, value_key=e_k)) + if event.source is not None and len(event.source) > 0: + event_where.append(_multiple_conditions(f"main.value ILIKE %(custom{i})s", event.source, + value_key="custom{i}")) + full_args = {**full_args, **_multiple_values(event.source, f"custom{i}")} + elif event_type == events.event_type.VIEW_IOS.ui_type: + event_from = event_from % f"{events.event_type.VIEW_IOS.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.VIEW_IOS.column} {op} %({e_k})s", + event.value, value_key=e_k)) + elif event_type == events.event_type.CUSTOM_IOS.ui_type: + event_from = event_from % f"{events.event_type.CUSTOM_IOS.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.CUSTOM_IOS.column} {op} %({e_k})s", + event.value, value_key=e_k)) + elif event_type == events.event_type.REQUEST_IOS.ui_type: + event_from = event_from % f"{events.event_type.REQUEST_IOS.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.REQUEST_IOS.column} {op} %({e_k})s", + event.value, value_key=e_k)) + elif event_type == events.event_type.ERROR_IOS.ui_type: + event_from = event_from % f"{events.event_type.ERROR_IOS.table} AS main INNER JOIN public.crashes_ios AS main1 USING(crash_id)" + if not is_any and event.value not in [None, "*", ""]: + event_where.append( + _multiple_conditions(f"(main1.reason {op} %({e_k})s OR main1.name {op} %({e_k})s)", + event.value, value_key=e_k)) + elif event_type == schemas.PerformanceEventType.fetch_failed: + event_from = event_from % f"{events.event_type.REQUEST.table} AS main " + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.REQUEST.column} {op} %({e_k})s", + event.value, value_key=e_k)) + col = performance_event.get_col(event_type) + colname = col["column"] + event_where.append(f"main.{colname} = FALSE") + # elif event_type == schemas.PerformanceEventType.fetch_duration: + # event_from = event_from % f"{events.event_type.REQUEST.table} AS main " + # if not is_any: + # event_where.append( + # _multiple_conditions(f"main.{events.event_type.REQUEST.column} {op} %({e_k})s", + # event.value, value_key=e_k)) + # col = performance_event.get_col(event_type) + # colname = col["column"] + # tname = "main" + # e_k += "_custom" + # full_args = {**full_args, **_multiple_values(event.source, value_key=e_k)} + # event_where.append(f"{tname}.{colname} IS NOT NULL AND {tname}.{colname}>0 AND " + + # _multiple_conditions(f"{tname}.{colname} {event.sourceOperator} %({e_k})s", + # event.source, value_key=e_k)) + elif event_type in [schemas.PerformanceEventType.location_dom_complete, + schemas.PerformanceEventType.location_largest_contentful_paint_time, + schemas.PerformanceEventType.location_ttfb, + schemas.PerformanceEventType.location_avg_cpu_load, + schemas.PerformanceEventType.location_avg_memory_usage + ]: + event_from = event_from % f"{events.event_type.LOCATION.table} AS main " + col = performance_event.get_col(event_type) + colname = col["column"] + tname = "main" + if col.get("extraJoin") is not None: + tname = "ej" + event_from += f" INNER JOIN {col['extraJoin']} AS {tname} USING(session_id)" + event_where += [f"{tname}.timestamp >= main.timestamp", f"{tname}.timestamp >= %(startDate)s", + f"{tname}.timestamp <= %(endDate)s"] + if not is_any: + event_where.append( + _multiple_conditions(f"main.{events.event_type.LOCATION.column} {op} %({e_k})s", + event.value, value_key=e_k)) + e_k += "_custom" + full_args = {**full_args, **_multiple_values(event.source, value_key=e_k)} + + event_where.append(f"{tname}.{colname} IS NOT NULL AND {tname}.{colname}>0 AND " + + _multiple_conditions(f"{tname}.{colname} {event.sourceOperator} %({e_k})s", + event.source, value_key=e_k)) + elif event_type == schemas.PerformanceEventType.time_between_events: + event_from = event_from % f"{getattr(events.event_type, event.value[0].type).table} AS main INNER JOIN {getattr(events.event_type, event.value[1].type).table} AS main2 USING(session_id) " + if not isinstance(event.value[0].value, list): + event.value[0].value = [event.value[0].value] + if not isinstance(event.value[1].value, list): + event.value[1].value = [event.value[1].value] + event.value[0].value = helper.values_for_operator(value=event.value[0].value, + op=event.value[0].operator) + event.value[1].value = helper.values_for_operator(value=event.value[1].value, + op=event.value[0].operator) + e_k1 = e_k + "_e1" + e_k2 = e_k + "_e2" + full_args = {**full_args, + **_multiple_values(event.value[0].value, value_key=e_k1), + **_multiple_values(event.value[1].value, value_key=e_k2)} + s_op = __get_sql_operator(event.value[0].operator) + event_where += ["main2.timestamp >= %(startDate)s", "main2.timestamp <= %(endDate)s"] + if event_index > 0 and not or_events: + event_where.append("main2.session_id=event_0.session_id") + is_any = _isAny_opreator(event.value[0].operator) + if not is_any: + event_where.append( + _multiple_conditions( + f"main.{getattr(events.event_type, event.value[0].type).column} {s_op} %({e_k1})s", + event.value[0].value, value_key=e_k1)) + s_op = __get_sql_operator(event.value[1].operator) + is_any = _isAny_opreator(event.value[1].operator) + if not is_any: + event_where.append( + _multiple_conditions( + f"main2.{getattr(events.event_type, event.value[1].type).column} {s_op} %({e_k2})s", + event.value[1].value, value_key=e_k2)) + + e_k += "_custom" + full_args = {**full_args, **_multiple_values(event.source, value_key=e_k)} + event_where.append( + _multiple_conditions(f"main2.timestamp - main.timestamp {event.sourceOperator} %({e_k})s", + event.source, value_key=e_k)) + + elif event_type == schemas.EventType.request_details: + event_from = event_from % f"{events.event_type.REQUEST.table} AS main " + apply = False + for j, f in enumerate(event.filters): + is_any = _isAny_opreator(f.operator) + if is_any or len(f.value) == 0: + continue + f.value = helper.values_for_operator(value=f.value, op=f.operator) + op = __get_sql_operator(f.operator) + e_k_f = e_k + f"_fetch{j}" + full_args = {**full_args, **_multiple_values(f.value, value_key=e_k_f)} + if f.type == schemas.FetchFilterType._url: + event_where.append( + _multiple_conditions(f"main.{events.event_type.REQUEST.column} {op} %({e_k_f})s::text", + f.value, value_key=e_k_f)) + apply = True + elif f.type == schemas.FetchFilterType._status_code: + event_where.append( + _multiple_conditions(f"main.status_code {f.operator} %({e_k_f})s::integer", f.value, + value_key=e_k_f)) + apply = True + elif f.type == schemas.FetchFilterType._method: + event_where.append( + _multiple_conditions(f"main.method {op} %({e_k_f})s", f.value, value_key=e_k_f)) + apply = True + elif f.type == schemas.FetchFilterType._duration: + event_where.append( + _multiple_conditions(f"main.duration {f.operator} %({e_k_f})s::integer", f.value, + value_key=e_k_f)) + apply = True + elif f.type == schemas.FetchFilterType._request_body: + event_where.append( + _multiple_conditions(f"main.request_body {op} %({e_k_f})s::text", f.value, value_key=e_k_f)) + apply = True + elif f.type == schemas.FetchFilterType._response_body: + event_where.append( + _multiple_conditions(f"main.response_body {op} %({e_k_f})s::text", f.value, + value_key=e_k_f)) + apply = True + else: + print(f"undefined FETCH filter: {f.type}") + if not apply: + continue + elif event_type == schemas.EventType.graphql: + event_from = event_from % f"{events.event_type.GRAPHQL.table} AS main " + for j, f in enumerate(event.filters): + is_any = _isAny_opreator(f.operator) + if is_any or len(f.value) == 0: + continue + f.value = helper.values_for_operator(value=f.value, op=f.operator) + op = __get_sql_operator(f.operator) + e_k_f = e_k + f"_graphql{j}" + full_args = {**full_args, **_multiple_values(f.value, value_key=e_k_f)} + if f.type == schemas.GraphqlFilterType._name: + event_where.append( + _multiple_conditions(f"main.{events.event_type.GRAPHQL.column} {op} %({e_k_f})s", f.value, + value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._method: + event_where.append( + _multiple_conditions(f"main.method {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._request_body: + event_where.append( + _multiple_conditions(f"main.request_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._response_body: + event_where.append( + _multiple_conditions(f"main.response_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) + else: + print(f"undefined GRAPHQL filter: {f.type}") + else: + continue + if event_index == 0 or or_events: + event_where += ss_constraints + if is_not: + if event_index == 0 or or_events: + events_query_from.append(f"""\ + (SELECT + session_id, + 0 AS timestamp + FROM sessions + WHERE EXISTS(SELECT session_id + FROM {event_from} + WHERE {" AND ".join(event_where)} + AND sessions.session_id=ms.session_id) IS FALSE + AND project_id = %(projectId)s + AND start_ts >= %(startDate)s + AND start_ts <= %(endDate)s + AND duration IS NOT NULL + ) {"" if or_events else (f"AS event_{event_index}" + ("ON(TRUE)" if event_index > 0 else ""))}\ + """) + else: + events_query_from.append(f"""\ + (SELECT + event_0.session_id, + event_{event_index - 1}.timestamp AS timestamp + WHERE EXISTS(SELECT session_id FROM {event_from} WHERE {" AND ".join(event_where)}) IS FALSE + ) AS event_{event_index} {"ON(TRUE)" if event_index > 0 else ""}\ + """) + else: + events_query_from.append(f"""\ + (SELECT main.session_id, {"MIN" if event_index < (valid_events_count - 1) else "MAX"}(main.timestamp) AS timestamp + FROM {event_from} + WHERE {" AND ".join(event_where)} + GROUP BY 1 + ) {"" if or_events else (f"AS event_{event_index} " + ("ON(TRUE)" if event_index > 0 else ""))}\ + """) + event_index += 1 + if event_index > 0: + if or_events: + events_query_part = f"""SELECT + session_id, + MIN(timestamp) AS first_event_ts, + MAX(timestamp) AS last_event_ts + FROM ({events_joiner.join(events_query_from)}) AS u + GROUP BY 1""" + else: + events_query_part = f"""SELECT + event_0.session_id, + MIN(event_0.timestamp) AS first_event_ts, + MAX(event_{event_index - 1}.timestamp) AS last_event_ts + FROM {events_joiner.join(events_query_from)} + GROUP BY 1""" + else: + data.events = [] + # --------------------------------------------------------------------------- + if data.startDate is not None: + extra_constraints.append("s.start_ts >= %(startDate)s") + if data.endDate is not None: + extra_constraints.append("s.start_ts <= %(endDate)s") + # if data.platform is not None: + # if data.platform == schemas.PlatformType.mobile: + # extra_constraints.append(b"s.user_os in ('Android','BlackBerry OS','iOS','Tizen','Windows Phone')") + # elif data.platform == schemas.PlatformType.desktop: + # extra_constraints.append( + # b"s.user_os in ('Chrome OS','Fedora','Firefox OS','Linux','Mac OS X','Ubuntu','Windows')") + + if errors_only: + extra_from += f" INNER JOIN {events.event_type.ERROR.table} AS er USING (session_id) INNER JOIN public.errors AS ser USING (error_id)" + extra_constraints.append("ser.source = 'js_exception'") + extra_constraints.append("ser.project_id = %(project_id)s") + # if error_status != schemas.ErrorStatus.all: + # extra_constraints.append("ser.status = %(error_status)s") + # full_args["error_status"] = error_status + # if favorite_only: + # extra_from += " INNER JOIN public.user_favorite_errors AS ufe USING (error_id)" + # extra_constraints.append("ufe.user_id = %(userId)s") + + if favorite_only and not errors_only and user_id is not None: + extra_from += """INNER JOIN (SELECT user_id, session_id + FROM public.user_favorite_sessions + WHERE user_id = %(userId)s) AS favorite_sessions + USING (session_id)""" + elif not favorite_only and not errors_only and user_id is not None: + extra_from += """LEFT JOIN (SELECT user_id, session_id + FROM public.user_favorite_sessions + WHERE user_id = %(userId)s) AS favorite_sessions + USING (session_id)""" + extra_join = "" + if issue is not None: + extra_join = """ + INNER JOIN LATERAL(SELECT TRUE FROM events_common.issues INNER JOIN public.issues AS p_issues USING (issue_id) + WHERE issues.session_id=f.session_id + AND p_issues.type=%(issue_type)s + AND p_issues.context_string=%(issue_contextString)s + AND timestamp >= f.first_event_ts + AND timestamp <= f.last_event_ts) AS issues ON(TRUE) + """ + full_args["issue_contextString"] = issue["contextString"] + full_args["issue_type"] = issue["type"] + if extra_event: + extra_join += f"""INNER JOIN {extra_event} AS ev USING(session_id)""" + extra_constraints.append("ev.timestamp>=%(startDate)s") + extra_constraints.append("ev.timestamp<=%(endDate)s") + query_part = f"""\ + FROM {f"({events_query_part}) AS f" if len(events_query_part) > 0 else "public.sessions AS s"} + {extra_join} + {"INNER JOIN public.sessions AS s USING(session_id)" if len(events_query_part) > 0 else ""} + {extra_from} + WHERE + {" AND ".join(extra_constraints)}""" + return full_args, query_part + + +def search_by_metadata(tenant_id, user_id, m_key, m_value, project_id=None): + if project_id is None: + all_projects = projects.get_projects(tenant_id=tenant_id, recording_state=False) + else: + all_projects = [ + projects.get_project(tenant_id=tenant_id, project_id=int(project_id), include_last_session=False, + include_gdpr=False)] + + all_projects = {int(p["projectId"]): p["name"] for p in all_projects} + project_ids = list(all_projects.keys()) + + available_keys = metadata.get_keys_by_projects(project_ids) + for i in available_keys: + available_keys[i]["user_id"] = schemas.FilterType.user_id + available_keys[i]["user_anonymous_id"] = schemas.FilterType.user_anonymous_id + results = {} + for i in project_ids: + if m_key not in available_keys[i].values(): + available_keys.pop(i) + results[i] = {"total": 0, "sessions": [], "missingMetadata": True} + project_ids = list(available_keys.keys()) + if len(project_ids) > 0: + with pg_client.PostgresClient() as cur: + sub_queries = [] + for i in project_ids: + col_name = list(available_keys[i].keys())[list(available_keys[i].values()).index(m_key)] + sub_queries.append(cur.mogrify( + f"(SELECT COALESCE(COUNT(s.*)) AS count FROM public.sessions AS s WHERE s.project_id = %(id)s AND s.{col_name} = %(value)s) AS \"{i}\"", + {"id": i, "value": m_value}).decode('UTF-8')) + query = f"""SELECT {", ".join(sub_queries)};""" + cur.execute(query=query) + + rows = cur.fetchone() + + sub_queries = [] + for i in rows.keys(): + results[i] = {"total": rows[i], "sessions": [], "missingMetadata": False, "name": all_projects[int(i)]} + if rows[i] > 0: + col_name = list(available_keys[int(i)].keys())[list(available_keys[int(i)].values()).index(m_key)] + sub_queries.append( + cur.mogrify( + f"""( + SELECT * + FROM ( + SELECT DISTINCT ON(favorite_sessions.session_id, s.session_id) {SESSION_PROJECTION_COLS} + FROM public.sessions AS s LEFT JOIN (SELECT session_id + FROM public.user_favorite_sessions + WHERE user_favorite_sessions.user_id = %(userId)s + ) AS favorite_sessions USING (session_id) + WHERE s.project_id = %(id)s AND s.duration IS NOT NULL AND s.{col_name} = %(value)s + ) AS full_sessions + ORDER BY favorite DESC, issue_score DESC + LIMIT 10 + )""", + {"id": i, "value": m_value, "userId": user_id}).decode('UTF-8')) + if len(sub_queries) > 0: + cur.execute("\nUNION\n".join(sub_queries)) + rows = cur.fetchall() + for i in rows: + results[str(i["project_id"])]["sessions"].append(helper.dict_to_camel_case(i)) + return results + + +def search_by_issue(user_id, issue, project_id, start_date, end_date): + constraints = ["s.project_id = %(projectId)s", + "p_issues.context_string = %(issueContextString)s", + "p_issues.type = %(issueType)s"] + if start_date is not None: + constraints.append("start_ts >= %(startDate)s") + if end_date is not None: + constraints.append("start_ts <= %(endDate)s") + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify( + f"""SELECT DISTINCT ON(favorite_sessions.session_id, s.session_id) {SESSION_PROJECTION_COLS} + FROM public.sessions AS s + INNER JOIN events_common.issues USING (session_id) + INNER JOIN public.issues AS p_issues USING (issue_id) + LEFT JOIN (SELECT user_id, session_id + FROM public.user_favorite_sessions + WHERE user_id = %(userId)s) AS favorite_sessions + USING (session_id) + WHERE {" AND ".join(constraints)} + ORDER BY s.session_id DESC;""", + { + "issueContextString": issue["contextString"], + "issueType": issue["type"], "userId": user_id, + "projectId": project_id, + "startDate": start_date, + "endDate": end_date + })) + + rows = cur.fetchall() + return helper.list_to_camel_case(rows) + + +def get_user_sessions(project_id, user_id, start_date, end_date): + with pg_client.PostgresClient() as cur: + constraints = ["s.project_id = %(projectId)s", "s.user_id = %(userId)s"] + if start_date is not None: + constraints.append("s.start_ts >= %(startDate)s") + if end_date is not None: + constraints.append("s.start_ts <= %(endDate)s") + + query_part = f"""\ + FROM public.sessions AS s + WHERE {" AND ".join(constraints)}""" + + cur.execute(cur.mogrify(f"""\ + SELECT s.project_id, + s.session_id::text AS session_id, + s.user_uuid, + s.user_id, + s.user_os, + s.user_browser, + s.user_device, + s.user_country, + s.start_ts, + s.duration, + s.events_count, + s.pages_count, + s.errors_count + {query_part} + ORDER BY s.session_id + LIMIT 50;""", { + "projectId": project_id, + "userId": user_id, + "startDate": start_date, + "endDate": end_date + })) + + sessions = cur.fetchall() + return helper.list_to_camel_case(sessions) + + +def get_session_user(project_id, user_id): + with pg_client.PostgresClient() as cur: + query = cur.mogrify( + """\ + SELECT + user_id, + count(*) as session_count, + max(start_ts) as last_seen, + min(start_ts) as first_seen + FROM + "public".sessions + WHERE + project_id = %(project_id)s + AND user_id = %(userId)s + AND duration is not null + GROUP BY user_id; + """, + {"project_id": project_id, "userId": user_id} + ) + cur.execute(query=query) + data = cur.fetchone() + return helper.dict_to_camel_case(data) + + +def get_session_ids_by_user_ids(project_id, user_ids): + with pg_client.PostgresClient() as cur: + query = cur.mogrify( + """\ + SELECT session_id FROM public.sessions + WHERE + project_id = %(project_id)s AND user_id IN %(userId)s;""", + {"project_id": project_id, "userId": tuple(user_ids)} + ) + ids = cur.execute(query=query) + return ids + + +def delete_sessions_by_session_ids(session_ids): + with pg_client.PostgresClient(unlimited_query=True) as cur: + query = cur.mogrify( + """\ + DELETE FROM public.sessions + WHERE + session_id IN %(session_ids)s;""", + {"session_ids": tuple(session_ids)} + ) + cur.execute(query=query) + + return True + + +def delete_sessions_by_user_ids(project_id, user_ids): + with pg_client.PostgresClient(unlimited_query=True) as cur: + query = cur.mogrify( + """\ + DELETE FROM public.sessions + WHERE + project_id = %(project_id)s AND user_id IN %(userId)s;""", + {"project_id": project_id, "userId": tuple(user_ids)} + ) + cur.execute(query=query) + + return True + + +def count_all(): + with pg_client.PostgresClient(unlimited_query=True) as cur: + row = cur.execute(query="SELECT COUNT(session_id) AS count FROM public.sessions") + return row.get("count", 0) + + +def session_exists(project_id, session_id): + with pg_client.PostgresClient() as cur: + query = cur.mogrify("""SELECT 1 + FROM public.sessions + WHERE session_id=%(session_id)s + AND project_id=%(project_id)s""", + {"project_id": project_id, "session_id": session_id}) + cur.execute(query) + row = cur.fetchone() + return row is not None diff --git a/ee/api/chalicelib/core/sessions_devtool.py b/ee/api/chalicelib/core/sessions_devtool.py new file mode 100644 index 000000000..9435c2e24 --- /dev/null +++ b/ee/api/chalicelib/core/sessions_devtool.py @@ -0,0 +1,31 @@ +from decouple import config +from fastapi.security import SecurityScopes + +import schemas_ee +from chalicelib.core import permissions +from chalicelib.utils import s3 + +SCOPES = SecurityScopes([schemas_ee.Permissions.dev_tools]) + + +def __get_devtools_keys(project_id, session_id): + params = { + "sessionId": session_id, + "projectId": project_id + } + return [ + config("DEVTOOLS_MOB_PATTERN", default="%(sessionId)sdevtools") % params + ] + + +def get_urls(session_id, project_id, context: schemas_ee.CurrentContext): + if not permissions.check(security_scopes=SCOPES, context=context): + return [] + results = [] + for k in __get_devtools_keys(project_id=project_id, session_id=session_id): + results.append(s3.client.generate_presigned_url( + 'get_object', + Params={'Bucket': config("sessions_bucket"), 'Key': k}, + ExpiresIn=config("PRESIGNED_URL_EXPIRATION", cast=int, default=900) + )) + return results diff --git a/ee/api/chalicelib/core/sessions_exp.py b/ee/api/chalicelib/core/sessions_exp.py index add1a790d..0b77563f9 100644 --- a/ee/api/chalicelib/core/sessions_exp.py +++ b/ee/api/chalicelib/core/sessions_exp.py @@ -3,7 +3,8 @@ from typing import List, Union import schemas import schemas_ee from chalicelib.core import events, metadata, events_ios, \ - sessions_mobs, issues, projects, errors, resources, assist, performance_event, metrics + sessions_mobs, issues, projects, errors, resources, assist, performance_event, metrics, sessions_devtool, \ + sessions_notes from chalicelib.utils import pg_client, helper, metrics_helper, ch_client, exp_ch_helper SESSION_PROJECTION_COLS_CH = """\ @@ -58,8 +59,9 @@ def __group_metadata(session, project_metadata): return meta -def get_by_id2_pg(project_id, session_id, user_id, full_data=False, include_fav_viewed=False, group_metadata=False, - live=True): +# This function should not use Clickhouse because it doesn't have `file_key` +def get_by_id2_pg(project_id, session_id, context: schemas_ee.CurrentContext, full_data=False, include_fav_viewed=False, + group_metadata=False, live=True): with pg_client.PostgresClient() as cur: extra_query = [] if include_fav_viewed: @@ -76,13 +78,14 @@ def get_by_id2_pg(project_id, session_id, user_id, full_data=False, include_fav_ SELECT s.*, s.session_id::text AS session_id, - (SELECT project_key FROM public.projects WHERE project_id = %(project_id)s LIMIT 1) AS project_key + (SELECT project_key FROM public.projects WHERE project_id = %(project_id)s LIMIT 1) AS project_key, + encode(file_key,'hex') AS file_key {"," if len(extra_query) > 0 else ""}{",".join(extra_query)} {(",json_build_object(" + ",".join([f"'{m}',p.{m}" for m in metadata._get_column_names()]) + ") AS project_metadata") if group_metadata else ''} FROM public.sessions AS s {"INNER JOIN public.projects AS p USING (project_id)" if group_metadata else ""} WHERE s.project_id = %(project_id)s AND s.session_id = %(session_id)s;""", - {"project_id": project_id, "session_id": session_id, "userId": user_id} + {"project_id": project_id, "session_id": session_id, "userId": context.user_id} ) # print("===============") # print(query) @@ -100,23 +103,28 @@ def get_by_id2_pg(project_id, session_id, user_id, full_data=False, include_fav_ data['crashes'] = events_ios.get_crashes_by_session_id(session_id=session_id) data['userEvents'] = events_ios.get_customs_by_sessionId(project_id=project_id, session_id=session_id) - data['mobsUrl'] = sessions_mobs.get_ios(sessionId=session_id) + data['mobsUrl'] = sessions_mobs.get_ios(session_id=session_id) else: data['events'] = events.get_by_sessionId2_pg(project_id=project_id, session_id=session_id, group_clickrage=True) all_errors = events.get_errors_by_session_id(session_id=session_id, project_id=project_id) data['stackEvents'] = [e for e in all_errors if e['source'] != "js_exception"] # to keep only the first stack - data['errors'] = [errors.format_first_stack_frame(e) for e in all_errors if - e['source'] == "js_exception"][ - :500] # limit the number of errors to reduce the response-body size + # limit the number of errors to reduce the response-body size + data['errors'] = [errors.format_first_stack_frame(e) for e in all_errors + if e['source'] == "js_exception"][:500] data['userEvents'] = events.get_customs_by_sessionId2_pg(project_id=project_id, session_id=session_id) - data['mobsUrl'] = sessions_mobs.get_web(sessionId=session_id) + data['domURL'] = sessions_mobs.get_urls(session_id=session_id, project_id=project_id) + data['mobsUrl'] = sessions_mobs.get_urls_depercated(session_id=session_id) + data['devtoolsURL'] = sessions_devtool.get_urls(session_id=session_id, project_id=project_id, + context=context) data['resources'] = resources.get_by_session_id(session_id=session_id, project_id=project_id, start_ts=data["startTs"], duration=data["duration"]) + data['notes'] = sessions_notes.get_session_notes(tenant_id=context.tenant_id, project_id=project_id, + session_id=session_id, user_id=context.user_id) data['metadata'] = __group_metadata(project_metadata=data.pop("projectMetadata"), session=data) data['issues'] = issues.get_by_session_id(session_id=session_id, project_id=project_id) data['live'] = live and assist.is_live(project_id=project_id, @@ -286,6 +294,7 @@ def search_sessions(data: schemas.SessionsSearchPayloadSchema, project_id, user_ sessions = cur.execute(main_query) except Exception as err: print("--------- SESSIONS-CH SEARCH QUERY EXCEPTION -----------") + print(main_query) print("--------- PAYLOAD -----------") print(data.json()) print("--------------------") @@ -1542,3 +1551,14 @@ def count_all(): with pg_client.PostgresClient(unlimited_query=True) as cur: row = cur.execute(query="SELECT COUNT(session_id) AS count FROM public.sessions") return row.get("count", 0) + + +def session_exists(project_id, session_id): + with ch_client.ClickHouseClient() as cur: + query = cur.format("""SELECT 1 + FROM public.sessions + WHERE session_id=%(session_id)s + AND project_id=%(project_id)s""", + {"project_id": project_id, "session_id": session_id}) + row = cur.execute(query) + return row is not None diff --git a/ee/api/chalicelib/core/sessions_favorite.py b/ee/api/chalicelib/core/sessions_favorite.py index bcb79cfb7..7af995bad 100644 --- a/ee/api/chalicelib/core/sessions_favorite.py +++ b/ee/api/chalicelib/core/sessions_favorite.py @@ -1,65 +1,65 @@ from decouple import config -from chalicelib.core import sessions, sessions_favorite_exp +import schemas_ee +from chalicelib.core import sessions, sessions_favorite_exp, sessions_mobs, sessions_devtool from chalicelib.utils import pg_client, s3_extra -def add_favorite_session(project_id, user_id, session_id): +def add_favorite_session(context: schemas_ee.CurrentContext, project_id, session_id): with pg_client.PostgresClient() as cur: cur.execute( cur.mogrify(f"""\ INSERT INTO public.user_favorite_sessions(user_id, session_id) VALUES (%(userId)s,%(sessionId)s);""", - {"userId": user_id, "sessionId": session_id}) + {"userId": context.user_id, "sessionId": session_id}) ) - sessions_favorite_exp.add_favorite_session(project_id=project_id, user_id=user_id, session_id=session_id) - return sessions.get_by_id2_pg(project_id=project_id, session_id=session_id, user_id=user_id, full_data=False, - include_fav_viewed=True) + sessions_favorite_exp.add_favorite_session(project_id=project_id, user_id=context.user_id, session_id=session_id) + return sessions.get_by_id2_pg(project_id=project_id, session_id=session_id, + full_data=False, include_fav_viewed=True, context=context) -def remove_favorite_session(project_id, user_id, session_id): +def remove_favorite_session(context: schemas_ee.CurrentContext, project_id, session_id): with pg_client.PostgresClient() as cur: cur.execute( cur.mogrify(f"""\ DELETE FROM public.user_favorite_sessions WHERE user_id = %(userId)s AND session_id = %(sessionId)s;""", - {"userId": user_id, "sessionId": session_id}) + {"userId": context.user_id, "sessionId": session_id}) ) - sessions_favorite_exp.remove_favorite_session(project_id=project_id, user_id=user_id, session_id=session_id) - return sessions.get_by_id2_pg(project_id=project_id, session_id=session_id, user_id=user_id, full_data=False, - include_fav_viewed=True) + sessions_favorite_exp.remove_favorite_session(project_id=project_id, user_id=context.user_id, session_id=session_id) + return sessions.get_by_id2_pg(project_id=project_id, session_id=session_id, + full_data=False, include_fav_viewed=True, context=context) -def favorite_session(project_id, user_id, session_id): - if favorite_session_exists(user_id=user_id, session_id=session_id): - key = str(session_id) +def favorite_session(context: schemas_ee.CurrentContext, project_id, session_id): + keys = sessions_mobs.__get_mob_keys(project_id=project_id, session_id=session_id) + keys += sessions_mobs.__get_mob_keys_deprecated(session_id=session_id) # To support old sessions + keys += sessions_devtool.__get_devtools_keys(project_id=project_id, session_id=session_id) + + if favorite_session_exists(user_id=context.user_id, session_id=session_id): + tag = config('RETENTION_D_VALUE', default='default') + + for k in keys: + try: + s3_extra.tag_session(file_key=k, tag_value=tag) + except Exception as e: + print(f"!!!Error while tagging: {k} to {tag} for removal") + print(str(e)) + + return remove_favorite_session(context=context, project_id=project_id, session_id=session_id) + + tag = config('RETENTION_L_VALUE', default='vault') + + for k in keys: try: - s3_extra.tag_file(session_id=key, tag_value=config('RETENTION_D_VALUE', default='default')) + s3_extra.tag_session(file_key=k, tag_value=tag) except Exception as e: - print(f"!!!Error while tagging: {key} to default") + print(f"!!!Error while tagging: {k} to {tag} for vault") print(str(e)) - key = str(session_id) + "e" - try: - s3_extra.tag_file(session_id=key, tag_value=config('RETENTION_D_VALUE', default='default')) - except Exception as e: - print(f"!!!Error while tagging: {key} to default") - print(str(e)) - return remove_favorite_session(project_id=project_id, user_id=user_id, session_id=session_id) - key = str(session_id) - try: - s3_extra.tag_file(session_id=key, tag_value=config('RETENTION_L_VALUE', default='vault')) - except Exception as e: - print(f"!!!Error while tagging: {key} to vault") - print(str(e)) - key = str(session_id) + "e" - try: - s3_extra.tag_file(session_id=key, tag_value=config('RETENTION_L_VALUE', default='vault')) - except Exception as e: - print(f"!!!Error while tagging: {key} to vault") - print(str(e)) - return add_favorite_session(project_id=project_id, user_id=user_id, session_id=session_id) + + return add_favorite_session(context=context, project_id=project_id, session_id=session_id) def favorite_session_exists(user_id, session_id): @@ -89,4 +89,4 @@ def get_start_end_timestamp(project_id, user_id): {"userId": user_id, "project_id": project_id}) ) r = cur.fetchone() - return (0, 0) if r is None else (r["max_start_ts"], r["min_start_ts"]) + return (0, 0) if r is None else (r["min_start_ts"], r["max_start_ts"]) diff --git a/ee/api/chalicelib/core/sessions_notes.py b/ee/api/chalicelib/core/sessions_notes.py new file mode 100644 index 000000000..746eba4c8 --- /dev/null +++ b/ee/api/chalicelib/core/sessions_notes.py @@ -0,0 +1,170 @@ +from urllib.parse import urljoin + +from decouple import config + +import schemas +from chalicelib.core import sessions +from chalicelib.core.collaboration_slack import Slack +from chalicelib.utils import pg_client, helper +from chalicelib.utils.TimeUTC import TimeUTC + + +def get_note(tenant_id, project_id, user_id, note_id, share=None): + with pg_client.PostgresClient() as cur: + query = cur.mogrify(f"""SELECT sessions_notes.*, users.name AS creator_name + {",(SELECT name FROM users WHERE tenant_id=%(tenant_id)s AND user_id=%(share)s) AS share_name" if share else ""} + FROM sessions_notes INNER JOIN users USING (user_id) + WHERE sessions_notes.project_id = %(project_id)s + AND sessions_notes.note_id = %(note_id)s + AND sessions_notes.deleted_at IS NULL + AND (sessions_notes.user_id = %(user_id)s + OR sessions_notes.is_public AND users.tenant_id = %(tenant_id)s);""", + {"project_id": project_id, "user_id": user_id, "tenant_id": tenant_id, + "note_id": note_id, "share": share}) + + cur.execute(query=query) + row = cur.fetchone() + row = helper.dict_to_camel_case(row) + if row: + row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"]) + return row + + +def get_session_notes(tenant_id, project_id, session_id, user_id): + with pg_client.PostgresClient() as cur: + query = cur.mogrify(f"""SELECT sessions_notes.* + FROM sessions_notes + INNER JOIN users USING (user_id) + WHERE sessions_notes.project_id = %(project_id)s + AND sessions_notes.deleted_at IS NULL + AND sessions_notes.session_id = %(session_id)s + AND (sessions_notes.user_id = %(user_id)s + OR sessions_notes.is_public AND users.tenant_id = %(tenant_id)s) + ORDER BY created_at DESC;""", + {"project_id": project_id, "user_id": user_id, + "tenant_id": tenant_id, "session_id": session_id}) + + cur.execute(query=query) + rows = cur.fetchall() + rows = helper.list_to_camel_case(rows) + for row in rows: + row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"]) + return rows + + +def get_all_notes_by_project_id(tenant_id, project_id, user_id, data: schemas.SearchNoteSchema): + with pg_client.PostgresClient() as cur: + conditions = ["sessions_notes.project_id = %(project_id)s", "sessions_notes.deleted_at IS NULL"] + extra_params = {} + if data.tags and len(data.tags) > 0: + k = "tag_value" + conditions.append( + sessions._multiple_conditions(f"%({k})s = sessions_notes.tag", data.tags, value_key=k)) + extra_params = sessions._multiple_values(data.tags, value_key=k) + if data.shared_only: + conditions.append("sessions_notes.is_public AND users.tenant_id = %(tenant_id)s") + elif data.mine_only: + conditions.append("sessions_notes.user_id = %(user_id)s") + else: + conditions.append( + "(sessions_notes.user_id = %(user_id)s OR sessions_notes.is_public AND users.tenant_id = %(tenant_id)s)") + query = cur.mogrify(f"""SELECT sessions_notes.* + FROM sessions_notes + INNER JOIN users USING (user_id) + WHERE {" AND ".join(conditions)} + ORDER BY created_at {data.order} + LIMIT {data.limit} OFFSET {data.limit * (data.page - 1)};""", + {"project_id": project_id, "user_id": user_id, "tenant_id": tenant_id, **extra_params}) + + cur.execute(query=query) + rows = cur.fetchall() + rows = helper.list_to_camel_case(rows) + for row in rows: + row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"]) + return rows + + +def create(tenant_id, user_id, project_id, session_id, data: schemas.SessionNoteSchema): + with pg_client.PostgresClient() as cur: + query = cur.mogrify(f"""INSERT INTO public.sessions_notes (message, user_id, tag, session_id, project_id, timestamp, is_public) + VALUES (%(message)s, %(user_id)s, %(tag)s, %(session_id)s, %(project_id)s, %(timestamp)s, %(is_public)s) + RETURNING *;""", + {"user_id": user_id, "project_id": project_id, "session_id": session_id, **data.dict()}) + cur.execute(query) + result = helper.dict_to_camel_case(cur.fetchone()) + if result: + result["createdAt"] = TimeUTC.datetime_to_timestamp(result["createdAt"]) + return result + + +def edit(tenant_id, user_id, project_id, note_id, data: schemas.SessionUpdateNoteSchema): + sub_query = [] + if data.message is not None: + sub_query.append("message = %(message)s") + if data.tag is not None and len(data.tag) > 0: + sub_query.append("tag = %(tag)s") + if data.is_public is not None: + sub_query.append("is_public = %(is_public)s") + if data.timestamp is not None: + sub_query.append("timestamp = %(timestamp)s") + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify(f"""UPDATE public.sessions_notes + SET + {" ,".join(sub_query)} + WHERE + project_id = %(project_id)s + AND user_id = %(user_id)s + AND note_id = %(note_id)s + AND deleted_at ISNULL + RETURNING *;""", + {"project_id": project_id, "user_id": user_id, "note_id": note_id, **data.dict()}) + ) + row = helper.dict_to_camel_case(cur.fetchone()) + if row: + row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"]) + return row + + +def delete(tenant_id, user_id, project_id, note_id): + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify(""" UPDATE public.sessions_notes + SET deleted_at = timezone('utc'::text, now()) + WHERE note_id = %(note_id)s + AND project_id = %(project_id)s + AND user_id = %(user_id)s + AND deleted_at ISNULL;""", + {"project_id": project_id, "user_id": user_id, "note_id": note_id}) + ) + return {"data": {"state": "success"}} + + +def share_to_slack(tenant_id, user_id, project_id, note_id, webhook_id): + note = get_note(tenant_id=tenant_id, project_id=project_id, user_id=user_id, note_id=note_id, share=user_id) + if note is None: + return {"errors": ["Note not found"]} + session_url = urljoin(config('SITE_URL'), f"{note['projectId']}/session/{note['sessionId']}") + title = f"<{session_url}|Note for session {note['sessionId']}>" + + blocks = [{"type": "section", + "fields": [{"type": "mrkdwn", + "text": title}]}, + {"type": "section", + "fields": [{"type": "plain_text", + "text": note["message"]}]}] + if note["tag"]: + blocks.append({"type": "context", + "elements": [{"type": "plain_text", + "text": f"Tag: *{note['tag']}*"}]}) + bottom = f"Created by {note['creatorName'].capitalize()}" + if user_id != note["userId"]: + bottom += f"\nSent by {note['shareName']}: " + blocks.append({"type": "context", + "elements": [{"type": "plain_text", + "text": bottom}]}) + return Slack.send_raw( + tenant_id=tenant_id, + webhook_id=webhook_id, + body={"blocks": blocks} + ) diff --git a/ee/api/chalicelib/core/significance.py b/ee/api/chalicelib/core/significance.py index 3aa701f97..e3d6cc735 100644 --- a/ee/api/chalicelib/core/significance.py +++ b/ee/api/chalicelib/core/significance.py @@ -1,11 +1,10 @@ __author__ = "AZNAUROV David" __maintainer__ = "KRAIEM Taha Yassine" +from decouple import config + import schemas from chalicelib.core import events, metadata -from chalicelib.utils import dev - -from decouple import config if config("EXP_SESSIONS_SEARCH", cast=bool, default=False): from chalicelib.core import sessions_legacy as sessions @@ -189,9 +188,7 @@ def get_stages_and_events(filter_d, project_id) -> List[RealDictRow]: values=s["value"], value_key=f"value{i + 1}") n_stages_query.append(f""" (SELECT main.session_id, - {"MIN(main.timestamp)" if i + 1 < len(stages) else "MAX(main.timestamp)"} AS stage{i + 1}_timestamp, - '{event_type}' AS type, - '{s["operator"]}' AS operator + {"MIN(main.timestamp)" if i + 1 < len(stages) else "MAX(main.timestamp)"} AS stage{i + 1}_timestamp FROM {next_table} AS main {" ".join(extra_from)} WHERE main.timestamp >= {f"T{i}.stage{i}_timestamp" if i > 0 else "%(startTimestamp)s"} {f"AND main.session_id=T1.session_id" if i > 0 else ""} @@ -199,45 +196,55 @@ def get_stages_and_events(filter_d, project_id) -> List[RealDictRow]: {(" AND " + " AND ".join(stage_constraints)) if len(stage_constraints) > 0 else ""} {(" AND " + " AND ".join(first_stage_extra_constraints)) if len(first_stage_extra_constraints) > 0 and i == 0 else ""} GROUP BY main.session_id) - AS T{i + 1} {"USING (session_id)" if i > 0 else ""} + AS T{i + 1} {"ON (TRUE)" if i > 0 else ""} """) - if len(n_stages_query) == 0: + n_stages = len(n_stages_query) + if n_stages == 0: return [] n_stages_query = " LEFT JOIN LATERAL ".join(n_stages_query) n_stages_query += ") AS stages_t" n_stages_query = f""" - SELECT stages_and_issues_t.*,sessions.session_id, sessions.user_uuid FROM ( + SELECT stages_and_issues_t.*, sessions.user_uuid + FROM ( SELECT * FROM ( - SELECT * FROM - {n_stages_query} + SELECT T1.session_id, {",".join([f"stage{i + 1}_timestamp" for i in range(n_stages)])} + FROM {n_stages_query} LEFT JOIN LATERAL - ( - SELECT * FROM - (SELECT ISE.session_id, - ISS.type as issue_type, + ( SELECT ISS.type as issue_type, ISE.timestamp AS issue_timestamp, - ISS.context_string as issue_context, + COALESCE(ISS.context_string,'') as issue_context, ISS.issue_id as issue_id FROM events_common.issues AS ISE INNER JOIN issues AS ISS USING (issue_id) WHERE ISE.timestamp >= stages_t.stage1_timestamp AND ISE.timestamp <= stages_t.stage{i + 1}_timestamp AND ISS.project_id=%(project_id)s - {"AND ISS.type IN %(issueTypes)s" if len(filter_issues) > 0 else ""}) AS base_t - ) AS issues_t - USING (session_id)) AS stages_and_issues_t - inner join sessions USING(session_id); + AND ISE.session_id = stages_t.session_id + AND ISS.type!='custom' -- ignore custom issues because they are massive + {"AND ISS.type IN %(issueTypes)s" if len(filter_issues) > 0 else ""} + LIMIT 10 -- remove the limit to get exact stats + ) AS issues_t ON (TRUE) + ) AS stages_and_issues_t INNER JOIN sessions USING(session_id); """ # LIMIT 10000 params = {"project_id": project_id, "startTimestamp": filter_d["startDate"], "endTimestamp": filter_d["endDate"], "issueTypes": tuple(filter_issues), **values} with pg_client.PostgresClient() as cur: + query = cur.mogrify(n_stages_query, params) # print("---------------------------------------------------") - # print(cur.mogrify(n_stages_query, params)) + # print(query) # print("---------------------------------------------------") - cur.execute(cur.mogrify(n_stages_query, params)) - rows = cur.fetchall() + try: + cur.execute(query) + rows = cur.fetchall() + except Exception as err: + print("--------- FUNNEL SEARCH QUERY EXCEPTION -----------") + print(query.decode('UTF-8')) + print("--------- PAYLOAD -----------") + print(filter_d) + print("--------------------") + raise err return rows @@ -299,7 +306,21 @@ def pearson_corr(x: list, y: list): return r, confidence, False -def get_transitions_and_issues_of_each_type(rows: List[RealDictRow], all_issues_with_context, first_stage, last_stage): +# def tuple_or(t: tuple): +# x = 0 +# for el in t: +# x |= el # | is for bitwise OR +# return x +# +# The following function is correct optimization of the previous function because t is a list of 0,1 +def tuple_or(t: tuple): + for el in t: + if el > 0: + return 1 + return 0 + + +def get_transitions_and_issues_of_each_type(rows: List[RealDictRow], all_issues, first_stage, last_stage): """ Returns two lists with binary values 0/1: @@ -318,12 +339,6 @@ def get_transitions_and_issues_of_each_type(rows: List[RealDictRow], all_issues_ transitions = [] n_sess_affected = 0 errors = {} - for issue in all_issues_with_context: - split = issue.split('__^__') - errors[issue] = { - "errors": [], - "issue_type": split[0], - "context": split[1]} for row in rows: t = 0 @@ -331,38 +346,26 @@ def get_transitions_and_issues_of_each_type(rows: List[RealDictRow], all_issues_ last_ts = row[f'stage{last_stage}_timestamp'] if first_ts is None: continue - elif first_ts is not None and last_ts is not None: + elif last_ts is not None: t = 1 transitions.append(t) ic_present = False - for issue_type_with_context in errors: + for error_id in all_issues: + if error_id not in errors: + errors[error_id] = [] ic = 0 - issue_type = errors[issue_type_with_context]["issue_type"] - context = errors[issue_type_with_context]["context"] - if row['issue_type'] is not None: + row_issue_id = row['issue_id'] + if row_issue_id is not None: if last_ts is None or (first_ts < row['issue_timestamp'] < last_ts): - context_in_row = row['issue_context'] if row['issue_context'] is not None else '' - if issue_type == row['issue_type'] and context == context_in_row: + if error_id == row_issue_id: ic = 1 ic_present = True - errors[issue_type_with_context]["errors"].append(ic) + errors[error_id].append(ic) if ic_present and t: n_sess_affected += 1 - # def tuple_or(t: tuple): - # x = 0 - # for el in t: - # x |= el - # return x - def tuple_or(t: tuple): - for el in t: - if el > 0: - return 1 - return 0 - - errors = {key: errors[key]["errors"] for key in errors} all_errors = [tuple_or(t) for t in zip(*errors.values())] return transitions, errors, all_errors, n_sess_affected @@ -378,10 +381,9 @@ def get_affected_users_for_all_issues(rows, first_stage, last_stage): """ affected_users = defaultdict(lambda: set()) affected_sessions = defaultdict(lambda: set()) - contexts = defaultdict(lambda: None) + all_issues = {} n_affected_users_dict = defaultdict(lambda: None) n_affected_sessions_dict = defaultdict(lambda: None) - all_issues_with_context = set() n_issues_dict = defaultdict(lambda: 0) issues_by_session = defaultdict(lambda: 0) @@ -397,15 +399,13 @@ def get_affected_users_for_all_issues(rows, first_stage, last_stage): # check that the issue exists and belongs to subfunnel: if iss is not None and (row[f'stage{last_stage}_timestamp'] is None or (row[f'stage{first_stage}_timestamp'] < iss_ts < row[f'stage{last_stage}_timestamp'])): - context_string = row['issue_context'] if row['issue_context'] is not None else '' - issue_with_context = iss + '__^__' + context_string - contexts[issue_with_context] = {"context": context_string, "id": row["issue_id"]} - all_issues_with_context.add(issue_with_context) - n_issues_dict[issue_with_context] += 1 + if row["issue_id"] not in all_issues: + all_issues[row["issue_id"]] = {"context": row['issue_context'], "issue_type": row["issue_type"]} + n_issues_dict[row["issue_id"]] += 1 if row['user_uuid'] is not None: - affected_users[issue_with_context].add(row['user_uuid']) + affected_users[row["issue_id"]].add(row['user_uuid']) - affected_sessions[issue_with_context].add(row['session_id']) + affected_sessions[row["issue_id"]].add(row['session_id']) issues_by_session[row[f'session_id']] += 1 if len(affected_users) > 0: @@ -416,29 +416,28 @@ def get_affected_users_for_all_issues(rows, first_stage, last_stage): n_affected_sessions_dict.update({ iss: len(affected_sessions[iss]) for iss in affected_sessions }) - return all_issues_with_context, n_issues_dict, n_affected_users_dict, n_affected_sessions_dict, contexts + return all_issues, n_issues_dict, n_affected_users_dict, n_affected_sessions_dict def count_sessions(rows, n_stages): session_counts = {i: set() for i in range(1, n_stages + 1)} - for ind, row in enumerate(rows): + for row in rows: for i in range(1, n_stages + 1): if row[f"stage{i}_timestamp"] is not None: session_counts[i].add(row[f"session_id"]) + session_counts = {i: len(session_counts[i]) for i in session_counts} return session_counts def count_users(rows, n_stages): - users_in_stages = defaultdict(lambda: set()) - - for ind, row in enumerate(rows): + users_in_stages = {i: set() for i in range(1, n_stages + 1)} + for row in rows: for i in range(1, n_stages + 1): if row[f"stage{i}_timestamp"] is not None: users_in_stages[i].add(row["user_uuid"]) users_count = {i: len(users_in_stages[i]) for i in range(1, n_stages + 1)} - return users_count @@ -491,18 +490,18 @@ def get_issues(stages, rows, first_stage=None, last_stage=None, drop_only=False) last_stage = n_stages n_critical_issues = 0 - issues_dict = dict({"significant": [], - "insignificant": []}) + issues_dict = {"significant": [], + "insignificant": []} session_counts = count_sessions(rows, n_stages) drop = session_counts[first_stage] - session_counts[last_stage] - all_issues_with_context, n_issues_dict, affected_users_dict, affected_sessions, contexts = get_affected_users_for_all_issues( + all_issues, n_issues_dict, affected_users_dict, affected_sessions = get_affected_users_for_all_issues( rows, first_stage, last_stage) transitions, errors, all_errors, n_sess_affected = get_transitions_and_issues_of_each_type(rows, - all_issues_with_context, + all_issues, first_stage, last_stage) - # print("len(transitions) =", len(transitions)) + del rows if any(all_errors): total_drop_corr, conf, is_sign = pearson_corr(transitions, all_errors) @@ -515,33 +514,35 @@ def get_issues(stages, rows, first_stage=None, last_stage=None, drop_only=False) if drop_only: return total_drop_due_to_issues - for issue in all_issues_with_context: + for issue_id in all_issues: - if not any(errors[issue]): + if not any(errors[issue_id]): continue - r, confidence, is_sign = pearson_corr(transitions, errors[issue]) + r, confidence, is_sign = pearson_corr(transitions, errors[issue_id]) if r is not None and drop is not None and is_sign: - lost_conversions = int(r * affected_sessions[issue]) + lost_conversions = int(r * affected_sessions[issue_id]) else: lost_conversions = None if r is None: r = 0 - split = issue.split('__^__') issues_dict['significant' if is_sign else 'insignificant'].append({ - "type": split[0], - "title": helper.get_issue_title(split[0]), - "affected_sessions": affected_sessions[issue], - "unaffected_sessions": session_counts[1] - affected_sessions[issue], + "type": all_issues[issue_id]["issue_type"], + "title": helper.get_issue_title(all_issues[issue_id]["issue_type"]), + "affected_sessions": affected_sessions[issue_id], + "unaffected_sessions": session_counts[1] - affected_sessions[issue_id], "lost_conversions": lost_conversions, - "affected_users": affected_users_dict[issue], + "affected_users": affected_users_dict[issue_id], "conversion_impact": round(r * 100), - "context_string": contexts[issue]["context"], - "issue_id": contexts[issue]["id"] + "context_string": all_issues[issue_id]["context"], + "issue_id": issue_id }) if is_sign: - n_critical_issues += n_issues_dict[issue] + n_critical_issues += n_issues_dict[issue_id] + # To limit the number of returned issues to the frontend + issues_dict["significant"] = issues_dict["significant"][:20] + issues_dict["insignificant"] = issues_dict["insignificant"][:20] return n_critical_issues, issues_dict, total_drop_due_to_issues @@ -567,8 +568,7 @@ def get_top_insights(filter_d, project_id): }] counts = sessions.search_sessions(data=schemas.SessionsSearchCountSchema.parse_obj(filter_d), - project_id=project_id, - user_id=None, count_only=True) + project_id=project_id, user_id=None, count_only=True) output[0]["sessionsCount"] = counts["countSessions"] output[0]["usersCount"] = counts["countUsers"] return output, 0 diff --git a/ee/api/chalicelib/core/significance_exp.py b/ee/api/chalicelib/core/significance_exp.py index 1f845ec06..59cb93cd7 100644 --- a/ee/api/chalicelib/core/significance_exp.py +++ b/ee/api/chalicelib/core/significance_exp.py @@ -1,10 +1,15 @@ __author__ = "AZNAUROV David" __maintainer__ = "KRAIEM Taha Yassine" +from decouple import config + import schemas from chalicelib.core import events, metadata -from chalicelib.core import sessions_legacy as sessions -from chalicelib.utils import dev + +if config("EXP_SESSIONS_SEARCH", cast=bool, default=False): + from chalicelib.core import sessions_legacy as sessions +else: + from chalicelib.core import sessions """ todo: remove LIMIT from the query diff --git a/ee/api/chalicelib/core/signup.py b/ee/api/chalicelib/core/signup.py index 72317859f..d01e1379a 100644 --- a/ee/api/chalicelib/core/signup.py +++ b/ee/api/chalicelib/core/signup.py @@ -1,6 +1,9 @@ import json +from decouple import config + import schemas +import schemas_ee from chalicelib.core import users, telemetry, tenants from chalicelib.utils import captcha from chalicelib.utils import helper @@ -11,67 +14,55 @@ from chalicelib.utils.TimeUTC import TimeUTC def create_step1(data: schemas.UserSignupSchema): print(f"===================== SIGNUP STEP 1 AT {TimeUTC.to_human_readable(TimeUTC.now())} UTC") errors = [] - if tenants.tenants_exists(): + if not config("MULTI_TENANTS", cast=bool, default=False) and tenants.tenants_exists(): return {"errors": ["tenants already registered"]} email = data.email print(f"=====================> {email}") password = data.password - print("Verifying email validity") - if email is None or len(email) < 5 or not helper.is_valid_email(email): + if email is None or len(email) < 5: errors.append("Invalid email address.") else: - print("Verifying email existance") if users.email_exists(email): errors.append("Email address already in use.") if users.get_deleted_user_by_email(email) is not None: errors.append("Email address previously deleted.") - print("Verifying captcha") if helper.allow_captcha() and not captcha.is_valid(data.g_recaptcha_response): errors.append("Invalid captcha.") - print("Verifying password validity") if len(password) < 6: errors.append("Password is too short, it must be at least 6 characters long.") - print("Verifying fullname validity") fullname = data.fullname if fullname is None or len(fullname) < 1 or not helper.is_alphabet_space_dash(fullname): errors.append("Invalid full name.") - print("Verifying company's name validity") - company_name = data.organizationName - if company_name is None or len(company_name) < 1: - errors.append("invalid organization's name") - - print("Verifying project's name validity") - project_name = data.projectName - if project_name is None or len(project_name) < 1: - project_name = "my first project" + organization_name = data.organizationName + if organization_name is None or len(organization_name) < 1: + errors.append("Invalid organization name.") if len(errors) > 0: - print("==> error") + print(f"==> error for email:{data.email}, fullname:{data.fullname}, organizationName:{data.organizationName}") print(errors) return {"errors": errors} - print("No errors detected") - print("Decomposed infos") - params = {"email": email, "password": password, - "fullname": fullname, "companyName": company_name, - "projectName": project_name, - "data": json.dumps({"lastAnnouncementView": TimeUTC.now()})} - query = """\ - WITH t AS ( - INSERT INTO public.tenants (name, version_number) - VALUES (%(companyName)s, (SELECT openreplay_version())) + project_name = "my first project" + params = { + "email": email, "password": password, "fullname": fullname, "projectName": project_name, + "data": json.dumps({"lastAnnouncementView": TimeUTC.now()}), "organizationName": organization_name, + "permissions": [p.value for p in schemas_ee.Permissions] + } + query = """WITH t AS ( + INSERT INTO public.tenants (name) + VALUES (%(organizationName)s) RETURNING tenant_id, api_key ), r AS ( INSERT INTO public.roles(tenant_id, name, description, permissions, protected) - VALUES ((SELECT tenant_id FROM t), 'Owner', 'Owner', '{"SESSION_REPLAY", "DEV_TOOLS", "METRICS", "ASSIST_LIVE", "ASSIST_CALL"}'::text[], TRUE), - ((SELECT tenant_id FROM t), 'Member', 'Member', '{"SESSION_REPLAY", "DEV_TOOLS", "METRICS", "ASSIST_LIVE", "ASSIST_CALL"}'::text[], FALSE) + VALUES ((SELECT tenant_id FROM t), 'Owner', 'Owner', %(permissions)s::text[], TRUE), + ((SELECT tenant_id FROM t), 'Member', 'Member', %(permissions)s::text[], FALSE) RETURNING * ), u AS ( @@ -109,7 +100,7 @@ def create_step1(data: schemas.UserSignupSchema): } c = { "tenantId": 1, - "name": company_name, + "name": organization_name, "apiKey": api_key, "remainingTrial": 14, "trialEnded": False, diff --git a/ee/api/chalicelib/core/telemetry.py b/ee/api/chalicelib/core/telemetry.py index a002f8501..f3ec7c904 100644 --- a/ee/api/chalicelib/core/telemetry.py +++ b/ee/api/chalicelib/core/telemetry.py @@ -20,7 +20,7 @@ def process_data(data): def compute(): - with pg_client.PostgresClient() as cur: + with pg_client.PostgresClient(long_query=True) as cur: cur.execute( f"""UPDATE public.tenants SET t_integrations = COALESCE((SELECT COUNT(DISTINCT provider) @@ -39,17 +39,18 @@ def compute(): FROM public.projects WHERE deleted_at ISNULL AND projects.tenant_id = all_tenants.tenant_id), 0), - t_sessions=COALESCE((SELECT COUNT(*) - FROM public.sessions - INNER JOIN public.projects USING (project_id) - WHERE projects.tenant_id = all_tenants.tenant_id), 0), + t_sessions=t_sessions + COALESCE((SELECT COUNT(*) + FROM public.sessions INNER JOIN public.projects USING (project_id) + WHERE projects.tenant_id = all_tenants.tenant_id + AND start_ts >= (SELECT last_telemetry FROM tenants) + AND start_ts <=CAST(EXTRACT(epoch FROM date_trunc('day', now())) * 1000 AS BIGINT)), 0), t_users=COALESCE((SELECT COUNT(*) FROM public.users WHERE deleted_at ISNULL - AND users.tenant_id = all_tenants.tenant_id), 0) - FROM ( - SELECT tenant_id - FROM public.tenants + AND users.tenant_id = all_tenants.tenant_id), 0), + last_telemetry=CAST(EXTRACT(epoch FROM date_trunc('day', now())) * 1000 AS BIGINT) + FROM (SELECT tenant_id + FROM public.tenants ) AS all_tenants WHERE tenants.tenant_id = all_tenants.tenant_id RETURNING name,t_integrations,t_projects,t_sessions,t_users,tenant_key,opt_out, @@ -64,7 +65,7 @@ def compute(): def new_client(tenant_id): with pg_client.PostgresClient() as cur: cur.execute( - cur.mogrify(f"""SELECT *, + cur.mogrify(f"""SELECT *, openreplay_version() AS version_number, (SELECT email FROM public.users WHERE tenant_id=%(tenant_id)s AND role='owner' LIMIT 1) AS email FROM public.tenants WHERE tenant_id=%(tenant_id)s diff --git a/ee/api/chalicelib/core/tenants.py b/ee/api/chalicelib/core/tenants.py index 71119fd13..7f8e73ca8 100644 --- a/ee/api/chalicelib/core/tenants.py +++ b/ee/api/chalicelib/core/tenants.py @@ -1,3 +1,4 @@ +import schemas from chalicelib.core import users, license from chalicelib.utils import helper from chalicelib.utils import pg_client @@ -13,7 +14,7 @@ def get_by_tenant_key(tenant_key): t.api_key, t.created_at, '{license.EDITION}' AS edition, - t.version_number, + openreplay_version() AS version_number, t.opt_out FROM public.tenants AS t WHERE t.tenant_key = %(tenant_key)s AND t.deleted_at ISNULL @@ -33,7 +34,7 @@ def get_by_tenant_id(tenant_id): t.api_key, t.created_at, '{license.EDITION}' AS edition, - t.version_number, + openreplay_version() AS version_number, t.opt_out, t.tenant_key FROM public.tenants AS t @@ -86,7 +87,7 @@ def edit_client(tenant_id, changes): return helper.dict_to_camel_case(cur.fetchone()) -def update(tenant_id, user_id, data): +def update(tenant_id, user_id, data: schemas.UpdateTenantSchema): admin = users.get(user_id=user_id, tenant_id=tenant_id) if not admin["admin"] and not admin["superAdmin"]: @@ -94,10 +95,10 @@ def update(tenant_id, user_id, data): if "name" not in data and "optOut" not in data: return {"errors": ["please provide 'name' of 'optOut' attribute for update"]} changes = {} - if "name" in data: - changes["name"] = data["name"] - if "optOut" in data: - changes["optOut"] = data["optOut"] + if data.name is not None and len(data.name) > 0: + changes["name"] = data.name + if data.opt_out is not None: + changes["optOut"] = data.opt_out return edit_client(tenant_id=tenant_id, changes=changes) diff --git a/ee/api/chalicelib/core/users.py b/ee/api/chalicelib/core/users.py index ae998f83f..b55600da2 100644 --- a/ee/api/chalicelib/core/users.py +++ b/ee/api/chalicelib/core/users.py @@ -228,13 +228,6 @@ def create_member(tenant_id, user_id, data, background_tasks: BackgroundTasks): new_member = create_new_member(tenant_id=tenant_id, email=data["email"], invitation_token=invitation_token, admin=data.get("admin", False), name=name, role_id=role_id) new_member["invitationLink"] = __get_invitation_link(new_member.pop("invitationToken")) - # helper.async_post(config('email_basic') % 'member_invitation', - # { - # "email": data["email"], - # "invitationLink": new_member["invitationLink"], - # "clientId": tenants.get_by_tenant_id(tenant_id)["name"], - # "senderName": admin["name"] - # }) background_tasks.add_task(email_helper.send_team_invitation, **{ "recipient": data["email"], "invitation_link": new_member["invitationLink"], @@ -300,9 +293,8 @@ def generate_new_api_key(user_id): cur.mogrify( f"""UPDATE public.users SET api_key=generate_api_key(20) - WHERE - users.user_id = %(userId)s - AND deleted_at IS NULL + WHERE users.user_id = %(userId)s + AND deleted_at IS NULL RETURNING api_key;""", {"userId": user_id}) ) @@ -351,6 +343,47 @@ def edit(user_id_to_update, tenant_id, changes: schemas_ee.EditUserSchema, edito return {"data": user} +def edit_member(user_id_to_update, tenant_id, changes: schemas_ee.EditUserSchema, editor_id): + user = get_member(user_id=user_id_to_update, tenant_id=tenant_id) + if editor_id != user_id_to_update or changes.admin is not None and changes.admin != user["admin"]: + admin = get(tenant_id=tenant_id, user_id=editor_id) + if not admin["superAdmin"] and not admin["admin"]: + return {"errors": ["unauthorized"]} + _changes = {} + if editor_id == user_id_to_update: + if changes.admin is not None: + if user["superAdmin"]: + changes.admin = None + elif changes.admin != user["admin"]: + return {"errors": ["cannot change your own role"]} + if changes.roleId is not None: + if user["superAdmin"]: + changes.roleId = None + elif changes.roleId != user["roleId"]: + return {"errors": ["cannot change your own role"]} + + if changes.email is not None and changes.email != user["email"]: + if email_exists(changes.email): + return {"errors": ["email already exists."]} + if get_deleted_user_by_email(changes.email) is not None: + return {"errors": ["email previously deleted."]} + _changes["email"] = changes.email + + if changes.name is not None and len(changes.name) > 0: + _changes["name"] = changes.name + + if changes.admin is not None: + _changes["role"] = "admin" if changes.admin else "member" + + if changes.roleId is not None: + _changes["roleId"] = changes.roleId + + if len(_changes.keys()) > 0: + update(tenant_id=tenant_id, user_id=user_id_to_update, changes=_changes) + return {"data": get_member(tenant_id=tenant_id, user_id=user_id_to_update)} + return {"data": user} + + def get_by_email_only(email): with pg_client.PostgresClient() as cur: cur.execute( @@ -400,12 +433,49 @@ def get_by_email_reset(email, reset_token): return helper.dict_to_camel_case(r) +def get_member(tenant_id, user_id): + with pg_client.PostgresClient() as cur: + cur.execute( + cur.mogrify( + f"""SELECT + users.user_id, + users.email, + users.role, + users.name, + users.created_at, + (CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, + (CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin, + (CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member, + DATE_PART('day',timezone('utc'::text, now()) \ + - COALESCE(basic_authentication.invited_at,'2000-01-01'::timestamp ))>=1 AS expired_invitation, + basic_authentication.password IS NOT NULL OR users.origin IS NOT NULL AS joined, + invitation_token, + role_id, + roles.name AS role_name + FROM public.users + LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id + LEFT JOIN public.roles USING (role_id) + WHERE users.tenant_id = %(tenant_id)s AND users.deleted_at IS NULL AND users.user_id = %(user_id)s + ORDER BY name, user_id""", + {"tenant_id": tenant_id, "user_id": user_id}) + ) + u = helper.dict_to_camel_case(cur.fetchone()) + if u: + u["createdAt"] = TimeUTC.datetime_to_timestamp(u["createdAt"]) + if u["invitationToken"]: + u["invitationLink"] = __get_invitation_link(u.pop("invitationToken")) + else: + u["invitationLink"] = None + + return u + + def get_members(tenant_id): with pg_client.PostgresClient() as cur: cur.execute( cur.mogrify( f"""SELECT - users.user_id AS id, + users.user_id, users.email, users.role, users.name, @@ -423,7 +493,7 @@ def get_members(tenant_id): LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id LEFT JOIN public.roles USING (role_id) WHERE users.tenant_id = %(tenant_id)s AND users.deleted_at IS NULL - ORDER BY name, id""", + ORDER BY name, user_id""", {"tenant_id": tenant_id}) ) r = cur.fetchall() @@ -457,8 +527,8 @@ def delete_member(user_id, tenant_id, id_to_delete): with pg_client.PostgresClient() as cur: cur.execute( - cur.mogrify(f"""UPDATE public.users - SET deleted_at = timezone('utc'::text, now()) + cur.mogrify(f"""UPDATE public.users + SET deleted_at = timezone('utc'::text, now()), role_id=NULL WHERE user_id=%(user_id)s AND tenant_id=%(tenant_id)s;""", {"user_id": id_to_delete, "tenant_id": tenant_id})) cur.execute( @@ -628,7 +698,7 @@ def change_jwt_iat(user_id): return cur.fetchone().get("jwt_iat") -def authenticate(email, password, for_change_password=False, for_plugin=False): +def authenticate(email, password, for_change_password=False): with pg_client.PostgresClient() as cur: query = cur.mogrify( f"""SELECT @@ -675,7 +745,7 @@ def authenticate(email, password, for_change_password=False, for_plugin=False): return { "jwt": authorizers.generate_jwt(r['userId'], r['tenantId'], TimeUTC.datetime_to_timestamp(jwt_iat), - aud=f"plugin:{helper.get_stage_name()}" if for_plugin else f"front:{helper.get_stage_name()}"), + aud=f"front:{helper.get_stage_name()}"), "email": email, **r } diff --git a/ee/api/chalicelib/core/webhook.py b/ee/api/chalicelib/core/webhook.py index cb7cf509e..4ef0be6a9 100644 --- a/ee/api/chalicelib/core/webhook.py +++ b/ee/api/chalicelib/core/webhook.py @@ -1,3 +1,5 @@ +import logging + import requests from chalicelib.utils import pg_client, helper @@ -8,8 +10,7 @@ def get_by_id(webhook_id): with pg_client.PostgresClient() as cur: cur.execute( cur.mogrify("""\ - SELECT - webhook_id AS integration_id, webhook_id AS id, w.* + SELECT w.* FROM public.webhooks AS w where w.webhook_id =%(webhook_id)s AND deleted_at ISNULL;""", {"webhook_id": webhook_id}) @@ -43,8 +44,7 @@ def get_by_type(tenant_id, webhook_type): SELECT w.webhook_id AS integration_id, w.webhook_id AS id,w.webhook_id,w.endpoint,w.auth_header,w.type,w.index,w.name,w.created_at FROM public.webhooks AS w - where - w.tenant_id =%(tenant_id)s + WHERE w.tenant_id =%(tenant_id)s AND w.type =%(type)s AND deleted_at ISNULL;""", {"type": webhook_type, "tenant_id": tenant_id}) @@ -152,28 +152,24 @@ def trigger_batch(data_list): for w in data_list: if w["destination"] not in webhooks_map: webhooks_map[w["destination"]] = get_by_id(webhook_id=w["destination"]) - __trigger(hook=webhooks_map[w["destination"]], data=w["data"]) + if webhooks_map[w["destination"]] is None: + logging.error(f"!!Error webhook not found: webhook_id={w['destination']}") + else: + __trigger(hook=webhooks_map[w["destination"]], data=w["data"]) def __trigger(hook, data): - if hook["type"] == 'webhook': + if hook is not None and hook["type"] == 'webhook': headers = {} if hook["authHeader"] is not None and len(hook["authHeader"]) > 0: headers = {"Authorization": hook["authHeader"]} - # body = { - # "webhookId": hook["id"], - # "createdAt": TimeUTC.now(), - # "event": event, - # "data": data - # } - r = requests.post(url=hook["endpoint"], json=data, headers=headers) if r.status_code != 200: - print("=======> webhook: something went wrong") - print(r) - print(r.status_code) - print(r.text) + logging.error("=======> webhook: something went wrong for:") + logging.error(hook) + logging.error(r.status_code) + logging.error(r.text) return response = None try: @@ -182,5 +178,5 @@ def __trigger(hook, data): try: response = r.text except: - print("no response found") + logging.info("no response found") return response diff --git a/ee/api/chalicelib/utils/assist_helper.py b/ee/api/chalicelib/utils/assist_helper.py index 913435bd4..d182226c0 100644 --- a/ee/api/chalicelib/utils/assist_helper.py +++ b/ee/api/chalicelib/utils/assist_helper.py @@ -6,7 +6,7 @@ from time import time from decouple import config from chalicelib.core import assist -from chalicelib.utils import helper +from chalicelib.utils import helper_ee def __get_secret(): @@ -18,7 +18,7 @@ def get_temporary_credentials(): secret = __get_secret() if secret is None: return {"errors": ["secret not defined"]} - user = helper.generate_salt() + user = helper_ee.generate_salt() ttl = config("assist_ttl", cast=int, default=48) * 3600 timestamp = int(time()) + ttl username = str(timestamp) + ':' + user diff --git a/ee/api/chalicelib/utils/exp_ch_helper.py b/ee/api/chalicelib/utils/exp_ch_helper.py index 709b5e926..02de9addd 100644 --- a/ee/api/chalicelib/utils/exp_ch_helper.py +++ b/ee/api/chalicelib/utils/exp_ch_helper.py @@ -40,3 +40,9 @@ def get_user_viewed_sessions_table(timestamp=0): def get_user_viewed_errors_table(timestamp=0): return "experimental.user_viewed_errors" + + +def get_main_js_errors_sessions_table(timestamp=0): + return "experimental.js_errors_sessions_mv" # \ + # if config("EXP_7D_MV", cast=bool, default=True) \ + # and timestamp >= TimeUTC.now(delta_days=-7) else "experimental.events" diff --git a/ee/api/chalicelib/utils/helper_ee.py b/ee/api/chalicelib/utils/helper_ee.py new file mode 100644 index 000000000..919f25219 --- /dev/null +++ b/ee/api/chalicelib/utils/helper_ee.py @@ -0,0 +1,6 @@ +import random +import string + + +def generate_salt(): + return "".join(random.choices(string.hexdigits, k=36)) diff --git a/ee/api/chalicelib/utils/s3_extra.py b/ee/api/chalicelib/utils/s3_extra.py index bd74d8277..0e594c890 100644 --- a/ee/api/chalicelib/utils/s3_extra.py +++ b/ee/api/chalicelib/utils/s3_extra.py @@ -1,13 +1,16 @@ -from chalicelib.utils.s3 import client from decouple import config -def tag_file( session_id, tag_key='retention', tag_value='vault'): - return client.put_object_tagging( - Bucket=config("sessions_bucket"), - Key=session_id, - # VersionId='string', - # ContentMD5='string', - # ChecksumAlgorithm='CRC32'|'CRC32C'|'SHA1'|'SHA256', +from chalicelib.utils import s3 + + +def tag_session(file_key, tag_key='retention', tag_value='vault'): + return tag_file(file_key=file_key, bucket=config("sessions_bucket"), tag_key=tag_key, tag_value=tag_value) + + +def tag_file(file_key, bucket, tag_key, tag_value): + return s3.client.put_object_tagging( + Bucket=bucket, + Key=file_key, Tagging={ 'TagSet': [ { @@ -15,16 +18,5 @@ def tag_file( session_id, tag_key='retention', tag_value='vault'): 'Value': tag_value }, ] - }, - # ExpectedBucketOwner='string', - # RequestPayer='requester' + } ) - - # generate_presigned_url( - # 'put_object', - # Params={ - # 'Bucket': bucket, - # 'Key': key - # }, - # ExpiresIn=expires_in - # ) diff --git a/ee/api/clean.sh b/ee/api/clean.sh index 9aa916080..314321b83 100755 --- a/ee/api/clean.sh +++ b/ee/api/clean.sh @@ -32,7 +32,6 @@ rm -rf ./chalicelib/core/log_tool_stackdriver.py rm -rf ./chalicelib/core/log_tool_sumologic.py rm -rf ./chalicelib/core/metadata.py rm -rf ./chalicelib/core/mobile.py -rm -rf ./chalicelib/core/sessions.py rm -rf ./chalicelib/core/sessions_assignments.py rm -rf ./chalicelib/core/sessions_metas.py rm -rf ./chalicelib/core/sessions_mobs.py @@ -64,20 +63,18 @@ rm -rf ./routers/crons/__init__.py rm -rf ./routers/subs/__init__.py rm -rf ./routers/__init__.py rm -rf ./chalicelib/core/assist.py +rm -rf ./auth/__init__.py rm -rf ./auth/auth_apikey.py -rm -rf ./auth/auth_jwt.py rm -rf ./build.sh +rm -rf ./routers/base.py rm -rf ./routers/core.py rm -rf ./routers/crons/core_crons.py -rm -rf ./routers/subs/dashboard.py rm -rf ./db_changes.sql -rm -rf ./Dockerfile.bundle +rm -rf ./Dockerfile_bundle rm -rf ./entrypoint.bundle.sh rm -rf ./chalicelib/core/heatmaps.py -rm -rf ./routers/subs/insights.py rm -rf ./schemas.py rm -rf ./routers/subs/v1_api.py -rm -rf ./routers/subs/metrics.py #exp rm -rf ./chalicelib/core/custom_metrics.py rm -rf ./chalicelib/core/performance_event.py rm -rf ./chalicelib/core/saved_search.py diff --git a/ee/api/entrypoint.sh b/ee/api/entrypoint.sh index b5997ee3b..ebd646a7d 100755 --- a/ee/api/entrypoint.sh +++ b/ee/api/entrypoint.sh @@ -1,7 +1,5 @@ #!/bin/sh sh env_vars.sh source /tmp/.env.override -cd sourcemap-reader -nohup npm start & -cd .. + uvicorn app:app --host 0.0.0.0 --port $LISTEN_PORT --reload --proxy-headers diff --git a/ee/api/entrypoint_alerts.sh b/ee/api/entrypoint_alerts.sh index fa492d5b7..acf8b390a 100755 --- a/ee/api/entrypoint_alerts.sh +++ b/ee/api/entrypoint_alerts.sh @@ -1,4 +1,5 @@ #!/bin/sh +export ASSIST_KEY=ignore sh env_vars.sh source /tmp/.env.override uvicorn app:app --host 0.0.0.0 --port $LISTEN_PORT --reload diff --git a/ee/api/entrypoint_crons.sh b/ee/api/entrypoint_crons.sh index b6c03bf75..1673b9606 100755 --- a/ee/api/entrypoint_crons.sh +++ b/ee/api/entrypoint_crons.sh @@ -1,4 +1,5 @@ #!/bin/sh +export ASSIST_KEY=ignore sh env_vars.sh source /tmp/.env.override python app_crons.py $ACTION diff --git a/ee/api/env.default b/ee/api/env.default index 9d6fe66d7..f5574a8a1 100644 --- a/ee/api/env.default +++ b/ee/api/env.default @@ -14,7 +14,6 @@ S3_SECRET= SAML2_MD_URL= SITE_URL= announcement_url= -async_Token= captcha_key= captcha_server= ch_host= @@ -22,20 +21,15 @@ ch_port= ch_timeout=30 ch_receive_timeout=10 change_password_link=/reset-password?invitation=%s&&pass=%s -email_basic=http://127.0.0.1:8000/async/basic/%s -email_plans=http://127.0.0.1:8000/async/plans/%s -email_signup=http://127.0.0.1:8000/async/email_signup/%s idp_entityId= idp_sls_url= idp_sso_url= idp_x509cert= invitation_link=/api/users/invitation?token=%s -isEE=true -isFOS=false js_cache_bucket=sessions-assets jwt_algorithm=HS512 -jwt_exp_delta_seconds=2592000 -jwt_issuer=openreplay-default-ee +JWT_EXPIRATION=2592000 +JWT_ISSUER=openreplay-ee jwt_secret="SET A RANDOM STRING HERE" ASSIST_URL=http://assist-openreplay.app.svc.cluster.local:9001/assist/%s assist=/sockets-live @@ -45,27 +39,33 @@ pg_host=postgresql.db.svc.cluster.local pg_password=asayerPostgres pg_port=5432 pg_user=postgres -pg_timeout=30 -pg_minconn=20 -pg_maxconn=50 +PG_TIMEOUT=30 +PG_MINCONN=20 +PG_MAXCONN=50 PG_RETRY_MAX=50 PG_RETRY_INTERVAL=2 PG_POOL=true -put_S3_TTL=20 -sentryURL= sessions_bucket=mobs sessions_region=us-east-1 sourcemaps_bucket=sourcemaps -sourcemaps_reader=http://127.0.0.1:9000/sourcemaps/%s/sourcemaps -stage=default-ee +sourcemaps_reader=http://sourcemaps-reader-openreplay.app.svc.cluster.local:9000/sourcemaps/%s/sourcemaps version_number=1.0.0 FS_DIR=/mnt/efs EXP_SESSIONS_SEARCH=false EXP_AUTOCOMPLETE=false EXP_ERRORS_SEARCH=false +EXP_ERRORS_GET=false EXP_METRICS=true EXP_7D_MV=false EXP_ALERTS=false EXP_FUNNELS=false EXP_RESOURCES=true -TRACE_PERIOD=300 \ No newline at end of file +TRACE_PERIOD=300 +EFS_SESSION_MOB_PATTERN=%(sessionId)s +EFS_DEVTOOLS_MOB_PATTERN=%(sessionId)sdevtools +SESSION_MOB_PATTERN_S=%(sessionId)s/dom.mobs +SESSION_MOB_PATTERN_E=%(sessionId)s/dom.mobe +DEVTOOLS_MOB_PATTERN=%(sessionId)s/devtools.mob +PRESIGNED_URL_EXPIRATION=3600 +ASSIST_JWT_EXPIRATION=144000 +ASSIST_JWT_SECRET= \ No newline at end of file diff --git a/ee/api/or_dependencies.py b/ee/api/or_dependencies.py index ec0eb5d51..421f0853f 100644 --- a/ee/api/or_dependencies.py +++ b/ee/api/or_dependencies.py @@ -1,17 +1,20 @@ import json from typing import Callable +from fastapi import HTTPException, Depends +from fastapi import Security from fastapi.routing import APIRoute +from fastapi.security import SecurityScopes from starlette import status from starlette.exceptions import HTTPException from starlette.requests import Request from starlette.responses import Response, JSONResponse -import schemas +import schemas_ee from chalicelib.core import traces -async def OR_context(request: Request) -> schemas.CurrentContext: +async def OR_context(request: Request) -> schemas_ee.CurrentContext: if hasattr(request.state, "currentContext"): return request.state.currentContext else: @@ -43,3 +46,14 @@ class ORRoute(APIRoute): return response return custom_route_handler + + +def __check(security_scopes: SecurityScopes, context: schemas_ee.CurrentContext = Depends(OR_context)): + for scope in security_scopes.scopes: + if scope not in context.permissions: + raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, + detail="Not enough permissions") + + +def OR_scope(*scopes): + return Security(__check, scopes=list(scopes)) diff --git a/ee/api/requirements-alerts.txt b/ee/api/requirements-alerts.txt index 475a39b5e..02042a778 100644 --- a/ee/api/requirements-alerts.txt +++ b/ee/api/requirements-alerts.txt @@ -1,18 +1,18 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 -psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +urllib3==1.26.12 +boto3==1.26.14 +pyjwt==2.6.0 +psycopg2-binary==2.9.5 +elasticsearch==8.5.1 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.87.0 +uvicorn[standard]==0.20.0 python-decouple==3.6 -pydantic[email]==1.9.2 -apscheduler==3.9.1 +pydantic[email]==1.10.2 +apscheduler==3.9.1.post1 clickhouse-driver==0.2.4 python-multipart==0.0.5 \ No newline at end of file diff --git a/ee/api/requirements-crons.txt b/ee/api/requirements-crons.txt index 475a39b5e..02042a778 100644 --- a/ee/api/requirements-crons.txt +++ b/ee/api/requirements-crons.txt @@ -1,18 +1,18 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 -psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +urllib3==1.26.12 +boto3==1.26.14 +pyjwt==2.6.0 +psycopg2-binary==2.9.5 +elasticsearch==8.5.1 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.87.0 +uvicorn[standard]==0.20.0 python-decouple==3.6 -pydantic[email]==1.9.2 -apscheduler==3.9.1 +pydantic[email]==1.10.2 +apscheduler==3.9.1.post1 clickhouse-driver==0.2.4 python-multipart==0.0.5 \ No newline at end of file diff --git a/ee/api/requirements.txt b/ee/api/requirements.txt index bdf363b7b..ac4f27a9d 100644 --- a/ee/api/requirements.txt +++ b/ee/api/requirements.txt @@ -1,18 +1,18 @@ requests==2.28.1 -urllib3==1.26.10 -boto3==1.24.53 -pyjwt==2.4.0 -psycopg2-binary==2.9.3 -elasticsearch==8.3.3 -jira==3.3.1 +urllib3==1.26.12 +boto3==1.26.14 +pyjwt==2.6.0 +psycopg2-binary==2.9.5 +elasticsearch==8.5.1 +jira==3.4.1 -fastapi==0.80.0 -uvicorn[standard]==0.18.2 +fastapi==0.87.0 +uvicorn[standard]==0.20.0 python-decouple==3.6 -pydantic[email]==1.9.2 -apscheduler==3.9.1 +pydantic[email]==1.10.2 +apscheduler==3.9.1.post1 clickhouse-driver==0.2.4 python3-saml==1.14.0 diff --git a/ee/api/routers/core_dynamic.py b/ee/api/routers/core_dynamic.py index a414aed05..fb24aec96 100644 --- a/ee/api/routers/core_dynamic.py +++ b/ee/api/routers/core_dynamic.py @@ -1,19 +1,23 @@ -from typing import Optional +from typing import Optional, Union from decouple import config from fastapi import Body, Depends, BackgroundTasks -from starlette.responses import RedirectResponse +from starlette.responses import RedirectResponse, FileResponse import schemas import schemas_ee -from chalicelib.core import sessions +from chalicelib.core import sessions, assist, heatmaps, sessions_favorite, sessions_assignments, errors, errors_viewed, \ + errors_favorite, sessions_notes +from chalicelib.core import sessions_viewed from chalicelib.core import tenants, users, projects, license from chalicelib.core import webhook from chalicelib.core.collaboration_slack import Slack from chalicelib.utils import SAML2_helper from chalicelib.utils import helper -from or_dependencies import OR_context +from chalicelib.utils.TimeUTC import TimeUTC +from or_dependencies import OR_context, OR_scope from routers.base import get_routers +from schemas_ee import Permissions public_app, app, app_apikey = get_routers() @@ -46,7 +50,6 @@ def get_account(context: schemas.CurrentContext = Depends(OR_context)): @app.post('/account', tags=["account"]) -@app.put('/account', tags=["account"]) def edit_account(data: schemas_ee.EditUserSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return users.edit(tenant_id=context.tenant_id, user_id_to_update=context.user_id, changes=data, @@ -70,8 +73,8 @@ def get_project(projectId: int, context: schemas.CurrentContext = Depends(OR_con return {"data": data} -@app.put('/integrations/slack', tags=['integrations']) @app.post('/integrations/slack', tags=['integrations']) +@app.put('/integrations/slack', tags=['integrations']) def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentContext = Depends(OR_context)): n = Slack.add_channel(tenant_id=context.tenant_id, url=data.url, name=data.name) if n is None: @@ -81,7 +84,6 @@ def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentConte return {"data": n} -@app.put('/integrations/slack/{integrationId}', tags=['integrations']) @app.post('/integrations/slack/{integrationId}', tags=['integrations']) def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): @@ -98,7 +100,6 @@ def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = B @app.post('/client/members', tags=["client"]) -@app.put('/client/members', tags=["client"]) def add_member(background_tasks: BackgroundTasks, data: schemas_ee.CreateMemberSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): return users.create_member(tenant_id=context.tenant_id, user_id=context.user_id, data=data.dict(), @@ -123,7 +124,6 @@ def process_invitation_link(token: str): @public_app.post('/password/reset', tags=["users"]) -@public_app.put('/password/reset', tags=["users"]) def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema = Body(...)): if data is None or len(data.invitation) < 64 or len(data.passphrase) < 8: return {"errors": ["please provide a valid invitation & pass"]} @@ -137,11 +137,10 @@ def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema = @app.put('/client/members/{memberId}', tags=["client"]) -@app.post('/client/members/{memberId}', tags=["client"]) def edit_member(memberId: int, data: schemas_ee.EditMemberSchema, context: schemas.CurrentContext = Depends(OR_context)): - return users.edit(tenant_id=context.tenant_id, editor_id=context.user_id, changes=data, - user_id_to_update=memberId) + return users.edit_member(tenant_id=context.tenant_id, editor_id=context.user_id, changes=data, + user_id_to_update=memberId) @app.get('/metadata/session_search', tags=["metadata"]) @@ -171,3 +170,268 @@ def get_general_stats(): def get_projects(context: schemas.CurrentContext = Depends(OR_context)): return {"data": projects.get_projects(tenant_id=context.tenant_id, recording_state=True, gdpr=True, recorded=True, stack_integrations=True, user_id=context.user_id)} + + +@app.get('/{projectId}/sessions/{sessionId}', tags=["sessions"], dependencies=[OR_scope(Permissions.session_replay)]) +def get_session(projectId: int, sessionId: Union[int, str], background_tasks: BackgroundTasks, + context: schemas.CurrentContext = Depends(OR_context)): + if isinstance(sessionId, str): + return {"errors": ["session not found"]} + data = sessions.get_by_id2_pg(project_id=projectId, session_id=sessionId, full_data=True, + include_fav_viewed=True, group_metadata=True, context=context) + if data is None: + return {"errors": ["session not found"]} + if data.get("inDB"): + background_tasks.add_task(sessions_viewed.view_session, project_id=projectId, user_id=context.user_id, + session_id=sessionId) + return { + 'data': data + } + + +@app.get('/{projectId}/sessions/{sessionId}/errors/{errorId}/sourcemaps', tags=["sessions", "sourcemaps"], + dependencies=[OR_scope(Permissions.dev_tools)]) +def get_error_trace(projectId: int, sessionId: int, errorId: str, + context: schemas.CurrentContext = Depends(OR_context)): + data = errors.get_trace(project_id=projectId, error_id=errorId) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.post('/{projectId}/errors/search', tags=['errors'], dependencies=[OR_scope(Permissions.dev_tools)]) +def errors_search(projectId: int, data: schemas.SearchErrorsSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return {"data": errors.search(data, projectId, user_id=context.user_id)} + + +@app.get('/{projectId}/errors/stats', tags=['errors'], dependencies=[OR_scope(Permissions.dev_tools)]) +def errors_stats(projectId: int, startTimestamp: int, endTimestamp: int, + context: schemas.CurrentContext = Depends(OR_context)): + return errors.stats(projectId, user_id=context.user_id, startTimestamp=startTimestamp, endTimestamp=endTimestamp) + + +@app.get('/{projectId}/errors/{errorId}', tags=['errors'], dependencies=[OR_scope(Permissions.dev_tools)]) +def errors_get_details(projectId: int, errorId: str, background_tasks: BackgroundTasks, density24: int = 24, + density30: int = 30, context: schemas.CurrentContext = Depends(OR_context)): + data = errors.get_details(project_id=projectId, user_id=context.user_id, error_id=errorId, + **{"density24": density24, "density30": density30}) + if data.get("data") is not None: + background_tasks.add_task(errors_viewed.viewed_error, project_id=projectId, user_id=context.user_id, + error_id=errorId) + return data + + +@app.get('/{projectId}/errors/{errorId}/stats', tags=['errors'], dependencies=[OR_scope(Permissions.dev_tools)]) +def errors_get_details_right_column(projectId: int, errorId: str, startDate: int = TimeUTC.now(-7), + endDate: int = TimeUTC.now(), density: int = 7, + context: schemas.CurrentContext = Depends(OR_context)): + data = errors.get_details_chart(project_id=projectId, user_id=context.user_id, error_id=errorId, + **{"startDate": startDate, "endDate": endDate, "density": density}) + return data + + +@app.get('/{projectId}/errors/{errorId}/sourcemaps', tags=['errors'], dependencies=[OR_scope(Permissions.dev_tools)]) +def errors_get_details_sourcemaps(projectId: int, errorId: str, + context: schemas.CurrentContext = Depends(OR_context)): + data = errors.get_trace(project_id=projectId, error_id=errorId) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.get('/{projectId}/errors/{errorId}/{action}', tags=["errors"], dependencies=[OR_scope(Permissions.dev_tools)]) +def add_remove_favorite_error(projectId: int, errorId: str, action: str, startDate: int = TimeUTC.now(-7), + endDate: int = TimeUTC.now(), context: schemas.CurrentContext = Depends(OR_context)): + if action == "favorite": + return errors_favorite.favorite_error(project_id=projectId, user_id=context.user_id, error_id=errorId) + elif action == "sessions": + start_date = startDate + end_date = endDate + return { + "data": errors.get_sessions(project_id=projectId, user_id=context.user_id, error_id=errorId, + start_date=start_date, end_date=end_date)} + elif action in list(errors.ACTION_STATE.keys()): + return errors.change_state(project_id=projectId, user_id=context.user_id, error_id=errorId, action=action) + else: + return {"errors": ["undefined action"]} + + +@app.get('/{projectId}/assist/sessions/{sessionId}', tags=["assist"], dependencies=[OR_scope(Permissions.assist_live)]) +def get_live_session(projectId: int, sessionId: str, background_tasks: BackgroundTasks, + context: schemas_ee.CurrentContext = Depends(OR_context)): + data = assist.get_live_session_by_id(project_id=projectId, session_id=sessionId) + if data is None: + data = sessions.get_by_id2_pg(context=context, project_id=projectId, session_id=sessionId, full_data=True, + include_fav_viewed=True, group_metadata=True, live=False) + if data is None: + return {"errors": ["session not found"]} + if data.get("inDB"): + background_tasks.add_task(sessions_viewed.view_session, project_id=projectId, + user_id=context.user_id, session_id=sessionId) + return {'data': data} + + +@app.get('/{projectId}/unprocessed/{sessionId}/dom.mob', tags=["assist"], + dependencies=[OR_scope(Permissions.assist_live, Permissions.session_replay)]) +def get_live_session_replay_file(projectId: int, sessionId: Union[int, str], + context: schemas.CurrentContext = Depends(OR_context)): + not_found = {"errors": ["Replay file not found"]} + if isinstance(sessionId, str): + print(f"{sessionId} not a valid number.") + return not_found + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in DB.") + if not assist.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in Assist.") + return not_found + + path = assist.get_raw_mob_by_id(project_id=projectId, session_id=sessionId) + if path is None: + return not_found + + return FileResponse(path=path, media_type="application/octet-stream") + + +@app.get('/{projectId}/unprocessed/{sessionId}/devtools.mob', tags=["assist"], + dependencies=[OR_scope(Permissions.assist_live, Permissions.session_replay, Permissions.dev_tools)]) +def get_live_session_devtools_file(projectId: int, sessionId: Union[int, str], + context: schemas.CurrentContext = Depends(OR_context)): + not_found = {"errors": ["Devtools file not found"]} + if isinstance(sessionId, str): + print(f"{sessionId} not a valid number.") + return not_found + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in DB.") + if not assist.session_exists(project_id=projectId, session_id=sessionId): + print(f"{projectId}/{sessionId} not found in Assist.") + return not_found + + path = assist.get_raw_devtools_by_id(project_id=projectId, session_id=sessionId) + if path is None: + return {"errors": ["Devtools file not found"]} + + return FileResponse(path=path, media_type="application/octet-stream") + + +@app.post('/{projectId}/heatmaps/url', tags=["heatmaps"], dependencies=[OR_scope(Permissions.session_replay)]) +def get_heatmaps_by_url(projectId: int, data: schemas.GetHeatmapPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return {"data": heatmaps.get_by_url(project_id=projectId, data=data.dict())} + + +@app.get('/{projectId}/sessions/{sessionId}/favorite', tags=["sessions"], + dependencies=[OR_scope(Permissions.session_replay)]) +def add_remove_favorite_session2(projectId: int, sessionId: int, + context: schemas_ee.CurrentContext = Depends(OR_context)): + return { + "data": sessions_favorite.favorite_session(context=context, project_id=projectId, session_id=sessionId)} + + +@app.get('/{projectId}/sessions/{sessionId}/assign', tags=["sessions"], + dependencies=[OR_scope(Permissions.session_replay)]) +def assign_session(projectId: int, sessionId, context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_assignments.get_by_session(project_id=projectId, session_id=sessionId, + tenant_id=context.tenant_id, + user_id=context.user_id) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.get('/{projectId}/sessions/{sessionId}/assign/{issueId}', tags=["sessions", "issueTracking"], + dependencies=[OR_scope(Permissions.session_replay)]) +def assign_session(projectId: int, sessionId: int, issueId: str, + context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_assignments.get(project_id=projectId, session_id=sessionId, assignment_id=issueId, + tenant_id=context.tenant_id, user_id=context.user_id) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.post('/{projectId}/sessions/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"], + dependencies=[OR_scope(Permissions.session_replay)]) +def comment_assignment(projectId: int, sessionId: int, issueId: str, data: schemas.CommentAssignmentSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_assignments.comment(tenant_id=context.tenant_id, project_id=projectId, + session_id=sessionId, assignment_id=issueId, + user_id=context.user_id, message=data.message) + if "errors" in data.keys(): + return data + return { + 'data': data + } + + +@app.post('/{projectId}/sessions/{sessionId}/notes', tags=["sessions", "notes"], + dependencies=[OR_scope(Permissions.session_replay)]) +def create_note(projectId: int, sessionId: int, data: schemas.SessionNoteSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + if not sessions.session_exists(project_id=projectId, session_id=sessionId): + return {"errors": ["Session not found"]} + data = sessions_notes.create(tenant_id=context.tenant_id, project_id=projectId, + session_id=sessionId, user_id=context.user_id, data=data) + if "errors" in data.keys(): + return data + return { + 'data': data + } + + +@app.get('/{projectId}/sessions/{sessionId}/notes', tags=["sessions", "notes"], + dependencies=[OR_scope(Permissions.session_replay)]) +def get_session_notes(projectId: int, sessionId: int, context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_notes.get_session_notes(tenant_id=context.tenant_id, project_id=projectId, + session_id=sessionId, user_id=context.user_id) + if "errors" in data: + return data + return { + 'data': data + } + + +@app.post('/{projectId}/notes/{noteId}', tags=["sessions", "notes"], + dependencies=[OR_scope(Permissions.session_replay)]) +def edit_note(projectId: int, noteId: int, data: schemas.SessionUpdateNoteSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_notes.edit(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id, + note_id=noteId, data=data) + if "errors" in data.keys(): + return data + return { + 'data': data + } + + +@app.delete('/{projectId}/notes/{noteId}', tags=["sessions", "notes"], + dependencies=[OR_scope(Permissions.session_replay)]) +def delete_note(projectId: int, noteId: int, context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_notes.delete(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id, + note_id=noteId) + return data + + +@app.get('/{projectId}/notes/{noteId}/slack/{webhookId}', tags=["sessions", "notes"]) +def share_note_to_slack(projectId: int, noteId: int, webhookId: int, + context: schemas.CurrentContext = Depends(OR_context)): + return sessions_notes.share_to_slack(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id, + note_id=noteId, webhook_id=webhookId) + + +@app.post('/{projectId}/notes', tags=["sessions", "notes"], dependencies=[OR_scope(Permissions.session_replay)]) +def get_all_notes(projectId: int, data: schemas.SearchNoteSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = sessions_notes.get_all_notes_by_project_id(tenant_id=context.tenant_id, project_id=projectId, + user_id=context.user_id, data=data) + if "errors" in data: + return data + return {'data': data} diff --git a/ee/api/routers/subs/dashboard.py b/ee/api/routers/subs/dashboard.py new file mode 100644 index 000000000..206a234ca --- /dev/null +++ b/ee/api/routers/subs/dashboard.py @@ -0,0 +1,400 @@ +from fastapi import Body + +import schemas +from chalicelib.core import metadata +from chalicelib.core import metrics +from chalicelib.utils import helper +from or_dependencies import OR_scope +from routers.base import get_routers +from schemas_ee import Permissions + +public_app, app, app_apikey = get_routers([OR_scope(Permissions.metrics)]) + + +@app.get('/{projectId}/dashboard/metadata', tags=["dashboard", "metrics"]) +def get_metadata_map(projectId: int): + metamap = [] + for m in metadata.get(project_id=projectId): + metamap.append({"name": m["key"], "key": f"metadata{m['index']}"}) + return {"data": metamap} + + +@app.post('/{projectId}/dashboard/sessions', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/sessions', tags=["dashboard", "metrics"]) +def get_dashboard_processed_sessions(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_processed_sessions(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/errors', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/errors', tags=["dashboard", "metrics"]) +def get_dashboard_errors(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_errors(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/errors_trend', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/errors_trend', tags=["dashboard", "metrics"]) +def get_dashboard_errors_trend(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_errors_trend(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/application_activity', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/application_activity', tags=["dashboard", "metrics"]) +def get_dashboard_application_activity(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_application_activity(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/page_metrics', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/page_metrics', tags=["dashboard", "metrics"]) +def get_dashboard_page_metrics(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_page_metrics(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/user_activity', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/user_activity', tags=["dashboard", "metrics"]) +def get_dashboard_user_activity(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_user_activity(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/performance', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/performance', tags=["dashboard", "metrics"]) +def get_dashboard_performance(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_performance(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/slowest_images', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/slowest_images', tags=["dashboard", "metrics"]) +def get_dashboard_slowest_images(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_slowest_images(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/missing_resources', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/missing_resources', tags=["dashboard", "metrics"]) +def get_performance_sessions(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_missing_resources_trend(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/dashboard/network', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/network', tags=["dashboard", "metrics"]) +def get_network_widget(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_network(project_id=projectId, **data.dict())} + + +@app.get('/{projectId}/dashboard/{widget}/search', tags=["dashboard", "metrics"]) +def get_dashboard_autocomplete(projectId: int, widget: str, q: str, type: str = "", platform: str = None, + key: str = ""): + if q is None or len(q) == 0: + return {"data": []} + q = '^' + q + + if widget in ['performance']: + data = metrics.search(q, type, project_id=projectId, + platform=platform, performance=True) + elif widget in ['pages', 'pages_dom_buildtime', 'top_metrics', 'time_to_render', + 'impacted_sessions_by_slow_pages', 'pages_response_time']: + data = metrics.search(q, type, project_id=projectId, + platform=platform, pages_only=True) + elif widget in ['resources_loading_time']: + data = metrics.search(q, type, project_id=projectId, + platform=platform, performance=False) + elif widget in ['time_between_events', 'events']: + data = metrics.search(q, type, project_id=projectId, + platform=platform, performance=False, events_only=True) + elif widget in ['metadata']: + data = metrics.search(q, None, project_id=projectId, + platform=platform, metadata=True, key=key) + else: + return {"errors": [f"unsupported widget: {widget}"]} + return {'data': data} + + +# 1 +@app.post('/{projectId}/dashboard/slowest_resources', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/slowest_resources', tags=["dashboard", "metrics"]) +def get_dashboard_slowest_resources(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_slowest_resources(project_id=projectId, **data.dict())} + + +# 2 +@app.post('/{projectId}/dashboard/resources_loading_time', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/resources_loading_time', tags=["dashboard", "metrics"]) +def get_dashboard_resources(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_resources_loading_time(project_id=projectId, **data.dict())} + + +# 3 +@app.post('/{projectId}/dashboard/pages_dom_buildtime', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/pages_dom_buildtime', tags=["dashboard", "metrics"]) +def get_dashboard_pages_dom(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_pages_dom_build_time(project_id=projectId, **data.dict())} + + +# 4 +@app.post('/{projectId}/dashboard/busiest_time_of_day', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/busiest_time_of_day', tags=["dashboard", "metrics"]) +def get_dashboard_busiest_time_of_day(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_busiest_time_of_day(project_id=projectId, **data.dict())} + + +# 5 +@app.post('/{projectId}/dashboard/sessions_location', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/sessions_location', tags=["dashboard", "metrics"]) +def get_dashboard_sessions_location(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_sessions_location(project_id=projectId, **data.dict())} + + +# 6 +@app.post('/{projectId}/dashboard/speed_location', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/speed_location', tags=["dashboard", "metrics"]) +def get_dashboard_speed_location(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_speed_index_location(project_id=projectId, **data.dict())} + + +# 7 +@app.post('/{projectId}/dashboard/pages_response_time', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/pages_response_time', tags=["dashboard", "metrics"]) +def get_dashboard_pages_response_time(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_pages_response_time(project_id=projectId, **data.dict())} + + +# 8 +@app.post('/{projectId}/dashboard/pages_response_time_distribution', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/pages_response_time_distribution', tags=["dashboard", "metrics"]) +def get_dashboard_pages_response_time_distribution(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_pages_response_time_distribution(project_id=projectId, **data.dict())} + + +# 9 +@app.post('/{projectId}/dashboard/top_metrics', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/top_metrics', tags=["dashboard", "metrics"]) +def get_dashboard_top_metrics(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_top_metrics(project_id=projectId, **data.dict())} + + +# 10 +@app.post('/{projectId}/dashboard/time_to_render', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/time_to_render', tags=["dashboard", "metrics"]) +def get_dashboard_time_to_render(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_time_to_render(project_id=projectId, **data.dict())} + + +# 11 +@app.post('/{projectId}/dashboard/impacted_sessions_by_slow_pages', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/impacted_sessions_by_slow_pages', tags=["dashboard", "metrics"]) +def get_dashboard_impacted_sessions_by_slow_pages(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_impacted_sessions_by_slow_pages(project_id=projectId, **data.dict())} + + +# 12 +@app.post('/{projectId}/dashboard/memory_consumption', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/memory_consumption', tags=["dashboard", "metrics"]) +def get_dashboard_memory_consumption(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_memory_consumption(project_id=projectId, **data.dict())} + + +# 12.1 +@app.post('/{projectId}/dashboard/fps', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/fps', tags=["dashboard", "metrics"]) +def get_dashboard_avg_fps(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_avg_fps(project_id=projectId, **data.dict())} + + +# 12.2 +@app.post('/{projectId}/dashboard/cpu', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/cpu', tags=["dashboard", "metrics"]) +def get_dashboard_avg_cpu(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_avg_cpu(project_id=projectId, **data.dict())} + + +# 13 +@app.post('/{projectId}/dashboard/crashes', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/crashes', tags=["dashboard", "metrics"]) +def get_dashboard_impacted_sessions_by_slow_pages(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_crashes(project_id=projectId, **data.dict())} + + +# 14 +@app.post('/{projectId}/dashboard/domains_errors', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/domains_errors', tags=["dashboard", "metrics"]) +def get_dashboard_domains_errors(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_domains_errors(project_id=projectId, **data.dict())} + + +# 14.1 +@app.post('/{projectId}/dashboard/domains_errors_4xx', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/domains_errors_4xx', tags=["dashboard", "metrics"]) +def get_dashboard_domains_errors_4xx(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_domains_errors_4xx(project_id=projectId, **data.dict())} + + +# 14.2 +@app.post('/{projectId}/dashboard/domains_errors_5xx', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/domains_errors_5xx', tags=["dashboard", "metrics"]) +def get_dashboard_domains_errors_5xx(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_domains_errors_5xx(project_id=projectId, **data.dict())} + + +# 15 +@app.post('/{projectId}/dashboard/slowest_domains', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/slowest_domains', tags=["dashboard", "metrics"]) +def get_dashboard_slowest_domains(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_slowest_domains(project_id=projectId, **data.dict())} + + +# 16 +@app.post('/{projectId}/dashboard/errors_per_domains', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/errors_per_domains', tags=["dashboard", "metrics"]) +def get_dashboard_errors_per_domains(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_errors_per_domains(project_id=projectId, **data.dict())} + + +# 17 +@app.post('/{projectId}/dashboard/sessions_per_browser', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/sessions_per_browser', tags=["dashboard", "metrics"]) +def get_dashboard_sessions_per_browser(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_sessions_per_browser(project_id=projectId, **data.dict())} + + +# 18 +@app.post('/{projectId}/dashboard/calls_errors', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/calls_errors', tags=["dashboard", "metrics"]) +def get_dashboard_calls_errors(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_calls_errors(project_id=projectId, **data.dict())} + + +# 18.1 +@app.post('/{projectId}/dashboard/calls_errors_4xx', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/calls_errors_4xx', tags=["dashboard", "metrics"]) +def get_dashboard_calls_errors_4xx(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_calls_errors_4xx(project_id=projectId, **data.dict())} + + +# 18.2 +@app.post('/{projectId}/dashboard/calls_errors_5xx', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/calls_errors_5xx', tags=["dashboard", "metrics"]) +def get_dashboard_calls_errors_5xx(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_calls_errors_5xx(project_id=projectId, **data.dict())} + + +# 19 +@app.post('/{projectId}/dashboard/errors_per_type', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/errors_per_type', tags=["dashboard", "metrics"]) +def get_dashboard_errors_per_type(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_errors_per_type(project_id=projectId, **data.dict())} + + +# 20 +@app.post('/{projectId}/dashboard/resources_by_party', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/resources_by_party', tags=["dashboard", "metrics"]) +def get_dashboard_resources_by_party(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_resources_by_party(project_id=projectId, **data.dict())} + + +# 21 +@app.post('/{projectId}/dashboard/resource_type_vs_response_end', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/resource_type_vs_response_end', tags=["dashboard", "metrics"]) +def get_dashboard_errors_per_resource_type(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.resource_type_vs_response_end(project_id=projectId, **data.dict())} + + +# 22 +@app.post('/{projectId}/dashboard/resources_vs_visually_complete', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/resources_vs_visually_complete', tags=["dashboard", "metrics"]) +def get_dashboard_resources_vs_visually_complete(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_resources_vs_visually_complete(project_id=projectId, **data.dict())} + + +# 23 +@app.post('/{projectId}/dashboard/impacted_sessions_by_js_errors', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/impacted_sessions_by_js_errors', tags=["dashboard", "metrics"]) +def get_dashboard_impacted_sessions_by_js_errors(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_impacted_sessions_by_js_errors(project_id=projectId, **data.dict())} + + +# 24 +@app.post('/{projectId}/dashboard/resources_count_by_type', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/resources_count_by_type', tags=["dashboard", "metrics"]) +def get_dashboard_resources_count_by_type(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": metrics.get_resources_count_by_type(project_id=projectId, **data.dict())} + + +# # 25 +# @app.post('/{projectId}/dashboard/time_between_events', tags=["dashboard", "metrics"]) +# @app.get('/{projectId}/dashboard/time_between_events', tags=["dashboard", "metrics"]) +# def get_dashboard_resources_count_by_type(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): +# return {"errors": ["please choose 2 events"]} + + +@app.post('/{projectId}/dashboard/overview', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/overview', tags=["dashboard", "metrics"]) +def get_dashboard_group(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + results = [ + {"key": "count_sessions", + "data": metrics.get_processed_sessions(project_id=projectId, **data.dict())}, + *helper.explode_widget(data={**metrics.get_application_activity(project_id=projectId, **data.dict()), + "chart": metrics.get_performance(project_id=projectId, **data.dict()) + .get("chart", [])}), + *helper.explode_widget(data=metrics.get_page_metrics(project_id=projectId, **data.dict())), + *helper.explode_widget(data=metrics.get_user_activity(project_id=projectId, **data.dict())), + {"key": "avg_pages_dom_buildtime", + "data": metrics.get_pages_dom_build_time(project_id=projectId, **data.dict())}, + {"key": "avg_pages_response_time", + "data": metrics.get_pages_response_time(project_id=projectId, **data.dict()) + }, + *helper.explode_widget(metrics.get_top_metrics(project_id=projectId, **data.dict())), + {"key": "avg_time_to_render", "data": metrics.get_time_to_render(project_id=projectId, **data.dict())}, + {"key": "avg_used_js_heap_size", "data": metrics.get_memory_consumption(project_id=projectId, **data.dict())}, + {"key": "avg_cpu", "data": metrics.get_avg_cpu(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_fps, + "data": metrics.get_avg_fps(project_id=projectId, **data.dict())} + ] + results = sorted(results, key=lambda r: r["key"]) + return {"data": results} + + +@app.post('/{projectId}/dashboard/overview2', tags=["dashboard", "metrics"]) +@app.get('/{projectId}/dashboard/overview2', tags=["dashboard", "metrics"]) +def get_dashboard_group(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + results = [ + {"key": schemas.TemplatePredefinedKeys.count_sessions, + "data": metrics.get_processed_sessions(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_image_load_time, + "data": metrics.get_application_activity_avg_image_load_time(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_page_load_time, + "data": metrics.get_application_activity_avg_page_load_time(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_request_load_time, + "data": metrics.get_application_activity_avg_request_load_time(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_dom_content_load_start, + "data": metrics.get_page_metrics_avg_dom_content_load_start(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_first_contentful_pixel, + "data": metrics.get_page_metrics_avg_first_contentful_pixel(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_visited_pages, + "data": metrics.get_user_activity_avg_visited_pages(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_session_duration, + "data": metrics.get_user_activity_avg_session_duration(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_pages_dom_buildtime, + "data": metrics.get_pages_dom_build_time(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_pages_response_time, + "data": metrics.get_pages_response_time(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_response_time, + "data": metrics.get_top_metrics_avg_response_time(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_first_paint, + "data": metrics.get_top_metrics_avg_first_paint(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_dom_content_loaded, + "data": metrics.get_top_metrics_avg_dom_content_loaded(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_till_first_bit, + "data": metrics.get_top_metrics_avg_till_first_bit(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_time_to_interactive, + "data": metrics.get_top_metrics_avg_time_to_interactive(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.count_requests, + "data": metrics.get_top_metrics_count_requests(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_time_to_render, + "data": metrics.get_time_to_render(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_used_js_heap_size, + "data": metrics.get_memory_consumption(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_cpu, + "data": metrics.get_avg_cpu(project_id=projectId, **data.dict())}, + {"key": schemas.TemplatePredefinedKeys.avg_fps, + "data": metrics.get_avg_fps(project_id=projectId, **data.dict())} + ] + results = sorted(results, key=lambda r: r["key"]) + return {"data": results} diff --git a/ee/api/routers/subs/insights.py b/ee/api/routers/subs/insights.py new file mode 100644 index 000000000..aa3ca2674 --- /dev/null +++ b/ee/api/routers/subs/insights.py @@ -0,0 +1,110 @@ +from fastapi import Body + +import schemas +from chalicelib.core import insights +from or_dependencies import OR_scope +from routers.base import get_routers +from schemas_ee import Permissions + +public_app, app, app_apikey = get_routers([OR_scope(Permissions.metrics)]) + + +@app.post('/{projectId}/insights/journey', tags=["insights"]) +@app.get('/{projectId}/insights/journey', tags=["insights"]) +def get_insights_journey(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.journey(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/users_acquisition', tags=["insights"]) +@app.get('/{projectId}/insights/users_acquisition', tags=["insights"]) +def get_users_acquisition(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.users_acquisition(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/users_retention', tags=["insights"]) +@app.get('/{projectId}/insights/users_retention', tags=["insights"]) +def get_users_retention(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.users_retention(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/feature_retention', tags=["insights"]) +@app.get('/{projectId}/insights/feature_retention', tags=["insights"]) +def get_feature_rentention(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.feature_retention(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/feature_acquisition', tags=["insights"]) +@app.get('/{projectId}/insights/feature_acquisition', tags=["insights"]) +def get_feature_acquisition(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.feature_acquisition(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/feature_popularity_frequency', tags=["insights"]) +@app.get('/{projectId}/insights/feature_popularity_frequency', tags=["insights"]) +def get_feature_popularity_frequency(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.feature_popularity_frequency(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/feature_intensity', tags=["insights"]) +@app.get('/{projectId}/insights/feature_intensity', tags=["insights"]) +def get_feature_intensity(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.feature_intensity(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/feature_adoption', tags=["insights"]) +@app.get('/{projectId}/insights/feature_adoption', tags=["insights"]) +def get_feature_adoption(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.feature_adoption(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/feature_adoption_top_users', tags=["insights"]) +@app.get('/{projectId}/insights/feature_adoption_top_users', tags=["insights"]) +def get_feature_adoption(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.feature_adoption_top_users(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/users_active', tags=["insights"]) +@app.get('/{projectId}/insights/users_active', tags=["insights"]) +def get_users_active(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.users_active(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/users_power', tags=["insights"]) +@app.get('/{projectId}/insights/users_power', tags=["insights"]) +def get_users_power(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.users_power(project_id=projectId, **data.dict())} + + +@app.post('/{projectId}/insights/users_slipping', tags=["insights"]) +@app.get('/{projectId}/insights/users_slipping', tags=["insights"]) +def get_users_slipping(projectId: int, data: schemas.MetricPayloadSchema = Body(...)): + return {"data": insights.users_slipping(project_id=projectId, **data.dict())} + +# +# +# @app.route('/{projectId}/dashboard/{widget}/search', methods=['GET']) +# def get_dashboard_autocomplete(projectId:int, widget): +# params = app.current_request.query_params +# if params is None or params.get('q') is None or len(params.get('q')) == 0: +# return {"data": []} +# params['q'] = '^' + params['q'] +# +# if widget in ['performance']: +# data = dashboard.search(params.get('q', ''), params.get('type', ''), project_id=projectId, +# platform=params.get('platform', None), performance=True) +# elif widget in ['pages', 'pages_dom_buildtime', 'top_metrics', 'time_to_render', +# 'impacted_sessions_by_slow_pages', 'pages_response_time']: +# data = dashboard.search(params.get('q', ''), params.get('type', ''), project_id=projectId, +# platform=params.get('platform', None), pages_only=True) +# elif widget in ['resources_loading_time']: +# data = dashboard.search(params.get('q', ''), params.get('type', ''), project_id=projectId, +# platform=params.get('platform', None), performance=False) +# elif widget in ['time_between_events', 'events']: +# data = dashboard.search(params.get('q', ''), params.get('type', ''), project_id=projectId, +# platform=params.get('platform', None), performance=False, events_only=True) +# elif widget in ['metadata']: +# data = dashboard.search(params.get('q', ''), None, project_id=projectId, +# platform=params.get('platform', None), metadata=True, key=params.get("key")) +# else: +# return {"errors": [f"unsupported widget: {widget}"]} +# return {'data': data} diff --git a/ee/api/routers/subs/metrics.py b/ee/api/routers/subs/metrics.py new file mode 100644 index 000000000..2d296251b --- /dev/null +++ b/ee/api/routers/subs/metrics.py @@ -0,0 +1,238 @@ +from fastapi import Body, Depends + +import schemas +from chalicelib.core import dashboards, custom_metrics, funnels +from or_dependencies import OR_context, OR_scope +from routers.base import get_routers +from schemas_ee import Permissions + +public_app, app, app_apikey = get_routers([OR_scope(Permissions.metrics)]) + + +@app.post('/{projectId}/dashboards', tags=["dashboard"]) +@app.put('/{projectId}/dashboards', tags=["dashboard"]) +def create_dashboards(projectId: int, data: schemas.CreateDashboardSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return dashboards.create_dashboard(project_id=projectId, user_id=context.user_id, data=data) + + +@app.get('/{projectId}/dashboards', tags=["dashboard"]) +def get_dashboards(projectId: int, context: schemas.CurrentContext = Depends(OR_context)): + return {"data": dashboards.get_dashboards(project_id=projectId, user_id=context.user_id)} + + +@app.get('/{projectId}/dashboards/{dashboardId}', tags=["dashboard"]) +def get_dashboard(projectId: int, dashboardId: int, context: schemas.CurrentContext = Depends(OR_context)): + data = dashboards.get_dashboard(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId) + if data is None: + return {"errors": ["dashboard not found"]} + return {"data": data} + + +@app.post('/{projectId}/dashboards/{dashboardId}', tags=["dashboard"]) +@app.put('/{projectId}/dashboards/{dashboardId}', tags=["dashboard"]) +def update_dashboard(projectId: int, dashboardId: int, data: schemas.EditDashboardSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return {"data": dashboards.update_dashboard(project_id=projectId, user_id=context.user_id, + dashboard_id=dashboardId, data=data)} + + +@app.delete('/{projectId}/dashboards/{dashboardId}', tags=["dashboard"]) +def delete_dashboard(projectId: int, dashboardId: int, context: schemas.CurrentContext = Depends(OR_context)): + return dashboards.delete_dashboard(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId) + + +@app.get('/{projectId}/dashboards/{dashboardId}/pin', tags=["dashboard"]) +def pin_dashboard(projectId: int, dashboardId: int, context: schemas.CurrentContext = Depends(OR_context)): + return {"data": dashboards.pin_dashboard(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId)} + + +@app.post('/{projectId}/dashboards/{dashboardId}/widgets', tags=["dashboard"]) +@app.put('/{projectId}/dashboards/{dashboardId}/widgets', tags=["dashboard"]) +def add_widget_to_dashboard(projectId: int, dashboardId: int, + data: schemas.AddWidgetToDashboardPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return {"data": dashboards.add_widget(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId, + data=data)} + + +@app.post('/{projectId}/dashboards/{dashboardId}/metrics', tags=["dashboard"]) +@app.put('/{projectId}/dashboards/{dashboardId}/metrics', tags=["dashboard"]) +def create_metric_and_add_to_dashboard(projectId: int, dashboardId: int, + data: schemas.CreateCustomMetricsSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return {"data": dashboards.create_metric_add_widget(project_id=projectId, user_id=context.user_id, + dashboard_id=dashboardId, data=data)} + + +@app.post('/{projectId}/dashboards/{dashboardId}/widgets/{widgetId}', tags=["dashboard"]) +@app.put('/{projectId}/dashboards/{dashboardId}/widgets/{widgetId}', tags=["dashboard"]) +def update_widget_in_dashboard(projectId: int, dashboardId: int, widgetId: int, + data: schemas.UpdateWidgetPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return dashboards.update_widget(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId, + widget_id=widgetId, data=data) + + +@app.delete('/{projectId}/dashboards/{dashboardId}/widgets/{widgetId}', tags=["dashboard"]) +def remove_widget_from_dashboard(projectId: int, dashboardId: int, widgetId: int, + context: schemas.CurrentContext = Depends(OR_context)): + return dashboards.remove_widget(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId, + widget_id=widgetId) + + +@app.post('/{projectId}/dashboards/{dashboardId}/widgets/{widgetId}/chart', tags=["dashboard"]) +def get_widget_chart(projectId: int, dashboardId: int, widgetId: int, + data: schemas.CustomMetricChartPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = dashboards.make_chart_widget(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId, + widget_id=widgetId, data=data) + if data is None: + return {"errors": ["widget not found"]} + return {"data": data} + + +@app.get('/{projectId}/metrics/templates', tags=["dashboard"]) +def get_templates(projectId: int, context: schemas.CurrentContext = Depends(OR_context)): + return {"data": dashboards.get_templates(project_id=projectId, user_id=context.user_id)} + + +@app.post('/{projectId}/metrics/try', tags=["dashboard"]) +@app.put('/{projectId}/metrics/try', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/try', tags=["customMetrics"]) +@app.put('/{projectId}/custom_metrics/try', tags=["customMetrics"]) +def try_custom_metric(projectId: int, data: schemas.TryCustomMetricsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return {"data": custom_metrics.merged_live(project_id=projectId, data=data, user_id=context.user_id)} + + +@app.post('/{projectId}/metrics/try/sessions', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/try/sessions', tags=["customMetrics"]) +def try_custom_metric_sessions(projectId: int, data: schemas.CustomMetricSessionsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = custom_metrics.try_sessions(project_id=projectId, user_id=context.user_id, data=data) + return {"data": data} + + +@app.post('/{projectId}/metrics/try/issues', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/try/issues', tags=["customMetrics"]) +def try_custom_metric_funnel_issues(projectId: int, data: schemas.CustomMetricSessionsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + if len(data.series) == 0: + return {"data": []} + data.series[0].filter.startDate = data.startTimestamp + data.series[0].filter.endDate = data.endTimestamp + data = funnels.get_issues_on_the_fly_widget(project_id=projectId, data=data.series[0].filter) + return {"data": data} + + +@app.post('/{projectId}/metrics', tags=["dashboard"]) +@app.put('/{projectId}/metrics', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics', tags=["customMetrics"]) +@app.put('/{projectId}/custom_metrics', tags=["customMetrics"]) +def add_custom_metric(projectId: int, data: schemas.CreateCustomMetricsSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return custom_metrics.create(project_id=projectId, user_id=context.user_id, data=data) + + +@app.get('/{projectId}/metrics', tags=["dashboard"]) +@app.get('/{projectId}/custom_metrics', tags=["customMetrics"]) +def get_custom_metrics(projectId: int, context: schemas.CurrentContext = Depends(OR_context)): + return {"data": custom_metrics.get_all(project_id=projectId, user_id=context.user_id)} + + +@app.get('/{projectId}/metrics/{metric_id}', tags=["dashboard"]) +@app.get('/{projectId}/custom_metrics/{metric_id}', tags=["customMetrics"]) +def get_custom_metric(projectId: int, metric_id: str, context: schemas.CurrentContext = Depends(OR_context)): + data = custom_metrics.get(project_id=projectId, user_id=context.user_id, metric_id=metric_id) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} + + +@app.post('/{projectId}/metrics/{metric_id}/sessions', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/{metric_id}/sessions', tags=["customMetrics"]) +def get_custom_metric_sessions(projectId: int, metric_id: int, + data: schemas.CustomMetricSessionsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = custom_metrics.get_sessions(project_id=projectId, user_id=context.user_id, metric_id=metric_id, data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} + + +@app.post('/{projectId}/metrics/{metric_id}/issues', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/{metric_id}/issues', tags=["customMetrics"]) +def get_custom_metric_funnel_issues(projectId: int, metric_id: int, + data: schemas.CustomMetricSessionsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = custom_metrics.get_funnel_issues(project_id=projectId, user_id=context.user_id, metric_id=metric_id, + data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} + + +@app.post('/{projectId}/metrics/{metric_id}/issues/{issueId}/sessions', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/{metric_id}/issues/{issueId}/sessions', tags=["customMetrics"]) +def get_metric_funnel_issue_sessions(projectId: int, metric_id: int, issueId: str, + data: schemas.CustomMetricSessionsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = custom_metrics.get_funnel_sessions_by_issue(project_id=projectId, user_id=context.user_id, + metric_id=metric_id, issue_id=issueId, data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} + + +@app.post('/{projectId}/metrics/{metric_id}/errors', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/{metric_id}/errors', tags=["customMetrics"]) +def get_custom_metric_errors_list(projectId: int, metric_id: int, + data: schemas.CustomMetricSessionsPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = custom_metrics.get_errors_list(project_id=projectId, user_id=context.user_id, metric_id=metric_id, + data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} + + +@app.post('/{projectId}/metrics/{metric_id}/chart', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/{metric_id}/chart', tags=["customMetrics"]) +def get_custom_metric_chart(projectId: int, metric_id: int, data: schemas.CustomMetricChartPayloadSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = dashboards.make_chart_metrics(project_id=projectId, user_id=context.user_id, metric_id=metric_id, + data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} + + +@app.post('/{projectId}/metrics/{metric_id}', tags=["dashboard"]) +@app.put('/{projectId}/metrics/{metric_id}', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/{metric_id}', tags=["customMetrics"]) +@app.put('/{projectId}/custom_metrics/{metric_id}', tags=["customMetrics"]) +def update_custom_metric(projectId: int, metric_id: int, data: schemas.UpdateCustomMetricsSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + data = custom_metrics.update(project_id=projectId, user_id=context.user_id, metric_id=metric_id, data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} + + +@app.post('/{projectId}/metrics/{metric_id}/status', tags=["dashboard"]) +@app.put('/{projectId}/metrics/{metric_id}/status', tags=["dashboard"]) +@app.post('/{projectId}/custom_metrics/{metric_id}/status', tags=["customMetrics"]) +@app.put('/{projectId}/custom_metrics/{metric_id}/status', tags=["customMetrics"]) +def update_custom_metric_state(projectId: int, metric_id: int, + data: schemas.UpdateCustomMetricsStatusSchema = Body(...), + context: schemas.CurrentContext = Depends(OR_context)): + return { + "data": custom_metrics.change_state(project_id=projectId, user_id=context.user_id, metric_id=metric_id, + status=data.active)} + + +@app.delete('/{projectId}/metrics/{metric_id}', tags=["dashboard"]) +@app.delete('/{projectId}/custom_metrics/{metric_id}', tags=["customMetrics"]) +def delete_custom_metric(projectId: int, metric_id: int, context: schemas.CurrentContext = Depends(OR_context)): + return {"data": custom_metrics.delete(project_id=projectId, user_id=context.user_id, metric_id=metric_id)} diff --git a/ee/api/schemas_ee.py b/ee/api/schemas_ee.py index 458bdc052..9690eb334 100644 --- a/ee/api/schemas_ee.py +++ b/ee/api/schemas_ee.py @@ -4,12 +4,26 @@ from pydantic import BaseModel, Field, EmailStr import schemas from chalicelib.utils.TimeUTC import TimeUTC +from enum import Enum + + +class Permissions(str, Enum): + session_replay = "SESSION_REPLAY" + dev_tools = "DEV_TOOLS" + # errors = "ERRORS" + metrics = "METRICS" + assist_live = "ASSIST_LIVE" + assist_call = "ASSIST_CALL" + + +class CurrentContext(schemas.CurrentContext): + permissions: List[Optional[Permissions]] = Field(...) class RolePayloadSchema(BaseModel): name: str = Field(...) description: Optional[str] = Field(None) - permissions: List[str] = Field(...) + permissions: List[Permissions] = Field(...) all_projects: bool = Field(True) projects: List[int] = Field([]) diff --git a/ee/backend/internal/db/datasaver/messages.go b/ee/backend/internal/db/datasaver/messages.go index 3187a0c91..f28bd3b8f 100644 --- a/ee/backend/internal/db/datasaver/messages.go +++ b/ee/backend/internal/db/datasaver/messages.go @@ -3,31 +3,40 @@ package datasaver import ( "fmt" "log" - "openreplay/backend/pkg/messages" + . "openreplay/backend/pkg/messages" ) -func (mi *Saver) InsertMessage(sessionID uint64, msg messages.Message) error { +func (mi *Saver) InsertMessage(msg Message) error { + sessionID := msg.SessionID() switch m := msg.(type) { // Common - case *messages.Metadata: + case *Metadata: if err := mi.pg.InsertMetadata(sessionID, m); err != nil { return fmt.Errorf("insert metadata err: %s", err) } return nil - case *messages.IssueEvent: + case *IssueEvent: + session, err := mi.pg.GetSession(sessionID) + if err != nil { + log.Printf("can't get session info for CH: %s", err) + } else { + if err := mi.ch.InsertIssue(session, m); err != nil { + log.Printf("can't insert issue event into clickhouse: %s", err) + } + } return mi.pg.InsertIssueEvent(sessionID, m) //TODO: message adapter (transformer) (at the level of pkg/message) for types: *IOSMetadata, *IOSIssueEvent and others // Web - case *messages.SessionStart: + case *SessionStart: return mi.pg.HandleWebSessionStart(sessionID, m) - case *messages.SessionEnd: + case *SessionEnd: return mi.pg.HandleWebSessionEnd(sessionID, m) - case *messages.UserID: + case *UserID: return mi.pg.InsertWebUserID(sessionID, m) - case *messages.UserAnonymousID: + case *UserAnonymousID: return mi.pg.InsertWebUserAnonymousID(sessionID, m) - case *messages.CustomEvent: + case *CustomEvent: session, err := mi.pg.GetSession(sessionID) if err != nil { log.Printf("can't get session info for CH: %s", err) @@ -37,17 +46,19 @@ func (mi *Saver) InsertMessage(sessionID uint64, msg messages.Message) error { } } return mi.pg.InsertWebCustomEvent(sessionID, m) - case *messages.ClickEvent: + case *ClickEvent: return mi.pg.InsertWebClickEvent(sessionID, m) - case *messages.InputEvent: + case *InputEvent: return mi.pg.InsertWebInputEvent(sessionID, m) // Unique Web messages - case *messages.PageEvent: + case *PageEvent: return mi.pg.InsertWebPageEvent(sessionID, m) - case *messages.ErrorEvent: - return mi.pg.InsertWebErrorEvent(sessionID, m) - case *messages.FetchEvent: + case *JSException: + return mi.pg.InsertWebJSException(m) + case *IntegrationEvent: + return mi.pg.InsertWebIntegrationEvent(m) + case *FetchEvent: session, err := mi.pg.GetSession(sessionID) if err != nil { log.Printf("can't get session info for CH: %s", err) @@ -62,7 +73,7 @@ func (mi *Saver) InsertMessage(sessionID uint64, msg messages.Message) error { } } return mi.pg.InsertWebFetchEvent(sessionID, m) - case *messages.GraphQLEvent: + case *GraphQLEvent: session, err := mi.pg.GetSession(sessionID) if err != nil { log.Printf("can't get session info for CH: %s", err) @@ -72,39 +83,30 @@ func (mi *Saver) InsertMessage(sessionID uint64, msg messages.Message) error { } } return mi.pg.InsertWebGraphQLEvent(sessionID, m) - case *messages.IntegrationEvent: - return mi.pg.InsertWebErrorEvent(sessionID, &messages.ErrorEvent{ - MessageID: m.Meta().Index, - Timestamp: m.Timestamp, - Source: m.Source, - Name: m.Name, - Message: m.Message, - Payload: m.Payload, - }) - case *messages.SetPageLocation: + case *SetPageLocation: return mi.pg.InsertSessionReferrer(sessionID, m.Referrer) // IOS - case *messages.IOSSessionStart: + case *IOSSessionStart: return mi.pg.InsertIOSSessionStart(sessionID, m) - case *messages.IOSSessionEnd: + case *IOSSessionEnd: return mi.pg.InsertIOSSessionEnd(sessionID, m) - case *messages.IOSUserID: + case *IOSUserID: return mi.pg.InsertIOSUserID(sessionID, m) - case *messages.IOSUserAnonymousID: + case *IOSUserAnonymousID: return mi.pg.InsertIOSUserAnonymousID(sessionID, m) - case *messages.IOSCustomEvent: + case *IOSCustomEvent: return mi.pg.InsertIOSCustomEvent(sessionID, m) - case *messages.IOSClickEvent: + case *IOSClickEvent: return mi.pg.InsertIOSClickEvent(sessionID, m) - case *messages.IOSInputEvent: + case *IOSInputEvent: return mi.pg.InsertIOSInputEvent(sessionID, m) // Unique IOS messages - case *messages.IOSNetworkCall: + case *IOSNetworkCall: return mi.pg.InsertIOSNetworkCall(sessionID, m) - case *messages.IOSScreenEnter: + case *IOSScreenEnter: return mi.pg.InsertIOSScreenEnter(sessionID, m) - case *messages.IOSCrash: + case *IOSCrash: return mi.pg.InsertIOSCrash(sessionID, m) } diff --git a/ee/backend/internal/db/datasaver/stats.go b/ee/backend/internal/db/datasaver/stats.go index e018a2575..c18918c63 100644 --- a/ee/backend/internal/db/datasaver/stats.go +++ b/ee/backend/internal/db/datasaver/stats.go @@ -32,12 +32,14 @@ func (si *Saver) InsertStats(session *types.Session, msg messages.Message) error return si.ch.InsertWebPageEvent(session, m) case *messages.ResourceEvent: return si.ch.InsertWebResourceEvent(session, m) - case *messages.ErrorEvent: - return si.ch.InsertWebErrorEvent(session, m) + case *messages.JSException: + return si.ch.InsertWebErrorEvent(session, types.WrapJSException(m)) + case *messages.IntegrationEvent: + return si.ch.InsertWebErrorEvent(session, types.WrapIntegrationEvent(m)) } return nil } -func (si *Saver) CommitStats(optimize bool) error { +func (si *Saver) CommitStats() error { return si.ch.Commit() } diff --git a/ee/backend/internal/storage/encryptor.go b/ee/backend/internal/storage/encryptor.go new file mode 100644 index 000000000..457f45323 --- /dev/null +++ b/ee/backend/internal/storage/encryptor.go @@ -0,0 +1,65 @@ +package storage + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "errors" + "fmt" + "math/rand" +) + +const letterSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + +func GenerateEncryptionKey() []byte { + return append(generateRandomBytes(16), generateRandomBytes(16)...) +} + +func generateRandomBytes(size int) []byte { + b := make([]byte, size) + for i := range b { + b[i] = letterSet[rand.Int63()%int64(len(letterSet))] + } + return b +} + +func fillLastBlock(rawText []byte, blockSize int) []byte { + padding := blockSize - len(rawText)%blockSize + padText := bytes.Repeat([]byte{byte(padding)}, padding) + return append(rawText, padText...) +} + +func EncryptData(data, fullKey []byte) ([]byte, error) { + if len(fullKey) != 32 { + return nil, errors.New("wrong format of encryption key") + } + key, iv := fullKey[:16], fullKey[16:] + // Fill the last block of data by zeros + paddedData := fillLastBlock(data, aes.BlockSize) + // Create new AES cipher with CBC encryptor + block, err := aes.NewCipher(key) + if err != nil { + return nil, fmt.Errorf("cbc encryptor failed: %s", err) + } + mode := cipher.NewCBCEncrypter(block, iv) + // Encrypting data + ciphertext := make([]byte, len(paddedData)) + mode.CryptBlocks(ciphertext, paddedData) + // Return encrypted data + return ciphertext, nil +} + +func DecryptData(data, fullKey []byte) ([]byte, error) { + if len(fullKey) != 32 { + return nil, errors.New("wrong format of encryption key") + } + key, iv := fullKey[:16], fullKey[16:] + block, err := aes.NewCipher(key) + if err != nil { + return nil, fmt.Errorf("cbc encryptor failed: %s", err) + } + cbc := cipher.NewCBCDecrypter(block, iv) + res := make([]byte, len(data)) + cbc.CryptBlocks(res, data) + return res, nil +} diff --git a/ee/backend/pkg/db/clickhouse/bulk.go b/ee/backend/pkg/db/clickhouse/bulk.go new file mode 100644 index 000000000..706b66f68 --- /dev/null +++ b/ee/backend/pkg/db/clickhouse/bulk.go @@ -0,0 +1,55 @@ +package clickhouse + +import ( + "context" + "errors" + "fmt" + "log" + + "github.com/ClickHouse/clickhouse-go/v2/lib/driver" +) + +type Bulk interface { + Append(args ...interface{}) error + Send() error +} + +type bulkImpl struct { + conn driver.Conn + query string + values [][]interface{} +} + +func NewBulk(conn driver.Conn, query string) (Bulk, error) { + switch { + case conn == nil: + return nil, errors.New("clickhouse connection is empty") + case query == "": + return nil, errors.New("query is empty") + } + return &bulkImpl{ + conn: conn, + query: query, + values: make([][]interface{}, 0), + }, nil +} + +func (b *bulkImpl) Append(args ...interface{}) error { + b.values = append(b.values, args) + return nil +} + +func (b *bulkImpl) Send() error { + batch, err := b.conn.PrepareBatch(context.Background(), b.query) + if err != nil { + return fmt.Errorf("can't create new batch: %s", err) + } + for _, set := range b.values { + if err := batch.Append(set...); err != nil { + log.Printf("can't append value set to batch, err: %s", err) + log.Printf("failed query: %s", b.query) + } + } + b.values = make([][]interface{}, 0) + return batch.Send() +} diff --git a/ee/backend/pkg/db/clickhouse/connector.go b/ee/backend/pkg/db/clickhouse/connector.go index e15ca13b2..d882f793f 100644 --- a/ee/backend/pkg/db/clickhouse/connector.go +++ b/ee/backend/pkg/db/clickhouse/connector.go @@ -1,13 +1,11 @@ package clickhouse import ( - "context" "errors" "fmt" "github.com/ClickHouse/clickhouse-go/v2" "github.com/ClickHouse/clickhouse-go/v2/lib/driver" "log" - "math" "openreplay/backend/pkg/db/types" "openreplay/backend/pkg/hashid" "openreplay/backend/pkg/messages" @@ -18,54 +16,6 @@ import ( "openreplay/backend/pkg/license" ) -type Bulk interface { - Append(args ...interface{}) error - Send() error -} - -type bulkImpl struct { - conn driver.Conn - query string - values [][]interface{} -} - -func NewBulk(conn driver.Conn, query string) (Bulk, error) { - switch { - case conn == nil: - return nil, errors.New("clickhouse connection is empty") - case query == "": - return nil, errors.New("query is empty") - } - return &bulkImpl{ - conn: conn, - query: query, - values: make([][]interface{}, 0), - }, nil -} - -func (b *bulkImpl) Append(args ...interface{}) error { - b.values = append(b.values, args) - return nil -} - -func (b *bulkImpl) Send() error { - batch, err := b.conn.PrepareBatch(context.Background(), b.query) - if err != nil { - return fmt.Errorf("can't create new batch: %s", err) - } - for _, set := range b.values { - if err := batch.Append(set...); err != nil { - log.Printf("can't append value set to batch, err: %s", err) - log.Printf("failed query: %s", b.query) - } - } - b.values = make([][]interface{}, 0) - return batch.Send() -} - -var CONTEXT_MAP = map[uint64]string{0: "unknown", 1: "self", 2: "same-origin-ancestor", 3: "same-origin-descendant", 4: "same-origin", 5: "cross-origin-ancestor", 6: "cross-origin-descendant", 7: "cross-origin-unreachable", 8: "multiple-contexts"} -var CONTAINER_TYPE_MAP = map[uint64]string{0: "window", 1: "iframe", 2: "embed", 3: "object"} - type Connector interface { Prepare() error Commit() error @@ -74,12 +24,13 @@ type Connector interface { InsertWebPageEvent(session *types.Session, msg *messages.PageEvent) error InsertWebClickEvent(session *types.Session, msg *messages.ClickEvent) error InsertWebInputEvent(session *types.Session, msg *messages.InputEvent) error - InsertWebErrorEvent(session *types.Session, msg *messages.ErrorEvent) error + InsertWebErrorEvent(session *types.Session, msg *types.ErrorEvent) error InsertWebPerformanceTrackAggr(session *types.Session, msg *messages.PerformanceTrackAggr) error InsertAutocomplete(session *types.Session, msgType, msgValue string) error InsertRequest(session *types.Session, msg *messages.FetchEvent, savePayload bool) error InsertCustom(session *types.Session, msg *messages.CustomEvent) error InsertGraphQL(session *types.Session, msg *messages.GraphQLEvent) error + InsertIssue(session *types.Session, msg *messages.IssueEvent) error } type connectorImpl struct { @@ -131,11 +82,13 @@ var batches = map[string]string{ "pages": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, url, request_start, response_start, response_end, dom_content_loaded_event_start, dom_content_loaded_event_end, load_event_start, load_event_end, first_paint, first_contentful_paint_time, speed_index, visually_complete, time_to_interactive, event_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "clicks": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, label, hesitation_time, event_type) VALUES (?, ?, ?, ?, ?, ?, ?)", "inputs": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, label, event_type) VALUES (?, ?, ?, ?, ?, ?)", - "errors": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, source, name, message, error_id, event_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", + "errors": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, source, name, message, error_id, event_type, error_tags_keys, error_tags_values) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "performance": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, url, min_fps, avg_fps, max_fps, min_cpu, avg_cpu, max_cpu, min_total_js_heap_size, avg_total_js_heap_size, max_total_js_heap_size, min_used_js_heap_size, avg_used_js_heap_size, max_used_js_heap_size, event_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "requests": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, url, request_body, response_body, status, method, duration, success, event_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "custom": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, name, payload, event_type) VALUES (?, ?, ?, ?, ?, ?, ?)", "graphql": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, name, request_body, response_body, event_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + "issuesEvents": "INSERT INTO experimental.events (session_id, project_id, message_id, datetime, issue_id, issue_type, event_type) VALUES (?, ?, ?, ?, ?, ?, ?)", + "issues": "INSERT INTO experimental.issues (project_id, issue_id, type, context_string) VALUES (?, ?, ?, ?)", } func (c *connectorImpl) Prepare() error { @@ -162,6 +115,39 @@ func (c *connectorImpl) checkError(name string, err error) { } } +func (c *connectorImpl) InsertIssue(session *types.Session, msg *messages.IssueEvent) error { + issueID := hashid.IssueID(session.ProjectID, msg) + // Check issue type before insert to avoid panic from clickhouse lib + switch msg.Type { + case "click_rage", "dead_click", "excessive_scrolling", "bad_request", "missing_resource", "memory", "cpu", "slow_resource", "slow_page_load", "crash", "ml_cpu", "ml_memory", "ml_dead_click", "ml_click_rage", "ml_mouse_thrashing", "ml_excessive_scrolling", "ml_slow_resources", "custom", "js_exception": + default: + return fmt.Errorf("unknown issueType: %s", msg.Type) + } + // Insert issue event to batches + if err := c.batches["issuesEvents"].Append( + session.SessionID, + uint16(session.ProjectID), + msg.MessageID, + datetime(msg.Timestamp), + issueID, + msg.Type, + "ISSUE", + ); err != nil { + c.checkError("issuesEvents", err) + return fmt.Errorf("can't append to issuesEvents batch: %s", err) + } + if err := c.batches["issues"].Append( + uint16(session.ProjectID), + issueID, + msg.Type, + msg.ContextString, + ); err != nil { + c.checkError("issues", err) + return fmt.Errorf("can't append to issues batch: %s", err) + } + return nil +} + func (c *connectorImpl) InsertWebSession(session *types.Session) error { if session.Duration == nil { return errors.New("trying to insert session with nil duration") @@ -297,7 +283,13 @@ func (c *connectorImpl) InsertWebInputEvent(session *types.Session, msg *message return nil } -func (c *connectorImpl) InsertWebErrorEvent(session *types.Session, msg *messages.ErrorEvent) error { +func (c *connectorImpl) InsertWebErrorEvent(session *types.Session, msg *types.ErrorEvent) error { + keys, values := make([]string, 0, len(msg.Tags)), make([]*string, 0, len(msg.Tags)) + for k, v := range msg.Tags { + keys = append(keys, k) + values = append(values, v) + } + if err := c.batches["errors"].Append( session.SessionID, uint16(session.ProjectID), @@ -306,8 +298,10 @@ func (c *connectorImpl) InsertWebErrorEvent(session *types.Session, msg *message msg.Source, nullableString(msg.Name), msg.Message, - hashid.WebErrorID(session.ProjectID, msg), + msg.ID(session.ProjectID), "ERROR", + keys, + values, ); err != nil { c.checkError("errors", err) return fmt.Errorf("can't append to errors batch: %s", err) @@ -420,40 +414,3 @@ func (c *connectorImpl) InsertGraphQL(session *types.Session, msg *messages.Grap } return nil } - -func nullableUint16(v uint16) *uint16 { - var p *uint16 = nil - if v != 0 { - p = &v - } - return p -} - -func nullableUint32(v uint32) *uint32 { - var p *uint32 = nil - if v != 0 { - p = &v - } - return p -} - -func nullableString(v string) *string { - var p *string = nil - if v != "" { - p = &v - } - return p -} - -func datetime(timestamp uint64) time.Time { - t := time.Unix(int64(timestamp/1e3), 0) - // Temporal solution for not correct timestamps in performance messages - if t.Year() < 2022 || t.Year() > 2025 { - return time.Now() - } - return t -} - -func getSqIdx(messageID uint64) uint { - return uint(messageID % math.MaxInt32) -} diff --git a/ee/backend/pkg/db/clickhouse/insert_type.go b/ee/backend/pkg/db/clickhouse/insert_type.go new file mode 100644 index 000000000..b83898d6f --- /dev/null +++ b/ee/backend/pkg/db/clickhouse/insert_type.go @@ -0,0 +1,38 @@ +package clickhouse + +import ( + "time" +) + +func nullableUint16(v uint16) *uint16 { + var p *uint16 = nil + if v != 0 { + p = &v + } + return p +} + +func nullableUint32(v uint32) *uint32 { + var p *uint32 = nil + if v != 0 { + p = &v + } + return p +} + +func nullableString(v string) *string { + var p *string = nil + if v != "" { + p = &v + } + return p +} + +func datetime(timestamp uint64) time.Time { + t := time.Unix(int64(timestamp/1e3), 0) + // Temporal solution for not correct timestamps in performance messages + if t.Year() < 2022 || t.Year() > 2025 { + return time.Now() + } + return t +} diff --git a/ee/backend/pkg/failover/failover.go b/ee/backend/pkg/failover/failover.go index d69a2c86a..1b9321afc 100644 --- a/ee/backend/pkg/failover/failover.go +++ b/ee/backend/pkg/failover/failover.go @@ -8,7 +8,6 @@ import ( "openreplay/backend/pkg/messages" "openreplay/backend/pkg/queue" "openreplay/backend/pkg/queue/types" - "strconv" ) const numberOfPartitions = 16 @@ -55,19 +54,16 @@ func NewSessionFinder(cfg *config.Config, stg *storage.Storage) (SessionFinder, done: make(chan struct{}, 1), } finder.producer = queue.NewProducer(cfg.MessageSizeLimit, false) - finder.consumer = queue.NewMessageConsumer( + finder.consumer = queue.NewConsumer( cfg.GroupFailover, []string{ cfg.TopicFailover, }, - func(sessionID uint64, iter messages.Iterator, meta *types.Meta) { - for iter.Next() { - if iter.Type() == 127 { - m := iter.Message().Decode().(*messages.SessionSearch) - finder.findSession(sessionID, m.Timestamp, m.Partition) - } - } - }, + messages.NewMessageIterator( + func(msg messages.Message) { + m := msg.(*messages.SessionSearch) + finder.findSession(m.SessionID(), m.Timestamp, m.Partition) + }, []int{messages.MsgSessionSearch}, true), true, cfg.MessageSizeLimit, ) @@ -93,7 +89,9 @@ func (s *sessionFinderImpl) worker() { } func (s *sessionFinderImpl) findSession(sessionID, timestamp, partition uint64) { - err := s.storage.UploadKey(strconv.FormatUint(sessionID, 10), 5) + sessEnd := &messages.SessionEnd{Timestamp: timestamp} + sessEnd.SetSessionID(sessionID) + err := s.storage.UploadSessionFiles(sessEnd) if err == nil { log.Printf("found session: %d in partition: %d, original: %d", sessionID, partition, sessionID%numberOfPartitions) @@ -128,7 +126,7 @@ func (s *sessionFinderImpl) nextPartition(partition uint64) uint64 { // Create sessionSearch message and send it to queue func (s *sessionFinderImpl) sendSearchMessage(sessionID, timestamp, partition uint64) { msg := &messages.SessionSearch{Timestamp: timestamp, Partition: partition} - if err := s.producer.ProduceToPartition(s.topicName, partition, sessionID, messages.Encode(msg)); err != nil { + if err := s.producer.ProduceToPartition(s.topicName, partition, sessionID, msg.Encode()); err != nil { log.Printf("can't send SessionSearch to failover topic: %s; sessID: %d", err, sessionID) } } diff --git a/ee/backend/pkg/kafka/consumer.go b/ee/backend/pkg/kafka/consumer.go index ca37917f1..14f8d5a68 100644 --- a/ee/backend/pkg/kafka/consumer.go +++ b/ee/backend/pkg/kafka/consumer.go @@ -2,6 +2,7 @@ package kafka import ( "log" + "openreplay/backend/pkg/messages" "os" "time" @@ -9,16 +10,15 @@ import ( "gopkg.in/confluentinc/confluent-kafka-go.v1/kafka" "openreplay/backend/pkg/env" - "openreplay/backend/pkg/queue/types" ) type Message = kafka.Message type Consumer struct { - c *kafka.Consumer - messageHandler types.MessageHandler - commitTicker *time.Ticker - pollTimeout uint + c *kafka.Consumer + messageIterator messages.MessageIterator + commitTicker *time.Ticker + pollTimeout uint lastReceivedPrtTs map[int32]int64 } @@ -26,7 +26,7 @@ type Consumer struct { func NewConsumer( group string, topics []string, - messageHandler types.MessageHandler, + messageIterator messages.MessageIterator, autoCommit bool, messageSizeLimit int, ) *Consumer { @@ -47,6 +47,16 @@ func NewConsumer( kafkaConfig.SetKey("ssl.key.location", os.Getenv("KAFKA_SSL_KEY")) kafkaConfig.SetKey("ssl.certificate.location", os.Getenv("KAFKA_SSL_CERT")) } + + // Apply Kerberos configuration + if env.Bool("KAFKA_USE_KERBEROS") { + kafkaConfig.SetKey("security.protocol", "sasl_plaintext") + kafkaConfig.SetKey("sasl.mechanisms", "GSSAPI") + kafkaConfig.SetKey("sasl.kerberos.service.name", os.Getenv("KERBEROS_SERVICE_NAME")) + kafkaConfig.SetKey("sasl.kerberos.principal", os.Getenv("KERBEROS_PRINCIPAL")) + kafkaConfig.SetKey("sasl.kerberos.keytab", os.Getenv("KERBEROS_KEYTAB_LOCATION")) + } + c, err := kafka.NewConsumer(kafkaConfig) if err != nil { log.Fatalln(err) @@ -70,7 +80,7 @@ func NewConsumer( return &Consumer{ c: c, - messageHandler: messageHandler, + messageIterator: messageIterator, commitTicker: commitTicker, pollTimeout: 200, lastReceivedPrtTs: make(map[int32]int64), @@ -171,11 +181,14 @@ func (consumer *Consumer) ConsumeNext() error { return errors.Wrap(e.TopicPartition.Error, "Consumer Partition Error") } ts := e.Timestamp.UnixMilli() - consumer.messageHandler(decodeKey(e.Key), e.Value, &types.Meta{ - Topic: *(e.TopicPartition.Topic), - ID: uint64(e.TopicPartition.Offset), - Timestamp: ts, - }) + consumer.messageIterator.Iterate( + e.Value, + messages.NewBatchInfo( + decodeKey(e.Key), + *(e.TopicPartition.Topic), + uint64(e.TopicPartition.Offset), + uint64(e.TopicPartition.Partition), + ts)) consumer.lastReceivedPrtTs[e.TopicPartition.Partition] = ts case kafka.Error: if e.Code() == kafka.ErrAllBrokersDown || e.Code() == kafka.ErrMaxPollExceeded { @@ -194,16 +207,3 @@ func (consumer *Consumer) Close() { log.Printf("Kafka consumer close error: %v", err) } } - -func (consumer *Consumer) HasFirstPartition() bool { - assigned, err := consumer.c.Assignment() - if err != nil { - return false - } - for _, p := range assigned { - if p.Partition == 1 { - return true - } - } - return false -} diff --git a/ee/backend/pkg/kafka/producer.go b/ee/backend/pkg/kafka/producer.go index 6fb893b7a..f895241a7 100644 --- a/ee/backend/pkg/kafka/producer.go +++ b/ee/backend/pkg/kafka/producer.go @@ -30,6 +30,15 @@ func NewProducer(messageSizeLimit int, useBatch bool) *Producer { kafkaConfig.SetKey("ssl.key.location", os.Getenv("KAFKA_SSL_KEY")) kafkaConfig.SetKey("ssl.certificate.location", os.Getenv("KAFKA_SSL_CERT")) } + // Apply Kerberos configuration + if env.Bool("KAFKA_USE_KERBEROS") { + kafkaConfig.SetKey("security.protocol", "sasl_plaintext") + kafkaConfig.SetKey("sasl.mechanisms", "GSSAPI") + kafkaConfig.SetKey("sasl.kerberos.service.name", os.Getenv("KERBEROS_SERVICE_NAME")) + kafkaConfig.SetKey("sasl.kerberos.principal", os.Getenv("KERBEROS_PRINCIPAL")) + kafkaConfig.SetKey("sasl.kerberos.keytab", os.Getenv("KERBEROS_KEYTAB_LOCATION")) + } + producer, err := kafka.NewProducer(kafkaConfig) if err != nil { log.Fatalln(err) diff --git a/ee/backend/pkg/queue/import.go b/ee/backend/pkg/queue/import.go index a0c6a02f1..2aaf22f94 100644 --- a/ee/backend/pkg/queue/import.go +++ b/ee/backend/pkg/queue/import.go @@ -3,12 +3,13 @@ package queue import ( "openreplay/backend/pkg/kafka" "openreplay/backend/pkg/license" + "openreplay/backend/pkg/messages" "openreplay/backend/pkg/queue/types" ) -func NewConsumer(group string, topics []string, handler types.MessageHandler, autoCommit bool, messageSizeLimit int) types.Consumer { +func NewConsumer(group string, topics []string, iterator messages.MessageIterator, autoCommit bool, messageSizeLimit int) types.Consumer { license.CheckLicense() - return kafka.NewConsumer(group, topics, handler, autoCommit, messageSizeLimit) + return kafka.NewConsumer(group, topics, iterator, autoCommit, messageSizeLimit) } func NewProducer(messageSizeLimit int, useBatch bool) types.Producer { diff --git a/ee/connectors/deploy/requirements_bigquery.txt b/ee/connectors/deploy/requirements_bigquery.txt index 933c884b3..d4d63c953 100644 --- a/ee/connectors/deploy/requirements_bigquery.txt +++ b/ee/connectors/deploy/requirements_bigquery.txt @@ -1,7 +1,7 @@ kafka-python==2.0.2 -psycopg2-binary==2.8.6 -SQLAlchemy==1.3.23 +psycopg2-binary==2.9.3 +SQLAlchemy==1.4.43 google-cloud-bigquery -pandas==1.2.3 -PyYAML==5.4.1 -pandas-gbq==0.14.1 +pandas==1.5.1 +PyYAML +pandas-gbq diff --git a/ee/connectors/deploy/requirements_clickhouse.txt b/ee/connectors/deploy/requirements_clickhouse.txt index 15381bdad..b21ea36c5 100644 --- a/ee/connectors/deploy/requirements_clickhouse.txt +++ b/ee/connectors/deploy/requirements_clickhouse.txt @@ -1,14 +1,14 @@ -certifi==2020.12.5 -chardet==4.0.0 -clickhouse-driver==0.2.0 -clickhouse-sqlalchemy==0.1.5 -idna==2.10 +certifi==2022.09.24 +chardet==5.0.0 +clickhouse-driver==0.2.4 +clickhouse-sqlalchemy==0.2.2 +idna==3.4 kafka-python==2.0.2 -pandas==1.2.3 -pytz==2021.1 -requests==2.25.1 -SQLAlchemy==1.3.23 -tzlocal==2.1 -urllib3==1.26.5 -PyYAML==5.4.1 +pandas==1.5.1 +pytz==2022.6 +requests==2.28.1 +SQLAlchemy==1.4.43 +tzlocal +urllib3==1.26.12 +PyYAML diff --git a/ee/connectors/deploy/requirements_pg.txt b/ee/connectors/deploy/requirements_pg.txt index 12f72ec7d..09bf8b34d 100644 --- a/ee/connectors/deploy/requirements_pg.txt +++ b/ee/connectors/deploy/requirements_pg.txt @@ -1,12 +1,12 @@ -certifi==2020.12.5 -chardet==4.0.0 -idna==2.10 +certifi==2022.09.24 +chardet==5.0.0 +idna==3.4 kafka-python==2.0.2 -pandas==1.2.3 -psycopg2-binary==2.8.6 -pytz==2021.1 -requests==2.25.1 -SQLAlchemy==1.3.23 -tzlocal==2.1 -urllib3==1.26.5 -PyYAML==5.4.1 +pandas==1.5.1 +psycopg2-binary==2.9.3 +pytz==2022.6 +requests==2.28.1 +SQLAlchemy==1.4.43 +tzlocal +urllib3==1.26.12 +PyYAML diff --git a/ee/connectors/deploy/requirements_redshift.txt b/ee/connectors/deploy/requirements_redshift.txt index 42080cd4a..e4182cb92 100644 --- a/ee/connectors/deploy/requirements_redshift.txt +++ b/ee/connectors/deploy/requirements_redshift.txt @@ -1,15 +1,14 @@ -certifi==2020.12.5 -chardet==4.0.0 -clickhouse-driver==0.2.0 -clickhouse-sqlalchemy==0.1.5 -idna==2.10 +certifi==2022.09.24 +chardet==5.0.0 +clickhouse-driver==0.2.4 +clickhouse-sqlalchemy==0.2.2 +idna==3.4 kafka-python==2.0.2 -psycopg2-binary==2.8.6 -pytz==2021.1 -requests==2.25.1 -SQLAlchemy==1.3.23 -tzlocal==2.1 -urllib3==1.26.5 +psycopg2-binary==2.9.3 +pytz==2022.6 +requests==2.28.1 +SQLAlchemy==1.4.43 +tzlocal +urllib3==1.26.12 pandas-redshift PyYAML -awswrangler diff --git a/ee/connectors/deploy/requirements_snowflake.txt b/ee/connectors/deploy/requirements_snowflake.txt index cc81ec16c..895326b32 100644 --- a/ee/connectors/deploy/requirements_snowflake.txt +++ b/ee/connectors/deploy/requirements_snowflake.txt @@ -1,34 +1,33 @@ -pandas==1.2.3 +pandas==1.5.1 kafka-python==2.0.2 -SQLAlchemy==1.3.23 -snowflake-connector-python==2.4.1 -snowflake-sqlalchemy==1.2.4 -PyYAML==5.4.1 -asn1crypto==1.4.0 -azure-common==1.1.25 -azure-core==1.8.2 -azure-storage-blob==12.5.0 -boto3==1.15.18 -botocore==1.18.18 -certifi==2020.6.20 -cffi==1.14.3 -chardet==3.0.4 -cryptography==3.4.7 -idna==2.10 -isodate==0.6.0 -jmespath==0.10.0 -msrest==0.6.19 -oauthlib==3.1.0 -oscrypto==1.2.1 -pycparser==2.20 -pycryptodomex==3.9.8 -PyJWT==1.7.1 -pyOpenSSL==19.1.0 -python-dateutil==2.8.1 -pytz==2020.1 -requests==2.23.0 -requests-oauthlib==1.3.0 -s3transfer==0.3.3 -six==1.15.0 -urllib3==1.26.5 +SQLAlchemy==1.4.43 +snowflake-connector-python==2.8.2 +snowflake-sqlalchemy==1.4.4 +PyYAML +asn1crypto==1.5.1 +azure-common==1.1.28 +azure-core==1.26.1 +azure-storage-blob==12.14.1 +boto3==1.26.3 +botocore==1.29.3 +certifi==2022.09.24 +cffi==1.15.1 +chardet==5.0.0 +idna==3.4 +isodate +jmespath==1.0.1 +msrest==0.7.1 +oauthlib==3.2.2 +oscrypto==1.3.0 +pycparser==2.21 +pycryptodomex==3.15.0 +PyJWT==2.5.0 +pyOpenSSL==22.1.0 +python-dateutil==2.8.2 +pytz==2022.6 +requests==2.28.1 +requests-oauthlib==1.3.1 +s3transfer==0.6.0 +six==1.16.0 +urllib3==1.26.12 diff --git a/ee/connectors/msgcodec/messages.py b/ee/connectors/msgcodec/messages.py index e1fe393a4..41181d924 100644 --- a/ee/connectors/msgcodec/messages.py +++ b/ee/connectors/msgcodec/messages.py @@ -63,7 +63,7 @@ class SessionStart(Message): self.user_id = user_id -class SessionEnd(Message): +class SessionEndDeprecated(Message): __id__ = 3 def __init__(self, timestamp): @@ -213,15 +213,6 @@ class MouseMove(Message): self.y = y -class MouseClickDepricated(Message): - __id__ = 21 - - def __init__(self, id, hesitation_time, label): - self.id = id - self.hesitation_time = hesitation_time - self.label = label - - class ConsoleLog(Message): __id__ = 22 @@ -254,7 +245,7 @@ class PageRenderTiming(Message): self.time_to_interactive = time_to_interactive -class JSException(Message): +class JSExceptionDeprecated(Message): __id__ = 25 def __init__(self, name, message, payload): @@ -349,18 +340,6 @@ class ClickEvent(Message): self.selector = selector -class ErrorEvent(Message): - __id__ = 34 - - def __init__(self, message_id, timestamp, source, name, message, payload): - self.message_id = message_id - self.timestamp = timestamp - self.source = source - self.name = name - self.message = message - self.payload = payload - - class ResourceEvent(Message): __id__ = 35 @@ -589,6 +568,23 @@ class PerformanceTrackAggr(Message): self.max_used_js_heap_size = max_used_js_heap_size +class LoadFontFace(Message): + __id__ = 57 + + def __init__(self, parent_id, family, source, descriptors): + self.parent_id = parent_id + self.family = family + self.source = source + self.descriptors = descriptors + + +class SetNodeFocus(Message): + __id__ = 58 + + def __init__(self, id): + self.id = id + + class LongTask(Message): __id__ = 59 @@ -752,6 +748,32 @@ class Zustand(Message): self.state = state +class JSException(Message): + __id__ = 78 + + def __init__(self, name, message, payload, metadata): + self.name = name + self.message = message + self.payload = payload + self.metadata = metadata + + +class SessionEnd(Message): + __id__ = 126 + + def __init__(self, timestamp, encryption_key): + self.timestamp = timestamp + self.encryption_key = encryption_key + + +class SessionSearch(Message): + __id__ = 127 + + def __init__(self, timestamp, partition): + self.timestamp = timestamp + self.partition = partition + + class IOSBatchMeta(Message): __id__ = 107 diff --git a/ee/connectors/msgcodec/msgcodec.py b/ee/connectors/msgcodec/msgcodec.py index d53c3e75d..38bb6d3c2 100644 --- a/ee/connectors/msgcodec/msgcodec.py +++ b/ee/connectors/msgcodec/msgcodec.py @@ -124,7 +124,7 @@ class MessageCodec(Codec): ) if message_id == 3: - return SessionEnd( + return SessionEndDeprecated( timestamp=self.read_uint(reader) ) @@ -237,13 +237,6 @@ class MessageCodec(Codec): y=self.read_uint(reader) ) - if message_id == 21: - return MouseClickDepricated( - id=self.read_uint(reader), - hesitation_time=self.read_uint(reader), - label=self.read_string(reader) - ) - if message_id == 22: return ConsoleLog( level=self.read_string(reader), @@ -271,7 +264,7 @@ class MessageCodec(Codec): ) if message_id == 25: - return JSException( + return JSExceptionDeprecated( name=self.read_string(reader), message=self.read_string(reader), payload=self.read_string(reader) @@ -347,16 +340,6 @@ class MessageCodec(Codec): selector=self.read_string(reader) ) - if message_id == 34: - return ErrorEvent( - message_id=self.read_uint(reader), - timestamp=self.read_uint(reader), - source=self.read_string(reader), - name=self.read_string(reader), - message=self.read_string(reader), - payload=self.read_string(reader) - ) - if message_id == 35: return ResourceEvent( message_id=self.read_uint(reader), @@ -541,6 +524,19 @@ class MessageCodec(Codec): max_used_js_heap_size=self.read_uint(reader) ) + if message_id == 57: + return LoadFontFace( + parent_id=self.read_uint(reader), + family=self.read_string(reader), + source=self.read_string(reader), + descriptors=self.read_string(reader) + ) + + if message_id == 58: + return SetNodeFocus( + id=self.read_int(reader) + ) + if message_id == 59: return LongTask( timestamp=self.read_uint(reader), @@ -668,6 +664,26 @@ class MessageCodec(Codec): state=self.read_string(reader) ) + if message_id == 78: + return JSException( + name=self.read_string(reader), + message=self.read_string(reader), + payload=self.read_string(reader), + metadata=self.read_string(reader) + ) + + if message_id == 126: + return SessionEnd( + timestamp=self.read_uint(reader), + encryption_key=self.read_string(reader) + ) + + if message_id == 127: + return SessionSearch( + timestamp=self.read_uint(reader), + partition=self.read_uint(reader) + ) + if message_id == 107: return IOSBatchMeta( timestamp=self.read_uint(reader), diff --git a/ee/scripts/helm/db/clickhouse/Chart.yaml b/ee/scripts/helm/db/clickhouse/Chart.yaml deleted file mode 100644 index c7a0eb3d6..000000000 --- a/ee/scripts/helm/db/clickhouse/Chart.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v2 -name: clickhouse -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 1.16.0 diff --git a/ee/scripts/helm/db/clickhouse/templates/_helpers.tpl b/ee/scripts/helm/db/clickhouse/templates/_helpers.tpl deleted file mode 100644 index 44cfadff0..000000000 --- a/ee/scripts/helm/db/clickhouse/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "clickhouse.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "clickhouse.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "clickhouse.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "clickhouse.labels" -}} -helm.sh/chart: {{ include "clickhouse.chart" . }} -{{ include "clickhouse.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "clickhouse.selectorLabels" -}} -app.kubernetes.io/name: {{ include "clickhouse.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "clickhouse.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "clickhouse.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/ee/scripts/helm/db/clickhouse/templates/statefulset.yaml b/ee/scripts/helm/db/clickhouse/templates/statefulset.yaml deleted file mode 100644 index 392976eec..000000000 --- a/ee/scripts/helm/db/clickhouse/templates/statefulset.yaml +++ /dev/null @@ -1,69 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ include "clickhouse.fullname" . }} - labels: - {{- include "clickhouse.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.replicaCount }} - serviceName: {{ include "clickhouse.fullname" . }} - selector: - matchLabels: - {{- include "clickhouse.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "clickhouse.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "clickhouse.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }} - env: - {{- range $key, $value := .Values.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- end }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - containerPort: 9000 - name: web - - containerPort: 8123 - name: data - volumeMounts: - - name: ch-volume - mountPath: /var/lib/mydata - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - volumeClaimTemplates: - - metadata: - name: ch-volume - spec: - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: {{ .Values.storageSize }} diff --git a/ee/scripts/helm/db/clickhouse/values.yaml b/ee/scripts/helm/db/clickhouse/values.yaml deleted file mode 100644 index 4cba1c1f8..000000000 --- a/ee/scripts/helm/db/clickhouse/values.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# Default values for clickhouse. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -image: - repository: yandex/clickhouse-server - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "20.9" - -imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -podAnnotations: {} - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -env: {} - -service: - webPort: 9000 - dataPort: 8123 - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -nodeSelector: {} - -tolerations: [] - -affinity: {} -storageSize: 8G diff --git a/ee/scripts/helm/db/kafka/.helmignore b/ee/scripts/helm/db/kafka/.helmignore deleted file mode 100755 index f0c131944..000000000 --- a/ee/scripts/helm/db/kafka/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/ee/scripts/helm/db/kafka/Chart.yaml b/ee/scripts/helm/db/kafka/Chart.yaml deleted file mode 100755 index 165e70d55..000000000 --- a/ee/scripts/helm/db/kafka/Chart.yaml +++ /dev/null @@ -1,22 +0,0 @@ -annotations: - category: Infrastructure -apiVersion: v1 -appVersion: 2.6.0 -description: Apache Kafka is a distributed streaming platform. -engine: gotpl -home: https://github.com/bitnami/charts/tree/master/bitnami/kafka -icon: https://bitnami.com/assets/stacks/kafka/img/kafka-stack-110x117.png -keywords: -- kafka -- zookeeper -- streaming -- producer -- consumer -maintainers: -- email: containers@bitnami.com - name: Bitnami -name: kafka -sources: -- https://github.com/bitnami/bitnami-docker-kafka -- https://kafka.apache.org/ -version: 11.8.6 diff --git a/ee/scripts/helm/db/kafka/README.md b/ee/scripts/helm/db/kafka/README.md deleted file mode 100755 index 5584bd43d..000000000 --- a/ee/scripts/helm/db/kafka/README.md +++ /dev/null @@ -1,737 +0,0 @@ -# Kafka - -[Kafka](https://www.kafka.org/) is a distributed streaming platform used for building real-time data pipelines and streaming apps. It is horizontally scalable, fault-tolerant, wicked fast, and runs in production in thousands of companies. - -## TL;DR - -```console -helm repo add bitnami https://charts.bitnami.com/bitnami -helm install my-release bitnami/kafka -``` - -## Introduction - -This chart bootstraps a [Kafka](https://github.com/bitnami/bitnami-docker-kafka) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 2.12+ or Helm 3.0-beta3+ -- PV provisioner support in the underlying infrastructure - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -helm repo add bitnami https://charts.bitnami.com/bitnami -helm install my-release bitnami/kafka -``` - -These commands deploy Kafka on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```console -helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Parameters - -The following tables lists the configurable parameters of the Kafka chart and their default values per section/component: - -### Global parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `global.imageRegistry` | Global Docker image registry | `nil` | -| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | - -### Common parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `nameOverride` | String to partially override kafka.fullname | `nil` | -| `fullnameOverride` | String to fully override kafka.fullname | `nil` | -| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | -| `commonLabels` | Labels to add to all deployed objects | `{}` | -| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | -| `extraDeploy` | Array of extra objects to deploy with the release | `nil` (evaluated as a template) | - -### Kafka parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `image.registry` | Kafka image registry | `docker.io` | -| `image.repository` | Kafka image name | `bitnami/kafka` | -| `image.tag` | Kafka image tag | `{TAG_NAME}` | -| `image.pullPolicy` | Kafka image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `image.debug` | Set to true if you would like to see extra information on logs | `false` | -| `config` | Configuration file for Kafka. Auto-generated based on other parameters when not specified | `nil` | -| `existingConfigmap` | Name of existing ConfigMap with Kafka configuration | `nil` | -| `log4j` | An optional log4j.properties file to overwrite the default of the Kafka brokers. | `nil` | -| `existingLog4jConfigMap` | The name of an existing ConfigMap containing a log4j.properties file. | `nil` | -| `heapOpts` | Kafka's Java Heap size | `-Xmx1024m -Xms1024m` | -| `deleteTopicEnable` | Switch to enable topic deletion or not | `false` | -| `autoCreateTopicsEnable` | Switch to enable auto creation of topics. Enabling auto creation of topics not recommended for production or similar environments | `false` | -| `logFlushIntervalMessages` | The number of messages to accept before forcing a flush of data to disk | `10000` | -| `logFlushIntervalMs` | The maximum amount of time a message can sit in a log before we force a flush | `1000` | -| `logRetentionBytes` | A size-based retention policy for logs | `_1073741824` | -| `logRetentionCheckIntervalMs` | The interval at which log segments are checked to see if they can be deleted | `300000` | -| `logRetentionHours` | The minimum age of a log file to be eligible for deletion due to age | `168` | -| `logSegmentBytes` | The maximum size of a log segment file. When this size is reached a new log segment will be created | `_1073741824` | -| `logsDirs` | A comma separated list of directories under which to store log files | `/bitnami/kafka/data` | -| `maxMessageBytes` | The largest record batch size allowed by Kafka | `1000012` | -| `defaultReplicationFactor` | Default replication factors for automatically created topics | `1` | -| `offsetsTopicReplicationFactor` | The replication factor for the offsets topic | `1` | -| `transactionStateLogReplicationFactor` | The replication factor for the transaction topic | `1` | -| `transactionStateLogMinIsr` | Overridden min.insync.replicas config for the transaction topic | `1` | -| `numIoThreads` | The number of threads doing disk I/O | `8` | -| `numNetworkThreads` | The number of threads handling network requests | `3` | -| `numPartitions` | The default number of log partitions per topic | `1` | -| `numRecoveryThreadsPerDataDir` | The number of threads per data directory to be used for log recovery at startup and flushing at shutdown | `1` | -| `socketReceiveBufferBytes` | The receive buffer (SO_RCVBUF) used by the socket server | `102400` | -| `socketRequestMaxBytes` | The maximum size of a request that the socket server will accept (protection against OOM) | `_104857600` | -| `socketSendBufferBytes` | The send buffer (SO_SNDBUF) used by the socket server | `102400` | -| `zookeeperConnectionTimeoutMs` | Timeout in ms for connecting to Zookeeper | `6000` | -| `extraEnvVars` | Extra environment variables to add to kafka pods | `[]` | -| `extraVolumes` | Extra volume(s) to add to Kafka statefulset | `[]` | -| `extraVolumeMounts` | Extra volumeMount(s) to add to Kafka containers | `[]` | -| `auth.clientProtocol` | Authentication protocol for communications with clients. Allowed protocols: `plaintext`, `tls`, `mtls`, `sasl` and `sasl_tls` | `plaintext` | -| `auth.interBrokerProtocol` | Authentication protocol for inter-broker communications. Allowed protocols: `plaintext`, `tls`, `mtls`, `sasl` and `sasl_tls` | `plaintext` | -| `auth.saslMechanisms` | SASL mechanisms when either `auth.interBrokerProtocol` or `auth.clientProtocol` are `sasl`. Allowed types: `plain`, `scram-sha-256`, `scram-sha-512` | `plain,scram-sha-256,scram-sha-512` | -| `auth.saslInterBrokerMechanism` | SASL mechanism to use as inter broker protocol, it must be included at `auth.saslMechanisms` | `plain` | -| `auth.jksSecret` | Name of the existing secret containing the truststore and one keystore per Kafka broker you have in the cluster | `nil` | -| `auth.jksPassword` | Password to access the JKS files when they are password-protected | `nil` | -| `auth.tlsEndpointIdentificationAlgorithm` | The endpoint identification algorithm to validate server hostname using server certificate | `https` | -| `auth.jaas.interBrokerUser` | Kafka inter broker communication user for SASL authentication | `admin` | -| `auth.jaas.interBrokerPassword` | Kafka inter broker communication password for SASL authentication | `nil` | -| `auth.jaas.zookeeperUser` | Kafka Zookeeper user for SASL authentication | `nil` | -| `auth.jaas.zookeeperPassword` | Kafka Zookeeper password for SASL authentication | `nil` | -| `auth.jaas.existingSecret` | Name of the existing secret containing credentials for brokerUser, interBrokerUser and zookeeperUser | `nil` | -| `auth.jaas.clientUsers` | List of Kafka client users to be created, separated by commas. This values will override `auth.jaas.clientUser` | `[]` | -| `auth.jaas.clientPasswords` | List of passwords for `auth.jaas.clientUsers`. It is mandatory to provide the passwords when using `auth.jaas.clientUsers` | `[]` | -| `listeners` | The address(es) the socket server listens on. Auto-calculated it's set to an empty array | `[]` | -| `advertisedListeners` | The address(es) (hostname:port) the broker will advertise to producers and consumers. Auto-calculated it's set to an empty array | `[]` | -| `listenerSecurityProtocolMap` | The protocol->listener mapping. Auto-calculated it's set to nil | `nil` | -| `allowPlaintextListener` | Allow to use the PLAINTEXT listener | `true` | -| `interBrokerListenerName` | The listener that the brokers should communicate on | `INTERNAL` | - -### Statefulset parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `replicaCount` | Number of Kafka nodes | `1` | -| `updateStrategy` | Update strategy for the stateful set | `RollingUpdate` | -| `rollingUpdatePartition` | Partition update strategy | `nil` | -| `podLabels` | Kafka pod labels | `{}` (evaluated as a template) | -| `podAnnotations` | Kafka Pod annotations | `{}` (evaluated as a template) | -| `affinity` | Affinity for pod assignment | `{}` (evaluated as a template) | -| `priorityClassName` | Name of the existing priority class to be used by kafka pods | `""` | -| `nodeSelector` | Node labels for pod assignment | `{}` (evaluated as a template) | -| `tolerations` | Tolerations for pod assignment | `[]` (evaluated as a template) | -| `podSecurityContext` | Kafka pods' Security Context | `{}` | -| `containerSecurityContext` | Kafka containers' Security Context | `{}` | -| `resources.limits` | The resources limits for Kafka containers | `{}` | -| `resources.requests` | The requested resources for Kafka containers | `{}` | -| `livenessProbe` | Liveness probe configuration for Kafka | `Check values.yaml file` | -| `readinessProbe` | Readiness probe configuration for Kafka | `Check values.yaml file` | -| `customLivenessProbe` | Custom Liveness probe configuration for Kafka | `{}` | -| `customReadinessProbe` | Custom Readiness probe configuration for Kafka | `{}` | -| `pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` | -| `pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `nil` | -| `pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `1` | -| `command` | Override kafka container command | `['/scripts/setup.sh']` (evaluated as a template) | -| `args` | Override kafka container arguments | `[]` (evaluated as a template) | -| `sidecars` | Attach additional sidecar containers to the Kafka pod | `{}` | - -### Exposure parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `service.type` | Kubernetes Service type | `ClusterIP` | -| `service.port` | Kafka port for client connections | `9092` | -| `service.internalPort` | Kafka port for inter-broker connections | `9093` | -| `service.externalPort` | Kafka port for external connections | `9094` | -| `service.nodePorts.client` | Nodeport for client connections | `""` | -| `service.nodePorts.external` | Nodeport for external connections | `""` | -| `service.loadBalancerIP` | loadBalancerIP for Kafka Service | `nil` | -| `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | -| `service.annotations` | Service annotations | `{}`(evaluated as a template) | -| `externalAccess.enabled` | Enable Kubernetes external cluster access to Kafka brokers | `false` | -| `externalAccess.autoDiscovery.enabled` | Enable using an init container to auto-detect external IPs/ports by querying the K8s API | `false` | -| `externalAccess.autoDiscovery.image.registry` | Init container auto-discovery image registry (kubectl) | `docker.io` | -| `externalAccess.autoDiscovery.image.repository` | Init container auto-discovery image name (kubectl) | `bitnami/kubectl` | -| `externalAccess.autoDiscovery.image.tag` | Init container auto-discovery image tag (kubectl) | `{TAG_NAME}` | -| `externalAccess.autoDiscovery.image.pullPolicy` | Init container auto-discovery image pull policy (kubectl) | `Always` | -| `externalAccess.autoDiscovery.resources.limits` | Init container auto-discovery resource limits | `{}` | -| `externalAccess.autoDiscovery.resources.requests` | Init container auto-discovery resource requests | `{}` | -| `externalAccess.service.type` | Kubernetes Service type for external access. It can be NodePort or LoadBalancer | `LoadBalancer` | -| `externalAccess.service.port` | Kafka port used for external access when service type is LoadBalancer | `9094` | -| `externalAccess.service.loadBalancerIPs` | Array of load balancer IPs for Kafka brokers | `[]` | -| `externalAccess.service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | -| `externalAccess.service.domain` | Domain or external ip used to configure Kafka external listener when service type is NodePort | `nil` | -| `externalAccess.service.nodePorts` | Array of node ports used to configure Kafka external listener when service type is NodePort | `[]` | -| `externalAccess.service.annotations` | Service annotations for external access | `{}`(evaluated as a template) | - -### Persistence parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `persistence.enabled` | Enable Kafka data persistence using PVC, note that Zookeeper persistence is unaffected | `true` | -| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim`, the value is evaluated as a template | `nil` | -| `persistence.storageClass` | PVC Storage Class for Kafka data volume | `nil` | -| `persistence.accessMode` | PVC Access Mode for Kafka data volume | `ReadWriteOnce` | -| `persistence.size` | PVC Storage Request for Kafka data volume | `8Gi` | -| `persistence.annotations` | Annotations for the PVC | `{}`(evaluated as a template) | - -### RBAC parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `serviceAccount.create` | Enable creation of ServiceAccount for Kafka pods | `true` | -| `serviceAccount.name` | Name of the created serviceAccount | Generated using the `kafka.fullname` template | -| `rbac.create` | Weather to create & use RBAC resources or not | `false` | - -### Volume Permissions parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | -| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | -| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/minideb` | -| `volumePermissions.image.tag` | Init container volume-permissions image tag | `buster` | -| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | -| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `volumePermissions.resources.limits` | Init container volume-permissions resource limits | `{}` | -| `volumePermissions.resources.requests` | Init container volume-permissions resource requests | `{}` | - -### Metrics parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `metrics.kafka.enabled` | Whether or not to create a standalone Kafka exporter to expose Kafka metrics | `false` | -| `metrics.kafka.image.registry` | Kafka exporter image registry | `docker.io` | -| `metrics.kafka.image.repository` | Kafka exporter image name | `bitnami/kafka-exporter` | -| `metrics.kafka.image.tag` | Kafka exporter image tag | `{TAG_NAME}` | -| `metrics.kafka.image.pullPolicy` | Kafka exporter image pull policy | `IfNotPresent` | -| `metrics.kafka.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `metrics.kafka.extraFlags` | Extra flags to be passed to Kafka exporter | `{}` | -| `metrics.kafka.certificatesSecret` | Name of the existing secret containing the optional certificate and key files | `nil` | -| `metrics.kafka.resources.limits` | Kafka Exporter container resource limits | `{}` | -| `metrics.kafka.resources.requests` | Kafka Exporter container resource requests | `{}` | -| `metrics.kafka.service.type` | Kubernetes service type (`ClusterIP`, `NodePort` or `LoadBalancer`) for Kafka Exporter | `ClusterIP` | -| `metrics.kafka.service.port` | Kafka Exporter Prometheus port | `9308` | -| `metrics.kafka.service.nodePort` | Kubernetes HTTP node port | `""` | -| `metrics.kafka.service.annotations` | Annotations for Prometheus metrics service | `Check values.yaml file` | -| `metrics.kafka.service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` | -| `metrics.kafka.service.clusterIP` | Static clusterIP or None for headless services | `nil` | -| `metrics.jmx.enabled` | Whether or not to expose JMX metrics to Prometheus | `false` | -| `metrics.jmx.image.registry` | JMX exporter image registry | `docker.io` | -| `metrics.jmx.image.repository` | JMX exporter image name | `bitnami/jmx-exporter` | -| `metrics.jmx.image.tag` | JMX exporter image tag | `{TAG_NAME}` | -| `metrics.jmx.image.pullPolicy` | JMX exporter image pull policy | `IfNotPresent` | -| `metrics.jmx.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `metrics.jmx.resources.limits` | JMX Exporter container resource limits | `{}` | -| `metrics.jmx.resources.requests` | JMX Exporter container resource requests | `{}` | -| `metrics.jmx.service.type` | Kubernetes service type (`ClusterIP`, `NodePort` or `LoadBalancer`) for JMX Exporter | `ClusterIP` | -| `metrics.jmx.service.port` | JMX Exporter Prometheus port | `5556` | -| `metrics.jmx.service.nodePort` | Kubernetes HTTP node port | `""` | -| `metrics.jmx.service.annotations` | Annotations for Prometheus metrics service | `Check values.yaml file` | -| `metrics.jmx.service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` | -| `metrics.jmx.service.clusterIP` | Static clusterIP or None for headless services | `nil` | -| `metrics.jmx.whitelistObjectNames` | Allows setting which JMX objects you want to expose to via JMX stats to JMX Exporter | (see `values.yaml`) | -| `metrics.jmx.config` | Configuration file for JMX exporter | (see `values.yaml`) | -| `metrics.jmx.existingConfigmap` | Name of existing ConfigMap with JMX exporter configuration | `nil` | -| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (requires `metrics.kafka.enabled` or `metrics.jmx.enabled` to be `true`) | `false` | -| `metrics.serviceMonitor.namespace` | Namespace which Prometheus is running in | `monitoring` | -| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped | `nil` | -| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `nil` (Prometheus Operator default value) | -| `metrics.serviceMonitor.selector` | ServiceMonitor selector labels | `nil` (Prometheus Operator default value) | - -### Zookeeper chart parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `zookeeper.enabled` | Switch to enable or disable the Zookeeper helm chart | `true` | -| `zookeeper.persistence.enabled` | Enable Zookeeper persistence using PVC | `true` | -| `externalZookeeper.servers` | Server or list of external Zookeeper servers to use | `[]` | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, - -```console -helm install my-release \ - --set replicaCount=3 \ - bitnami/kafka -``` - -The above command deploys Kafka with 3 brokers (replicas). - -Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, - -```console -helm install my-release -f values.yaml bitnami/kafka -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -## Configuration and installation details - -### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) - -It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. - -Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. - -### Production configuration and horizontal scaling - -This chart includes a `values-production.yaml` file where you can find some parameters oriented to production configuration in comparison to the regular `values.yaml`. You can use this file instead of the default one. - -- Number of Kafka nodes: - -```diff -- replicaCount: 1 -+ replicaCount: 3 -``` - -- Allow to use the PLAINTEXT listener: - -```diff -- allowPlaintextListener: true -+ allowPlaintextListener: false -``` - -- Default replication factors for automatically created topics: - -```diff -- defaultReplicationFactor: 1 -+ defaultReplicationFactor: 3 -``` - -- Allow auto creation of topics. - -```diff -- autoCreateTopicsEnable: true -+ autoCreateTopicsEnable: false -``` - -- The replication factor for the offsets topic: - -```diff -- offsetsTopicReplicationFactor: 1 -+ offsetsTopicReplicationFactor: 3 -``` - -- The replication factor for the transaction topic: - -```diff -- transactionStateLogReplicationFactor: 1 -+ transactionStateLogReplicationFactor: 3 -``` - -- Overridden min.insync.replicas config for the transaction topic: - -```diff -- transactionStateLogMinIsr: 1 -+ transactionStateLogMinIsr: 3 -``` - -- Switch to enable the Kafka SASAL authentication on client and inter-broker communications: - -```diff -- auth.clientProtocol: plaintext -+ auth.clientProtocol: sasl -- auth.interBrokerProtocol: plaintext -+ auth.interBrokerProtocol: sasl -``` - -- Enable Zookeeper authentication: - -```diff -+ auth.jaas.zookeeperUser: zookeeperUser -+ auth.jaas.zookeeperPassword: zookeeperPassword -- zookeeper.auth.enabled: false -+ zookeeper.auth.enabled: true -+ zookeeper.auth.clientUser: zookeeperUser -+ zookeeper.auth.clientPassword: zookeeperPassword -+ zookeeper.auth.serverUsers: zookeeperUser -+ zookeeper.auth.serverPasswords: zookeeperPassword -``` - -- Enable Pod Disruption Budget: - -```diff -- pdb.create: false -+ pdb.create: true -``` - -- Create a separate Kafka metrics exporter: - -```diff -- metrics.kafka.enabled: false -+ metrics.kafka.enabled: true -``` - -- Expose JMX metrics to Prometheus: - -```diff -- metrics.jmx.enabled: false -+ metrics.jmx.enabled: true -``` - -- Enable Zookeeper metrics: - -```diff -+ zookeeper.metrics.enabled: true -``` - -To horizontally scale this chart once it has been deployed, you can upgrade the statefulset using a new value for the `replicaCount` parameter. Please note that, when enabling TLS encryption, you must update your JKS secret including the keystore for the new replicas. - -### Setting custom parameters - -Any environment variable beginning with `KAFKA_CFG_` will be mapped to its corresponding Kafka key. For example, use `KAFKA_CFG_BACKGROUND_THREADS` in order to set `background.threads`. In order to pass custom environment variables use the `extraEnvVars` property. - -### Listeners configuration - -This chart allows you to automatically configure Kafka with 3 listeners: - -- One for inter-broker communications. -- A second one for communications with clients within the K8s cluster. -- (optional) a third listener for communications with clients outside the K8s cluster. Check [this section](#accessing-kafka-brokers-from-outside-the-clusters) for more information. - -For more complex configurations, set the `listeners`, `advertisedListeners` and `listenerSecurityProtocolMap` parameters as needed. - -### Enable security for Kafka and Zookeeper - -You can configure different authentication protocols for each listener you configure in Kafka. For instance, you can use `sasl_tls` authentication for client communications, while using `tls` for inter-broker communications. This table shows the available protocols and the security they provide: - -| Method | Authentication | Encryption via TLS | -|-----------|-------------------------------|--------------------| -| plaintext | None | No | -| tls | None | Yes | -| mtls | Yes (two-way authentication) | Yes | -| sasl | Yes (via SASL) | No | -| sasl_tls | Yes (via SASL) | Yes | - -If you enabled SASL authentication on any listener, you can set the SASL credentials using the parameters below: - -- `auth.jaas.clientUsers`/`auth.jaas.clientPasswords`: when enabling SASL authentication for communications with clients. -- `auth.jaas.interBrokerUser`/`auth.jaas.interBrokerPassword`: when enabling SASL authentication for inter-broker communications. -- `auth.jaas.zookeeperUser`/`auth.jaas.zookeeperPassword`: In the case that the Zookeeper chart is deployed with SASL authentication enabled. - -In order to configure TLS authentication/encryption, you **must** create a secret containing the Java Key Stores (JKS) files: the truststore (`kafka.truststore.jks`) and one keystore (`kafka.keystore.jks`) per Kafka broker you have in the cluster. Then, you need pass the secret name with the `--auth.jksSecret` parameter when deploying the chart. - -> **Note**: If the JKS files are password protected (recommended), you will need to provide the password to get access to the keystores. To do so, use the `auth.jksPassword` parameter to provide your password. - -For instance, to configure TLS authentication on a Kafka cluster with 2 Kafka brokers use the command below to create the secret: - -```console -kubectl create secret generic kafka-jks --from-file=./kafka.truststore.jks --from-file=./kafka-0.keystore.jks --from-file=./kafka-1.keystore.jks -``` - -> **Note**: the command above assumes you already created the trustore and keystores files. This [script](https://raw.githubusercontent.com/confluentinc/confluent-platform-security-tools/master/kafka-generate-ssl.sh) can help you with the JKS files generation. - -As an alternative to manually create the secret before installing the chart, you can put your JKS files inside the chart folder `files/jks`, an a secret including them will be generated. Please note this alternative requires to have the chart downloaded locally, so you will have to clone this repository or fetch the chart before installing it. - -You can deploy the chart with authentication using the following parameters: - -```console -replicaCount=2 -auth.clientProtocol=sasl -auth.interBrokerProtocol=tls -auth.certificatesSecret=kafka-jks -auth.certificatesPassword=jksPassword -auth.jaas.clientUsers[0]=brokerUser -auth.jaas.clientPassword[0]=brokerPassword -auth.jaas.zookeeperUser=zookeeperUser -auth.jaas.zookeeperPassword=zookeeperPassword -zookeeper.auth.enabled=true -zookeeper.auth.serverUsers=zookeeperUser -zookeeper.auth.serverPasswords=zookeeperPassword -zookeeper.auth.clientUser=zookeeperUser -zookeeper.auth.clientPassword=zookeeperPassword -``` - -If you also enable exposing metrics using the Kafka expoter, and you are using `sasl_tls`, `tls`, or `mtls` authentication protocols, you need to mount the CA certificated used to sign the brokers certificates in the exporter so it can validate the Kafka brokers. To do so, create a secret containing the CA, and set the `metrics.certificatesSecret` parameter. As an alternative, you can skip TLS validation using extra flags: - -```console -metrics.kafka.extraFlags={tls.insecure-skip-tls-verify: ""} -``` - -### Accessing Kafka brokers from outside the cluster - -In order to access Kafka Brokers from outside the cluster, an additional listener and advertised listener must be configured. Additionally, a specific service per kafka pod will be created. - -There are two ways of configuring external access. Using LoadBalancer services or using NodePort services. - -#### Using LoadBalancer services - -You have two alternatives to use LoadBalancer services: - -- Option A) Use random load balancer IPs using an **initContainer** that waits for the IPs to be ready and discover them automatically. - -```console -externalAccess.enabled=true -externalAccess.service.type=LoadBalancer -externalAccess.service.port=9094 -externalAccess.autoDiscovery.enabled=true -serviceAccount.create=true -rbac.create=true -``` - -Note: This option requires creating RBAC rules on clusters where RBAC policies are enabled. - -- Option B) Manually specify the load balancer IPs: - -```console -externalAccess.enabled=true -externalAccess.service.type=LoadBalancer -externalAccess.service.port=9094 -externalAccess.service.loadBalancerIPs[0]='external-ip-1' -externalAccess.service.loadBalancerIPs[1]='external-ip-2'} -``` - -Note: You need to know in advance the load balancer IPs so each Kafka broker advertised listener is configured with it. - -#### Using NodePort services - -You have two alternatives to use NodePort services: - -- Option A) Use random node ports using an **initContainer** that discover them automatically. - -```console -externalAccess.enabled=true -externalAccess.service.type=NodePort -externalAccess.autoDiscovery.enabled=true -serviceAccount.create=true -rbac.create=true -``` - -Note: This option requires creating RBAC rules on clusters where RBAC policies are enabled. - -- Option B) Manually specify the node ports: - -```console -externalAccess.enabled=true -externalAccess.service.type=NodePort -externalAccess.serivce.nodePorts[0]='node-port-1' -externalAccess.serivce.nodePorts[1]='node-port-2' -``` - -Note: You need to know in advance the node ports that will be exposed so each Kafka broker advertised listener is configured with it. - -The pod will try to get the external ip of the node using `curl -s https://ipinfo.io/ip` unless `externalAccess.service.domain` is provided. - -Following the aforementioned steps will also allow to connect the brokers from the outside using the cluster's default service (when `service.type` is `LoadBalancer` or `NodePort`). Use the property `service.externalPort` to specify the port used for external connections. - -### Sidecars - -If you have a need for additional containers to run within the same pod as Kafka (e.g. an additional metrics or logging exporter), you can do so via the `sidecars` config parameter. Simply define your container according to the Kubernetes container spec. - -```yaml -sidecars: - - name: your-image-name - image: your-image - imagePullPolicy: Always - ports: - - name: portname - containerPort: 1234 -``` - -### Deploying extra resources - -There are cases where you may want to deploy extra objects, such as Kafka Connect. For covering this case, the chart allows adding the full specification of other objects using the `extraDeploy` parameter. The following example would create a deployment including a Kafka Connect deployment so you can connect Kafka with MongoDB: - -```yaml -## Extra objects to deploy (value evaluated as a template) -## -extraDeploy: |- - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: {{ include "kafka.fullname" . }}-connect - labels: {{- include "kafka.labels" . | nindent 6 }} - app.kubernetes.io/component: connector - spec: - replicas: 1 - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 8 }} - app.kubernetes.io/component: connector - template: - metadata: - labels: {{- include "kafka.labels" . | nindent 10 }} - app.kubernetes.io/component: connector - spec: - containers: - - name: connect - image: KAFKA-CONNECT-IMAGE - imagePullPolicy: IfNotPresent - ports: - - name: connector - containerPort: 8083 - volumeMounts: - - name: configuration - mountPath: /opt/bitnami/kafka/config - volumes: - - name: configuration - configMap: - name: {{ include "kafka.fullname" . }}-connect - - apiVersion: v1 - kind: ConfigMap - metadata: - name: {{ include "kafka.fullname" . }}-connect - labels: {{- include "kafka.labels" . | nindent 6 }} - app.kubernetes.io/component: connector - data: - connect-standalone.properties: |- - bootstrap.servers = {{ include "kafka.fullname" . }}-0.{{ include "kafka.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}:{{ .Values.service.port }} - ... - mongodb.properties: |- - connection.uri=mongodb://root:password@mongodb-hostname:27017 - ... - - apiVersion: v1 - kind: Service - metadata: - name: {{ include "kafka.fullname" . }}-connect - labels: {{- include "kafka.labels" . | nindent 6 }} - app.kubernetes.io/component: connector - spec: - ports: - - protocol: TCP - port: 8083 - targetPort: connector - selector: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: connector -``` - -You can create the Kafka Connect image using the Dockerfile below: - -```Dockerfile -FROM bitnami/kafka:latest -# Download MongoDB Connector for Apache Kafka https://www.confluent.io/hub/mongodb/kafka-connect-mongodb -RUN mkdir -p /opt/bitnami/kafka/plugins && \ - cd /opt/bitnami/kafka/plugins && \ - curl --remote-name --location --silent https://search.maven.org/remotecontent?filepath=org/mongodb/kafka/mongo-kafka-connect/1.2.0/mongo-kafka-connect-1.2.0-all.jar -CMD /opt/bitnami/kafka/bin/connect-standalone.sh /opt/bitnami/kafka/config/connect-standalone.properties /opt/bitnami/kafka/config/mongo.properties -``` - -## Persistence - -The [Bitnami Kafka](https://github.com/bitnami/bitnami-docker-kafka) image stores the Kafka data at the `/bitnami/kafka` path of the container. - -Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. See the [Parameters](#persistence-parameters) section to configure the PVC or to disable persistence. - -### Adjust permissions of persistent volume mountpoint - -As the image run as non-root by default, it is necessary to adjust the ownership of the persistent volume so that the container can write data into it. - -By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions. -As an alternative, this chart supports using an initContainer to change the ownership of the volume before mounting it in the final destination. - -You can enable this initContainer by setting `volumePermissions.enabled` to `true`. - -## Upgrading - -### To 11.8.0 - -External access to brokers can now be archived through the cluster's Kafka service. - -- `service.nodePort` -> deprecated in favor of `service.nodePorts.client` and `service.nodePorts.external` - -### To 11.7.0 - -The way to configure the users and passwords changed. Now it is allowed to create multiple users during the installation by providing the list of users and passwords. - -- `auth.jaas.clientUser` (string) -> deprecated in favor of `auth.jaas.clientUsers` (array). -- `auth.jaas.clientPassword` (string) -> deprecated in favor of `auth.jaas.clientPasswords` (array). - -### To 11.0.0 - -The way to configure listeners and authentication on Kafka is totally refactored allowing users to configure different authentication protocols on different listeners. Please check the sections [Listeners Configuration](listeners-configuration) and [Listeners Configuration](enable-kafka-for-kafka-and-zookeeper) for more information. - -Backwards compatibility is not guaranteed you adapt your values.yaml to the new format. Here you can find some parameters that were renamed or disappeared in favor of new ones on this major version: - -- `auth.enabled` -> deprecated in favor of `auth.clientProtocol` and `auth.interBrokerProtocol` parameters. -- `auth.ssl` -> deprecated in favor of `auth.clientProtocol` and `auth.interBrokerProtocol` parameters. -- `auth.certificatesSecret` -> renamed to `auth.jksSecret`. -- `auth.certificatesPassword` -> renamed to `auth.jksPassword`. -- `sslEndpointIdentificationAlgorithm` -> renamedo to `auth.tlsEndpointIdentificationAlgorithm`. -- `auth.interBrokerUser` -> renamed to `auth.jaas.interBrokerUser` -- `auth.interBrokerPassword` -> renamed to `auth.jaas.interBrokerPassword` -- `auth.zookeeperUser` -> renamed to `auth.jaas.zookeeperUser` -- `auth.zookeeperPassword` -> renamed to `auth.jaas.zookeeperPassword` -- `auth.existingSecret` -> renamed to `auth.jaas.existingSecret` -- `service.sslPort` -> deprecated in favor of `service.internalPort` -- `service.nodePorts.kafka` and `service.nodePorts.ssl` -> deprecated in favor of `service.nodePort` -- `metrics.kafka.extraFlag` -> new parameter -- `metrics.kafka.certificatesSecret` -> new parameter - -### To 10.0.0 - -If you are setting the `config` or `log4j` parameter, backwards compatibility is not guaranteed, because the `KAFKA_MOUNTED_CONFDIR` has moved from `/opt/bitnami/kafka/conf` to `/bitnami/kafka/config`. In order to continue using these parameters, you must also upgrade your image to `docker.io/bitnami/kafka:2.4.1-debian-10-r38` or later. - -### To 9.0.0 - -Backwards compatibility is not guaranteed you adapt your values.yaml to the new format. Here you can find some parameters that were renamed on this major version: - -```diff -- securityContext.enabled -- securityContext.fsGroup -- securityContext.fsGroup -+ podSecurityContext -- externalAccess.service.loadBalancerIP -+ externalAccess.service.loadBalancerIPs -- externalAccess.service.nodePort -+ externalAccess.service.nodePorts -- metrics.jmx.configMap.enabled -- metrics.jmx.configMap.overrideConfig -+ metrics.jmx.config -- metrics.jmx.configMap.overrideName -+ metrics.jmx.existingConfigmap -``` - -Ports names were prefixed with the protocol to comply with Istio (see https://istio.io/docs/ops/deployment/requirements/). - -### To 8.0.0 - -There is not backwards compatibility since the brokerID changes to the POD_NAME. For more information see [this PR](https://github.com/bitnami/charts/pull/2028). - -### To 7.0.0 - -Backwards compatibility is not guaranteed when Kafka metrics are enabled, unless you modify the labels used on the exporter deployments. -Use the workaround below to upgrade from versions previous to 7.0.0. The following example assumes that the release name is kafka: - -```console -helm upgrade kafka bitnami/kafka --version 6.1.8 --set metrics.kafka.enabled=false -helm upgrade kafka bitnami/kafka --version 7.0.0 --set metrics.kafka.enabled=true -``` - -### To 2.0.0 - -Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. -Use the workaround below to upgrade from versions previous to 2.0.0. The following example assumes that the release name is kafka: - -```console -kubectl delete statefulset kafka-kafka --cascade=false -kubectl delete statefulset kafka-zookeeper --cascade=false -``` - -### To 1.0.0 - -Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. -Use the workaround below to upgrade from versions previous to 1.0.0. The following example assumes that the release name is kafka: - -```console -kubectl delete statefulset kafka-kafka --cascade=false -kubectl delete statefulset kafka-zookeeper --cascade=false -``` diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/.helmignore b/ee/scripts/helm/db/kafka/charts/zookeeper/.helmignore deleted file mode 100755 index f0c131944..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/Chart.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/Chart.yaml deleted file mode 100755 index c3b15dc5c..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/Chart.yaml +++ /dev/null @@ -1,20 +0,0 @@ -annotations: - category: Infrastructure -apiVersion: v1 -appVersion: 3.6.2 -description: A centralized service for maintaining configuration information, naming, - providing distributed synchronization, and providing group services for distributed - applications. -engine: gotpl -home: https://github.com/bitnami/charts/tree/master/bitnami/zookeeper -icon: https://bitnami.com/assets/stacks/zookeeper/img/zookeeper-stack-110x117.png -keywords: -- zookeeper -maintainers: -- email: containers@bitnami.com - name: Bitnami -name: zookeeper -sources: -- https://github.com/bitnami/bitnami-docker-zookeeper -- https://zookeeper.apache.org/ -version: 5.21.9 diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/README.md b/ee/scripts/helm/db/kafka/charts/zookeeper/README.md deleted file mode 100755 index 0291875ed..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/README.md +++ /dev/null @@ -1,297 +0,0 @@ -# ZooKeeper - -[ZooKeeper](https://zookeeper.apache.org/) is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or other by distributed applications. - -## TL;DR - -```console -$ helm repo add bitnami https://charts.bitnami.com/bitnami -$ helm install my-release bitnami/zookeeper -``` - -## Introduction - -This chart bootstraps a [ZooKeeper](https://github.com/bitnami/bitnami-docker-zookeeper) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 2.12+ or Helm 3.0-beta3+ -- PV provisioner support in the underlying infrastructure - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -$ helm repo add bitnami https://charts.bitnami.com/bitnami -$ helm install my-release bitnami/zookeeper -``` - -These commands deploy ZooKeeper on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```console -$ helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Parameters - -The following tables lists the configurable parameters of the ZooKeeper chart and their default values per section/component: - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `global.imageRegistry` | Global Docker image registry | `nil` | -| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | - -### Common parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `nameOverride` | String to partially override zookeeper.fullname | `nil` | -| `fullnameOverride` | String to fully override zookeeper.fullname | `nil` | -| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | -| `commonLabels` | Labels to add to all deployed objects | `{}` | -| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | -| `schedulerName` | Kubernetes pod scheduler registry | `nil` (use the default-scheduler) | - -### Zookeeper chart parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `image.registry` | ZooKeeper image registry | `docker.io` | -| `image.repository` | ZooKeeper Image name | `bitnami/zookeeper` | -| `image.tag` | ZooKeeper Image tag | `{TAG_NAME}` | -| `image.pullPolicy` | ZooKeeper image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `image.debug` | Specify if debug values should be set | `false` | -| `tickTime` | Basic time unit in milliseconds used by ZooKeeper for heartbeats | `2000` | -| `initLimit` | Time the ZooKeeper servers in quorum have to connect to a leader | `10` | -| `syncLimit` | How far out of date a server can be from a leader | `5` | -| `maxClientCnxns` | Number of concurrent connections that a single client may make to a single member | `60` | -| `maxSessionTimeout` | Maximum session timeout in milliseconds that the server will allow the client to negotiate. | `40000` | -| `autopurge.snapRetainCount` | Number of retains snapshots for autopurge | `3` | -| `autopurge.purgeInterval` | The time interval in hours for which the purge task has to be triggered | `0` | -| `fourlwCommandsWhitelist` | A list of comma separated Four Letter Words commands to use | `srvr, mntr` | -| `listenOnAllIPs` | Allow Zookeeper to listen for connections from its peers on all available IP addresses. | `false` | -| `allowAnonymousLogin` | Allow to accept connections from unauthenticated users | `yes` | -| `auth.existingSecret` | Use existing secret (ignores previous password) | `nil` | -| `auth.enabled` | Enable ZooKeeper auth | `false` | -| `auth.clientUser` | User that will use ZooKeeper clients to auth | `nil` | -| `auth.clientPassword` | Password that will use ZooKeeper clients to auth | `nil` | -| `auth.serverUsers` | List of user to be created | `nil` | -| `auth.serverPasswords` | List of passwords to assign to users when created | `nil` | -| `heapSize` | Size in MB for the Java Heap options (Xmx and XMs) | `[]` | -| `logLevel` | Log level of ZooKeeper server | `ERROR` | -| `jvmFlags` | Default JVMFLAGS for the ZooKeeper process | `nil` | -| `config` | Configure ZooKeeper with a custom zoo.conf file | `nil` | -| `dataLogDir` | Data log directory | `""` | - -### Statefulset parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `replicaCount` | Number of ZooKeeper nodes | `1` | -| `updateStrategy` | Update strategy for the statefulset | `RollingUpdate` | -| `rollingUpdatePartition` | Partition update strategy | `nil` | -| `podManagementPolicy` | Pod management policy | `Parallel` | -| `podLabels` | ZooKeeper pod labels | `{}` (evaluated as a template) | -| `podAnnotations` | ZooKeeper Pod annotations | `{}` (evaluated as a template) | -| `affinity` | Affinity for pod assignment | `{}` (evaluated as a template) | -| `nodeSelector` | Node labels for pod assignment | `{}` (evaluated as a template) | -| `tolerations` | Tolerations for pod assignment | `[]` (evaluated as a template) | -| `priorityClassName` | Name of the existing priority class to be used by ZooKeeper pods | `""` | -| `securityContext.enabled` | Enable security context (ZooKeeper master pod) | `true` | -| `securityContext.fsGroup` | Group ID for the container (ZooKeeper master pod) | `1001` | -| `securityContext.runAsUser` | User ID for the container (ZooKeeper master pod) | `1001` | -| `resources` | CPU/Memory resource requests/limits | Memory: `256Mi`, CPU: `250m` | -| `livenessProbe` | Liveness probe configuration for ZooKeeper | Check `values.yaml` file | -| `readinessProbe` | Readiness probe configuration for ZooKeeper | Check `values.yaml` file | -| `extraVolumes` | Extra volumes | `nil` | -| `extraVolumeMounts` | Mount extra volume(s) | `nil` | -| `podDisruptionBudget.maxUnavailable` | Max number of pods down simultaneously | `1` | - -### Exposure parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `service.type` | Kubernetes Service type | `ClusterIP` | -| `service.port` | ZooKeeper port | `2181` | -| `service.followerPort` | ZooKeeper follower port | `2888` | -| `service.electionPort` | ZooKeeper election port | `3888` | -| `service.publishNotReadyAddresses` | If the ZooKeeper headless service should publish DNS records for not ready pods | `true` | -| `serviceAccount.create` | Enable creation of ServiceAccount for zookeeper pod | `false` | -| `serviceAccount.name` | The name of the service account to use. If not set and `create` is `true`, a name is generated | Generated using the `zookeeper.fullname` template | -| `service.tls.client_enable` | Enable tls for client connections | `false` | -| `service.tls.quorum_enable` | Enable tls for quorum protocol | `false` | -| `service.tls.disable_base_client_port` | Remove client port from service definitions. | `false` | -| `service.tls.client_port` | Service port for tls client connections | `3181` | -| `service.tls.client_keystore_path` | KeyStore file path. Refer to extraVolumes and extraVolumeMounts for mounting files into the pods | `/tls_key_store/key_store_file` | -| `service.tls.client_keystore_password` | KeyStore password. You can use environment variables. | `nil` | -| `service.tls.client_truststore_path` | TrustStore file path. Refer to extraVolumes and extraVolumeMounts for mounting files into the pods | `/tls_trust_store/trust_store_file` | -| `service.tls.client_truststore_password` | TrustStore password. You can use environment variables. | `nil` | -| `service.tls.quorum_keystore_path` | KeyStore file path. Refer to extraVolumes and extraVolumeMounts for mounting files into the pods | `/tls_key_store/key_store_file` | -| `service.tls.quorum_keystore_password` | KeyStore password. You can use environment variables. | `nil` | -| `service.tls.quorum_truststore_path` | TrustStore file path. Refer to extraVolumes and extraVolumeMounts for mounting files into the pods | `/tls_trust_store/trust_store_file` | -| `service.tls.quorum_truststore_password` | TrustStore password. You can use environment variables. | `nil` | -| `service.annotations` | Annotations for the Service | `{}` | -| `service.headless.annotations` | Annotations for the Headless Service | `{}` | -| `networkPolicy.enabled` | Enable NetworkPolicy | `false` | -| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | - -### Persistence parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `persistence.enabled` | Enable Zookeeper data persistence using PVC | `true` | -| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim` | `nil` (evaluated as a template) | -| `persistence.storageClass` | PVC Storage Class for ZooKeeper data volume | `nil` | -| `persistence.accessMode` | PVC Access Mode for ZooKeeper data volume | `ReadWriteOnce` | -| `persistence.size` | PVC Storage Request for ZooKeeper data volume | `8Gi` | -| `persistence.annotations` | Annotations for the PVC | `{}` (evaluated as a template) | -| `persistence.dataLogDir.size` | PVC Storage Request for ZooKeeper's Data log directory | `8Gi` | -| `persistence.dataLogDir.existingClaim` | Provide an existing `PersistentVolumeClaim` for Zookeeper's Data log directory | `nil` (evaluated as a template) | - -### Volume Permissions parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | -| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | -| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/minideb` | -| `volumePermissions.image.tag` | Init container volume-permissions image tag | `buster` | -| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | -| `volumePermissions.resources` | Init container resource requests/limit | `nil` | - -### Metrics parameters - -| Parameter | Description | Default | -|-------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------| -| `metrics.enabled` | Enable prometheus to access zookeeper metrics endpoint | `false` | -| `metrics.containerPort` | Port where a Jetty server will expose Prometheus metrics | `9141` | -| `metrics.service.type` | Kubernetes service type (`ClusterIP`, `NodePort` or `LoadBalancer`) for Jetty server exposing Prometheus metrics | `ClusterIP` | -| `metrics.service.port` | Prometheus metrics service port | `9141` | -| `metrics.service.annotations` | Service annotations for Prometheus to auto-discover the metrics endpoint | `{prometheus.io/scrape: "true", prometheus.io/port: "9141"}` | -| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | -| `metrics.serviceMonitor.namespace` | Namespace for the ServiceMonitor Resource | The Release Namespace | -| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `nil` (Prometheus Operator default value) | -| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `nil` (Prometheus Operator default value) | -| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `nil` | -| `metrics.prometheusRule.enabled` | if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) | `false` | -| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource | The Release Namespace | -| `metrics.prometheusRule.selector` | Prometheus instance selector labels | `nil` | -| `metrics.prometheusRule.rules` | Prometheus Rule definitions (see values.yaml for examples) | `[]` | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, - -```console -$ helm install my-release \ - --set auth.clientUser=newUser \ - bitnami/zookeeper -``` - -The above command sets the ZooKeeper user to `newUser`. - -Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, - -```console -$ helm install my-release -f values.yaml bitnami/zookeeper -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -## Configuration and installation details - -### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) - -It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. - -Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. - -### Production configuration - -This chart includes a `values-production.yaml` file where you can find some parameters oriented to production configuration in comparison to the regular `values.yaml`. You can use this file instead of the default one. - -- Number of ZooKeeper nodes: - -```diff -- replicaCount: 1 -+ replicaCount: 3 -``` - -- Enable prometheus metrics: - -```diff -- metrics.enabled: false -+ metrics.enabled: true -``` - -### Log level - -You can configure the ZooKeeper log level using the `ZOO_LOG_LEVEL` environment variable. By default, it is set to `ERROR` because of each readiness probe produce an `INFO` message on connection and a `WARN` message on disconnection. - -## Persistence - -The [Bitnami ZooKeeper](https://github.com/bitnami/bitnami-docker-zookeeper) image stores the ZooKeeper data and configurations at the `/bitnami/zookeeper` path of the container. - -Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. -See the [Parameters](#parameters) section to configure the PVC or to disable persistence. - -### Adjust permissions of persistent volume mountpoint - -As the image run as non-root by default, it is necessary to adjust the ownership of the persistent volume so that the container can write data into it. - -By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions. -As an alternative, this chart supports using an initContainer to change the ownership of the volume before mounting it in the final destination. - -You can enable this initContainer by setting `volumePermissions.enabled` to `true`. - -### Data Log Directory - -You can use a dedicated device for logs (instead of using the data directory) to help avoiding competition between logging and snapshots. To do so, set the `dataLogDir` parameter with the path to be used for writing transaction logs. Alternatively, set this parameter with an empty string an it result in the log being written to the data directory (Zookeeper's default behavior). - -When using a dedicated device for logs, you can use a PVC to persist the logs. To do so, set `persistence.enabled` to `true`. See the [Persistence Parameters](#persistence-parameters) section for more information. - -## Upgrading - -### To 5.21.0 - -A couple of parameters related to Zookeeper metrics were renamed or disappeared in favor of new ones: - -- `metrics.port` is renamed to `metrics.containerPort`. -- `metrics.annotations` is deprecated in favor of `metrics.service.annotations`. - -### To 3.0.0 - -This new version of the chart includes the new ZooKeeper major version 3.5.5. Note that to perform an automatic upgrade -of the application, each node will need to have at least one snapshot file created in the data directory. If not, the -new version of the application won't be able to start the service. Please refer to [ZOOKEEPER-3056](https://issues.apache.org/jira/browse/ZOOKEEPER-3056) -in order to find ways to workaround this issue in case you are facing it. - -### To 2.0.0 - -Backwards compatibility is not guaranteed unless you modify the labels used on the chart's statefulsets. -Use the workaround below to upgrade from versions previous to 2.0.0. The following example assumes that the release name is `zookeeper`: - -```console -$ kubectl delete statefulset zookeeper-zookeeper --cascade=false -``` - -### To 1.0.0 - -Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. -Use the workaround below to upgrade from versions previous to 1.0.0. The following example assumes that the release name is zookeeper: - -```console -$ kubectl delete statefulset zookeeper-zookeeper --cascade=false -``` diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/NOTES.txt b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/NOTES.txt deleted file mode 100755 index 3cc2edbed..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/NOTES.txt +++ /dev/null @@ -1,57 +0,0 @@ -{{- if contains .Values.service.type "LoadBalancer" }} -{{- if not .Values.auth.clientPassword }} -------------------------------------------------------------------------------- - WARNING - - By specifying "serviceType=LoadBalancer" and not specifying "auth.enabled=true" - you have most likely exposed the ZooKeeper service externally without any - authentication mechanism. - - For security reasons, we strongly suggest that you switch to "ClusterIP" or - "NodePort". As alternative, you can also specify a valid password on the - "auth.clientPassword" parameter. - -------------------------------------------------------------------------------- -{{- end }} -{{- end }} - -** Please be patient while the chart is being deployed ** - -ZooKeeper can be accessed via port 2181 on the following DNS name from within your cluster: - - {{ template "zookeeper.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} - -To connect to your ZooKeeper server run the following commands: - - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "zookeeper.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=zookeeper" -o jsonpath="{.items[0].metadata.name}") - kubectl exec -it $POD_NAME -- zkCli.sh - -To connect to your ZooKeeper server from outside the cluster execute the following commands: - -{{- if contains "NodePort" .Values.service.type }} - - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "zookeeper.fullname" . }}) - zkCli.sh $NODE_IP:$NODE_PORT - -{{- else if contains "LoadBalancer" .Values.service.type }} - - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "zookeeper.fullname" . }}' - - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "zookeeper.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - zkCli.sh $SERVICE_IP:2181 - -{{- else if contains "ClusterIP" .Values.service.type }} - - kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "zookeeper.fullname" . }} 2181:2181 & - zkCli.sh 127.0.0.1:2181 - -{{- end }} - -{{- if and (contains "bitnami/" .Values.image.repository) (not (.Values.image.tag | toString | regexFind "-r\\d+$|sha256:")) }} - -WARNING: Rolling tag detected ({{ .Values.image.repository }}:{{ .Values.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. -+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ - -{{- end }} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/_helpers.tpl b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/_helpers.tpl deleted file mode 100755 index f82502d69..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/_helpers.tpl +++ /dev/null @@ -1,212 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "zookeeper.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "zookeeper.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "zookeeper.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* - Create the name of the service account to use - */}} -{{- define "zookeeper.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (include "zookeeper.fullname" .) .Values.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Zookeeper image name -*/}} -{{- define "zookeeper.image" -}} -{{- $registryName := .Values.image.registry -}} -{{- $repositoryName := .Values.image.repository -}} -{{- $tag := .Values.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names -*/}} -{{- define "zookeeper.imagePullSecrets" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -Also, we can not use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} -{{- if .Values.global.imagePullSecrets }} -imagePullSecrets: -{{- range .Values.global.imagePullSecrets }} - - name: {{ . }} -{{- end }} -{{- else if or .Values.image.pullSecrets .Values.volumePermissions.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.volumePermissions.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- end -}} -{{- else if or .Values.image.pullSecrets .Values.volumePermissions.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.volumePermissions.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- end -}} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "zookeeper.labels" -}} -app.kubernetes.io/name: {{ include "zookeeper.name" . }} -helm.sh/chart: {{ include "zookeeper.chart" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Renders a value that contains template. -Usage: -{{ include "zookeeper.tplValue" ( dict "value" .Values.path.to.the.Value "context" $) }} -*/}} -{{- define "zookeeper.tplValue" -}} - {{- if typeIs "string" .value }} - {{- tpl .value .context }} - {{- else }} - {{- tpl (.value | toYaml) .context }} - {{- end }} -{{- end -}} - -{{/* -Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector -*/}} -{{- define "zookeeper.matchLabels" -}} -app.kubernetes.io/name: {{ include "zookeeper.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Return ZooKeeper Client Password -*/}} -{{- define "zookeeper.clientPassword" -}} -{{- if .Values.auth.clientPassword -}} - {{- .Values.auth.clientPassword -}} -{{- else -}} - {{- randAlphaNum 10 -}} -{{- end -}} -{{- end -}} - -{{/* -Return ZooKeeper Servers Passwords -*/}} -{{- define "zookeeper.serverPasswords" -}} -{{- if .Values.auth.serverPasswords -}} - {{- .Values.auth.serverPasswords -}} -{{- else -}} - {{- randAlphaNum 10 -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper image name (for the init container volume-permissions image) -*/}} -{{- define "zookeeper.volumePermissions.image" -}} -{{- $registryName := .Values.volumePermissions.image.registry -}} -{{- $repositoryName := .Values.volumePermissions.image.repository -}} -{{- $tag := .Values.volumePermissions.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Storage Class -*/}} -{{- define "zookeeper.storageClass" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -*/}} -{{- if .Values.global -}} - {{- if .Values.global.storageClass -}} - {{- if (eq "-" .Values.global.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.global.storageClass -}} - {{- end -}} - {{- else -}} - {{- if .Values.persistence.storageClass -}} - {{- if (eq "-" .Values.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} - {{- end -}} - {{- end -}} - {{- end -}} -{{- else -}} - {{- if .Values.persistence.storageClass -}} - {{- if (eq "-" .Values.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} - {{- end -}} - {{- end -}} -{{- end -}} -{{- end -}} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/configmap.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/configmap.yaml deleted file mode 100755 index 1a4061565..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.config }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: - zoo.cfg: |- -{{ .Values.config | indent 4 }} -{{- end -}} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/metrics-svc.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/metrics-svc.yaml deleted file mode 100755 index 3e26ed6c8..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/metrics-svc.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if .Values.metrics.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "zookeeper.fullname" . }}-metrics - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} - annotations: - {{- if .Values.metrics.service.annotations }} - {{ include "zookeeper.tplValue" ( dict "value" .Values.metrics.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.metrics.service.type }} - ports: - - name: tcp-metrics - port: {{ .Values.metrics.service.port }} - targetPort: metrics - selector: {{- include "zookeeper.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper -{{- end }} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/networkpolicy.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/networkpolicy.yaml deleted file mode 100755 index f7e30b4bc..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/networkpolicy.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -kind: NetworkPolicy -apiVersion: networking.k8s.io/v1 -metadata: - name: {{ include "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - podSelector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 6 }} - ingress: - # Allow inbound connections to zookeeper - - ports: - - port: {{ .Values.service.port }} - from: - {{- if not .Values.networkPolicy.allowExternal }} - - podSelector: - matchLabels: - {{ include "zookeeper.fullname" . }}-client: "true" - - podSelector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 14 }} - {{- else }} - - podSelector: - matchLabels: {} - {{- end }} - # Internal ports - - ports: &intranodes_ports - - port: {{ .Values.service.followerPort }} - - port: {{ .Values.service.electionPort }} - from: - - podSelector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 14 }} - egress: - - ports: *intranodes_ports - # Allow outbound connections from zookeeper nodes - -{{- end }} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/poddisruptionbudget.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/poddisruptionbudget.yaml deleted file mode 100755 index 818950c66..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- $replicaCount := int .Values.replicaCount }} -{{- if gt $replicaCount 1 }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: zookeeper - {{- toYaml .Values.podDisruptionBudget | nindent 2 }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/prometheusrules.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/prometheusrules.yaml deleted file mode 100755 index 9cda3985c..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/prometheusrules.yaml +++ /dev/null @@ -1,27 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled .Values.metrics.prometheusRule.rules }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ include "zookeeper.fullname" . }} - {{- if .Values.metrics.prometheusRule.namespace }} - namespace: {{ .Values.metrics.prometheusRule.namespace }} - {{- else }} - namespace: {{ .Release.Namespace }} - {{- end }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- range $key, $value := .Values.metrics.prometheusRule.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - groups: - - name: {{ include "zookeeper.fullname" . }} - rules: {{- toYaml .Values.metrics.prometheusRule.rules | nindent 6 }} -{{- end }} - diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/secrets.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/secrets.yaml deleted file mode 100755 index b3d727fec..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/secrets.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -type: Opaque -data: - client-password: {{ include "zookeeper.clientPassword" . | b64enc | quote }} - server-password: {{ include "zookeeper.serverPasswords" . | b64enc | quote }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/serviceaccount.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/serviceaccount.yaml deleted file mode 100755 index 3f7ef39fd..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/serviceaccount.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "zookeeper.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - role: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/servicemonitor.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/servicemonitor.yaml deleted file mode 100755 index 5782dad59..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/servicemonitor.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "zookeeper.fullname" . }} - {{- if .Values.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.metrics.serviceMonitor.namespace }} - {{- else }} - namespace: {{ .Release.Namespace }} - {{- end }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- range $key, $value := .Values.metrics.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: zookeeper - endpoints: - - port: tcp-metrics - path: "/metrics" - {{- if .Values.metrics.serviceMonitor.interval }} - interval: {{ .Values.metrics.serviceMonitor.interval }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} - {{- end }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/statefulset.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/statefulset.yaml deleted file mode 100755 index fa1e5231f..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/statefulset.yaml +++ /dev/null @@ -1,334 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - role: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - serviceName: {{ template "zookeeper.fullname" . }}-headless - replicas: {{ .Values.replicaCount }} - podManagementPolicy: {{ .Values.podManagementPolicy }} - updateStrategy: - type: {{ .Values.updateStrategy }} - {{- if (eq "Recreate" .Values.updateStrategy) }} - rollingUpdate: null - {{- else if .Values.rollingUpdatePartition }} - rollingUpdate: - partition: {{ .Values.rollingUpdatePartition }} - {{- end }} - selector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: zookeeper - template: - metadata: - name: {{ template "zookeeper.fullname" . }} - labels: {{- include "zookeeper.labels" . | nindent 8 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.podLabels }} - {{- include "zookeeper.tplValue" (dict "value" .Values.podLabels "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.podAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.podAnnotations "context" $) | nindent 8 }} - {{- end }} - spec: - {{- if .Values.schedulerName }} - schedulerName: {{ .Values.schedulerName }} - {{- end }} - {{- include "zookeeper.imagePullSecrets" . | nindent 6 }} - serviceAccountName: {{ template "zookeeper.serviceAccountName" . }} - {{- if .Values.securityContext.enabled }} - securityContext: - fsGroup: {{ .Values.securityContext.fsGroup }} - {{- end }} - {{- if .Values.affinity }} - affinity: {{- include "zookeeper.tplValue" (dict "value" .Values.affinity "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: {{- include "zookeeper.tplValue" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.tolerations }} - tolerations: {{- include "zookeeper.tplValue" (dict "value" .Values.tolerations "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.priorityClassName }} - priorityClassName: {{ .Values.priorityClassName }} - {{- end }} - {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} - initContainers: - - name: volume-permissions - image: {{ template "zookeeper.volumePermissions.image" . }} - imagePullPolicy: {{ default "" .Values.volumePermissions.image.pullPolicy | quote }} - command: - - chown - args: - - -R - - {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} - - /bitnami/zookeeper - {{- if .Values.dataLogDir }} - - {{ .Values.dataLogDir }} - {{- end }} - securityContext: - runAsUser: 0 - {{- if .Values.volumePermissions.resources }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: data - mountPath: /bitnami/zookeeper - {{- if .Values.dataLogDir }} - - name: data-log - mountPath: {{ .Values.dataLogDir }} - {{- end }} - {{- end }} - containers: - - name: zookeeper - image: {{ template "zookeeper.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - {{- if .Values.securityContext.enabled }} - securityContext: - runAsUser: {{ .Values.securityContext.runAsUser }} - {{- end }} - command: - - bash - - -ec - - | - # Execute entrypoint as usual after obtaining ZOO_SERVER_ID based on POD hostname - HOSTNAME=`hostname -s` - if [[ $HOSTNAME =~ (.*)-([0-9]+)$ ]]; then - ORD=${BASH_REMATCH[2]} - export ZOO_SERVER_ID=$((ORD+1)) - else - echo "Failed to get index from hostname $HOST" - exit 1 - fi - exec /entrypoint.sh /run.sh - {{- if .Values.resources }} - resources: {{- toYaml .Values.resources | nindent 12 }} - {{- end }} - env: - - name: ZOO_DATA_LOG_DIR - value: {{ .Values.dataLogDir | quote }} - - name: ZOO_PORT_NUMBER - value: {{ .Values.service.port | quote }} - - name: ZOO_TICK_TIME - value: {{ .Values.tickTime | quote }} - - name: ZOO_INIT_LIMIT - value: {{ .Values.initLimit | quote }} - - name: ZOO_SYNC_LIMIT - value: {{ .Values.syncLimit | quote }} - - name: ZOO_MAX_CLIENT_CNXNS - value: {{ .Values.maxClientCnxns | quote }} - - name: ZOO_4LW_COMMANDS_WHITELIST - value: {{ .Values.fourlwCommandsWhitelist | quote }} - - name: ZOO_LISTEN_ALLIPS_ENABLED - value: {{ ternary "yes" "no" .Values.listenOnAllIPs | quote }} - - name: ZOO_AUTOPURGE_INTERVAL - value: {{ .Values.autopurge.purgeInterval | quote }} - - name: ZOO_AUTOPURGE_RETAIN_COUNT - value: {{ .Values.autopurge.snapRetainCount | quote }} - - name: ZOO_MAX_SESSION_TIMEOUT - value: {{ .Values.maxSessionTimeout | quote }} - - name: ZOO_SERVERS - {{- $replicaCount := int .Values.replicaCount }} - {{- $followerPort := int .Values.service.followerPort }} - {{- $electionPort := int .Values.service.electionPort }} - {{- $releaseNamespace := .Release.Namespace }} - {{- $zookeeperFullname := include "zookeeper.fullname" . }} - {{- $zookeeperHeadlessServiceName := printf "%s-%s" $zookeeperFullname "headless" | trunc 63 }} - {{- $clusterDomain := .Values.clusterDomain }} - value: {{ range $i, $e := until $replicaCount }}{{ $zookeeperFullname }}-{{ $e }}.{{ $zookeeperHeadlessServiceName }}.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $followerPort }}:{{ $electionPort }} {{ end }} - - name: ZOO_ENABLE_AUTH - value: {{ ternary "yes" "no" .Values.auth.enabled | quote }} - {{- if .Values.auth.enabled }} - - name: ZOO_CLIENT_USER - value: {{ .Values.auth.clientUser | quote }} - - name: ZOO_CLIENT_PASSWORD - valueFrom: - secretKeyRef: - name: {{ if .Values.auth.existingSecret }}{{ .Values.auth.existingSecret }}{{ else }}{{ template "zookeeper.fullname" . }}{{ end }} - key: client-password - - name: ZOO_SERVER_USERS - value: {{ .Values.auth.serverUsers | quote }} - - name: ZOO_SERVER_PASSWORDS - valueFrom: - secretKeyRef: - name: {{ if .Values.auth.existingSecret }}{{ .Values.auth.existingSecret }}{{ else }}{{ template "zookeeper.fullname" . }}{{ end }} - key: server-password - {{- end }} - - name: ZOO_HEAP_SIZE - value: {{ .Values.heapSize | quote }} - - name: ZOO_LOG_LEVEL - value: {{ .Values.logLevel | quote }} - - name: ALLOW_ANONYMOUS_LOGIN - value: {{ ternary "yes" "no" .Values.allowAnonymousLogin | quote }} - {{- if .Values.jvmFlags }} - - name: JVMFLAGS - value: {{ .Values.jvmFlags | quote }} - {{- end }} - {{- if .Values.metrics.enabled }} - - name: ZOO_ENABLE_PROMETHEUS_METRICS - value: "yes" - - name: ZOO_PROMETHEUS_METRICS_PORT_NUMBER - value: {{ .Values.metrics.containerPort | quote }} - {{- end }} - {{- if .Values.service.tls.client_enable }} - - name: ZOO_TLS_CLIENT_ENABLE - value: {{ .Values.service.tls.client_enable | quote }} - - name: ZOO_TLS_CLIENT_KEYSTORE_FILE - value: {{ .Values.service.tls.client_keystore_path | quote }} - - name: ZOO_TLS_CLIENT_KEYSTORE_PASSWORD - value: {{ .Values.service.tls.client_keystore_password | quote }} - - name: ZOO_TLS_CLIENT_TRUSTSTORE_FILE - value: {{ .Values.service.tls.client_truststore_path | quote }} - - name: ZOO_TLS_CLIENT_TRUSTSTORE_PASSWORD - value: {{ .Values.service.tls.client_truststore_password | quote }} - {{ end }} - {{- if .Values.service.tls.quorum_enable }} - - name: ZOO_TLS_QUORUM_ENABLE - value: {{ .Values.service.tls.quorum_enable | quote }} - - name: ZOO_TLS_QUORUM_KEYSTORE_FILE - value: {{ .Values.service.tls.quorum_keystore_path | quote }} - - name: ZOO_TLS_QUORUM_KEYSTORE_PASSWORD - value: {{ .Values.service.tls.quorum_keystore_password | quote }} - - name: ZOO_TLS_QUORUM_TRUSTSTORE_FILE - value: {{ .Values.service.tls.quorum_truststore_path | quote }} - - name: ZOO_TLS_QUORUM_TRUSTSTORE_PASSWORD - value: {{ .Values.service.tls.quorum_truststore_password | quote }} - {{ end }} - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - {{- if .Values.extraEnvVars }} - {{- toYaml .Values.extraEnvVars | nindent 12 }} - {{- end }} - ports: - {{ if not .Values.service.tls.disable_base_client_port }} - - name: client - containerPort: {{ .Values.service.port }} - {{ end }} - {{ if .Values.service.tls.client_enable }} - - name: client-tls - containerPort: {{ .Values.service.tls.client_port }} - {{ end }} - - name: follower - containerPort: {{ .Values.service.followerPort }} - - name: election - containerPort: {{ .Values.service.electionPort }} - {{- if .Values.metrics.enabled }} - - name: metrics - containerPort: {{ .Values.metrics.containerPort }} - {{- end }} - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - exec: - {{- if not .Values.service.tls.disable_base_client_port }} - command: ['/bin/bash', '-c', 'echo "ruok" | timeout {{ .Values.livenessProbe.probeCommandTimeout }} nc -w {{ .Values.livenessProbe.probeCommandTimeout }} localhost {{ .Values.service.port }} | grep imok'] - {{- else }} - command: ['/bin/bash', '-c', 'echo "ruok" | timeout {{ .Values.livenessProbe.probeCommandTimeout }} openssl s_client -quiet -crlf -connect localhost:{{ .Values.service.tls.client_port }} | grep imok'] - {{- end }} - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - exec: - {{- if not .Values.service.tls.disable_base_client_port }} - command: ['/bin/bash', '-c', 'echo "ruok" | timeout {{ .Values.readinessProbe.probeCommandTimeout }} nc -w {{ .Values.readinessProbe.probeCommandTimeout }} localhost {{ .Values.service.port }} | grep imok'] - {{- else }} - command: ['/bin/bash', '-c', 'echo "ruok" | timeout {{ .Values.readinessProbe.probeCommandTimeout }} openssl s_client -quiet -crlf -connect localhost:{{ .Values.service.tls.client_port }} | grep imok'] - {{- end }} - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - {{- end }} - volumeMounts: - - name: data - mountPath: /bitnami/zookeeper - {{- if .Values.dataLogDir }} - - name: data-log - mountPath: {{ .Values.dataLogDir }} - {{- end }} - {{- if .Values.config }} - - name: config - mountPath: /opt/bitnami/zookeeper/conf/zoo.cfg - subPath: zoo.cfg - {{- end }} - {{- if .Values.extraVolumeMounts }} - {{- toYaml .Values.extraVolumeMounts | nindent 12 }} - {{- end }} - volumes: - {{- if .Values.config }} - - name: config - configMap: - name: {{ template "zookeeper.fullname" . }} - {{- end }} - {{- if and .Values.persistence.enabled .Values.persistence.existingClaim }} - - name: data - persistentVolumeClaim: - claimName: {{ printf "%s" (tpl .Values.persistence.existingClaim .) }} - {{- else if not .Values.persistence.enabled }} - - name: data - emptyDir: {} - {{- end }} - {{- if and .Values.persistence.enabled .Values.persistence.dataLogDir.existingClaim }} - - name: data-log - persistentVolumeClaim: - claimName: {{ printf "%s" (tpl .Values.persistence.dataLogDir.existingClaim .) }} - {{- else if and ( not .Values.persistence.enabled ) .Values.dataLogDir }} - - name: data-log - emptyDir: {} - {{- end }} - {{- if .Values.extraVolumes }} - {{- toYaml .Values.extraVolumes | nindent 8 }} - {{- end }} - {{- if and .Values.persistence.enabled (not (and .Values.persistence.existingClaim .Values.persistence.dataLogDir.existingClaim) )}} - volumeClaimTemplates: - {{- if not .Values.persistence.existingClaim }} - - metadata: - name: data - annotations: - {{- range $key, $value := .Values.persistence.annotations }} - {{ $key }}: {{ $value }} - {{- end }} - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{- include "zookeeper.storageClass" . | nindent 8 }} - {{- end }} - {{- if and (not .Values.persistence.dataLogDir.existingClaim) .Values.dataLogDir }} - - metadata: - name: data-log - annotations: - {{- range $key, $value := .Values.persistence.annotations }} - {{ $key }}: {{ $value }} - {{- end }} - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.dataLogDir.size | quote }} - {{- include "zookeeper.storageClass" . | nindent 8 }} - {{- end }} - {{- end }} diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/svc-headless.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/svc-headless.yaml deleted file mode 100755 index 972efb51d..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/svc-headless.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "zookeeper.fullname" . }}-headless - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.commonAnnotations .Values.service.annotations }} - annotations: - {{- if .Values.service.headless.annotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.service.headless.annotations "context" $ ) | nindent 4 }}\ - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: ClusterIP - clusterIP: None - publishNotReadyAddresses: {{ .Values.service.publishNotReadyAddresses }} - ports: - {{ if not .Values.service.tls.disable_base_client_port }} - - name: tcp-client - port: 2181 - targetPort: client - {{ end }} - {{ if .Values.service.tls.client_enable }} - - name: tcp-client-tls - port: {{ .Values.service.tls.client_port }} - targetPort: client-tls - {{ end }} - - name: follower - port: 2888 - targetPort: follower - - name: tcp-election - port: 3888 - targetPort: election - selector: {{- include "zookeeper.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/svc.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/templates/svc.yaml deleted file mode 100755 index da3a2895a..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/templates/svc.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.commonAnnotations .Values.service.annotations }} - annotations: - {{- if .Values.service.annotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.service.annotations "context" $ ) | nindent 4 }}\ - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.service.type }} - ports: - {{ if not .Values.service.tls.disable_base_client_port }} - - name: tcp-client - port: 2181 - targetPort: client - {{ end }} - {{ if .Values.service.tls.client_enable }} - - name: tcp-client-tls - port: {{ .Values.service.tls.client_port }} - targetPort: client-tls - {{ end }} - - name: follower - port: 2888 - targetPort: follower - - name: tcp-election - port: 3888 - targetPort: election - selector: {{- include "zookeeper.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/values-production.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/values-production.yaml deleted file mode 100755 index 7d678603f..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/values-production.yaml +++ /dev/null @@ -1,430 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -# global: -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami Zookeeper image version -## ref: https://hub.docker.com/r/bitnami/zookeeper/tags/ -## -image: - registry: docker.io - repository: bitnami/zookeeper - tag: 3.6.2-debian-10-r10 - - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Set to true if you would like to see extra information on logs - ## It turns BASH and NAMI debugging in minideb - ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging - ## - debug: false - -## String to partially override zookeeper.fullname template (will maintain the release name) -# nameOverride: - -## String to fully override zookeeper.fullname template -# fullnameOverride: - -## Kubernetes Cluster Domain -## -clusterDomain: cluster.local - -## Add labels to all the deployed resources -## -commonLabels: {} - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -## Init containers parameters: -## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - resources: {} - -## extraVolumes and extraVolumeMounts allows you to mount other volumes -## Example Use Cases: -## mount certificates to enable tls -# extraVolumes: -# - name: zookeeper-keystore -# secret: -# defaultMode: 288 -# secretName: zookeeper-keystore -# - name: zookeeper-trustsore -# secret: -# defaultMode: 288 -# secretName: zookeeper-truststore -# extraVolumeMounts: -# - name: zookeeper-keystore -# mountPath: /certs/keystore -# readOnly: true -# - name: zookeeper-truststore -# mountPath: /certs/truststore -# readOnly: true - - -## StatefulSet controller supports automated updates. There are two valid update strategies: RollingUpdate and OnDelete -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets -## -updateStrategy: RollingUpdate - -## Limits the number of pods of the replicated application that are down simultaneously from voluntary disruptions -## The PDB will only be created if replicaCount is greater than 1 -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions -## -podDisruptionBudget: - maxUnavailable: 1 - -## Partition update strategy -## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -## -# rollingUpdatePartition: - -## StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: OrderedReady and Parallel -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy -## -podManagementPolicy: Parallel - -## Number of ZooKeeper nodes -## -replicaCount: 3 - -## Basic time unit in milliseconds used by ZooKeeper for heartbeats -## -tickTime: 2000 - -## ZooKeeper uses to limit the length of time the ZooKeeper servers in quorum have to connect to a leader -## -initLimit: 10 - -## How far out of date a server can be from a leader -## -syncLimit: 5 - -## Limits the number of concurrent connections that a single client may make to a single member of the ZooKeeper ensemble -## -maxClientCnxns: 60 - -## Maximum session timeout in milliseconds that the server will allow the client to negotiate. Defaults to 20 times the tickTime. -## -maxSessionTimeout: 40000 - -## A list of comma separated Four Letter Words commands to use -## -fourlwCommandsWhitelist: srvr, mntr, ruok - -## Allow zookeeper to listen for peers on all IPs -## -listenOnAllIPs: false - -## Allow to accept connections from unauthenticated users -## -allowAnonymousLogin: true - -autopurge: - ## Retains the snapRetainCount most recent snapshots and the corresponding transaction logs and deletes the rest - ## - snapRetainCount: 3 - ## The time interval in hours for which the purge task has to be triggered. Set to a positive integer (1 and above) to enable the auto purging. - ## - purgeInterval: 0 - -auth: - ## Use existing secret (ignores previous password) - ## - # existingSecret: - ## Enable Zookeeper auth. It uses SASL/Digest-MD5 - ## - enabled: false - ## User that will use Zookeeper clients to auth - ## - clientUser: - ## Password that will use Zookeeper clients to auth - ## - clientPassword: - ## Comma, semicolon or whitespace separated list of user to be created. Specify them as a string, for example: "user1,user2,admin" - ## - serverUsers: - ## Comma, semicolon or whitespace separated list of passwords to assign to users when created. Specify them as a string, for example: "pass4user1, pass4user2, pass4admin" - ## - serverPasswords: - -## Size in MB for the Java Heap options (Xmx and XMs). This env var is ignored if Xmx an Xms are configured via JVMFLAGS -## -heapSize: 1024 - -## Log level for the Zookeeper server. ERROR by default. Have in mind if you set it to INFO or WARN the ReadinessProve will produce a lot of logs. -## -logLevel: ERROR - -## Data log directory. Specifying this option will direct zookeeper to write the transaction log to the dataLogDir rather than the dataDir. -## This allows a dedicated log device to be used, and helps avoid competition between logging and snaphots. -## Example: -## dataLogDir: /bitnami/zookeeper/dataLog -## -dataLogDir: "" - -## Default JVMFLAGS for the ZooKeeper process -## -# jvmFlags: - -## Configure ZooKeeper with a custom zoo.cfg file -## -# config: - -## Kubernetes configuration -## For minikube, set this to NodePort, elsewhere use LoadBalancer -## -service: - type: ClusterIP - port: 2181 - followerPort: 2888 - electionPort: 3888 - publishNotReadyAddresses: true - tls: - client_enable: true - quorum_enable: true - disable_base_client_port: true - - client_port: 3181 - - client_keystore_path: /tls_key_store/key_store_file - client_keystore_password: "" - client_truststore_path: /tls_trust_store/trust_store_file - client_truststore_password: "" - - quorum_keystore_path: /tls_key_store/key_store_file - quorum_keystore_password: "" - quorum_truststore_path: /tls_trust_store/trust_store_file - quorum_truststore_password: "" - annotations: {} - headless: - annotations: {} - -## Service account for Zookeeper to use. -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: false - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the zookeeper.fullname template - # name: - -## Zookeeper Pod Security Context -securityContext: - enabled: true - fsGroup: 1001 - runAsUser: 1001 - -## Zookeeper data Persistent Volume Storage Class -## If defined, storageClassName: -## If set to "-", storageClassName: "", which disables dynamic provisioning -## If undefined (the default) or set to null, no storageClassName spec is -## set, choosing the default provisioner. (gp2 on AWS, standard on -## GKE, AWS & OpenStack) -## -persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - annotations: {} - dataLogDir: - size: 8Gi - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - -## Node labels for pod assignment -## Ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Labels -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -podLabels: {} - -## Annotations -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -podAnnotations: {} - -## Name of the priority class to be used by zookeeper pods, priority class needs to be created beforehand -## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ -priorityClassName: "" - -## Affinity for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Scheduler name -## https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: stork - -## Configure resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - requests: - memory: 256Mi - cpu: 250m - -## Configure extra options for liveness and readiness probes -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) -## -livenessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - probeCommandTimeout: 2 - -readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - probeCommandTimeout: 2 - -## Network policies -## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ -## -networkPolicy: - ## Specifies whether a NetworkPolicy should be created - ## - enabled: true - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port Redis is listening - ## on. When true, zookeeper accept connections from any source - ## (with the correct destination port). - ## - allowExternal: true - -## Zookeeper Prometheus Exporter configuration -## -metrics: - enabled: false - - ## Zookeeper Prometheus Exporter container port - ## - containerPort: 9141 - - ## Service configuration - ## - service: - ## Zookeeper Prometheus Exporter service type - ## - type: ClusterIP - ## Zookeeper Prometheus Exporter service port - ## - port: 9141 - ## Annotations for the Zookeeper Prometheus Exporter metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.service.port }}" - prometheus.io/path: "/metrics" - - ## Prometheus Operator ServiceMonitor configuration - ## - serviceMonitor: - enabled: false - ## Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) - ## - namespace: - - ## Interval at which metrics should be scraped. - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # interval: 10s - - ## Timeout after which the scrape is ended - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # scrapeTimeout: 10s - - ## ServiceMonitor selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - - ## Prometheus Operator PrometheusRule configuration - ## - prometheusRule: - enabled: false - ## Namespace for the PrometheusRule Resource (defaults to the Release Namespace) - ## - namespace: - - ## PrometheusRule selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - - ## Some example rules. - rules: [] - # - alert: ZookeeperSyncedFollowers - # annotations: - # message: The number of synced followers for the leader node in Zookeeper deployment my-release is less than 2. This usually means that some of the Zookeeper nodes aren't communicating properly. If it doesn't resolve itself you can try killing the pods (one by one). - # expr: max(synced_followers{service="my-release-metrics"}) < 2 - # for: 5m - # labels: - # severity: critical - # - alert: ZookeeperOutstandingRequests - # annotations: - # message: The number of outstanding requests for Zookeeper pod {{ $labels.pod }} is greater than 10. This can indicate a performance issue with the Pod or cluster a whole. - # expr: outstanding_requests{service="my-release-metrics"} > 10 - # for: 5m - # labels: - # severity: critical diff --git a/ee/scripts/helm/db/kafka/charts/zookeeper/values.yaml b/ee/scripts/helm/db/kafka/charts/zookeeper/values.yaml deleted file mode 100755 index a40decb54..000000000 --- a/ee/scripts/helm/db/kafka/charts/zookeeper/values.yaml +++ /dev/null @@ -1,430 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -# global: -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami Zookeeper image version -## ref: https://hub.docker.com/r/bitnami/zookeeper/tags/ -## -image: - registry: docker.io - repository: bitnami/zookeeper - tag: 3.6.2-debian-10-r10 - - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Set to true if you would like to see extra information on logs - ## It turns BASH and NAMI debugging in minideb - ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging - ## - debug: false - -## String to partially override zookeeper.fullname template (will maintain the release name) -# nameOverride: - -## String to fully override zookeeper.fullname template -# fullnameOverride: - -## Kubernetes Cluster Domain -## -clusterDomain: cluster.local - -## Add labels to all the deployed resources -## -commonLabels: {} - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -## Init containers parameters: -## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - resources: {} - -## extraVolumes and extraVolumeMounts allows you to mount other volumes -## Example Use Cases: -## mount certificates to enable tls -# extraVolumes: -# - name: zookeeper-keystore -# secret: -# defaultMode: 288 -# secretName: zookeeper-keystore -# - name: zookeeper-trustsore -# secret: -# defaultMode: 288 -# secretName: zookeeper-truststore -# extraVolumeMounts: -# - name: zookeeper-keystore -# mountPath: /certs/keystore -# readOnly: true -# - name: zookeeper-truststore -# mountPath: /certs/truststore -# readOnly: true - -## StatefulSet controller supports automated updates. There are two valid update strategies: RollingUpdate and OnDelete -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets -## -updateStrategy: RollingUpdate - -## Limits the number of pods of the replicated application that are down simultaneously from voluntary disruptions -## The PDB will only be created if replicaCount is greater than 1 -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions -## -podDisruptionBudget: - maxUnavailable: 1 - -## Partition update strategy -## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -## -# rollingUpdatePartition: - -## StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: OrderedReady and Parallel -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy -## -podManagementPolicy: Parallel - -## Number of ZooKeeper nodes -## -replicaCount: 1 - -## Basic time unit in milliseconds used by ZooKeeper for heartbeats -## -tickTime: 2000 - -## ZooKeeper uses to limit the length of time the ZooKeeper servers in quorum have to connect to a leader -## -initLimit: 10 - -## How far out of date a server can be from a leader -## -syncLimit: 5 - -## Limits the number of concurrent connections that a single client may make to a single member of the ZooKeeper ensemble -## -maxClientCnxns: 60 - -## A list of comma separated Four Letter Words commands to use -## -fourlwCommandsWhitelist: srvr, mntr, ruok - -## Allow zookeeper to listen for peers on all IPs -## -listenOnAllIPs: false - -## Allow to accept connections from unauthenticated users -## -allowAnonymousLogin: true - -autopurge: - ## Retains the snapRetainCount most recent snapshots and the corresponding transaction logs and deletes the rest - ## - snapRetainCount: 3 - ## The time interval in hours for which the purge task has to be triggered. Set to a positive integer (1 and above) to enable the auto purging. - ## - purgeInterval: 0 - -## Maximum session timeout in milliseconds that the server will allow the client to negotiate. Defaults to 20 times the tickTime. -## -maxSessionTimeout: 40000 - -auth: - ## Use existing secret (ignores previous password) - ## - # existingSecret: - ## Enable Zookeeper auth. It uses SASL/Digest-MD5 - ## - enabled: false - ## User that will use Zookeeper clients to auth - ## - clientUser: - ## Password that will use Zookeeper clients to auth - ## - clientPassword: - ## Comma, semicolon or whitespace separated list of user to be created. Specify them as a string, for example: "user1,user2,admin" - ## - serverUsers: - ## Comma, semicolon or whitespace separated list of passwords to assign to users when created. Specify them as a string, for example: "pass4user1, pass4user2, pass4admin" - ## - serverPasswords: - -## Size in MB for the Java Heap options (Xmx and XMs). This env var is ignored if Xmx an Xms are configured via JVMFLAGS -## -heapSize: 1024 - -## Log level for the Zookeeper server. ERROR by default. Have in mind if you set it to INFO or WARN the ReadinessProve will produce a lot of logs. -## -logLevel: ERROR - -## Data log directory. Specifying this option will direct zookeeper to write the transaction log to the dataLogDir rather than the dataDir. -## This allows a dedicated log device to be used, and helps avoid competition between logging and snaphots. -## Example: -## dataLogDir: /bitnami/zookeeper/dataLog -## -dataLogDir: "" - -## Default JVMFLAGS for the ZooKeeper process -## -# jvmFlags: - -## Configure ZooKeeper with a custom zoo.cfg file -## -# config: - -## Kubernetes configuration -## For minikube, set this to NodePort, elsewhere use LoadBalancer -## -service: - type: ClusterIP - port: 2181 - followerPort: 2888 - electionPort: 3888 - publishNotReadyAddresses: true - tls: - client_enable: false - quorum_enable: false - disable_base_client_port: false - - client_port: 3181 - - client_keystore_path: /tls_key_store/key_store_file - client_keystore_password: "" - client_truststore_path: /tls_trust_store/trust_store_file - client_truststore_password: "" - - quorum_keystore_path: /tls_key_store/key_store_file - quorum_keystore_password: "" - quorum_truststore_path: /tls_trust_store/trust_store_file - quorum_truststore_password: "" - annotations: {} - headless: - annotations: {} - -## Service account for Zookeeper to use. -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: false - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the zookeeper.fullname template - # name: - -## Zookeeper Pod Security Context -securityContext: - enabled: true - fsGroup: 1001 - runAsUser: 1001 - -## Zookeeper data Persistent Volume Storage Class -## If defined, storageClassName: -## If set to "-", storageClassName: "", which disables dynamic provisioning -## If undefined (the default) or set to null, no storageClassName spec is -## set, choosing the default provisioner. (gp2 on AWS, standard on -## GKE, AWS & OpenStack) -## -persistence: - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - - enabled: true - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - annotations: {} - dataLogDir: - size: 8Gi - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - - -## Node labels for pod assignment -## Ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Labels -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -podLabels: {} - -## Annotations -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -podAnnotations: {} - -## Name of the priority class to be used by zookeeper pods, priority class needs to be created beforehand -## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ -priorityClassName: "" - -## Affinity for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Scheduler name -## https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: stork - -## Configure resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - requests: - memory: 256Mi - cpu: 250m - -## Configure extra options for liveness and readiness probes -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) -## -livenessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - probeCommandTimeout: 2 - -readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - probeCommandTimeout: 2 - -## Network policies -## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ -## -networkPolicy: - ## Specifies whether a NetworkPolicy should be created - ## - enabled: false - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port Redis is listening - ## on. When true, zookeeper accept connections from any source - ## (with the correct destination port). - ## - # allowExternal: true - -## Zookeeper Prometheus Exporter configuration -## -metrics: - enabled: false - - ## Zookeeper Prometheus Exporter container port - ## - containerPort: 9141 - - ## Service configuration - ## - service: - ## Zookeeper Prometheus Exporter service type - ## - type: ClusterIP - ## Zookeeper Prometheus Exporter service port - ## - port: 9141 - ## Annotations for the Zookeeper Prometheus Exporter metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.service.port }}" - prometheus.io/path: "/metrics" - - ## Prometheus Operator ServiceMonitor configuration - ## - serviceMonitor: - enabled: false - ## Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) - ## - namespace: - - ## Interval at which metrics should be scraped. - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # interval: 10s - - ## Timeout after which the scrape is ended - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # scrapeTimeout: 10s - - ## ServiceMonitor selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - - ## Prometheus Operator PrometheusRule configuration - ## - prometheusRule: - enabled: false - ## Namespace for the PrometheusRule Resource (defaults to the Release Namespace) - ## - namespace: - - ## PrometheusRule selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - - ## Some example rules. - rules: [] - # - alert: ZookeeperSyncedFollowers - # annotations: - # message: The number of synced followers for the leader node in Zookeeper deployment my-release is less than 2. This usually means that some of the Zookeeper nodes aren't communicating properly. If it doesn't resolve itself you can try killing the pods (one by one). - # expr: max(synced_followers{service="my-release-metrics"}) < 2 - # for: 5m - # labels: - # severity: critical - # - alert: ZookeeperOutstandingRequests - # annotations: - # message: The number of outstanding requests for Zookeeper pod {{ $labels.pod }} is greater than 10. This can indicate a performance issue with the Pod or cluster a whole. - # expr: outstanding_requests{service="my-release-metrics"} > 10 - # for: 5m - # labels: - # severity: critical diff --git a/ee/scripts/helm/db/kafka/files/jks/README.md b/ee/scripts/helm/db/kafka/files/jks/README.md deleted file mode 100755 index e110a8825..000000000 --- a/ee/scripts/helm/db/kafka/files/jks/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Java Key Stores - -You can copy here your Java Key Stores (JKS) files so a secret is created including them. Remember to use a truststore (`kafka.truststore.jks`) and one keystore (`kafka.keystore.jks`) per Kafka broker you have in the cluster. For instance, if you have 3 brokers you need to copy here the following files: - -- kafka.truststore.jks -- kafka-0.keystore.jks -- kafka-1.keystore.jks -- kafka-2.keystore.jks - -Find more info in [this section](https://github.com/bitnami/charts/tree/master/bitnami/kafka#enable-security-for-kafka-and-zookeeper) of the README.md file. diff --git a/ee/scripts/helm/db/kafka/kafka.yaml b/ee/scripts/helm/db/kafka/kafka.yaml deleted file mode 100644 index acd718957..000000000 --- a/ee/scripts/helm/db/kafka/kafka.yaml +++ /dev/null @@ -1,521 +0,0 @@ ---- -# Source: kafka/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kafka - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka ---- -# Source: kafka/templates/scripts-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: kafka-scripts - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm -data: - setup.sh: |- - #!/bin/bash - - ID="${MY_POD_NAME#"kafka-"}" - export KAFKA_CFG_BROKER_ID="$ID" - - exec /entrypoint.sh /run.sh ---- -# Source: kafka/charts/zookeeper/templates/svc-headless.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka-zookeeper-headless - namespace: db - labels: - app.kubernetes.io/name: zookeeper - helm.sh/chart: zookeeper-5.21.9 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: zookeeper -spec: - type: ClusterIP - clusterIP: None - publishNotReadyAddresses: true - ports: - - - name: tcp-client - port: 2181 - targetPort: client - - - - name: follower - port: 2888 - targetPort: follower - - name: tcp-election - port: 3888 - targetPort: election - selector: - app.kubernetes.io/name: zookeeper - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: zookeeper ---- -# Source: kafka/charts/zookeeper/templates/svc.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka-zookeeper - namespace: db - labels: - app.kubernetes.io/name: zookeeper - helm.sh/chart: zookeeper-5.21.9 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: zookeeper -spec: - type: ClusterIP - ports: - - - name: tcp-client - port: 2181 - targetPort: client - - - - name: follower - port: 2888 - targetPort: follower - - name: tcp-election - port: 3888 - targetPort: election - selector: - app.kubernetes.io/name: zookeeper - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: zookeeper ---- -# Source: kafka/templates/kafka-metrics-svc.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka-metrics - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: metrics - annotations: - - prometheus.io/path: /metrics - prometheus.io/port: '9308' - prometheus.io/scrape: "true" -spec: - type: ClusterIP - ports: - - name: http-metrics - port: 9308 - protocol: TCP - targetPort: metrics - nodePort: null - selector: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: metrics ---- -# Source: kafka/templates/svc-headless.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka-headless - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka -spec: - type: ClusterIP - clusterIP: None - ports: - - name: tcp-client - port: 9092 - protocol: TCP - targetPort: kafka-client - - name: tcp-internal - port: 9093 - protocol: TCP - targetPort: kafka-internal - selector: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: kafka ---- -# Source: kafka/templates/svc.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka -spec: - type: ClusterIP - ports: - - name: tcp-client - port: 9092 - protocol: TCP - targetPort: kafka-client - nodePort: null - selector: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: kafka ---- -# Source: kafka/templates/kafka-metrics-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: kafka-exporter - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: metrics -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: metrics - template: - metadata: - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: metrics - spec: - containers: - - name: kafka-exporter - image: docker.io/bitnami/kafka-exporter:1.2.0-debian-10-r220 - imagePullPolicy: "IfNotPresent" - command: - - /bin/bash - - -ec - - | - read -r -a sasl_passwords <<< "$(tr ',;' ' ' <<< "${SASL_USER_PASSWORD}")" - kafka_exporter \ - --kafka.server=kafka-0.kafka-headless.db.svc.cluster.local:9092 \ - --kafka.server=kafka-1.kafka-headless.db.svc.cluster.local:9092 \ - --web.listen-address=:9308 - ports: - - name: metrics - containerPort: 9308 - resources: - limits: {} - requests: {} ---- -# Source: kafka/charts/zookeeper/templates/statefulset.yaml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: kafka-zookeeper - namespace: db - labels: - app.kubernetes.io/name: zookeeper - helm.sh/chart: zookeeper-5.21.9 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: zookeeper - role: zookeeper -spec: - serviceName: kafka-zookeeper-headless - replicas: 1 - podManagementPolicy: Parallel - updateStrategy: - type: RollingUpdate - selector: - matchLabels: - app.kubernetes.io/name: zookeeper - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: zookeeper - template: - metadata: - name: kafka-zookeeper - labels: - app.kubernetes.io/name: zookeeper - helm.sh/chart: zookeeper-5.21.9 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: zookeeper - spec: - - serviceAccountName: default - securityContext: - fsGroup: 1001 - containers: - - name: zookeeper - image: docker.io/bitnami/zookeeper:3.6.2-debian-10-r10 - imagePullPolicy: "IfNotPresent" - securityContext: - runAsUser: 1001 - command: - - bash - - -ec - - | - # Execute entrypoint as usual after obtaining ZOO_SERVER_ID based on POD hostname - HOSTNAME=`hostname -s` - if [[ $HOSTNAME =~ (.*)-([0-9]+)$ ]]; then - ORD=${BASH_REMATCH[2]} - export ZOO_SERVER_ID=$((ORD+1)) - else - echo "Failed to get index from hostname $HOST" - exit 1 - fi - exec /entrypoint.sh /run.sh - resources: - requests: - cpu: 250m - memory: 256Mi - env: - - name: ZOO_DATA_LOG_DIR - value: "" - - name: ZOO_PORT_NUMBER - value: "2181" - - name: ZOO_TICK_TIME - value: "2000" - - name: ZOO_INIT_LIMIT - value: "10" - - name: ZOO_SYNC_LIMIT - value: "5" - - name: ZOO_MAX_CLIENT_CNXNS - value: "60" - - name: ZOO_4LW_COMMANDS_WHITELIST - value: "srvr, mntr, ruok" - - name: ZOO_LISTEN_ALLIPS_ENABLED - value: "no" - - name: ZOO_AUTOPURGE_INTERVAL - value: "0" - - name: ZOO_AUTOPURGE_RETAIN_COUNT - value: "3" - - name: ZOO_MAX_SESSION_TIMEOUT - value: "40000" - - name: ZOO_SERVERS - value: kafka-zookeeper-0.kafka-zookeeper-headless.db.svc.cluster.local:2888:3888 - - name: ZOO_ENABLE_AUTH - value: "no" - - name: ZOO_HEAP_SIZE - value: "1024" - - name: ZOO_LOG_LEVEL - value: "ERROR" - - name: ALLOW_ANONYMOUS_LOGIN - value: "yes" - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - ports: - - - name: client - containerPort: 2181 - - - - name: follower - containerPort: 2888 - - name: election - containerPort: 3888 - livenessProbe: - exec: - command: ['/bin/bash', '-c', 'echo "ruok" | timeout 2 nc -w 2 localhost 2181 | grep imok'] - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 6 - readinessProbe: - exec: - command: ['/bin/bash', '-c', 'echo "ruok" | timeout 2 nc -w 2 localhost 2181 | grep imok'] - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 6 - volumeMounts: - - name: data - mountPath: /bitnami/zookeeper - volumes: - volumeClaimTemplates: - - metadata: - name: data - annotations: - spec: - accessModes: - - "ReadWriteOnce" - resources: - requests: - storage: "8Gi" ---- -# Source: kafka/templates/statefulset.yaml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: kafka - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka -spec: - podManagementPolicy: Parallel - replicas: 2 - selector: - matchLabels: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: kafka - serviceName: kafka-headless - updateStrategy: - type: "RollingUpdate" - template: - metadata: - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka - spec: - securityContext: - fsGroup: 1001 - runAsUser: 1001 - serviceAccountName: kafka - containers: - - name: kafka - image: docker.io/bitnami/kafka:2.6.0-debian-10-r30 - imagePullPolicy: "IfNotPresent" - command: - - /scripts/setup.sh - env: - - name: BITNAMI_DEBUG - value: "false" - - name: MY_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: MY_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KAFKA_CFG_ZOOKEEPER_CONNECT - value: "kafka-zookeeper" - - name: KAFKA_INTER_BROKER_LISTENER_NAME - value: "INTERNAL" - - name: KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP - value: "INTERNAL:PLAINTEXT,CLIENT:PLAINTEXT" - - name: KAFKA_CFG_LISTENERS - value: "INTERNAL://:9093,CLIENT://:9092" - - name: KAFKA_CFG_ADVERTISED_LISTENERS - value: "INTERNAL://$(MY_POD_NAME).kafka-headless.db.svc.cluster.local:9093,CLIENT://$(MY_POD_NAME).kafka-headless.db.svc.cluster.local:9092" - - name: ALLOW_PLAINTEXT_LISTENER - value: "yes" - - name: KAFKA_CFG_DELETE_TOPIC_ENABLE - value: "false" - - name: KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE - value: "true" - - name: KAFKA_HEAP_OPTS - value: "-Xmx1024m -Xms1024m" - - name: KAFKA_CFG_LOG_FLUSH_INTERVAL_MESSAGES - value: "10000" - - name: KAFKA_CFG_LOG_FLUSH_INTERVAL_MS - value: "1000" - - name: KAFKA_CFG_LOG_RETENTION_BYTES - value: "1073741824" - - name: KAFKA_CFG_LOG_RETENTION_CHECK_INTERVALS_MS - value: "300000" - - name: KAFKA_CFG_LOG_RETENTION_HOURS - value: "168" - - name: KAFKA_CFG_MESSAGE_MAX_BYTES - value: "1000012" - - name: KAFKA_CFG_LOG_SEGMENT_BYTES - value: "1073741824" - - name: KAFKA_CFG_LOG_DIRS - value: "/bitnami/kafka/data" - - name: KAFKA_CFG_DEFAULT_REPLICATION_FACTOR - value: "1" - - name: KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR - value: "1" - - name: KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR - value: "1" - - name: KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR - value: "1" - - name: KAFKA_CFG_NUM_IO_THREADS - value: "8" - - name: KAFKA_CFG_NUM_NETWORK_THREADS - value: "3" - - name: KAFKA_CFG_NUM_PARTITIONS - value: "1" - - name: KAFKA_CFG_NUM_RECOVERY_THREADS_PER_DATA_DIR - value: "1" - - name: KAFKA_CFG_SOCKET_RECEIVE_BUFFER_BYTES - value: "102400" - - name: KAFKA_CFG_SOCKET_REQUEST_MAX_BYTES - value: "104857600" - - name: KAFKA_CFG_SOCKET_SEND_BUFFER_BYTES - value: "102400" - - name: KAFKA_CFG_ZOOKEEPER_CONNECTION_TIMEOUT_MS - value: "6000" - ports: - - name: kafka-client - containerPort: 9092 - - name: kafka-internal - containerPort: 9093 - livenessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: 10 - timeoutSeconds: 5 - failureThreshold: - periodSeconds: - successThreshold: - readinessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: 5 - timeoutSeconds: 5 - failureThreshold: 6 - periodSeconds: - successThreshold: - resources: - limits: {} - requests: {} - volumeMounts: - - name: data - mountPath: /bitnami/kafka - - name: scripts - mountPath: /scripts/setup.sh - subPath: setup.sh - volumes: - - name: scripts - configMap: - name: kafka-scripts - defaultMode: 0755 - volumeClaimTemplates: - - metadata: - name: data - spec: - accessModes: - - "ReadWriteOnce" - resources: - requests: - storage: "8Gi" diff --git a/ee/scripts/helm/db/kafka/requirements.lock b/ee/scripts/helm/db/kafka/requirements.lock deleted file mode 100755 index 115d0b229..000000000 --- a/ee/scripts/helm/db/kafka/requirements.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: zookeeper - repository: https://charts.bitnami.com/bitnami - version: 5.21.9 -digest: sha256:2f3c43ce02e3966648b8c89be121fe39537f62ea1d161ad908f51ddc90e4243e -generated: "2020-09-29T07:43:56.483358254Z" diff --git a/ee/scripts/helm/db/kafka/requirements.yaml b/ee/scripts/helm/db/kafka/requirements.yaml deleted file mode 100755 index 533875258..000000000 --- a/ee/scripts/helm/db/kafka/requirements.yaml +++ /dev/null @@ -1,5 +0,0 @@ -dependencies: - - name: zookeeper - version: 5.x.x - repository: https://charts.bitnami.com/bitnami - condition: zookeeper.enabled diff --git a/ee/scripts/helm/db/kafka/templates/NOTES.txt b/ee/scripts/helm/db/kafka/templates/NOTES.txt deleted file mode 100755 index 0347c21c4..000000000 --- a/ee/scripts/helm/db/kafka/templates/NOTES.txt +++ /dev/null @@ -1,181 +0,0 @@ -{{- $replicaCount := int .Values.replicaCount -}} -{{- $releaseNamespace := .Release.Namespace -}} -{{- $clusterDomain := .Values.clusterDomain -}} -{{- $fullname := include "kafka.fullname" . -}} -{{- $clientProtocol := include "kafka.listenerType" ( dict "protocol" .Values.auth.clientProtocol ) -}} -{{- $servicePort := int .Values.service.port -}} -{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs -}} -{{- if and .Values.externalAccess.enabled (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerIPListLength )) (eq .Values.externalAccess.service.type "LoadBalancer") }} - -############################################################################### -### ERROR: You enabled external access to Kafka brokers without specifying ### -### the array of load balancer IPs for Kafka brokers. ### -############################################################################### - -This deployment will be incomplete until you configure the array of load balancer -IPs for Kafka brokers. To complete your deployment follow the steps below: - -1. Wait for the load balancer IPs (it may take a few minutes for them to be available): - - kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "kafka.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=kafka,pod" -w - -2. Obtain the load balancer IPs and upgrade your chart: - - {{- range $i, $e := until $replicaCount }} - LOAD_BALANCER_IP_{{ add $i 1 }}="$(kubectl get svc --namespace {{ $releaseNamespace }} {{ $fullname }}-{{ $i }}-external -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" - {{- end }} - -3. Upgrade you chart: - - helm upgrade {{ .Release.Name }} bitnami/{{ .Chart.Name }} \ - --set replicaCount={{ $replicaCount }} \ - --set externalAccess.enabled=true \ - {{- range $i, $e := until $replicaCount }} - --set externalAccess.service.loadBalancerIPs[{{ $i }}]=$LOAD_BALANCER_IP_{{ add $i 1 }} \ - {{- end }} - --set externalAccess.service.type=LoadBalancer - -{{- else }} - -{{- if and (or (eq .Values.service.type "LoadBalancer") .Values.externalAccess.enabled) (eq .Values.auth.clientProtocol "plaintext") }} ---------------------------------------------------------------------------------------------- - WARNING - - By specifying "serviceType=LoadBalancer" and not configuring the authentication - you have most likely exposed the Kafka service externally without any - authentication mechanism. - - For security reasons, we strongly suggest that you switch to "ClusterIP" or - "NodePort". As alternative, you can also configure the Kafka authentication. - ---------------------------------------------------------------------------------------------- -{{- end }} - -** Please be patient while the chart is being deployed ** - -Kafka can be accessed by consumers via port {{ $servicePort }} on the following DNS name from within your cluster: - - {{ $fullname }}.{{ $releaseNamespace }}.svc.{{ $clusterDomain }} - -Each Kafka broker can be accessed by producers via port {{ $servicePort }} on the following DNS name(s) from within your cluster: - -{{- $brokerList := list }} -{{- range $e, $i := until $replicaCount }} -{{- $brokerList = append $brokerList (printf "%s-%d.%s-headless.%s.svc.%s:%d" $fullname $i $fullname $releaseNamespace $clusterDomain $servicePort) }} -{{- end }} -{{ join "\n" $brokerList | nindent 4 }} - - -{{- if (include "kafka.client.saslAuthentication" .) }} - -You need to configure your Kafka client to access using SASL authentication. To do so, you need to create the 'kafka_jaas.conf' and 'client.properties' configuration files by executing these commands: - - - kafka_jaas.conf: - -cat > kafka_jaas.conf < client.properties <<>(Value) - name: kafka_controller_$1_$2_$4 - labels: - broker_id: "$3" - - pattern: kafka.controller<>(Value) - name: kafka_controller_$1_$2_$3 - - pattern: kafka.controller<>(Value) - name: kafka_controller_$1_$2_$3 - - pattern: kafka.controller<>(Count) - name: kafka_controller_$1_$2_$3 - - pattern: kafka.server<>(Value) - name: kafka_server_$1_$2_$4 - labels: - client_id: "$3" - - pattern : kafka.network<>(Value) - name: kafka_network_$1_$2_$4 - labels: - network_processor: $3 - - pattern : kafka.network<>(Count) - name: kafka_network_$1_$2_$4 - labels: - request: $3 - - pattern: kafka.server<>(Count|OneMinuteRate) - name: kafka_server_$1_$2_$4 - labels: - topic: $3 - - pattern: kafka.server<>(Value) - name: kafka_server_$1_$2_$3_$4 - - pattern: kafka.server<>(Count|Value|OneMinuteRate) - name: kafka_server_$1_total_$2_$3 - - pattern: kafka.server<>(queue-size) - name: kafka_server_$1_$2 - - pattern: java.lang<(.+)>(\w+) - name: java_lang_$1_$4_$3_$2 - - pattern: java.lang<>(\w+) - name: java_lang_$1_$3_$2 - - pattern : java.lang - - pattern: kafka.log<>Value - name: kafka_log_$1_$2 - labels: - topic: $3 - partition: $4 -{{- end -}} diff --git a/ee/scripts/helm/db/kafka/templates/jmx-metrics-svc.yaml b/ee/scripts/helm/db/kafka/templates/jmx-metrics-svc.yaml deleted file mode 100755 index 83edd8422..000000000 --- a/ee/scripts/helm/db/kafka/templates/jmx-metrics-svc.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{{- if .Values.metrics.jmx.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" . }}-jmx-metrics - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.metrics.jmx.service.annotations .Values.commonAnnotations }} - annotations: - {{- if .Values.metrics.jmx.service.annotations }} - {{ include "kafka.tplValue" ( dict "value" .Values.metrics.jmx.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.metrics.jmx.service.type }} - {{- if eq .Values.metrics.jmx.service.type "LoadBalancer" }} - {{- if .Values.metrics.jmx.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.metrics.jmx.service.loadBalancerIP }} - {{- end }} - {{- if .Values.metrics.jmx.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- toYaml .Values.metrics.jmx.service.loadBalancerSourceRanges | nindent 4 }} - {{- end }} - {{- end }} - {{- if and (eq .Values.metrics.jmx.service.type "ClusterIP") .Values.metrics.jmx.service.clusterIP }} - clusterIP: {{ .Values.metrics.jmx.service.clusterIP }} - {{- end }} - ports: - - name: http-metrics - port: {{ .Values.metrics.jmx.service.port }} - protocol: TCP - targetPort: metrics - {{- if and (or (eq .Values.metrics.jmx.service.type "NodePort") (eq .Values.metrics.jmx.service.type "LoadBalancer")) (not (empty .Values.metrics.jmx.service.nodePort)) }} - nodePort: {{ .Values.metrics.jmx.service.nodePort }} - {{- else if eq .Values.metrics.jmx.service.type "ClusterIP" }} - nodePort: null - {{- end }} - selector: {{- include "kafka.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: kafka -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/kafka-metrics-deployment.yaml b/ee/scripts/helm/db/kafka/templates/kafka-metrics-deployment.yaml deleted file mode 100755 index c547fbb39..000000000 --- a/ee/scripts/helm/db/kafka/templates/kafka-metrics-deployment.yaml +++ /dev/null @@ -1,87 +0,0 @@ -{{- if .Values.metrics.kafka.enabled }} -{{- $replicaCount := int .Values.replicaCount -}} -{{- $releaseNamespace := .Release.Namespace -}} -{{- $clusterDomain := .Values.clusterDomain -}} -{{- $fullname := include "kafka.fullname" . -}} -{{- $servicePort := int .Values.service.port -}} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "kafka.fullname" . }}-exporter - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: metrics - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - replicas: 1 - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: metrics - template: - metadata: - labels: {{- include "kafka.labels" . | nindent 8 }} - app.kubernetes.io/component: metrics - spec: -{{- include "kafka.imagePullSecrets" . | indent 6 }} - containers: - - name: kafka-exporter - image: {{ include "kafka.metrics.kafka.image" . }} - imagePullPolicy: {{ .Values.metrics.kafka.image.pullPolicy | quote }} - command: - - /bin/bash - - -ec - - | - read -r -a sasl_passwords <<< "$(tr ',;' ' ' <<< "${SASL_USER_PASSWORD}")" - kafka_exporter \ - {{- range $i, $e := until $replicaCount }} - --kafka.server={{ $fullname }}-{{ $i }}.{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $servicePort }} \ - {{- end }} - {{- if (include "kafka.client.saslAuthentication" .) }} - --sasl.enabled \ - --sasl.username="$SASL_USERNAME" \ - --sasl.password="${sasl_passwords[0]}" \ - {{- end }} - {{- if (include "kafka.tlsEncryption" .) }} - --tls.enabled \ - {{- if .Values.metrics.kafka.certificatesSecret }} - --tls.ca-file="/opt/bitnami/kafka-exporter/certs/ca-file" \ - --tls.cert-file="/opt/bitnami/kafka-exporter/certs/cert-file" \ - --tls.key-file="/opt/bitnami/kafka-exporter/certs/key-file" \ - {{- end }} - {{- end }} - {{- range $key, $value := .Values.metrics.kafka.extraFlags }} - --{{ $key }}{{ if $value }}={{ $value }}{{ end }} \ - {{- end }} - --web.listen-address=:9308 - {{- if (include "kafka.client.saslAuthentication" .) }} - env: - - name: SASL_USERNAME - value: {{ index .Values.auth.jaas.clientUsers 0 | quote }} - - name: SASL_USER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "kafka.jaasSecretName" . }} - key: client-passwords - {{- end }} - ports: - - name: metrics - containerPort: 9308 - {{- if .Values.metrics.kafka.resources }} - resources: {{ toYaml .Values.metrics.kafka.resources | nindent 12 }} - {{- end }} - {{- if and (include "kafka.tlsEncryption" .) .Values.metrics.kafka.certificatesSecret }} - volumeMounts: - - name: kafka-exporter-certificates - mountPath: /opt/bitnami/kafka-exporter/certs/ - readOnly: true - volumes: - - name: kafka-exporter-certificates - secret: - secretName: {{ .Values.metrics.kafka.certificatesSecret }} - defaultMode: 0440 - {{- end }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/kafka-metrics-svc.yaml b/ee/scripts/helm/db/kafka/templates/kafka-metrics-svc.yaml deleted file mode 100755 index 54a4ccb0b..000000000 --- a/ee/scripts/helm/db/kafka/templates/kafka-metrics-svc.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{{- if .Values.metrics.kafka.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" . }}-metrics - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: metrics - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.metrics.kafka.service.annotations .Values.commonAnnotations }} - annotations: - {{- if .Values.metrics.kafka.service.annotations }} - {{ include "kafka.tplValue" ( dict "value" .Values.metrics.kafka.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.metrics.kafka.service.type }} - {{- if eq .Values.metrics.kafka.service.type "LoadBalancer" }} - {{- if .Values.metrics.kafka.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.metrics.kafka.service.loadBalancerIP }} - {{- end }} - {{- if .Values.metrics.kafka.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- toYaml .Values.metrics.kafka.service.loadBalancerSourceRanges | nindent 4 }} - {{- end }} - {{- end }} - {{- if and (eq .Values.metrics.kafka.service.type "ClusterIP") .Values.metrics.kafka.service.clusterIP }} - clusterIP: {{ .Values.metrics.kafka.service.clusterIP }} - {{- end }} - ports: - - name: http-metrics - port: {{ .Values.metrics.kafka.service.port }} - protocol: TCP - targetPort: metrics - {{- if and (or (eq .Values.metrics.kafka.service.type "NodePort") (eq .Values.metrics.kafka.service.type "LoadBalancer")) (not (empty .Values.metrics.kafka.service.nodePort)) }} - nodePort: {{ .Values.metrics.kafka.service.nodePort }} - {{- else if eq .Values.metrics.kafka.service.type "ClusterIP" }} - nodePort: null - {{- end }} - selector: {{- include "kafka.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: metrics -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/log4j-configmap.yaml b/ee/scripts/helm/db/kafka/templates/log4j-configmap.yaml deleted file mode 100755 index 0a34d50dd..000000000 --- a/ee/scripts/helm/db/kafka/templates/log4j-configmap.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if (include "kafka.log4j.createConfigMap" .) }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "kafka.log4j.configMapName" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: - log4j.properties: |- - {{ .Values.log4j | nindent 4 }} -{{- end -}} diff --git a/ee/scripts/helm/db/kafka/templates/poddisruptionbudget.yaml b/ee/scripts/helm/db/kafka/templates/poddisruptionbudget.yaml deleted file mode 100755 index cf515becb..000000000 --- a/ee/scripts/helm/db/kafka/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- $replicaCount := int .Values.replicaCount }} -{{- if and .Values.pdb.create (gt $replicaCount 1) }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - {{- if .Values.pdb.minAvailable }} - minAvailable: {{ .Values.pdb.minAvailable }} - {{- end }} - {{- if .Values.pdb.maxUnavailable }} - maxUnavailable: {{ .Values.pdb.maxUnavailable }} - {{- end }} - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: kafka -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/role.yaml b/ee/scripts/helm/db/kafka/templates/role.yaml deleted file mode 100755 index 943c5bf3c..000000000 --- a/ee/scripts/helm/db/kafka/templates/role.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -rules: - - apiGroups: - - "" - resources: - - services - verbs: - - get - - list - - watch -{{- end -}} diff --git a/ee/scripts/helm/db/kafka/templates/rolebinding.yaml b/ee/scripts/helm/db/kafka/templates/rolebinding.yaml deleted file mode 100755 index 78f940f85..000000000 --- a/ee/scripts/helm/db/kafka/templates/rolebinding.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if and .Values.serviceAccount.create .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -roleRef: - kind: Role - name: {{ template "kafka.fullname" . }} - apiGroup: rbac.authorization.k8s.io -subjects: - - kind: ServiceAccount - name: {{ template "kafka.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/scripts-configmap.yaml b/ee/scripts/helm/db/kafka/templates/scripts-configmap.yaml deleted file mode 100755 index 705545a61..000000000 --- a/ee/scripts/helm/db/kafka/templates/scripts-configmap.yaml +++ /dev/null @@ -1,118 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "kafka.fullname" . }}-scripts - labels: {{- include "kafka.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: - {{- $fullname := include "kafka.fullname" . }} - {{- $releaseNamespace := .Release.Namespace }} - {{- $clusterDomain := .Values.clusterDomain }} - {{- $interBrokerPort := .Values.service.internalPort }} - {{- $clientPort := .Values.service.port }} - {{- if .Values.externalAccess.autoDiscovery.enabled }} - auto-discovery.sh: |- - #!/bin/bash - - SVC_NAME="${MY_POD_NAME}-external" - - {{- if eq .Values.externalAccess.service.type "LoadBalancer" }} - # Auxiliar functions - retry_while() { - local -r cmd="${1:?cmd is missing}" - local -r retries="${2:-12}" - local -r sleep_time="${3:-5}" - local return_value=1 - - read -r -a command <<< "$cmd" - for ((i = 1 ; i <= retries ; i+=1 )); do - "${command[@]}" && return_value=0 && break - sleep "$sleep_time" - done - return $return_value - } - k8s_svc_lb_ip() { - local namespace=${1:?namespace is missing} - local service=${2:?service is missing} - local service_ip=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].ip}") - local service_hostname=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].hostname}") - - if [[ -n ${service_ip} ]]; then - echo "${service_ip}" - else - echo "${service_hostname}" - fi - } - k8s_svc_lb_ip_ready() { - local namespace=${1:?namespace is missing} - local service=${2:?service is missing} - [[ -n "$(k8s_svc_lb_ip "$namespace" "$service")" ]] - } - # Wait until LoadBalancer IP is ready - retry_while "k8s_svc_lb_ip_ready {{ $releaseNamespace }} $SVC_NAME" || exit 1 - # Obtain LoadBalancer external IP - k8s_svc_lb_ip "{{ $releaseNamespace }}" "$SVC_NAME" | tee "$SHARED_FILE" - {{- else if eq .Values.externalAccess.service.type "NodePort" }} - k8s_svc_node_port() { - local namespace=${1:?namespace is missing} - local service=${2:?service is missing} - local index=${3:-0} - local node_port="$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.spec.ports[$index].nodePort}")" - echo "$node_port" - } - k8s_svc_node_port "{{ $releaseNamespace }}" "$SVC_NAME" | tee "$SHARED_FILE" - {{- end }} - {{- end }} - setup.sh: |- - #!/bin/bash - - ID="${MY_POD_NAME#"{{ $fullname }}-"}" - export KAFKA_CFG_BROKER_ID="$ID" - - {{- if .Values.externalAccess.enabled }} - # Configure external ip and port - {{- if eq .Values.externalAccess.service.type "LoadBalancer" }} - {{- if .Values.externalAccess.autoDiscovery.enabled }} - export EXTERNAL_ACCESS_IP="$(<${SHARED_FILE})" - {{- else }} - export EXTERNAL_ACCESS_IP=$(echo '{{ .Values.externalAccess.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") - {{- end }} - export EXTERNAL_ACCESS_PORT={{ .Values.externalAccess.service.port }} - {{- else if eq .Values.externalAccess.service.type "NodePort" }} - {{- if .Values.externalAccess.service.domain }} - export EXTERNAL_ACCESS_IP={{ .Values.externalAccess.service.domain }} - {{- else }} - export EXTERNAL_ACCESS_IP=$(curl -s https://ipinfo.io/ip) - {{- end }} - {{- if .Values.externalAccess.autoDiscovery.enabled }} - export EXTERNAL_ACCESS_PORT="$(<${SHARED_FILE})" - {{- else }} - export EXTERNAL_ACCESS_PORT=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") - {{- end }} - {{- end }} - - # Configure Kafka advertised listeners - {{- if .Values.advertisedListeners }} - export KAFKA_CFG_ADVERTISED_LISTENERS={{ .Values.advertisedListeners }} - {{- else }} - export KAFKA_CFG_ADVERTISED_LISTENERS="INTERNAL://${MY_POD_NAME}.{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $interBrokerPort }},CLIENT://${MY_POD_NAME}.{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $clientPort }},EXTERNAL://${EXTERNAL_ACCESS_IP}:${EXTERNAL_ACCESS_PORT}" - {{- end }} - {{- end }} - - {{- if (include "kafka.tlsEncryption" .) }} - if [[ -f "/certs/kafka.truststore.jks" ]] && [[ -f "/certs/kafka-${ID}.keystore.jks" ]]; then - mkdir -p /opt/bitnami/kafka/config/certs - cp "/certs/kafka.truststore.jks" "/opt/bitnami/kafka/config/certs/kafka.truststore.jks" - cp "/certs/kafka-${ID}.keystore.jks" "/opt/bitnami/kafka/config/certs/kafka.keystore.jks" - else - echo "Couldn't find the expected Java Key Stores (JKS) files! They are mandatory when encryption via TLS is enabled." - exit 1 - fi - {{- end }} - - exec /entrypoint.sh /run.sh diff --git a/ee/scripts/helm/db/kafka/templates/serviceaccount.yaml b/ee/scripts/helm/db/kafka/templates/serviceaccount.yaml deleted file mode 100755 index 790790b3f..000000000 --- a/ee/scripts/helm/db/kafka/templates/serviceaccount.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "kafka.serviceAccountName" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/servicemonitor-jmx-metrics.yaml b/ee/scripts/helm/db/kafka/templates/servicemonitor-jmx-metrics.yaml deleted file mode 100755 index 250bb5306..000000000 --- a/ee/scripts/helm/db/kafka/templates/servicemonitor-jmx-metrics.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if and .Values.metrics.jmx.enabled .Values.metrics.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kafka.fullname" . }}-jmx-metrics - {{- if .Values.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.metrics.serviceMonitor.namespace }} - {{- end }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- range $key, $value := .Values.metrics.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: kafka - endpoints: - - port: http-metrics - path: "/" - {{- if .Values.metrics.serviceMonitor.interval }} - interval: {{ .Values.metrics.serviceMonitor.interval }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} - {{- end }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/servicemonitor-metrics.yaml b/ee/scripts/helm/db/kafka/templates/servicemonitor-metrics.yaml deleted file mode 100755 index 951bf7c41..000000000 --- a/ee/scripts/helm/db/kafka/templates/servicemonitor-metrics.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if and .Values.metrics.kafka.enabled .Values.metrics.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kafka.fullname" . }}-metrics - {{- if .Values.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.metrics.serviceMonitor.namespace }} - {{- end }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: metrics - {{- range $key, $value := .Values.metrics.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: metrics - endpoints: - - port: http-metrics - path: "/metrics" - {{- if .Values.metrics.serviceMonitor.interval }} - interval: {{ .Values.metrics.serviceMonitor.interval }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} - {{- end }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/statefulset.yaml b/ee/scripts/helm/db/kafka/templates/statefulset.yaml deleted file mode 100755 index e9b5ce8f9..000000000 --- a/ee/scripts/helm/db/kafka/templates/statefulset.yaml +++ /dev/null @@ -1,435 +0,0 @@ -{{- $replicaCount := int .Values.replicaCount }} -{{- $fullname := include "kafka.fullname" . }} -{{- $releaseNamespace := .Release.Namespace }} -{{- $clusterDomain := .Values.clusterDomain }} -{{- $interBrokerPort := .Values.service.internalPort }} -{{- $clientPort := .Values.service.port }} -{{- $interBrokerProtocol := include "kafka.listenerType" ( dict "protocol" .Values.auth.interBrokerProtocol ) -}} -{{- $clientProtocol := include "kafka.listenerType" ( dict "protocol" .Values.auth.clientProtocol ) -}} -{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} -{{- if not (and .Values.externalAccess.enabled (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerIPListLength )) (eq .Values.externalAccess.service.type "LoadBalancer")) }} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ include "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - podManagementPolicy: Parallel - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: kafka - serviceName: {{ template "kafka.fullname" . }}-headless - updateStrategy: - type: {{ .Values.updateStrategy | quote }} - {{- if (eq "OnDelete" .Values.updateStrategy) }} - rollingUpdate: null - {{- else if .Values.rollingUpdatePartition }} - rollingUpdate: - partition: {{ .Values.rollingUpdatePartition }} - {{- end }} - template: - metadata: - labels: {{- include "kafka.labels" . | nindent 8 }} - app.kubernetes.io/component: kafka - {{- if .Values.podLabels }} - {{- include "kafka.tplValue" (dict "value" .Values.podLabels "context" $) | nindent 8 }} - {{- end }} - {{- if or (include "kafka.createConfigmap" .) (include "kafka.createJaasSecret" .) .Values.externalAccess.enabled (include "kafka.metrics.jmx.createConfigmap" .) .Values.podAnnotations }} - annotations: - {{- if (include "kafka.createConfigmap" .) }} - checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - {{- end }} - {{- if (include "kafka.createJaasSecret" .) }} - checksum/secret: {{ include (print $.Template.BasePath "/jaas-secret.yaml") . | sha256sum }} - {{- end }} - {{- if .Values.externalAccess.enabled }} - checksum/scripts: {{ include (print $.Template.BasePath "/scripts-configmap.yaml") . | sha256sum }} - {{- end }} - {{- if (include "kafka.metrics.jmx.createConfigmap" .) }} - checksum/jmx-configuration: {{ include (print $.Template.BasePath "/jmx-configmap.yaml") . | sha256sum }} - {{- end }} - {{- if .Values.podAnnotations }} - {{- include "kafka.tplValue" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} - {{- end }} - {{- end }} - spec: -{{- include "kafka.imagePullSecrets" . | indent 6 }} - {{- if .Values.affinity }} - affinity: {{- include "kafka.tplValue" ( dict "value" .Values.affinity "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: {{- include "kafka.tplValue" ( dict "value" .Values.nodeSelector "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.tolerations }} - tolerations: {{- include "kafka.tplValue" ( dict "value" .Values.tolerations "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.priorityClassName }} - priorityClassName: {{ .Values.priorityClassName }} - {{- end }} - {{- if .Values.podSecurityContext }} - securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} - {{- end }} - {{- if .Values.serviceAccount.create }} - serviceAccountName: {{ template "kafka.serviceAccountName" . }} - {{- end }} - {{- if or (and .Values.volumePermissions.enabled .Values.persistence.enabled) (and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled) }} - initContainers: - {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} - - name: volume-permissions - image: {{ include "kafka.volumePermissions.image" . }} - imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} - command: - - /bin/bash - args: - - -ec - - | - mkdir -p /bitnami/kafka - chown -R "{{ .Values.podSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }}" "/bitnami/kafka" - securityContext: - runAsUser: 0 - {{- if .Values.volumePermissions.resources }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: data - mountPath: /bitnami/kafka - {{- end }} - {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled }} - - name: auto-discovery - image: {{ include "kafka.externalAccess.autoDiscovery.image" . }} - imagePullPolicy: {{ .Values.externalAccess.autoDiscovery.image.pullPolicy | quote }} - command: - - /scripts/auto-discovery.sh - env: - - name: MY_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: SHARED_FILE - value: "/shared/info.txt" - {{- if .Values.externalAccess.autoDiscovery.resources }} - resources: {{- toYaml .Values.externalAccess.autoDiscovery.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: shared - mountPath: /shared - - name: scripts - mountPath: /scripts/auto-discovery.sh - subPath: auto-discovery.sh - {{- end }} - {{- end }} - containers: - - name: kafka - image: {{ include "kafka.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - command: {{- include "kafka.tplValue" (dict "value" .Values.command "context" $) | nindent 12 }} - {{- if .Values.args }} - args: {{- include "kafka.tplValue" (dict "value" .Values.args "context" $) | nindent 12 }} - {{- end }} - env: - - name: BITNAMI_DEBUG - value: {{ ternary "true" "false" .Values.image.debug | quote }} - - name: MY_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: MY_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KAFKA_CFG_ZOOKEEPER_CONNECT - {{- if .Values.zookeeper.enabled }} - value: {{ include "kafka.zookeeper.fullname" . | quote }} - {{- else }} - value: {{ join "," .Values.externalZookeeper.servers | quote }} - {{- end }} - - name: KAFKA_INTER_BROKER_LISTENER_NAME - value: {{ .Values.interBrokerListenerName | quote }} - - name: KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP - {{- if .Values.listenerSecurityProtocolMap }} - value: {{ .Values.listenerSecurityProtocolMap | quote }} - {{- else if .Values.externalAccess.enabled }} - value: "INTERNAL:{{ $interBrokerProtocol }},CLIENT:{{ $clientProtocol }},EXTERNAL:{{ $clientProtocol }}" - {{- else }} - value: "INTERNAL:{{ $interBrokerProtocol }},CLIENT:{{ $clientProtocol }}" - {{- end }} - {{- if or ($clientProtocol | regexFind "SASL") ($interBrokerProtocol | regexFind "SASL") .Values.auth.jaas.zookeeperUser }} - - name: KAFKA_CFG_SASL_ENABLED_MECHANISMS - value: {{ include "kafka.auth.saslMechanisms" ( dict "type" .Values.auth.saslMechanisms ) }} - - name: KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL - value: {{ upper .Values.auth.saslInterBrokerMechanism | quote }} - {{- end }} - - name: KAFKA_CFG_LISTENERS - {{- if .Values.listeners }} - value: {{ .Values.listeners }} - {{- else if .Values.externalAccess.enabled }} - value: "INTERNAL://:{{ $interBrokerPort }},CLIENT://:9092,EXTERNAL://:9094" - {{- else }} - value: "INTERNAL://:{{ $interBrokerPort }},CLIENT://:9092" - {{- end }} - {{- if .Values.externalAccess.enabled }} - {{- if .Values.externalAccess.autoDiscovery.enabled }} - - name: SHARED_FILE - value: "/shared/info.txt" - {{- end }} - {{- else }} - - name: KAFKA_CFG_ADVERTISED_LISTENERS - {{- if .Values.advertisedListeners }} - value: {{ .Values.advertisedListeners }} - {{- else }} - value: "INTERNAL://$(MY_POD_NAME).{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $interBrokerPort }},CLIENT://$(MY_POD_NAME).{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $clientPort }}" - {{- end }} - {{- end }} - - name: ALLOW_PLAINTEXT_LISTENER - value: {{ ternary "yes" "no" (or .Values.auth.enabled .Values.allowPlaintextListener) | quote }} - {{- if or (include "kafka.client.saslAuthentication" .) (include "kafka.interBroker.saslAuthentication" .) }} - - name: KAFKA_OPTS - value: "-Djava.security.auth.login.config=/opt/bitnami/kafka/config/kafka_jaas.conf" - {{- if (include "kafka.client.saslAuthentication" .) }} - - name: KAFKA_CLIENT_USERS - value: {{ join "," .Values.auth.jaas.clientUsers | quote }} - - name: KAFKA_CLIENT_PASSWORDS - valueFrom: - secretKeyRef: - name: {{ include "kafka.jaasSecretName" . }} - key: client-passwords - {{- end }} - {{- if .Values.auth.jaas.zookeeperUser }} - - name: KAFKA_ZOOKEEPER_PROTOCOL - value: "SASL" - - name: KAFKA_ZOOKEEPER_USER - value: {{ .Values.auth.jaas.zookeeperUser | quote }} - - name: KAFKA_ZOOKEEPER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "kafka.jaasSecretName" . }} - key: zookeeper-password - {{- end }} - {{- if (include "kafka.interBroker.saslAuthentication" .) }} - - name: KAFKA_INTER_BROKER_USER - value: {{ .Values.auth.jaas.interBrokerUser | quote }} - - name: KAFKA_INTER_BROKER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "kafka.jaasSecretName" . }} - key: inter-broker-password - {{- end }} - {{- end }} - {{- if (include "kafka.tlsEncryption" .) }} - - name: KAFKA_CFG_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM - value: {{ .Values.auth.tlsEndpointIdentificationAlgorithm | quote }} - {{- if .Values.auth.jksPassword }} - - name: KAFKA_CERTIFICATE_PASSWORD - value: {{ .Values.auth.jksPassword | quote }} - {{- end }} - {{- end }} - {{- if .Values.metrics.jmx.enabled }} - - name: JMX_PORT - value: "5555" - {{- end }} - - name: KAFKA_CFG_DELETE_TOPIC_ENABLE - value: {{ .Values.deleteTopicEnable | quote }} - - name: KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE - value: {{ .Values.autoCreateTopicsEnable | quote }} - - name: KAFKA_HEAP_OPTS - value: {{ .Values.heapOpts | quote }} - - name: KAFKA_CFG_LOG_FLUSH_INTERVAL_MESSAGES - value: {{ .Values.logFlushIntervalMessages | quote }} - - name: KAFKA_CFG_LOG_FLUSH_INTERVAL_MS - value: {{ .Values.logFlushIntervalMs | quote }} - - name: KAFKA_CFG_LOG_RETENTION_BYTES - value: {{ .Values.logRetentionBytes | replace "_" "" | quote }} - - name: KAFKA_CFG_LOG_RETENTION_CHECK_INTERVALS_MS - value: {{ .Values.logRetentionCheckIntervalMs | quote }} - - name: KAFKA_CFG_LOG_RETENTION_HOURS - value: {{ .Values.logRetentionHours | quote }} - - name: KAFKA_CFG_MESSAGE_MAX_BYTES - value: {{ .Values.maxMessageBytes | replace "_" "" | quote }} - - name: KAFKA_CFG_LOG_SEGMENT_BYTES - value: {{ .Values.logSegmentBytes | replace "_" "" | quote }} - - name: KAFKA_CFG_LOG_DIRS - value: {{ .Values.logsDirs | quote }} - - name: KAFKA_CFG_DEFAULT_REPLICATION_FACTOR - value: {{ .Values.defaultReplicationFactor | quote }} - - name: KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR - value: {{ .Values.offsetsTopicReplicationFactor | quote }} - - name: KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR - value: {{ .Values.transactionStateLogReplicationFactor | quote }} - - name: KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR - value: {{ .Values.transactionStateLogMinIsr | quote }} - - name: KAFKA_CFG_NUM_IO_THREADS - value: {{ .Values.numIoThreads | quote }} - - name: KAFKA_CFG_NUM_NETWORK_THREADS - value: {{ .Values.numNetworkThreads | quote }} - - name: KAFKA_CFG_NUM_PARTITIONS - value: {{ .Values.numPartitions | quote }} - - name: KAFKA_CFG_NUM_RECOVERY_THREADS_PER_DATA_DIR - value: {{ .Values.numRecoveryThreadsPerDataDir | quote }} - - name: KAFKA_CFG_SOCKET_RECEIVE_BUFFER_BYTES - value: {{ .Values.socketReceiveBufferBytes | quote }} - - name: KAFKA_CFG_SOCKET_REQUEST_MAX_BYTES - value: {{ .Values.socketRequestMaxBytes | replace "_" "" | quote }} - - name: KAFKA_CFG_SOCKET_SEND_BUFFER_BYTES - value: {{ .Values.socketSendBufferBytes | quote }} - - name: KAFKA_CFG_ZOOKEEPER_CONNECTION_TIMEOUT_MS - value: {{ .Values.zookeeperConnectionTimeoutMs | quote }} - {{- if .Values.extraEnvVars }} - {{ include "kafka.tplValue" ( dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} - {{- end }} - ports: - - name: kafka-client - containerPort: 9092 - - name: kafka-internal - containerPort: {{ $interBrokerPort }} - {{- if .Values.externalAccess.enabled }} - - name: kafka-external - containerPort: 9094 - {{- end }} - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - {{- else if .Values.customLivenessProbe }} - livenessProbe: {{- include "kafka.tplValue" (dict "value" .Values.customlivenessProbe "context" $) | nindent 12 }} - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - successThreshold: {{ .Values.readinessProbe.successThreshold }} - {{- else if .Values.customReadinessProbe }} - readinessProbe: {{- include "kafka.tplValue" (dict "value" .Values.customreadinessProbe "context" $) | nindent 12 }} - {{- end }} - {{- if .Values.resources }} - resources: {{- toYaml .Values.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: data - mountPath: /bitnami/kafka - {{- if or .Values.config .Values.existingConfigmap }} - - name: kafka-config - mountPath: /bitnami/kafka/config/server.properties - subPath: server.properties - {{- end }} - {{- if or .Values.log4j .Values.existingLog4jConfigMap }} - - name: log4j-config - mountPath: /bitnami/kafka/config/log4j.properties - subPath: log4j.properties - {{- end }} - - name: scripts - mountPath: /scripts/setup.sh - subPath: setup.sh - {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled }} - - name: shared - mountPath: /shared - {{- end }} - {{- if (include "kafka.tlsEncryption" .) }} - - name: kafka-certificates - mountPath: /certs - readOnly: true - {{- end }} - {{- if .Values.extraVolumeMounts }} - {{- toYaml .Values.extraVolumeMounts | nindent 12 }} - {{- end }} - {{- if .Values.metrics.jmx.enabled }} - - name: jmx-exporter - image: {{ template "kafka.metrics.jmx.image" . }} - imagePullPolicy: {{ .Values.metrics.jmx.image.pullPolicy | quote }} - command: - - java - - -XX:+UnlockExperimentalVMOptions - - -XX:+UseCGroupMemoryLimitForHeap - - -XX:MaxRAMFraction=1 - - -XshowSettings:vm - - -jar - - jmx_prometheus_httpserver.jar - - "5556" - - /etc/jmx-kafka/jmx-kafka-prometheus.yml - ports: - - name: metrics - containerPort: 5556 - {{- if .Values.metrics.jmx.resources }} - resources: {{- toYaml .Values.metrics.jmx.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: jmx-config - mountPath: /etc/jmx-kafka - {{- end }} - {{- if .Values.sidecars }} - {{- include "kafka.tplValue" (dict "value" .Values.sidecars "context" $) | nindent 8 }} - {{- end }} - volumes: - {{- if or .Values.config .Values.existingConfigmap }} - - name: kafka-config - configMap: - name: {{ include "kafka.configmapName" . }} - {{- end }} - {{- if or .Values.log4j .Values.existingLog4jConfigMap }} - - name: log4j-config - configMap: - name: {{ include "kafka.log4j.configMapName" . }} - {{ end }} - - name: scripts - configMap: - name: {{ include "kafka.fullname" . }}-scripts - defaultMode: 0755 - {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled }} - - name: shared - emptyDir: {} - {{- end }} - {{- if .Values.metrics.jmx.enabled }} - - name: jmx-config - configMap: - name: {{ include "kafka.metrics.jmx.configmapName" . }} - {{- end }} - {{- if (include "kafka.tlsEncryption" .) }} - - name: kafka-certificates - secret: - secretName: {{ include "kafka.jksSecretName" . }} - defaultMode: 256 - {{- end }} - {{- if .Values.extraVolumes }} - {{- toYaml .Values.extraVolumes | nindent 8 }} - {{- end }} -{{- if not .Values.persistence.enabled }} - - name: data - emptyDir: {} -{{- else if .Values.persistence.existingClaim }} - - name: data - persistentVolumeClaim: - claimName: {{ printf "%s" (tpl .Values.persistence.existingClaim .) }} -{{- else }} - volumeClaimTemplates: - - metadata: - name: data - {{- if .Values.persistence.annotations }} - annotations: {{- include "kafka.tplValue" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} - {{- end }} - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{ include "kafka.storageClass" . | nindent 8 }} -{{- end }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/svc-external-access.yaml b/ee/scripts/helm/db/kafka/templates/svc-external-access.yaml deleted file mode 100755 index eefe0046d..000000000 --- a/ee/scripts/helm/db/kafka/templates/svc-external-access.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if .Values.externalAccess.enabled }} -{{- $fullName := include "kafka.fullname" . }} -{{- $replicaCount := .Values.replicaCount | int }} -{{- $root := . }} - -{{- range $i, $e := until $replicaCount }} -{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" $ }}-{{ $i }}-external - labels: {{- include "kafka.labels" $ | nindent 4 }} - app.kubernetes.io/component: kafka - pod: {{ $targetPod }} - {{- if $root.Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" $root.Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or $root.Values.externalAccess.service.annotations $root.Values.commonAnnotations }} - annotations: - {{- if $root.Values.externalAccess.service.annotations }} - {{ include "kafka.tplValue" ( dict "value" $root.Values.externalAccess.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if $root.Values.commonAnnotations }} - {{- include "kafka.tplValue" ( dict "value" $root.Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ $root.Values.externalAccess.service.type }} - {{- if eq $root.Values.externalAccess.service.type "LoadBalancer" }} - {{- if not (empty $root.Values.externalAccess.service.loadBalancerIPs) }} - loadBalancerIP: {{ index $root.Values.externalAccess.service.loadBalancerIPs $i }} - {{- end }} - {{- if $root.Values.externalAccess.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- toYaml $root.Values.externalAccess.service.loadBalancerSourceRanges | nindent 4 }} - {{- end }} - {{- end }} - ports: - - name: tcp-kafka - port: {{ $root.Values.externalAccess.service.port }} - {{- if not (empty $root.Values.externalAccess.service.nodePorts) }} - nodePort: {{ index $root.Values.externalAccess.service.nodePorts $i }} - {{- else }} - nodePort: null - {{- end }} - targetPort: kafka-external - selector: {{- include "kafka.matchLabels" $ | nindent 4 }} - app.kubernetes.io/component: kafka - statefulset.kubernetes.io/pod-name: {{ $targetPod }} ---- -{{- end }} -{{- end }} diff --git a/ee/scripts/helm/db/kafka/templates/svc-headless.yaml b/ee/scripts/helm/db/kafka/templates/svc-headless.yaml deleted file mode 100755 index e7c2e5e6e..000000000 --- a/ee/scripts/helm/db/kafka/templates/svc-headless.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" . }}-headless - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - type: ClusterIP - clusterIP: None - ports: - - name: tcp-client - port: {{ .Values.service.port }} - protocol: TCP - targetPort: kafka-client - - name: tcp-internal - port: {{ .Values.service.internalPort }} - protocol: TCP - targetPort: kafka-internal - selector: {{- include "kafka.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: kafka diff --git a/ee/scripts/helm/db/kafka/templates/svc.yaml b/ee/scripts/helm/db/kafka/templates/svc.yaml deleted file mode 100755 index 189cb9ffd..000000000 --- a/ee/scripts/helm/db/kafka/templates/svc.yaml +++ /dev/null @@ -1,49 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.service.annotations .Values.commonAnnotations }} - annotations: - {{- if .Values.service.annotations }} - {{ include "kafka.tplValue" ( dict "value" .Values.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.service.type }} - {{- if eq .Values.service.type "LoadBalancer" }} - {{- if .Values.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.service.loadBalancerIP }} - {{- end }} - {{- if .Values.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} - {{- end }} - {{- end }} - ports: - - name: tcp-client - port: {{ .Values.service.port }} - protocol: TCP - targetPort: kafka-client - {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.client)) }} - nodePort: {{ .Values.service.nodePorts.client }} - {{- else if eq .Values.service.type "ClusterIP" }} - nodePort: null - {{- end }} - {{- if and .Values.externalAccess.enabled (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) }} - - name: tcp-external - port: {{ .Values.service.externalPort }} - protocol: TCP - targetPort: kafka-external - {{- if (not (empty .Values.service.nodePorts.external)) }} - nodePort: {{ .Values.service.nodePorts.external }} - {{- end }} - {{- end }} - selector: {{- include "kafka.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: kafka diff --git a/ee/scripts/helm/db/kafka/values-production.yaml b/ee/scripts/helm/db/kafka/values-production.yaml deleted file mode 100755 index af6f43dba..000000000 --- a/ee/scripts/helm/db/kafka/values-production.yaml +++ /dev/null @@ -1,931 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -# global: -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami Kafka image version -## ref: https://hub.docker.com/r/bitnami/kafka/tags/ -## -image: - registry: docker.io - repository: bitnami/kafka - tag: 2.6.0-debian-10-r30 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Set to true if you would like to see extra information on logs - ## - debug: false - -## String to partially override kafka.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override kafka.fullname template -## -# fullnameOverride: - -## Kubernetes Cluster Domain -## -clusterDomain: cluster.local - -## Add labels to all the deployed resources -## -commonLabels: {} - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -## Kafka Configuration -## Specify content for server.properties -## The server.properties is auto-generated based on other parameters when this paremeter is not specified -## -## Example: -## config: |- -## broker.id=-1 -## listeners=PLAINTEXT://:9092 -## advertised.listeners=PLAINTEXT://KAFKA_IP:9092 -## num.network.threads=3 -## num.io.threads=8 -## socket.send.buffer.bytes=102400 -## socket.receive.buffer.bytes=102400 -## socket.request.max.bytes=104857600 -## log.dirs=/bitnami/kafka/data -## num.partitions=1 -## num.recovery.threads.per.data.dir=1 -## offsets.topic.replication.factor=1 -## transaction.state.log.replication.factor=1 -## transaction.state.log.min.isr=1 -## log.flush.interval.messages=10000 -## log.flush.interval.ms=1000 -## log.retention.hours=168 -## log.retention.bytes=1073741824 -## log.segment.bytes=1073741824 -## log.retention.check.interval.ms=300000 -## zookeeper.connect=ZOOKEEPER_SERVICE_NAME -## zookeeper.connection.timeout.ms=6000 -## group.initial.rebalance.delay.ms=0 -## -# config: - -## ConfigMap with Kafka Configuration -## NOTE: This will override config -## -# existingConfigmap: - -## Kafka Log4J Configuration -## An optional log4j.properties file to overwrite the default of the Kafka brokers. -## See an example log4j.properties at: -## https://github.com/apache/kafka/blob/trunk/config/log4j.properties -## -# log4j: - -## Kafka Log4j ConfigMap -## The name of an existing ConfigMap containing a log4j.properties file. -## NOTE: this will override log4j. -## -# existingLog4jConfigMap: - -## Kafka's Java Heap size -## -heapOpts: -Xmx1024m -Xms1024m - -## Switch to enable topic deletion or not. -## -deleteTopicEnable: false - -## Switch to enable auto creation of topics. -## Enabling auto creation of topics not recommended for production or similar environments. -## -autoCreateTopicsEnable: false - -## The number of messages to accept before forcing a flush of data to disk. -## -logFlushIntervalMessages: 10000 - -## The maximum amount of time a message can sit in a log before we force a flush. -## -logFlushIntervalMs: 1000 - -## A size-based retention policy for logs. -## -logRetentionBytes: _1073741824 - -## The interval at which log segments are checked to see if they can be deleted. -## -logRetentionCheckIntervalMs: 300000 - -## The minimum age of a log file to be eligible for deletion due to age. -## -logRetentionHours: 168 - -## The maximum size of a log segment file. When this size is reached a new log segment will be created. -## -logSegmentBytes: _1073741824 - -## A comma separated list of directories under which to store log files. -## -logsDirs: /bitnami/kafka/data - -## The largest record batch size allowed by Kafka -## -maxMessageBytes: _1000012 - -## Default replication factors for automatically created topics -## -defaultReplicationFactor: 3 - -## The replication factor for the offsets topic -## -offsetsTopicReplicationFactor: 3 - -## The replication factor for the transaction topic -## -transactionStateLogReplicationFactor: 3 - -## Overridden min.insync.replicas config for the transaction topic -## -transactionStateLogMinIsr: 3 - -## The number of threads doing disk I/O. -## -numIoThreads: 8 - -## The number of threads handling network requests. -## -numNetworkThreads: 3 - -## The default number of log partitions per topic. -## -numPartitions: 1 - -## The number of threads per data directory to be used for log recovery at startup and flushing at shutdown. -## -numRecoveryThreadsPerDataDir: 1 - -## The receive buffer (SO_RCVBUF) used by the socket server. -## -socketReceiveBufferBytes: 102400 - -## The maximum size of a request that the socket server will accept (protection against OOM). -## -socketRequestMaxBytes: _104857600 - -## The send buffer (SO_SNDBUF) used by the socket server. -## -socketSendBufferBytes: 102400 - -## Timeout in ms for connecting to zookeeper. -## -zookeeperConnectionTimeoutMs: 6000 - -## Command and args for running the container. Use array form -## -command: - - /scripts/setup.sh -args: - -## All the parameters from the configuration file can be overwritten by using environment variables with this format: KAFKA_CFG_{KEY} -## ref: https://github.com/bitnami/bitnami-docker-kafka#configuration -## Example: -## extraEnvVars: -## - name: KAFKA_CFG_BACKGROUND_THREADS -## value: "10" -## -extraEnvVars: [] - -## extraVolumes and extraVolumeMounts allows you to mount other volumes -## Examples: -# extraVolumes: -# - name: kafka-jaas -# secret: -# secretName: kafka-jaas -# extraVolumeMounts: -# - name: kafka-jaas -# mountPath: /bitnami/kafka/config/kafka_jaas.conf -# subPath: kafka_jaas.conf -extraVolumes: [] -extraVolumeMounts: [] - -## Extra objects to deploy (value evaluated as a template) -## -extraDeploy: [] - -## Authentication parameteres -## https://github.com/bitnami/bitnami-docker-kafka#security -## -auth: - ## Authentication protocol for client and inter-broker communications - ## Supported values: 'plaintext', 'tls', 'mtls', 'sasl' and 'sasl_tls' - ## This table shows the security provided on each protocol: - ## | Method | Authentication | Encryption via TLS | - ## | plaintext | None | No | - ## | tls | None | Yes | - ## | mtls | Yes (two-way authentication) | Yes | - ## | sasl | Yes (via SASL) | No | - ## | sasl_tls | Yes (via SASL) | Yes | - ## - clientProtocol: sasl - interBrokerProtocol: sasl - - ## Allowed SASL mechanisms when clientProtocol or interBrokerProtocol are using either sasl or sasl_tls - ## - saslMechanisms: plain,scram-sha-256,scram-sha-512 - ## SASL mechanism for inter broker communication - ## - saslInterBrokerMechanism: plain - - ## Name of the existing secret containing the truststore and - ## one keystore per Kafka broker you have in the Kafka cluster. - ## MANDATORY when 'tls', 'mtls', or 'sasl_tls' authentication protocols are used. - ## Create this secret following the steps below: - ## 1) Generate your trustore and keystore files. Helpful script: https://raw.githubusercontent.com/confluentinc/confluent-platform-security-tools/master/kafka-generate-ssl.sh - ## 2) Rename your truststore to `kafka.truststore.jks`. - ## 3) Rename your keystores to `kafka-X.keystore.jks` where X is the ID of each Kafka broker. - ## 4) Run the command below where SECRET_NAME is the name of the secret you want to create: - ## kubectl create secret generic SECRET_NAME --from-file=./kafka.truststore.jks --from-file=./kafka-0.keystore.jks --from-file=./kafka-1.keystore.jks ... - ## Alternatively, you can put your JKS files under the files/jks directory - ## - # jksSecret: - - ## Password to access the JKS files when they are password-protected. - ## - # jksPassword: - - ## The endpoint identification algorithm used by clients to validate server host name. - ## Disable server host name verification by setting it to an empty string - ## See: https://docs.confluent.io/current/kafka/authentication_ssl.html#optional-settings - ## - tlsEndpointIdentificationAlgorithm: https - - ## JAAS configuration for SASL authentication - ## MANDATORY when method is 'sasl', or 'sasl_tls' - ## - jaas: - ## Kafka client user list - ## - ## clientUsers: - ## - user1 - ## - user2 - ## - clientUsers: - - user - - ## Kafka client passwords - ## - ## clientPasswords: - ## - password1 - ## - password2 - ## - clientPasswords: [] - - ## Kafka inter broker communication user - ## - interBrokerUser: admin - - ## Kafka inter broker communication password - ## - interBrokerPassword: "" - - ## Kafka Zookeeper user - ## - zookeeperUser: zookeeperUser - - ## Kafka Zookeeper password - ## - zookeeperPassword: zookeeperPassword - - ## Name of the existing secret containing credentials for clientUsers, interBrokerUser and zookeeperUser. - ## Create this secret running the command below where SECRET_NAME is the name of the secret you want to create: - ## kubectl create secret generic SECRET_NAME --from-literal=client-password=CLIENT_PASSWORD1,CLIENT_PASSWORD2 --from-literal=inter-broker-password=INTER_BROKER_PASSWORD --from-literal=zookeeper-password=ZOOKEEPER_PASSWORD - ## - # existingSecret: - -## The address(es) the socket server listens on. -## When it's set to an empty array, the listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -listeners: [] - -## The address(es) (hostname:port) the brokers will advertise to producers and consumers. -## When it's set to an empty array, the advertised listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -advertisedListeners: [] - -## The listener->protocol mapping -## When it's nil, the listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -# listenerSecurityProtocolMap: - -## Allow to use the PLAINTEXT listener. -## -allowPlaintextListener: false - -## Name of listener used for communication between brokers. -## -interBrokerListenerName: INTERNAL - -## Number of Kafka brokers to deploy -## -replicaCount: 3 - -## StrategyType, can be set to RollingUpdate or OnDelete by default. -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets -## -updateStrategy: RollingUpdate - -## Partition update strategy -## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -## -# rollingUpdatePartition: - -## Pod labels. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -podLabels: {} - -## Pod annotations. Evaluated as a template -## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -## -podAnnotations: {} - -## Name of the priority class to be used by kafka pods, priority class needs to be created beforehand -## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ -priorityClassName: "" - -## Affinity for pod assignment. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Node labels for pod assignment. Evaluated as a template -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Kafka pods' Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod -## -podSecurityContext: - fsGroup: 1001 - runAsUser: 1001 - -## Kafka containers' Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container -## Example: -## containerSecurityContext: -## capabilities: -## drop: ["NET_RAW"] -## readOnlyRootFilesystem: true -## -containerSecurityContext: {} - -## Kafka containers' resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 250m - # memory: 1Gi - requests: {} - # cpu: 250m - # memory: 256Mi - -## Kafka containers' liveness and readiness probes. Evaluated as a template. -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes -## -livenessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: 10 - timeoutSeconds: 5 - # failureThreshold: 3 - # periodSeconds: 10 - # successThreshold: 1 -readinessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: 5 - failureThreshold: 6 - timeoutSeconds: 5 - # periodSeconds: 10 - # successThreshold: 1 - -## Pod Disruption Budget configuration -## The PDB will only be created if replicaCount is greater than 1 -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions -## -pdb: - create: true - ## Min number of pods that must still be available after the eviction - ## - # minAvailable: 1 - ## Max number of pods that can be unavailable after the eviction - ## - maxUnavailable: 1 - -## Add sidecars to the pod. -## Example: -## sidecars: -## - name: your-image-name -## image: your-image -## imagePullPolicy: Always -## ports: -## - name: portname -## containerPort: 1234 -## -sidecars: {} - -## Service parameters -## -service: - ## Service type - ## - type: ClusterIP - ## Kafka port for client connections - ## - port: 9092 - ## Kafka port for inter-broker connections - ## - internalPort: 9093 - ## Kafka port for external connections - ## - externalPort: 9094 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePorts: - client: "" - external: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Provide any additional annotations which may be required. Evaluated as a template - ## - annotations: {} - -## External Access to Kafka brokers configuration -## -externalAccess: - ## Enable Kubernetes external cluster access to Kafka brokers - ## - enabled: false - - ## External IPs auto-discovery configuration - ## An init container is used to auto-detect LB IPs or node ports by querying the K8s API - ## Note: RBAC might be required - ## - autoDiscovery: - ## Enable external IP/ports auto-discovery - ## - enabled: false - ## Bitnami Kubectl image - ## ref: https://hub.docker.com/r/bitnami/kubectl/tags/ - ## - image: - registry: docker.io - repository: bitnami/kubectl - tag: 1.17.12-debian-10-r3 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## Init Container resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Parameters to configure K8s service(s) used to externally access Kafka brokers - ## A new service per broker will be created - ## - service: - ## Service type. Allowed values: LoadBalancer or NodePort - ## - type: LoadBalancer - ## Port used when service type is LoadBalancer - ## - port: 9094 - ## Array of load balancer IPs for each Kafka broker. Length must be the same as replicaCount - ## Example: - ## loadBalancerIPs: - ## - X.X.X.X - ## - Y.Y.Y.Y - ## - loadBalancerIPs: [] - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Array of node ports used for each Kafka broker. Length must be the same as replicaCount - ## Example: - ## nodePorts: - ## - 30001 - ## - 30002 - ## - nodePorts: [] - ## When service type is NodePort, you can specify the domain used for Kafka advertised listeners. - ## If not specified, the container will try to get the kubernetes node external IP - ## - # domain: mydomain.com - ## Provide any additional annotations which may be required. Evaluated as a template - ## - annotations: {} - -## Persistence paramaters -## -persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - ## PV Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. - ## - # storageClass: "-" - ## PV Access Mode - ## - accessModes: - - ReadWriteOnce - ## PVC size - ## - size: 8Gi - ## PVC annotations - ## - annotations: {} - -## Init Container paramaters -## Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each component -## values from the securityContext section of the component -## -volumePermissions: - enabled: false - ## Bitnami Minideb image - ## ref: https://hub.docker.com/r/bitnami/minideb/tags/ - ## - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## Init Container resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - -## Kafka pods ServiceAccount -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: true - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the fluentd.fullname template - ## - # name: - -## Role Based Access -## ref: https://kubernetes.io/docs/admin/authorization/rbac/ -## -rbac: - ## Specifies whether RBAC rules should be created - ## binding Kafka ServiceAccount to a role - ## that allows Kafka pods querying the K8s API - ## - create: false - -## Prometheus Exporters / Metrics -## -metrics: - ## Prometheus Kafka Exporter: exposes complimentary metrics to JMX Exporter - ## - kafka: - enabled: true - - ## Bitnami Kafka exporter image - ## ref: https://hub.docker.com/r/bitnami/kafka-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/kafka-exporter - tag: 1.2.0-debian-10-r220 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Extra flags to be passed to Kafka exporter - ## Example: - ## extraFlags: - ## tls.insecure-skip-tls-verify: "" - ## web.telemetry-path: "/metrics" - ## - extraFlags: {} - - ## Name of the existing secret containing the optional certificate and key files - ## for Kafka Exporter client authentication - ## - # certificatesSecret: - - ## Prometheus Kafka Exporter' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Service configuration - ## - service: - ## Kafka Exporter Service type - ## - type: ClusterIP - ## Kafka Exporter Prometheus port - ## - port: 9308 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePort: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Set the Cluster IP to use - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address - ## - # clusterIP: None - ## Annotations for the Kafka Exporter Prometheus metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.kafka.service.port }}" - prometheus.io/path: "/metrics" - - ## Prometheus JMX Exporter: exposes the majority of Kafkas metrics - ## - jmx: - enabled: true - - ## Bitnami JMX exporter image - ## ref: https://hub.docker.com/r/bitnami/jmx-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/jmx-exporter - tag: 0.14.0-debian-10-r15 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Prometheus JMX Exporter' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Service configuration - ## - service: - ## JMX Exporter Service type - ## - type: ClusterIP - ## JMX Exporter Prometheus port - ## - port: 5556 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePort: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Set the Cluster IP to use - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address - ## - # clusterIP: None - ## Annotations for the JMX Exporter Prometheus metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.jmx.service.port }}" - prometheus.io/path: "/" - - ## JMX Whitelist Objects, can be set to control which JMX metrics are exposed. Only whitelisted - ## values will be exposed via JMX Exporter. They must also be exposed via Rules. To expose all metrics - ## (warning its crazy excessive and they aren't formatted in a prometheus style) (1) `whitelistObjectNames: []` - ## (2) commented out above `overrideConfig`. - ## - whitelistObjectNames: - - kafka.controller:* - - kafka.server:* - - java.lang:* - - kafka.network:* - - kafka.log:* - - ## Prometheus JMX exporter configuration - ## Specify content for jmx-kafka-prometheus.yml. Evaluated as a template - ## - ## Credits to the incubator/kafka chart for the JMX configuration. - ## https://github.com/helm/charts/tree/master/incubator/kafka - ## - config: |- - jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:5555/jmxrmi - lowercaseOutputName: true - lowercaseOutputLabelNames: true - ssl: false - {{- if .Values.metrics.jmx.whitelistObjectNames }} - whitelistObjectNames: ["{{ join "\",\"" .Values.metrics.jmx.whitelistObjectNames }}"] - {{- end }} - - ## ConfigMap with Prometheus JMX exporter configuration - ## NOTE: This will override metrics.jmx.config - ## - # existingConfigmap: - - ## Prometheus Operator ServiceMonitor configuration - ## - serviceMonitor: - enabled: false - ## Namespace in which Prometheus is running - ## - # namespace: monitoring - - ## Interval at which metrics should be scraped. - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # interval: 10s - - ## Timeout after which the scrape is ended - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # scrapeTimeout: 10s - - ## ServiceMonitor selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - -## -## Zookeeper chart configuration -## -## https://github.com/bitnami/charts/blob/master/bitnami/zookeeper/values.yaml -## -zookeeper: - enabled: true - auth: - ## Enable Zookeeper auth - ## - enabled: true - ## User that will use Zookeeper clients to auth - ## - clientUser: zookeeperUser - ## Password that will use Zookeeper clients to auth - ## - clientPassword: zookeeperPassword - ## Comma, semicolon or whitespace separated list of user to be created. Specify them as a string, for example: "user1,user2,admin" - ## - serverUsers: zookeeperUser - ## Comma, semicolon or whitespace separated list of passwords to assign to users when created. Specify them as a string, for example: "pass4user1, pass4user2, pass4admin" - ## - serverPasswords: zookeeperPassword - metrics: - enabled: true - -## This value is only used when zookeeper.enabled is set to false -## -externalZookeeper: - ## Server or list of external zookeeper servers to use. - ## - servers: [] diff --git a/ee/scripts/helm/db/kafka/values.yaml b/ee/scripts/helm/db/kafka/values.yaml deleted file mode 100755 index 154d71bd5..000000000 --- a/ee/scripts/helm/db/kafka/values.yaml +++ /dev/null @@ -1,934 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -# global: -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami Kafka image version -## ref: https://hub.docker.com/r/bitnami/kafka/tags/ -## -image: - registry: docker.io - repository: bitnami/kafka - tag: 2.6.0-debian-10-r30 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Set to true if you would like to see extra information on logs - ## - debug: false - -## String to partially override kafka.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override kafka.fullname template -## -# fullnameOverride: - -## Kubernetes Cluster Domain -## -clusterDomain: cluster.local - -## Add labels to all the deployed resources -## -commonLabels: {} - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -## Kafka Configuration -## Specify content for server.properties -## The server.properties is auto-generated based on other parameters when this paremeter is not specified -## -## Example: -## config: |- -## broker.id=-1 -## listeners=PLAINTEXT://:9092 -## advertised.listeners=PLAINTEXT://KAFKA_IP:9092 -## num.network.threads=3 -## num.io.threads=8 -## socket.send.buffer.bytes=102400 -## socket.receive.buffer.bytes=102400 -## socket.request.max.bytes=104857600 -## log.dirs=/bitnami/kafka/data -## num.partitions=1 -## num.recovery.threads.per.data.dir=1 -## offsets.topic.replication.factor=1 -## transaction.state.log.replication.factor=1 -## transaction.state.log.min.isr=1 -## log.flush.interval.messages=10000 -## log.flush.interval.ms=1000 -## log.retention.hours=168 -## log.retention.bytes=1073741824 -## log.segment.bytes=1073741824 -## log.retention.check.interval.ms=300000 -## zookeeper.connect=ZOOKEEPER_SERVICE_NAME -## zookeeper.connection.timeout.ms=6000 -## group.initial.rebalance.delay.ms=0 -## -# config: - -## ConfigMap with Kafka Configuration -## NOTE: This will override config -## -# existingConfigmap: - -## Kafka Log4J Configuration -## An optional log4j.properties file to overwrite the default of the Kafka brokers. -## See an example log4j.properties at: -## https://github.com/apache/kafka/blob/trunk/config/log4j.properties -## -# log4j: - -## Kafka Log4j ConfigMap -## The name of an existing ConfigMap containing a log4j.properties file. -## NOTE: this will override log4j. -## -# existingLog4jConfigMap: - -## Kafka's Java Heap size -## -heapOpts: -Xmx1024m -Xms1024m - -## Switch to enable topic deletion or not. -## -deleteTopicEnable: false - -## Switch to enable auto creation of topics. -## Enabling auto creation of topics not recommended for production or similar environments. -## -autoCreateTopicsEnable: true - -## The number of messages to accept before forcing a flush of data to disk. -## -logFlushIntervalMessages: 10000 - -## The maximum amount of time a message can sit in a log before we force a flush. -## -logFlushIntervalMs: 1000 - -## A size-based retention policy for logs. -## -logRetentionBytes: _1073741824 - -## The interval at which log segments are checked to see if they can be deleted. -## -logRetentionCheckIntervalMs: 300000 - -## The minimum age of a log file to be eligible for deletion due to age. -## -logRetentionHours: 168 - -## The maximum size of a log segment file. When this size is reached a new log segment will be created. -## -logSegmentBytes: _1073741824 - -## A comma separated list of directories under which to store log files. -## -logsDirs: /bitnami/kafka/data - -## The largest record batch size allowed by Kafka -## -maxMessageBytes: _1000012 - -## Default replication factors for automatically created topics -## -defaultReplicationFactor: 1 - -## The replication factor for the offsets topic -## -offsetsTopicReplicationFactor: 1 - -## The replication factor for the transaction topic -## -transactionStateLogReplicationFactor: 1 - -## Overridden min.insync.replicas config for the transaction topic -## -transactionStateLogMinIsr: 1 - -## The number of threads doing disk I/O. -## -numIoThreads: 8 - -## The number of threads handling network requests. -## -numNetworkThreads: 3 - -## The default number of log partitions per topic. -## -numPartitions: 1 - -## The number of threads per data directory to be used for log recovery at startup and flushing at shutdown. -## -numRecoveryThreadsPerDataDir: 1 - -## The receive buffer (SO_RCVBUF) used by the socket server. -## -socketReceiveBufferBytes: 102400 - -## The maximum size of a request that the socket server will accept (protection against OOM). -## -socketRequestMaxBytes: _104857600 - -## The send buffer (SO_SNDBUF) used by the socket server. -## -socketSendBufferBytes: 102400 - -## Timeout in ms for connecting to zookeeper. -## -zookeeperConnectionTimeoutMs: 6000 - -## Command and args for running the container. Use array form -## -command: - - /scripts/setup.sh -args: - -## All the parameters from the configuration file can be overwritten by using environment variables with this format: KAFKA_CFG_{KEY} -## ref: https://github.com/bitnami/bitnami-docker-kafka#configuration -## Example: -## extraEnvVars: -## - name: KAFKA_CFG_BACKGROUND_THREADS -## value: "10" -## -extraEnvVars: [] - -## extraVolumes and extraVolumeMounts allows you to mount other volumes -## Examples: -# extraVolumes: -# - name: kafka-jaas -# secret: -# secretName: kafka-jaas -# extraVolumeMounts: -# - name: kafka-jaas -# mountPath: /bitnami/kafka/config/kafka_jaas.conf -# subPath: kafka_jaas.conf -extraVolumes: [] -extraVolumeMounts: [] - -## Extra objects to deploy (value evaluated as a template) -## -extraDeploy: [] - -## Authentication parameteres -## https://github.com/bitnami/bitnami-docker-kafka#security -## -auth: - ## Authentication protocol for client and inter-broker communications - ## Supported values: 'plaintext', 'tls', 'mtls', 'sasl' and 'sasl_tls' - ## This table shows the security provided on each protocol: - ## | Method | Authentication | Encryption via TLS | - ## | plaintext | None | No | - ## | tls | None | Yes | - ## | mtls | Yes (two-way authentication) | Yes | - ## | sasl | Yes (via SASL) | No | - ## | sasl_tls | Yes (via SASL) | Yes | - ## - clientProtocol: plaintext - interBrokerProtocol: plaintext - - ## Allowed SASL mechanisms when clientProtocol or interBrokerProtocol are using either sasl or sasl_tls - ## - saslMechanisms: plain,scram-sha-256,scram-sha-512 - ## SASL mechanism for inter broker communication - ## - saslInterBrokerMechanism: plain - - ## Name of the existing secret containing the truststore and - ## one keystore per Kafka broker you have in the Kafka cluster. - ## MANDATORY when 'tls', 'mtls', or 'sasl_tls' authentication protocols are used. - ## Create this secret following the steps below: - ## 1) Generate your trustore and keystore files. Helpful script: https://raw.githubusercontent.com/confluentinc/confluent-platform-security-tools/master/kafka-generate-ssl.sh - ## 2) Rename your truststore to `kafka.truststore.jks`. - ## 3) Rename your keystores to `kafka-X.keystore.jks` where X is the ID of each Kafka broker. - ## 4) Run the command below where SECRET_NAME is the name of the secret you want to create: - ## kubectl create secret generic SECRET_NAME --from-file=./kafka.truststore.jks --from-file=./kafka-0.keystore.jks --from-file=./kafka-1.keystore.jks ... - ## Alternatively, you can put your JKS files under the files/jks directory - ## - # jksSecret: - - ## Password to access the JKS files when they are password-protected. - ## - # jksPassword: - - ## The endpoint identification algorithm used by clients to validate server host name. - ## Disable server host name verification by setting it to an empty string - ## See: https://docs.confluent.io/current/kafka/authentication_ssl.html#optional-settings - ## - tlsEndpointIdentificationAlgorithm: https - - ## JAAS configuration for SASL authentication - ## MANDATORY when method is 'sasl', or 'sasl_tls' - ## - jaas: - ## Kafka client user list - ## - ## clientUsers: - ## - user1 - ## - user2 - ## - clientUsers: - - user - - ## Kafka client passwords. This is mandatory if more than one user is specified in clientUsers. - ## - ## clientPasswords: - ## - password1 - ## - password2" - ## - clientPasswords: [] - - ## Kafka inter broker communication user - ## - interBrokerUser: admin - - ## Kafka inter broker communication password - ## - interBrokerPassword: "" - - ## Kafka Zookeeper user - ## - # zookeeperUser: - - ## Kafka Zookeeper password - ## - # zookeeperPassword: - - ## Name of the existing secret containing credentials for clientUsers, interBrokerUser and zookeeperUser. - ## Create this secret running the command below where SECRET_NAME is the name of the secret you want to create: - ## kubectl create secret generic SECRET_NAME --from-literal=client-passwords=CLIENT_PASSWORD1,CLIENT_PASSWORD2 --from-literal=inter-broker-password=INTER_BROKER_PASSWORD --from-literal=zookeeper-password=ZOOKEEPER_PASSWORD - ## - # existingSecret: - -## The address(es) the socket server listens on. -## When it's set to an empty array, the listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -listeners: [] - -## The address(es) (hostname:port) the brokers will advertise to producers and consumers. -## When it's set to an empty array, the advertised listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -advertisedListeners: [] - -## The listener->protocol mapping -## When it's nil, the listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -# listenerSecurityProtocolMap: - -## Allow to use the PLAINTEXT listener. -## -allowPlaintextListener: true - -## Name of listener used for communication between brokers. -## -interBrokerListenerName: INTERNAL - -## Number of Kafka brokers to deploy -## -replicaCount: 2 - -## StrategyType, can be set to RollingUpdate or OnDelete by default. -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets -## -updateStrategy: RollingUpdate - -## Partition update strategy -## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -## -# rollingUpdatePartition: - -## Pod labels. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -## -podLabels: {} - -## Pod annotations. Evaluated as a template -## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -## -podAnnotations: {} - -## Name of the priority class to be used by kafka pods, priority class needs to be created beforehand -## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ -## -priorityClassName: "" - -## Affinity for pod assignment. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Node labels for pod assignment. Evaluated as a template -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Kafka pods' Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod -## -podSecurityContext: - fsGroup: 1001 - runAsUser: 1001 - -## Kafka containers' Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container -## Example: -## containerSecurityContext: -## capabilities: -## drop: ["NET_RAW"] -## readOnlyRootFilesystem: true -## -containerSecurityContext: {} - -## Kafka containers' resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 250m - # memory: 1Gi - requests: {} - # cpu: 250m - # memory: 256Mi - -## Kafka containers' liveness and readiness probes. Evaluated as a template. -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes -## -livenessProbe: - enabled: true - initialDelaySeconds: 10 - timeoutSeconds: 5 - # failureThreshold: 3 - # periodSeconds: 10 - # successThreshold: 1 -readinessProbe: - enabled: true - initialDelaySeconds: 5 - failureThreshold: 6 - timeoutSeconds: 5 - # periodSeconds: 10 - # successThreshold: 1 - -## Custom liveness/readiness probes that will override the default ones -## -customLivenessProbe: {} -customReadinessProbe: {} - -## Pod Disruption Budget configuration -## The PDB will only be created if replicaCount is greater than 1 -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions -## -pdb: - create: true - ## Min number of pods that must still be available after the eviction - ## - # minAvailable: 1 - ## Max number of pods that can be unavailable after the eviction - ## - maxUnavailable: 1 - -## Add sidecars to the pod. -## Example: -## sidecars: -## - name: your-image-name -## image: your-image -## imagePullPolicy: Always -## ports: -## - name: portname -## containerPort: 1234 -## -sidecars: {} - -## Service parameters -## -service: - ## Service type - ## - type: ClusterIP - ## Kafka port for client connections - ## - port: 9092 - ## Kafka port for inter-broker connections - ## - internalPort: 9093 - ## Kafka port for external connections - ## - externalPort: 9094 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePorts: - client: "" - external: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Provide any additional annotations which may be required. Evaluated as a template - ## - annotations: {} - -## External Access to Kafka brokers configuration -## -externalAccess: - ## Enable Kubernetes external cluster access to Kafka brokers - ## - enabled: false - - ## External IPs auto-discovery configuration - ## An init container is used to auto-detect LB IPs or node ports by querying the K8s API - ## Note: RBAC might be required - ## - autoDiscovery: - ## Enable external IP/ports auto-discovery - ## - enabled: false - ## Bitnami Kubectl image - ## ref: https://hub.docker.com/r/bitnami/kubectl/tags/ - ## - image: - registry: docker.io - repository: bitnami/kubectl - tag: 1.17.12-debian-10-r3 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## Init Container resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Parameters to configure K8s service(s) used to externally access Kafka brokers - ## A new service per broker will be created - ## - service: - ## Service type. Allowed values: LoadBalancer or NodePort - ## - type: LoadBalancer - ## Port used when service type is LoadBalancer - ## - port: 9094 - ## Array of load balancer IPs for each Kafka broker. Length must be the same as replicaCount - ## Example: - ## loadBalancerIPs: - ## - X.X.X.X - ## - Y.Y.Y.Y - ## - loadBalancerIPs: [] - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Array of node ports used for each Kafka broker. Length must be the same as replicaCount - ## Example: - ## nodePorts: - ## - 30001 - ## - 30002 - ## - nodePorts: [] - ## When service type is NodePort, you can specify the domain used for Kafka advertised listeners. - ## If not specified, the container will try to get the kubernetes node external IP - ## - # domain: mydomain.com - ## Provide any additional annotations which may be required. Evaluated as a template - ## - annotations: {} - -## Persistence paramaters -## -persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - ## PV Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. - ## - # storageClass: "-" - ## PV Access Mode - ## - accessModes: - - ReadWriteOnce - ## PVC size - ## - size: 8Gi - ## PVC annotations - ## - annotations: {} - -## Init Container paramaters -## Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each component -## values from the securityContext section of the component -## -volumePermissions: - enabled: false - ## Bitnami Minideb image - ## ref: https://hub.docker.com/r/bitnami/minideb/tags/ - ## - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## Init Container resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - -## Kafka pods ServiceAccount -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: true - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the fluentd.fullname template - ## - # name: - -## Role Based Access -## ref: https://kubernetes.io/docs/admin/authorization/rbac/ -## -rbac: - ## Specifies whether RBAC rules should be created - ## binding Kafka ServiceAccount to a role - ## that allows Kafka pods querying the K8s API - ## - create: false - -## Prometheus Exporters / Metrics -## -metrics: - ## Prometheus Kafka Exporter: exposes complimentary metrics to JMX Exporter - ## - kafka: - enabled: false - - ## Bitnami Kafka exporter image - ## ref: https://hub.docker.com/r/bitnami/kafka-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/kafka-exporter - tag: 1.2.0-debian-10-r220 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Extra flags to be passed to Kafka exporter - ## Example: - ## extraFlags: - ## tls.insecure-skip-tls-verify: "" - ## web.telemetry-path: "/metrics" - ## - extraFlags: {} - - ## Name of the existing secret containing the optional certificate and key files - ## for Kafka Exporter client authentication - ## - # certificatesSecret: - - ## Prometheus Kafka Exporter' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Service configuration - ## - service: - ## Kafka Exporter Service type - ## - type: ClusterIP - ## Kafka Exporter Prometheus port - ## - port: 9308 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePort: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Set the Cluster IP to use - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address - ## - # clusterIP: None - ## Annotations for the Kafka Exporter Prometheus metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.kafka.service.port }}" - prometheus.io/path: "/metrics" - - ## Prometheus JMX Exporter: exposes the majority of Kafkas metrics - ## - jmx: - enabled: false - - ## Bitnami JMX exporter image - ## ref: https://hub.docker.com/r/bitnami/jmx-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/jmx-exporter - tag: 0.14.0-debian-10-r15 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Prometheus JMX Exporter' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Service configuration - ## - service: - ## JMX Exporter Service type - ## - type: ClusterIP - ## JMX Exporter Prometheus port - ## - port: 5556 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePort: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Set the Cluster IP to use - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address - ## - # clusterIP: None - ## Annotations for the JMX Exporter Prometheus metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.jmx.service.port }}" - prometheus.io/path: "/" - - ## JMX Whitelist Objects, can be set to control which JMX metrics are exposed. Only whitelisted - ## values will be exposed via JMX Exporter. They must also be exposed via Rules. To expose all metrics - ## (warning its crazy excessive and they aren't formatted in a prometheus style) (1) `whitelistObjectNames: []` - ## (2) commented out above `overrideConfig`. - ## - whitelistObjectNames: - - kafka.controller:* - - kafka.server:* - - java.lang:* - - kafka.network:* - - kafka.log:* - - ## Prometheus JMX exporter configuration - ## Specify content for jmx-kafka-prometheus.yml. Evaluated as a template - ## - ## Credits to the incubator/kafka chart for the JMX configuration. - ## https://github.com/helm/charts/tree/master/incubator/kafka - ## - config: |- - jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:5555/jmxrmi - lowercaseOutputName: true - lowercaseOutputLabelNames: true - ssl: false - {{- if .Values.metrics.jmx.whitelistObjectNames }} - whitelistObjectNames: ["{{ join "\",\"" .Values.metrics.jmx.whitelistObjectNames }}"] - {{- end }} - - ## ConfigMap with Prometheus JMX exporter configuration - ## NOTE: This will override metrics.jmx.config - ## - # existingConfigmap: - - ## Prometheus Operator ServiceMonitor configuration - ## - serviceMonitor: - enabled: false - ## Namespace in which Prometheus is running - ## - # namespace: monitoring - - ## Interval at which metrics should be scraped. - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # interval: 10s - - ## Timeout after which the scrape is ended - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # scrapeTimeout: 10s - - ## ServiceMonitor selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - -## -## Zookeeper chart configuration -## -## https://github.com/bitnami/charts/blob/master/bitnami/zookeeper/values.yaml -## -zookeeper: - enabled: true - auth: - ## Enable Zookeeper auth - ## - enabled: false - ## User that will use Zookeeper clients to auth - ## - # clientUser: - ## Password that will use Zookeeper clients to auth - ## - # clientPassword: - ## Comma, semicolon or whitespace separated list of user to be created. Specify them as a string, for example: "user1,user2,admin" - ## - # serverUsers: - ## Comma, semicolon or whitespace separated list of passwords to assign to users when created. Specify them as a string, for example: "pass4user1, pass4user2, pass4admin" - ## - # serverPasswords: - -## This value is only used when zookeeper.enabled is set to false -## -externalZookeeper: - ## Server or list of external zookeeper servers to use. - ## - servers: [] diff --git a/ee/scripts/helm/helm/databases/charts/clickhouse/.helmignore b/ee/scripts/helm/helm/databases/charts/clickhouse/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/ee/scripts/helm/helm/databases/charts/clickhouse/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/ee/scripts/helm/helm/databases/charts/clickhouse/templates/_helpers.tpl b/ee/scripts/helm/helm/databases/charts/clickhouse/templates/_helpers.tpl deleted file mode 100644 index 44cfadff0..000000000 --- a/ee/scripts/helm/helm/databases/charts/clickhouse/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "clickhouse.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "clickhouse.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "clickhouse.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "clickhouse.labels" -}} -helm.sh/chart: {{ include "clickhouse.chart" . }} -{{ include "clickhouse.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "clickhouse.selectorLabels" -}} -app.kubernetes.io/name: {{ include "clickhouse.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "clickhouse.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "clickhouse.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/clickhouse/templates/service.yaml b/ee/scripts/helm/helm/databases/charts/clickhouse/templates/service.yaml deleted file mode 100644 index 4496f556c..000000000 --- a/ee/scripts/helm/helm/databases/charts/clickhouse/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: clickhouse - labels: - {{- include "clickhouse.labels" . | nindent 4 }} -spec: - type: ClusterIP - ports: - - port: {{ .Values.service.webPort }} - targetPort: web - protocol: TCP - name: web - - port: {{ .Values.service.dataPort }} - targetPort: data - protocol: TCP - name: data - selector: - {{- include "clickhouse.selectorLabels" . | nindent 4 }} diff --git a/ee/scripts/helm/helm/databases/charts/clickhouse/values.yaml b/ee/scripts/helm/helm/databases/charts/clickhouse/values.yaml deleted file mode 100644 index 4cba1c1f8..000000000 --- a/ee/scripts/helm/helm/databases/charts/clickhouse/values.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# Default values for clickhouse. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -image: - repository: yandex/clickhouse-server - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "20.9" - -imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -podAnnotations: {} - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -env: {} - -service: - webPort: 9000 - dataPort: 8123 - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -nodeSelector: {} - -tolerations: [] - -affinity: {} -storageSize: 8G diff --git a/ee/scripts/helm/helm/databases/charts/kafka/Chart.yaml b/ee/scripts/helm/helm/databases/charts/kafka/Chart.yaml deleted file mode 100755 index 165e70d55..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/Chart.yaml +++ /dev/null @@ -1,22 +0,0 @@ -annotations: - category: Infrastructure -apiVersion: v1 -appVersion: 2.6.0 -description: Apache Kafka is a distributed streaming platform. -engine: gotpl -home: https://github.com/bitnami/charts/tree/master/bitnami/kafka -icon: https://bitnami.com/assets/stacks/kafka/img/kafka-stack-110x117.png -keywords: -- kafka -- zookeeper -- streaming -- producer -- consumer -maintainers: -- email: containers@bitnami.com - name: Bitnami -name: kafka -sources: -- https://github.com/bitnami/bitnami-docker-kafka -- https://kafka.apache.org/ -version: 11.8.6 diff --git a/ee/scripts/helm/helm/databases/charts/kafka/README.md b/ee/scripts/helm/helm/databases/charts/kafka/README.md deleted file mode 100755 index 5584bd43d..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/README.md +++ /dev/null @@ -1,737 +0,0 @@ -# Kafka - -[Kafka](https://www.kafka.org/) is a distributed streaming platform used for building real-time data pipelines and streaming apps. It is horizontally scalable, fault-tolerant, wicked fast, and runs in production in thousands of companies. - -## TL;DR - -```console -helm repo add bitnami https://charts.bitnami.com/bitnami -helm install my-release bitnami/kafka -``` - -## Introduction - -This chart bootstraps a [Kafka](https://github.com/bitnami/bitnami-docker-kafka) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 2.12+ or Helm 3.0-beta3+ -- PV provisioner support in the underlying infrastructure - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -helm repo add bitnami https://charts.bitnami.com/bitnami -helm install my-release bitnami/kafka -``` - -These commands deploy Kafka on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```console -helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Parameters - -The following tables lists the configurable parameters of the Kafka chart and their default values per section/component: - -### Global parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `global.imageRegistry` | Global Docker image registry | `nil` | -| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | - -### Common parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `nameOverride` | String to partially override kafka.fullname | `nil` | -| `fullnameOverride` | String to fully override kafka.fullname | `nil` | -| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | -| `commonLabels` | Labels to add to all deployed objects | `{}` | -| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | -| `extraDeploy` | Array of extra objects to deploy with the release | `nil` (evaluated as a template) | - -### Kafka parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `image.registry` | Kafka image registry | `docker.io` | -| `image.repository` | Kafka image name | `bitnami/kafka` | -| `image.tag` | Kafka image tag | `{TAG_NAME}` | -| `image.pullPolicy` | Kafka image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `image.debug` | Set to true if you would like to see extra information on logs | `false` | -| `config` | Configuration file for Kafka. Auto-generated based on other parameters when not specified | `nil` | -| `existingConfigmap` | Name of existing ConfigMap with Kafka configuration | `nil` | -| `log4j` | An optional log4j.properties file to overwrite the default of the Kafka brokers. | `nil` | -| `existingLog4jConfigMap` | The name of an existing ConfigMap containing a log4j.properties file. | `nil` | -| `heapOpts` | Kafka's Java Heap size | `-Xmx1024m -Xms1024m` | -| `deleteTopicEnable` | Switch to enable topic deletion or not | `false` | -| `autoCreateTopicsEnable` | Switch to enable auto creation of topics. Enabling auto creation of topics not recommended for production or similar environments | `false` | -| `logFlushIntervalMessages` | The number of messages to accept before forcing a flush of data to disk | `10000` | -| `logFlushIntervalMs` | The maximum amount of time a message can sit in a log before we force a flush | `1000` | -| `logRetentionBytes` | A size-based retention policy for logs | `_1073741824` | -| `logRetentionCheckIntervalMs` | The interval at which log segments are checked to see if they can be deleted | `300000` | -| `logRetentionHours` | The minimum age of a log file to be eligible for deletion due to age | `168` | -| `logSegmentBytes` | The maximum size of a log segment file. When this size is reached a new log segment will be created | `_1073741824` | -| `logsDirs` | A comma separated list of directories under which to store log files | `/bitnami/kafka/data` | -| `maxMessageBytes` | The largest record batch size allowed by Kafka | `1000012` | -| `defaultReplicationFactor` | Default replication factors for automatically created topics | `1` | -| `offsetsTopicReplicationFactor` | The replication factor for the offsets topic | `1` | -| `transactionStateLogReplicationFactor` | The replication factor for the transaction topic | `1` | -| `transactionStateLogMinIsr` | Overridden min.insync.replicas config for the transaction topic | `1` | -| `numIoThreads` | The number of threads doing disk I/O | `8` | -| `numNetworkThreads` | The number of threads handling network requests | `3` | -| `numPartitions` | The default number of log partitions per topic | `1` | -| `numRecoveryThreadsPerDataDir` | The number of threads per data directory to be used for log recovery at startup and flushing at shutdown | `1` | -| `socketReceiveBufferBytes` | The receive buffer (SO_RCVBUF) used by the socket server | `102400` | -| `socketRequestMaxBytes` | The maximum size of a request that the socket server will accept (protection against OOM) | `_104857600` | -| `socketSendBufferBytes` | The send buffer (SO_SNDBUF) used by the socket server | `102400` | -| `zookeeperConnectionTimeoutMs` | Timeout in ms for connecting to Zookeeper | `6000` | -| `extraEnvVars` | Extra environment variables to add to kafka pods | `[]` | -| `extraVolumes` | Extra volume(s) to add to Kafka statefulset | `[]` | -| `extraVolumeMounts` | Extra volumeMount(s) to add to Kafka containers | `[]` | -| `auth.clientProtocol` | Authentication protocol for communications with clients. Allowed protocols: `plaintext`, `tls`, `mtls`, `sasl` and `sasl_tls` | `plaintext` | -| `auth.interBrokerProtocol` | Authentication protocol for inter-broker communications. Allowed protocols: `plaintext`, `tls`, `mtls`, `sasl` and `sasl_tls` | `plaintext` | -| `auth.saslMechanisms` | SASL mechanisms when either `auth.interBrokerProtocol` or `auth.clientProtocol` are `sasl`. Allowed types: `plain`, `scram-sha-256`, `scram-sha-512` | `plain,scram-sha-256,scram-sha-512` | -| `auth.saslInterBrokerMechanism` | SASL mechanism to use as inter broker protocol, it must be included at `auth.saslMechanisms` | `plain` | -| `auth.jksSecret` | Name of the existing secret containing the truststore and one keystore per Kafka broker you have in the cluster | `nil` | -| `auth.jksPassword` | Password to access the JKS files when they are password-protected | `nil` | -| `auth.tlsEndpointIdentificationAlgorithm` | The endpoint identification algorithm to validate server hostname using server certificate | `https` | -| `auth.jaas.interBrokerUser` | Kafka inter broker communication user for SASL authentication | `admin` | -| `auth.jaas.interBrokerPassword` | Kafka inter broker communication password for SASL authentication | `nil` | -| `auth.jaas.zookeeperUser` | Kafka Zookeeper user for SASL authentication | `nil` | -| `auth.jaas.zookeeperPassword` | Kafka Zookeeper password for SASL authentication | `nil` | -| `auth.jaas.existingSecret` | Name of the existing secret containing credentials for brokerUser, interBrokerUser and zookeeperUser | `nil` | -| `auth.jaas.clientUsers` | List of Kafka client users to be created, separated by commas. This values will override `auth.jaas.clientUser` | `[]` | -| `auth.jaas.clientPasswords` | List of passwords for `auth.jaas.clientUsers`. It is mandatory to provide the passwords when using `auth.jaas.clientUsers` | `[]` | -| `listeners` | The address(es) the socket server listens on. Auto-calculated it's set to an empty array | `[]` | -| `advertisedListeners` | The address(es) (hostname:port) the broker will advertise to producers and consumers. Auto-calculated it's set to an empty array | `[]` | -| `listenerSecurityProtocolMap` | The protocol->listener mapping. Auto-calculated it's set to nil | `nil` | -| `allowPlaintextListener` | Allow to use the PLAINTEXT listener | `true` | -| `interBrokerListenerName` | The listener that the brokers should communicate on | `INTERNAL` | - -### Statefulset parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `replicaCount` | Number of Kafka nodes | `1` | -| `updateStrategy` | Update strategy for the stateful set | `RollingUpdate` | -| `rollingUpdatePartition` | Partition update strategy | `nil` | -| `podLabels` | Kafka pod labels | `{}` (evaluated as a template) | -| `podAnnotations` | Kafka Pod annotations | `{}` (evaluated as a template) | -| `affinity` | Affinity for pod assignment | `{}` (evaluated as a template) | -| `priorityClassName` | Name of the existing priority class to be used by kafka pods | `""` | -| `nodeSelector` | Node labels for pod assignment | `{}` (evaluated as a template) | -| `tolerations` | Tolerations for pod assignment | `[]` (evaluated as a template) | -| `podSecurityContext` | Kafka pods' Security Context | `{}` | -| `containerSecurityContext` | Kafka containers' Security Context | `{}` | -| `resources.limits` | The resources limits for Kafka containers | `{}` | -| `resources.requests` | The requested resources for Kafka containers | `{}` | -| `livenessProbe` | Liveness probe configuration for Kafka | `Check values.yaml file` | -| `readinessProbe` | Readiness probe configuration for Kafka | `Check values.yaml file` | -| `customLivenessProbe` | Custom Liveness probe configuration for Kafka | `{}` | -| `customReadinessProbe` | Custom Readiness probe configuration for Kafka | `{}` | -| `pdb.create` | Enable/disable a Pod Disruption Budget creation | `false` | -| `pdb.minAvailable` | Minimum number/percentage of pods that should remain scheduled | `nil` | -| `pdb.maxUnavailable` | Maximum number/percentage of pods that may be made unavailable | `1` | -| `command` | Override kafka container command | `['/scripts/setup.sh']` (evaluated as a template) | -| `args` | Override kafka container arguments | `[]` (evaluated as a template) | -| `sidecars` | Attach additional sidecar containers to the Kafka pod | `{}` | - -### Exposure parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `service.type` | Kubernetes Service type | `ClusterIP` | -| `service.port` | Kafka port for client connections | `9092` | -| `service.internalPort` | Kafka port for inter-broker connections | `9093` | -| `service.externalPort` | Kafka port for external connections | `9094` | -| `service.nodePorts.client` | Nodeport for client connections | `""` | -| `service.nodePorts.external` | Nodeport for external connections | `""` | -| `service.loadBalancerIP` | loadBalancerIP for Kafka Service | `nil` | -| `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | -| `service.annotations` | Service annotations | `{}`(evaluated as a template) | -| `externalAccess.enabled` | Enable Kubernetes external cluster access to Kafka brokers | `false` | -| `externalAccess.autoDiscovery.enabled` | Enable using an init container to auto-detect external IPs/ports by querying the K8s API | `false` | -| `externalAccess.autoDiscovery.image.registry` | Init container auto-discovery image registry (kubectl) | `docker.io` | -| `externalAccess.autoDiscovery.image.repository` | Init container auto-discovery image name (kubectl) | `bitnami/kubectl` | -| `externalAccess.autoDiscovery.image.tag` | Init container auto-discovery image tag (kubectl) | `{TAG_NAME}` | -| `externalAccess.autoDiscovery.image.pullPolicy` | Init container auto-discovery image pull policy (kubectl) | `Always` | -| `externalAccess.autoDiscovery.resources.limits` | Init container auto-discovery resource limits | `{}` | -| `externalAccess.autoDiscovery.resources.requests` | Init container auto-discovery resource requests | `{}` | -| `externalAccess.service.type` | Kubernetes Service type for external access. It can be NodePort or LoadBalancer | `LoadBalancer` | -| `externalAccess.service.port` | Kafka port used for external access when service type is LoadBalancer | `9094` | -| `externalAccess.service.loadBalancerIPs` | Array of load balancer IPs for Kafka brokers | `[]` | -| `externalAccess.service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | `[]` | -| `externalAccess.service.domain` | Domain or external ip used to configure Kafka external listener when service type is NodePort | `nil` | -| `externalAccess.service.nodePorts` | Array of node ports used to configure Kafka external listener when service type is NodePort | `[]` | -| `externalAccess.service.annotations` | Service annotations for external access | `{}`(evaluated as a template) | - -### Persistence parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `persistence.enabled` | Enable Kafka data persistence using PVC, note that Zookeeper persistence is unaffected | `true` | -| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim`, the value is evaluated as a template | `nil` | -| `persistence.storageClass` | PVC Storage Class for Kafka data volume | `nil` | -| `persistence.accessMode` | PVC Access Mode for Kafka data volume | `ReadWriteOnce` | -| `persistence.size` | PVC Storage Request for Kafka data volume | `8Gi` | -| `persistence.annotations` | Annotations for the PVC | `{}`(evaluated as a template) | - -### RBAC parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `serviceAccount.create` | Enable creation of ServiceAccount for Kafka pods | `true` | -| `serviceAccount.name` | Name of the created serviceAccount | Generated using the `kafka.fullname` template | -| `rbac.create` | Weather to create & use RBAC resources or not | `false` | - -### Volume Permissions parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | -| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | -| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/minideb` | -| `volumePermissions.image.tag` | Init container volume-permissions image tag | `buster` | -| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | -| `volumePermissions.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `volumePermissions.resources.limits` | Init container volume-permissions resource limits | `{}` | -| `volumePermissions.resources.requests` | Init container volume-permissions resource requests | `{}` | - -### Metrics parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `metrics.kafka.enabled` | Whether or not to create a standalone Kafka exporter to expose Kafka metrics | `false` | -| `metrics.kafka.image.registry` | Kafka exporter image registry | `docker.io` | -| `metrics.kafka.image.repository` | Kafka exporter image name | `bitnami/kafka-exporter` | -| `metrics.kafka.image.tag` | Kafka exporter image tag | `{TAG_NAME}` | -| `metrics.kafka.image.pullPolicy` | Kafka exporter image pull policy | `IfNotPresent` | -| `metrics.kafka.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `metrics.kafka.extraFlags` | Extra flags to be passed to Kafka exporter | `{}` | -| `metrics.kafka.certificatesSecret` | Name of the existing secret containing the optional certificate and key files | `nil` | -| `metrics.kafka.resources.limits` | Kafka Exporter container resource limits | `{}` | -| `metrics.kafka.resources.requests` | Kafka Exporter container resource requests | `{}` | -| `metrics.kafka.service.type` | Kubernetes service type (`ClusterIP`, `NodePort` or `LoadBalancer`) for Kafka Exporter | `ClusterIP` | -| `metrics.kafka.service.port` | Kafka Exporter Prometheus port | `9308` | -| `metrics.kafka.service.nodePort` | Kubernetes HTTP node port | `""` | -| `metrics.kafka.service.annotations` | Annotations for Prometheus metrics service | `Check values.yaml file` | -| `metrics.kafka.service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` | -| `metrics.kafka.service.clusterIP` | Static clusterIP or None for headless services | `nil` | -| `metrics.jmx.enabled` | Whether or not to expose JMX metrics to Prometheus | `false` | -| `metrics.jmx.image.registry` | JMX exporter image registry | `docker.io` | -| `metrics.jmx.image.repository` | JMX exporter image name | `bitnami/jmx-exporter` | -| `metrics.jmx.image.tag` | JMX exporter image tag | `{TAG_NAME}` | -| `metrics.jmx.image.pullPolicy` | JMX exporter image pull policy | `IfNotPresent` | -| `metrics.jmx.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `metrics.jmx.resources.limits` | JMX Exporter container resource limits | `{}` | -| `metrics.jmx.resources.requests` | JMX Exporter container resource requests | `{}` | -| `metrics.jmx.service.type` | Kubernetes service type (`ClusterIP`, `NodePort` or `LoadBalancer`) for JMX Exporter | `ClusterIP` | -| `metrics.jmx.service.port` | JMX Exporter Prometheus port | `5556` | -| `metrics.jmx.service.nodePort` | Kubernetes HTTP node port | `""` | -| `metrics.jmx.service.annotations` | Annotations for Prometheus metrics service | `Check values.yaml file` | -| `metrics.jmx.service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` | -| `metrics.jmx.service.clusterIP` | Static clusterIP or None for headless services | `nil` | -| `metrics.jmx.whitelistObjectNames` | Allows setting which JMX objects you want to expose to via JMX stats to JMX Exporter | (see `values.yaml`) | -| `metrics.jmx.config` | Configuration file for JMX exporter | (see `values.yaml`) | -| `metrics.jmx.existingConfigmap` | Name of existing ConfigMap with JMX exporter configuration | `nil` | -| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (requires `metrics.kafka.enabled` or `metrics.jmx.enabled` to be `true`) | `false` | -| `metrics.serviceMonitor.namespace` | Namespace which Prometheus is running in | `monitoring` | -| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped | `nil` | -| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `nil` (Prometheus Operator default value) | -| `metrics.serviceMonitor.selector` | ServiceMonitor selector labels | `nil` (Prometheus Operator default value) | - -### Zookeeper chart parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `zookeeper.enabled` | Switch to enable or disable the Zookeeper helm chart | `true` | -| `zookeeper.persistence.enabled` | Enable Zookeeper persistence using PVC | `true` | -| `externalZookeeper.servers` | Server or list of external Zookeeper servers to use | `[]` | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, - -```console -helm install my-release \ - --set replicaCount=3 \ - bitnami/kafka -``` - -The above command deploys Kafka with 3 brokers (replicas). - -Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, - -```console -helm install my-release -f values.yaml bitnami/kafka -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -## Configuration and installation details - -### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) - -It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. - -Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. - -### Production configuration and horizontal scaling - -This chart includes a `values-production.yaml` file where you can find some parameters oriented to production configuration in comparison to the regular `values.yaml`. You can use this file instead of the default one. - -- Number of Kafka nodes: - -```diff -- replicaCount: 1 -+ replicaCount: 3 -``` - -- Allow to use the PLAINTEXT listener: - -```diff -- allowPlaintextListener: true -+ allowPlaintextListener: false -``` - -- Default replication factors for automatically created topics: - -```diff -- defaultReplicationFactor: 1 -+ defaultReplicationFactor: 3 -``` - -- Allow auto creation of topics. - -```diff -- autoCreateTopicsEnable: true -+ autoCreateTopicsEnable: false -``` - -- The replication factor for the offsets topic: - -```diff -- offsetsTopicReplicationFactor: 1 -+ offsetsTopicReplicationFactor: 3 -``` - -- The replication factor for the transaction topic: - -```diff -- transactionStateLogReplicationFactor: 1 -+ transactionStateLogReplicationFactor: 3 -``` - -- Overridden min.insync.replicas config for the transaction topic: - -```diff -- transactionStateLogMinIsr: 1 -+ transactionStateLogMinIsr: 3 -``` - -- Switch to enable the Kafka SASAL authentication on client and inter-broker communications: - -```diff -- auth.clientProtocol: plaintext -+ auth.clientProtocol: sasl -- auth.interBrokerProtocol: plaintext -+ auth.interBrokerProtocol: sasl -``` - -- Enable Zookeeper authentication: - -```diff -+ auth.jaas.zookeeperUser: zookeeperUser -+ auth.jaas.zookeeperPassword: zookeeperPassword -- zookeeper.auth.enabled: false -+ zookeeper.auth.enabled: true -+ zookeeper.auth.clientUser: zookeeperUser -+ zookeeper.auth.clientPassword: zookeeperPassword -+ zookeeper.auth.serverUsers: zookeeperUser -+ zookeeper.auth.serverPasswords: zookeeperPassword -``` - -- Enable Pod Disruption Budget: - -```diff -- pdb.create: false -+ pdb.create: true -``` - -- Create a separate Kafka metrics exporter: - -```diff -- metrics.kafka.enabled: false -+ metrics.kafka.enabled: true -``` - -- Expose JMX metrics to Prometheus: - -```diff -- metrics.jmx.enabled: false -+ metrics.jmx.enabled: true -``` - -- Enable Zookeeper metrics: - -```diff -+ zookeeper.metrics.enabled: true -``` - -To horizontally scale this chart once it has been deployed, you can upgrade the statefulset using a new value for the `replicaCount` parameter. Please note that, when enabling TLS encryption, you must update your JKS secret including the keystore for the new replicas. - -### Setting custom parameters - -Any environment variable beginning with `KAFKA_CFG_` will be mapped to its corresponding Kafka key. For example, use `KAFKA_CFG_BACKGROUND_THREADS` in order to set `background.threads`. In order to pass custom environment variables use the `extraEnvVars` property. - -### Listeners configuration - -This chart allows you to automatically configure Kafka with 3 listeners: - -- One for inter-broker communications. -- A second one for communications with clients within the K8s cluster. -- (optional) a third listener for communications with clients outside the K8s cluster. Check [this section](#accessing-kafka-brokers-from-outside-the-clusters) for more information. - -For more complex configurations, set the `listeners`, `advertisedListeners` and `listenerSecurityProtocolMap` parameters as needed. - -### Enable security for Kafka and Zookeeper - -You can configure different authentication protocols for each listener you configure in Kafka. For instance, you can use `sasl_tls` authentication for client communications, while using `tls` for inter-broker communications. This table shows the available protocols and the security they provide: - -| Method | Authentication | Encryption via TLS | -|-----------|-------------------------------|--------------------| -| plaintext | None | No | -| tls | None | Yes | -| mtls | Yes (two-way authentication) | Yes | -| sasl | Yes (via SASL) | No | -| sasl_tls | Yes (via SASL) | Yes | - -If you enabled SASL authentication on any listener, you can set the SASL credentials using the parameters below: - -- `auth.jaas.clientUsers`/`auth.jaas.clientPasswords`: when enabling SASL authentication for communications with clients. -- `auth.jaas.interBrokerUser`/`auth.jaas.interBrokerPassword`: when enabling SASL authentication for inter-broker communications. -- `auth.jaas.zookeeperUser`/`auth.jaas.zookeeperPassword`: In the case that the Zookeeper chart is deployed with SASL authentication enabled. - -In order to configure TLS authentication/encryption, you **must** create a secret containing the Java Key Stores (JKS) files: the truststore (`kafka.truststore.jks`) and one keystore (`kafka.keystore.jks`) per Kafka broker you have in the cluster. Then, you need pass the secret name with the `--auth.jksSecret` parameter when deploying the chart. - -> **Note**: If the JKS files are password protected (recommended), you will need to provide the password to get access to the keystores. To do so, use the `auth.jksPassword` parameter to provide your password. - -For instance, to configure TLS authentication on a Kafka cluster with 2 Kafka brokers use the command below to create the secret: - -```console -kubectl create secret generic kafka-jks --from-file=./kafka.truststore.jks --from-file=./kafka-0.keystore.jks --from-file=./kafka-1.keystore.jks -``` - -> **Note**: the command above assumes you already created the trustore and keystores files. This [script](https://raw.githubusercontent.com/confluentinc/confluent-platform-security-tools/master/kafka-generate-ssl.sh) can help you with the JKS files generation. - -As an alternative to manually create the secret before installing the chart, you can put your JKS files inside the chart folder `files/jks`, an a secret including them will be generated. Please note this alternative requires to have the chart downloaded locally, so you will have to clone this repository or fetch the chart before installing it. - -You can deploy the chart with authentication using the following parameters: - -```console -replicaCount=2 -auth.clientProtocol=sasl -auth.interBrokerProtocol=tls -auth.certificatesSecret=kafka-jks -auth.certificatesPassword=jksPassword -auth.jaas.clientUsers[0]=brokerUser -auth.jaas.clientPassword[0]=brokerPassword -auth.jaas.zookeeperUser=zookeeperUser -auth.jaas.zookeeperPassword=zookeeperPassword -zookeeper.auth.enabled=true -zookeeper.auth.serverUsers=zookeeperUser -zookeeper.auth.serverPasswords=zookeeperPassword -zookeeper.auth.clientUser=zookeeperUser -zookeeper.auth.clientPassword=zookeeperPassword -``` - -If you also enable exposing metrics using the Kafka expoter, and you are using `sasl_tls`, `tls`, or `mtls` authentication protocols, you need to mount the CA certificated used to sign the brokers certificates in the exporter so it can validate the Kafka brokers. To do so, create a secret containing the CA, and set the `metrics.certificatesSecret` parameter. As an alternative, you can skip TLS validation using extra flags: - -```console -metrics.kafka.extraFlags={tls.insecure-skip-tls-verify: ""} -``` - -### Accessing Kafka brokers from outside the cluster - -In order to access Kafka Brokers from outside the cluster, an additional listener and advertised listener must be configured. Additionally, a specific service per kafka pod will be created. - -There are two ways of configuring external access. Using LoadBalancer services or using NodePort services. - -#### Using LoadBalancer services - -You have two alternatives to use LoadBalancer services: - -- Option A) Use random load balancer IPs using an **initContainer** that waits for the IPs to be ready and discover them automatically. - -```console -externalAccess.enabled=true -externalAccess.service.type=LoadBalancer -externalAccess.service.port=9094 -externalAccess.autoDiscovery.enabled=true -serviceAccount.create=true -rbac.create=true -``` - -Note: This option requires creating RBAC rules on clusters where RBAC policies are enabled. - -- Option B) Manually specify the load balancer IPs: - -```console -externalAccess.enabled=true -externalAccess.service.type=LoadBalancer -externalAccess.service.port=9094 -externalAccess.service.loadBalancerIPs[0]='external-ip-1' -externalAccess.service.loadBalancerIPs[1]='external-ip-2'} -``` - -Note: You need to know in advance the load balancer IPs so each Kafka broker advertised listener is configured with it. - -#### Using NodePort services - -You have two alternatives to use NodePort services: - -- Option A) Use random node ports using an **initContainer** that discover them automatically. - -```console -externalAccess.enabled=true -externalAccess.service.type=NodePort -externalAccess.autoDiscovery.enabled=true -serviceAccount.create=true -rbac.create=true -``` - -Note: This option requires creating RBAC rules on clusters where RBAC policies are enabled. - -- Option B) Manually specify the node ports: - -```console -externalAccess.enabled=true -externalAccess.service.type=NodePort -externalAccess.serivce.nodePorts[0]='node-port-1' -externalAccess.serivce.nodePorts[1]='node-port-2' -``` - -Note: You need to know in advance the node ports that will be exposed so each Kafka broker advertised listener is configured with it. - -The pod will try to get the external ip of the node using `curl -s https://ipinfo.io/ip` unless `externalAccess.service.domain` is provided. - -Following the aforementioned steps will also allow to connect the brokers from the outside using the cluster's default service (when `service.type` is `LoadBalancer` or `NodePort`). Use the property `service.externalPort` to specify the port used for external connections. - -### Sidecars - -If you have a need for additional containers to run within the same pod as Kafka (e.g. an additional metrics or logging exporter), you can do so via the `sidecars` config parameter. Simply define your container according to the Kubernetes container spec. - -```yaml -sidecars: - - name: your-image-name - image: your-image - imagePullPolicy: Always - ports: - - name: portname - containerPort: 1234 -``` - -### Deploying extra resources - -There are cases where you may want to deploy extra objects, such as Kafka Connect. For covering this case, the chart allows adding the full specification of other objects using the `extraDeploy` parameter. The following example would create a deployment including a Kafka Connect deployment so you can connect Kafka with MongoDB: - -```yaml -## Extra objects to deploy (value evaluated as a template) -## -extraDeploy: |- - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: {{ include "kafka.fullname" . }}-connect - labels: {{- include "kafka.labels" . | nindent 6 }} - app.kubernetes.io/component: connector - spec: - replicas: 1 - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 8 }} - app.kubernetes.io/component: connector - template: - metadata: - labels: {{- include "kafka.labels" . | nindent 10 }} - app.kubernetes.io/component: connector - spec: - containers: - - name: connect - image: KAFKA-CONNECT-IMAGE - imagePullPolicy: IfNotPresent - ports: - - name: connector - containerPort: 8083 - volumeMounts: - - name: configuration - mountPath: /opt/bitnami/kafka/config - volumes: - - name: configuration - configMap: - name: {{ include "kafka.fullname" . }}-connect - - apiVersion: v1 - kind: ConfigMap - metadata: - name: {{ include "kafka.fullname" . }}-connect - labels: {{- include "kafka.labels" . | nindent 6 }} - app.kubernetes.io/component: connector - data: - connect-standalone.properties: |- - bootstrap.servers = {{ include "kafka.fullname" . }}-0.{{ include "kafka.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}:{{ .Values.service.port }} - ... - mongodb.properties: |- - connection.uri=mongodb://root:password@mongodb-hostname:27017 - ... - - apiVersion: v1 - kind: Service - metadata: - name: {{ include "kafka.fullname" . }}-connect - labels: {{- include "kafka.labels" . | nindent 6 }} - app.kubernetes.io/component: connector - spec: - ports: - - protocol: TCP - port: 8083 - targetPort: connector - selector: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: connector -``` - -You can create the Kafka Connect image using the Dockerfile below: - -```Dockerfile -FROM bitnami/kafka:latest -# Download MongoDB Connector for Apache Kafka https://www.confluent.io/hub/mongodb/kafka-connect-mongodb -RUN mkdir -p /opt/bitnami/kafka/plugins && \ - cd /opt/bitnami/kafka/plugins && \ - curl --remote-name --location --silent https://search.maven.org/remotecontent?filepath=org/mongodb/kafka/mongo-kafka-connect/1.2.0/mongo-kafka-connect-1.2.0-all.jar -CMD /opt/bitnami/kafka/bin/connect-standalone.sh /opt/bitnami/kafka/config/connect-standalone.properties /opt/bitnami/kafka/config/mongo.properties -``` - -## Persistence - -The [Bitnami Kafka](https://github.com/bitnami/bitnami-docker-kafka) image stores the Kafka data at the `/bitnami/kafka` path of the container. - -Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. See the [Parameters](#persistence-parameters) section to configure the PVC or to disable persistence. - -### Adjust permissions of persistent volume mountpoint - -As the image run as non-root by default, it is necessary to adjust the ownership of the persistent volume so that the container can write data into it. - -By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions. -As an alternative, this chart supports using an initContainer to change the ownership of the volume before mounting it in the final destination. - -You can enable this initContainer by setting `volumePermissions.enabled` to `true`. - -## Upgrading - -### To 11.8.0 - -External access to brokers can now be archived through the cluster's Kafka service. - -- `service.nodePort` -> deprecated in favor of `service.nodePorts.client` and `service.nodePorts.external` - -### To 11.7.0 - -The way to configure the users and passwords changed. Now it is allowed to create multiple users during the installation by providing the list of users and passwords. - -- `auth.jaas.clientUser` (string) -> deprecated in favor of `auth.jaas.clientUsers` (array). -- `auth.jaas.clientPassword` (string) -> deprecated in favor of `auth.jaas.clientPasswords` (array). - -### To 11.0.0 - -The way to configure listeners and authentication on Kafka is totally refactored allowing users to configure different authentication protocols on different listeners. Please check the sections [Listeners Configuration](listeners-configuration) and [Listeners Configuration](enable-kafka-for-kafka-and-zookeeper) for more information. - -Backwards compatibility is not guaranteed you adapt your values.yaml to the new format. Here you can find some parameters that were renamed or disappeared in favor of new ones on this major version: - -- `auth.enabled` -> deprecated in favor of `auth.clientProtocol` and `auth.interBrokerProtocol` parameters. -- `auth.ssl` -> deprecated in favor of `auth.clientProtocol` and `auth.interBrokerProtocol` parameters. -- `auth.certificatesSecret` -> renamed to `auth.jksSecret`. -- `auth.certificatesPassword` -> renamed to `auth.jksPassword`. -- `sslEndpointIdentificationAlgorithm` -> renamedo to `auth.tlsEndpointIdentificationAlgorithm`. -- `auth.interBrokerUser` -> renamed to `auth.jaas.interBrokerUser` -- `auth.interBrokerPassword` -> renamed to `auth.jaas.interBrokerPassword` -- `auth.zookeeperUser` -> renamed to `auth.jaas.zookeeperUser` -- `auth.zookeeperPassword` -> renamed to `auth.jaas.zookeeperPassword` -- `auth.existingSecret` -> renamed to `auth.jaas.existingSecret` -- `service.sslPort` -> deprecated in favor of `service.internalPort` -- `service.nodePorts.kafka` and `service.nodePorts.ssl` -> deprecated in favor of `service.nodePort` -- `metrics.kafka.extraFlag` -> new parameter -- `metrics.kafka.certificatesSecret` -> new parameter - -### To 10.0.0 - -If you are setting the `config` or `log4j` parameter, backwards compatibility is not guaranteed, because the `KAFKA_MOUNTED_CONFDIR` has moved from `/opt/bitnami/kafka/conf` to `/bitnami/kafka/config`. In order to continue using these parameters, you must also upgrade your image to `docker.io/bitnami/kafka:2.4.1-debian-10-r38` or later. - -### To 9.0.0 - -Backwards compatibility is not guaranteed you adapt your values.yaml to the new format. Here you can find some parameters that were renamed on this major version: - -```diff -- securityContext.enabled -- securityContext.fsGroup -- securityContext.fsGroup -+ podSecurityContext -- externalAccess.service.loadBalancerIP -+ externalAccess.service.loadBalancerIPs -- externalAccess.service.nodePort -+ externalAccess.service.nodePorts -- metrics.jmx.configMap.enabled -- metrics.jmx.configMap.overrideConfig -+ metrics.jmx.config -- metrics.jmx.configMap.overrideName -+ metrics.jmx.existingConfigmap -``` - -Ports names were prefixed with the protocol to comply with Istio (see https://istio.io/docs/ops/deployment/requirements/). - -### To 8.0.0 - -There is not backwards compatibility since the brokerID changes to the POD_NAME. For more information see [this PR](https://github.com/bitnami/charts/pull/2028). - -### To 7.0.0 - -Backwards compatibility is not guaranteed when Kafka metrics are enabled, unless you modify the labels used on the exporter deployments. -Use the workaround below to upgrade from versions previous to 7.0.0. The following example assumes that the release name is kafka: - -```console -helm upgrade kafka bitnami/kafka --version 6.1.8 --set metrics.kafka.enabled=false -helm upgrade kafka bitnami/kafka --version 7.0.0 --set metrics.kafka.enabled=true -``` - -### To 2.0.0 - -Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. -Use the workaround below to upgrade from versions previous to 2.0.0. The following example assumes that the release name is kafka: - -```console -kubectl delete statefulset kafka-kafka --cascade=false -kubectl delete statefulset kafka-zookeeper --cascade=false -``` - -### To 1.0.0 - -Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. -Use the workaround below to upgrade from versions previous to 1.0.0. The following example assumes that the release name is kafka: - -```console -kubectl delete statefulset kafka-kafka --cascade=false -kubectl delete statefulset kafka-zookeeper --cascade=false -``` diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/.helmignore b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/.helmignore deleted file mode 100755 index f0c131944..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/Chart.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/Chart.yaml deleted file mode 100755 index c3b15dc5c..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/Chart.yaml +++ /dev/null @@ -1,20 +0,0 @@ -annotations: - category: Infrastructure -apiVersion: v1 -appVersion: 3.6.2 -description: A centralized service for maintaining configuration information, naming, - providing distributed synchronization, and providing group services for distributed - applications. -engine: gotpl -home: https://github.com/bitnami/charts/tree/master/bitnami/zookeeper -icon: https://bitnami.com/assets/stacks/zookeeper/img/zookeeper-stack-110x117.png -keywords: -- zookeeper -maintainers: -- email: containers@bitnami.com - name: Bitnami -name: zookeeper -sources: -- https://github.com/bitnami/bitnami-docker-zookeeper -- https://zookeeper.apache.org/ -version: 5.21.9 diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/README.md b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/README.md deleted file mode 100755 index 0291875ed..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/README.md +++ /dev/null @@ -1,297 +0,0 @@ -# ZooKeeper - -[ZooKeeper](https://zookeeper.apache.org/) is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or other by distributed applications. - -## TL;DR - -```console -$ helm repo add bitnami https://charts.bitnami.com/bitnami -$ helm install my-release bitnami/zookeeper -``` - -## Introduction - -This chart bootstraps a [ZooKeeper](https://github.com/bitnami/bitnami-docker-zookeeper) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 2.12+ or Helm 3.0-beta3+ -- PV provisioner support in the underlying infrastructure - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -$ helm repo add bitnami https://charts.bitnami.com/bitnami -$ helm install my-release bitnami/zookeeper -``` - -These commands deploy ZooKeeper on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```console -$ helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Parameters - -The following tables lists the configurable parameters of the ZooKeeper chart and their default values per section/component: - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `global.imageRegistry` | Global Docker image registry | `nil` | -| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | - -### Common parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `nameOverride` | String to partially override zookeeper.fullname | `nil` | -| `fullnameOverride` | String to fully override zookeeper.fullname | `nil` | -| `clusterDomain` | Default Kubernetes cluster domain | `cluster.local` | -| `commonLabels` | Labels to add to all deployed objects | `{}` | -| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | -| `schedulerName` | Kubernetes pod scheduler registry | `nil` (use the default-scheduler) | - -### Zookeeper chart parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `image.registry` | ZooKeeper image registry | `docker.io` | -| `image.repository` | ZooKeeper Image name | `bitnami/zookeeper` | -| `image.tag` | ZooKeeper Image tag | `{TAG_NAME}` | -| `image.pullPolicy` | ZooKeeper image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `image.debug` | Specify if debug values should be set | `false` | -| `tickTime` | Basic time unit in milliseconds used by ZooKeeper for heartbeats | `2000` | -| `initLimit` | Time the ZooKeeper servers in quorum have to connect to a leader | `10` | -| `syncLimit` | How far out of date a server can be from a leader | `5` | -| `maxClientCnxns` | Number of concurrent connections that a single client may make to a single member | `60` | -| `maxSessionTimeout` | Maximum session timeout in milliseconds that the server will allow the client to negotiate. | `40000` | -| `autopurge.snapRetainCount` | Number of retains snapshots for autopurge | `3` | -| `autopurge.purgeInterval` | The time interval in hours for which the purge task has to be triggered | `0` | -| `fourlwCommandsWhitelist` | A list of comma separated Four Letter Words commands to use | `srvr, mntr` | -| `listenOnAllIPs` | Allow Zookeeper to listen for connections from its peers on all available IP addresses. | `false` | -| `allowAnonymousLogin` | Allow to accept connections from unauthenticated users | `yes` | -| `auth.existingSecret` | Use existing secret (ignores previous password) | `nil` | -| `auth.enabled` | Enable ZooKeeper auth | `false` | -| `auth.clientUser` | User that will use ZooKeeper clients to auth | `nil` | -| `auth.clientPassword` | Password that will use ZooKeeper clients to auth | `nil` | -| `auth.serverUsers` | List of user to be created | `nil` | -| `auth.serverPasswords` | List of passwords to assign to users when created | `nil` | -| `heapSize` | Size in MB for the Java Heap options (Xmx and XMs) | `[]` | -| `logLevel` | Log level of ZooKeeper server | `ERROR` | -| `jvmFlags` | Default JVMFLAGS for the ZooKeeper process | `nil` | -| `config` | Configure ZooKeeper with a custom zoo.conf file | `nil` | -| `dataLogDir` | Data log directory | `""` | - -### Statefulset parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `replicaCount` | Number of ZooKeeper nodes | `1` | -| `updateStrategy` | Update strategy for the statefulset | `RollingUpdate` | -| `rollingUpdatePartition` | Partition update strategy | `nil` | -| `podManagementPolicy` | Pod management policy | `Parallel` | -| `podLabels` | ZooKeeper pod labels | `{}` (evaluated as a template) | -| `podAnnotations` | ZooKeeper Pod annotations | `{}` (evaluated as a template) | -| `affinity` | Affinity for pod assignment | `{}` (evaluated as a template) | -| `nodeSelector` | Node labels for pod assignment | `{}` (evaluated as a template) | -| `tolerations` | Tolerations for pod assignment | `[]` (evaluated as a template) | -| `priorityClassName` | Name of the existing priority class to be used by ZooKeeper pods | `""` | -| `securityContext.enabled` | Enable security context (ZooKeeper master pod) | `true` | -| `securityContext.fsGroup` | Group ID for the container (ZooKeeper master pod) | `1001` | -| `securityContext.runAsUser` | User ID for the container (ZooKeeper master pod) | `1001` | -| `resources` | CPU/Memory resource requests/limits | Memory: `256Mi`, CPU: `250m` | -| `livenessProbe` | Liveness probe configuration for ZooKeeper | Check `values.yaml` file | -| `readinessProbe` | Readiness probe configuration for ZooKeeper | Check `values.yaml` file | -| `extraVolumes` | Extra volumes | `nil` | -| `extraVolumeMounts` | Mount extra volume(s) | `nil` | -| `podDisruptionBudget.maxUnavailable` | Max number of pods down simultaneously | `1` | - -### Exposure parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `service.type` | Kubernetes Service type | `ClusterIP` | -| `service.port` | ZooKeeper port | `2181` | -| `service.followerPort` | ZooKeeper follower port | `2888` | -| `service.electionPort` | ZooKeeper election port | `3888` | -| `service.publishNotReadyAddresses` | If the ZooKeeper headless service should publish DNS records for not ready pods | `true` | -| `serviceAccount.create` | Enable creation of ServiceAccount for zookeeper pod | `false` | -| `serviceAccount.name` | The name of the service account to use. If not set and `create` is `true`, a name is generated | Generated using the `zookeeper.fullname` template | -| `service.tls.client_enable` | Enable tls for client connections | `false` | -| `service.tls.quorum_enable` | Enable tls for quorum protocol | `false` | -| `service.tls.disable_base_client_port` | Remove client port from service definitions. | `false` | -| `service.tls.client_port` | Service port for tls client connections | `3181` | -| `service.tls.client_keystore_path` | KeyStore file path. Refer to extraVolumes and extraVolumeMounts for mounting files into the pods | `/tls_key_store/key_store_file` | -| `service.tls.client_keystore_password` | KeyStore password. You can use environment variables. | `nil` | -| `service.tls.client_truststore_path` | TrustStore file path. Refer to extraVolumes and extraVolumeMounts for mounting files into the pods | `/tls_trust_store/trust_store_file` | -| `service.tls.client_truststore_password` | TrustStore password. You can use environment variables. | `nil` | -| `service.tls.quorum_keystore_path` | KeyStore file path. Refer to extraVolumes and extraVolumeMounts for mounting files into the pods | `/tls_key_store/key_store_file` | -| `service.tls.quorum_keystore_password` | KeyStore password. You can use environment variables. | `nil` | -| `service.tls.quorum_truststore_path` | TrustStore file path. Refer to extraVolumes and extraVolumeMounts for mounting files into the pods | `/tls_trust_store/trust_store_file` | -| `service.tls.quorum_truststore_password` | TrustStore password. You can use environment variables. | `nil` | -| `service.annotations` | Annotations for the Service | `{}` | -| `service.headless.annotations` | Annotations for the Headless Service | `{}` | -| `networkPolicy.enabled` | Enable NetworkPolicy | `false` | -| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | - -### Persistence parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `persistence.enabled` | Enable Zookeeper data persistence using PVC | `true` | -| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim` | `nil` (evaluated as a template) | -| `persistence.storageClass` | PVC Storage Class for ZooKeeper data volume | `nil` | -| `persistence.accessMode` | PVC Access Mode for ZooKeeper data volume | `ReadWriteOnce` | -| `persistence.size` | PVC Storage Request for ZooKeeper data volume | `8Gi` | -| `persistence.annotations` | Annotations for the PVC | `{}` (evaluated as a template) | -| `persistence.dataLogDir.size` | PVC Storage Request for ZooKeeper's Data log directory | `8Gi` | -| `persistence.dataLogDir.existingClaim` | Provide an existing `PersistentVolumeClaim` for Zookeeper's Data log directory | `nil` (evaluated as a template) | - -### Volume Permissions parameters - -| Parameter | Description | Default | -|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `volumePermissions.enabled` | Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` | `false` | -| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | -| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/minideb` | -| `volumePermissions.image.tag` | Init container volume-permissions image tag | `buster` | -| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | -| `volumePermissions.resources` | Init container resource requests/limit | `nil` | - -### Metrics parameters - -| Parameter | Description | Default | -|-------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------| -| `metrics.enabled` | Enable prometheus to access zookeeper metrics endpoint | `false` | -| `metrics.containerPort` | Port where a Jetty server will expose Prometheus metrics | `9141` | -| `metrics.service.type` | Kubernetes service type (`ClusterIP`, `NodePort` or `LoadBalancer`) for Jetty server exposing Prometheus metrics | `ClusterIP` | -| `metrics.service.port` | Prometheus metrics service port | `9141` | -| `metrics.service.annotations` | Service annotations for Prometheus to auto-discover the metrics endpoint | `{prometheus.io/scrape: "true", prometheus.io/port: "9141"}` | -| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | -| `metrics.serviceMonitor.namespace` | Namespace for the ServiceMonitor Resource | The Release Namespace | -| `metrics.serviceMonitor.interval` | Interval at which metrics should be scraped. | `nil` (Prometheus Operator default value) | -| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `nil` (Prometheus Operator default value) | -| `metrics.serviceMonitor.selector` | Prometheus instance selector labels | `nil` | -| `metrics.prometheusRule.enabled` | if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`) | `false` | -| `metrics.prometheusRule.namespace` | Namespace for the PrometheusRule Resource | The Release Namespace | -| `metrics.prometheusRule.selector` | Prometheus instance selector labels | `nil` | -| `metrics.prometheusRule.rules` | Prometheus Rule definitions (see values.yaml for examples) | `[]` | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, - -```console -$ helm install my-release \ - --set auth.clientUser=newUser \ - bitnami/zookeeper -``` - -The above command sets the ZooKeeper user to `newUser`. - -Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, - -```console -$ helm install my-release -f values.yaml bitnami/zookeeper -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -## Configuration and installation details - -### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) - -It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. - -Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. - -### Production configuration - -This chart includes a `values-production.yaml` file where you can find some parameters oriented to production configuration in comparison to the regular `values.yaml`. You can use this file instead of the default one. - -- Number of ZooKeeper nodes: - -```diff -- replicaCount: 1 -+ replicaCount: 3 -``` - -- Enable prometheus metrics: - -```diff -- metrics.enabled: false -+ metrics.enabled: true -``` - -### Log level - -You can configure the ZooKeeper log level using the `ZOO_LOG_LEVEL` environment variable. By default, it is set to `ERROR` because of each readiness probe produce an `INFO` message on connection and a `WARN` message on disconnection. - -## Persistence - -The [Bitnami ZooKeeper](https://github.com/bitnami/bitnami-docker-zookeeper) image stores the ZooKeeper data and configurations at the `/bitnami/zookeeper` path of the container. - -Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. -See the [Parameters](#parameters) section to configure the PVC or to disable persistence. - -### Adjust permissions of persistent volume mountpoint - -As the image run as non-root by default, it is necessary to adjust the ownership of the persistent volume so that the container can write data into it. - -By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions. -As an alternative, this chart supports using an initContainer to change the ownership of the volume before mounting it in the final destination. - -You can enable this initContainer by setting `volumePermissions.enabled` to `true`. - -### Data Log Directory - -You can use a dedicated device for logs (instead of using the data directory) to help avoiding competition between logging and snapshots. To do so, set the `dataLogDir` parameter with the path to be used for writing transaction logs. Alternatively, set this parameter with an empty string an it result in the log being written to the data directory (Zookeeper's default behavior). - -When using a dedicated device for logs, you can use a PVC to persist the logs. To do so, set `persistence.enabled` to `true`. See the [Persistence Parameters](#persistence-parameters) section for more information. - -## Upgrading - -### To 5.21.0 - -A couple of parameters related to Zookeeper metrics were renamed or disappeared in favor of new ones: - -- `metrics.port` is renamed to `metrics.containerPort`. -- `metrics.annotations` is deprecated in favor of `metrics.service.annotations`. - -### To 3.0.0 - -This new version of the chart includes the new ZooKeeper major version 3.5.5. Note that to perform an automatic upgrade -of the application, each node will need to have at least one snapshot file created in the data directory. If not, the -new version of the application won't be able to start the service. Please refer to [ZOOKEEPER-3056](https://issues.apache.org/jira/browse/ZOOKEEPER-3056) -in order to find ways to workaround this issue in case you are facing it. - -### To 2.0.0 - -Backwards compatibility is not guaranteed unless you modify the labels used on the chart's statefulsets. -Use the workaround below to upgrade from versions previous to 2.0.0. The following example assumes that the release name is `zookeeper`: - -```console -$ kubectl delete statefulset zookeeper-zookeeper --cascade=false -``` - -### To 1.0.0 - -Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments. -Use the workaround below to upgrade from versions previous to 1.0.0. The following example assumes that the release name is zookeeper: - -```console -$ kubectl delete statefulset zookeeper-zookeeper --cascade=false -``` diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/NOTES.txt b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/NOTES.txt deleted file mode 100755 index 3cc2edbed..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/NOTES.txt +++ /dev/null @@ -1,57 +0,0 @@ -{{- if contains .Values.service.type "LoadBalancer" }} -{{- if not .Values.auth.clientPassword }} -------------------------------------------------------------------------------- - WARNING - - By specifying "serviceType=LoadBalancer" and not specifying "auth.enabled=true" - you have most likely exposed the ZooKeeper service externally without any - authentication mechanism. - - For security reasons, we strongly suggest that you switch to "ClusterIP" or - "NodePort". As alternative, you can also specify a valid password on the - "auth.clientPassword" parameter. - -------------------------------------------------------------------------------- -{{- end }} -{{- end }} - -** Please be patient while the chart is being deployed ** - -ZooKeeper can be accessed via port 2181 on the following DNS name from within your cluster: - - {{ template "zookeeper.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} - -To connect to your ZooKeeper server run the following commands: - - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "zookeeper.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=zookeeper" -o jsonpath="{.items[0].metadata.name}") - kubectl exec -it $POD_NAME -- zkCli.sh - -To connect to your ZooKeeper server from outside the cluster execute the following commands: - -{{- if contains "NodePort" .Values.service.type }} - - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "zookeeper.fullname" . }}) - zkCli.sh $NODE_IP:$NODE_PORT - -{{- else if contains "LoadBalancer" .Values.service.type }} - - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "zookeeper.fullname" . }}' - - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "zookeeper.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - zkCli.sh $SERVICE_IP:2181 - -{{- else if contains "ClusterIP" .Values.service.type }} - - kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "zookeeper.fullname" . }} 2181:2181 & - zkCli.sh 127.0.0.1:2181 - -{{- end }} - -{{- if and (contains "bitnami/" .Values.image.repository) (not (.Values.image.tag | toString | regexFind "-r\\d+$|sha256:")) }} - -WARNING: Rolling tag detected ({{ .Values.image.repository }}:{{ .Values.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. -+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ - -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/_helpers.tpl b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/_helpers.tpl deleted file mode 100755 index f82502d69..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/_helpers.tpl +++ /dev/null @@ -1,212 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "zookeeper.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "zookeeper.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "zookeeper.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* - Create the name of the service account to use - */}} -{{- define "zookeeper.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (include "zookeeper.fullname" .) .Values.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Zookeeper image name -*/}} -{{- define "zookeeper.image" -}} -{{- $registryName := .Values.image.registry -}} -{{- $repositoryName := .Values.image.repository -}} -{{- $tag := .Values.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names -*/}} -{{- define "zookeeper.imagePullSecrets" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -Also, we can not use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} -{{- if .Values.global.imagePullSecrets }} -imagePullSecrets: -{{- range .Values.global.imagePullSecrets }} - - name: {{ . }} -{{- end }} -{{- else if or .Values.image.pullSecrets .Values.volumePermissions.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.volumePermissions.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- end -}} -{{- else if or .Values.image.pullSecrets .Values.volumePermissions.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.volumePermissions.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- end -}} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "zookeeper.labels" -}} -app.kubernetes.io/name: {{ include "zookeeper.name" . }} -helm.sh/chart: {{ include "zookeeper.chart" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Renders a value that contains template. -Usage: -{{ include "zookeeper.tplValue" ( dict "value" .Values.path.to.the.Value "context" $) }} -*/}} -{{- define "zookeeper.tplValue" -}} - {{- if typeIs "string" .value }} - {{- tpl .value .context }} - {{- else }} - {{- tpl (.value | toYaml) .context }} - {{- end }} -{{- end -}} - -{{/* -Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector -*/}} -{{- define "zookeeper.matchLabels" -}} -app.kubernetes.io/name: {{ include "zookeeper.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Return ZooKeeper Client Password -*/}} -{{- define "zookeeper.clientPassword" -}} -{{- if .Values.auth.clientPassword -}} - {{- .Values.auth.clientPassword -}} -{{- else -}} - {{- randAlphaNum 10 -}} -{{- end -}} -{{- end -}} - -{{/* -Return ZooKeeper Servers Passwords -*/}} -{{- define "zookeeper.serverPasswords" -}} -{{- if .Values.auth.serverPasswords -}} - {{- .Values.auth.serverPasswords -}} -{{- else -}} - {{- randAlphaNum 10 -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper image name (for the init container volume-permissions image) -*/}} -{{- define "zookeeper.volumePermissions.image" -}} -{{- $registryName := .Values.volumePermissions.image.registry -}} -{{- $repositoryName := .Values.volumePermissions.image.repository -}} -{{- $tag := .Values.volumePermissions.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Storage Class -*/}} -{{- define "zookeeper.storageClass" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -*/}} -{{- if .Values.global -}} - {{- if .Values.global.storageClass -}} - {{- if (eq "-" .Values.global.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.global.storageClass -}} - {{- end -}} - {{- else -}} - {{- if .Values.persistence.storageClass -}} - {{- if (eq "-" .Values.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} - {{- end -}} - {{- end -}} - {{- end -}} -{{- else -}} - {{- if .Values.persistence.storageClass -}} - {{- if (eq "-" .Values.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} - {{- end -}} - {{- end -}} -{{- end -}} -{{- end -}} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/configmap.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/configmap.yaml deleted file mode 100755 index 1a4061565..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.config }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: - zoo.cfg: |- -{{ .Values.config | indent 4 }} -{{- end -}} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/metrics-svc.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/metrics-svc.yaml deleted file mode 100755 index 3e26ed6c8..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/metrics-svc.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if .Values.metrics.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "zookeeper.fullname" . }}-metrics - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.metrics.service.annotations .Values.commonAnnotations }} - annotations: - {{- if .Values.metrics.service.annotations }} - {{ include "zookeeper.tplValue" ( dict "value" .Values.metrics.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.metrics.service.type }} - ports: - - name: tcp-metrics - port: {{ .Values.metrics.service.port }} - targetPort: metrics - selector: {{- include "zookeeper.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/networkpolicy.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/networkpolicy.yaml deleted file mode 100755 index f7e30b4bc..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/networkpolicy.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -kind: NetworkPolicy -apiVersion: networking.k8s.io/v1 -metadata: - name: {{ include "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - podSelector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 6 }} - ingress: - # Allow inbound connections to zookeeper - - ports: - - port: {{ .Values.service.port }} - from: - {{- if not .Values.networkPolicy.allowExternal }} - - podSelector: - matchLabels: - {{ include "zookeeper.fullname" . }}-client: "true" - - podSelector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 14 }} - {{- else }} - - podSelector: - matchLabels: {} - {{- end }} - # Internal ports - - ports: &intranodes_ports - - port: {{ .Values.service.followerPort }} - - port: {{ .Values.service.electionPort }} - from: - - podSelector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 14 }} - egress: - - ports: *intranodes_ports - # Allow outbound connections from zookeeper nodes - -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/poddisruptionbudget.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/poddisruptionbudget.yaml deleted file mode 100755 index 818950c66..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- $replicaCount := int .Values.replicaCount }} -{{- if gt $replicaCount 1 }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: zookeeper - {{- toYaml .Values.podDisruptionBudget | nindent 2 }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/prometheusrules.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/prometheusrules.yaml deleted file mode 100755 index 9cda3985c..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/prometheusrules.yaml +++ /dev/null @@ -1,27 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled .Values.metrics.prometheusRule.rules }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ include "zookeeper.fullname" . }} - {{- if .Values.metrics.prometheusRule.namespace }} - namespace: {{ .Values.metrics.prometheusRule.namespace }} - {{- else }} - namespace: {{ .Release.Namespace }} - {{- end }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- range $key, $value := .Values.metrics.prometheusRule.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - groups: - - name: {{ include "zookeeper.fullname" . }} - rules: {{- toYaml .Values.metrics.prometheusRule.rules | nindent 6 }} -{{- end }} - diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/secrets.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/secrets.yaml deleted file mode 100755 index b3d727fec..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/secrets.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.auth.enabled (not .Values.auth.existingSecret) -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -type: Opaque -data: - client-password: {{ include "zookeeper.clientPassword" . | b64enc | quote }} - server-password: {{ include "zookeeper.serverPasswords" . | b64enc | quote }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/serviceaccount.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/serviceaccount.yaml deleted file mode 100755 index 3f7ef39fd..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/serviceaccount.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "zookeeper.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - role: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/servicemonitor.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/servicemonitor.yaml deleted file mode 100755 index 5782dad59..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/servicemonitor.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "zookeeper.fullname" . }} - {{- if .Values.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.metrics.serviceMonitor.namespace }} - {{- else }} - namespace: {{ .Release.Namespace }} - {{- end }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- range $key, $value := .Values.metrics.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: zookeeper - endpoints: - - port: tcp-metrics - path: "/metrics" - {{- if .Values.metrics.serviceMonitor.interval }} - interval: {{ .Values.metrics.serviceMonitor.interval }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} - {{- end }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/statefulset.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/statefulset.yaml deleted file mode 100755 index fa1e5231f..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/statefulset.yaml +++ /dev/null @@ -1,334 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - role: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - serviceName: {{ template "zookeeper.fullname" . }}-headless - replicas: {{ .Values.replicaCount }} - podManagementPolicy: {{ .Values.podManagementPolicy }} - updateStrategy: - type: {{ .Values.updateStrategy }} - {{- if (eq "Recreate" .Values.updateStrategy) }} - rollingUpdate: null - {{- else if .Values.rollingUpdatePartition }} - rollingUpdate: - partition: {{ .Values.rollingUpdatePartition }} - {{- end }} - selector: - matchLabels: {{- include "zookeeper.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: zookeeper - template: - metadata: - name: {{ template "zookeeper.fullname" . }} - labels: {{- include "zookeeper.labels" . | nindent 8 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.podLabels }} - {{- include "zookeeper.tplValue" (dict "value" .Values.podLabels "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.podAnnotations }} - annotations: {{- include "zookeeper.tplValue" ( dict "value" .Values.podAnnotations "context" $) | nindent 8 }} - {{- end }} - spec: - {{- if .Values.schedulerName }} - schedulerName: {{ .Values.schedulerName }} - {{- end }} - {{- include "zookeeper.imagePullSecrets" . | nindent 6 }} - serviceAccountName: {{ template "zookeeper.serviceAccountName" . }} - {{- if .Values.securityContext.enabled }} - securityContext: - fsGroup: {{ .Values.securityContext.fsGroup }} - {{- end }} - {{- if .Values.affinity }} - affinity: {{- include "zookeeper.tplValue" (dict "value" .Values.affinity "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: {{- include "zookeeper.tplValue" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.tolerations }} - tolerations: {{- include "zookeeper.tplValue" (dict "value" .Values.tolerations "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.priorityClassName }} - priorityClassName: {{ .Values.priorityClassName }} - {{- end }} - {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} - initContainers: - - name: volume-permissions - image: {{ template "zookeeper.volumePermissions.image" . }} - imagePullPolicy: {{ default "" .Values.volumePermissions.image.pullPolicy | quote }} - command: - - chown - args: - - -R - - {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} - - /bitnami/zookeeper - {{- if .Values.dataLogDir }} - - {{ .Values.dataLogDir }} - {{- end }} - securityContext: - runAsUser: 0 - {{- if .Values.volumePermissions.resources }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: data - mountPath: /bitnami/zookeeper - {{- if .Values.dataLogDir }} - - name: data-log - mountPath: {{ .Values.dataLogDir }} - {{- end }} - {{- end }} - containers: - - name: zookeeper - image: {{ template "zookeeper.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - {{- if .Values.securityContext.enabled }} - securityContext: - runAsUser: {{ .Values.securityContext.runAsUser }} - {{- end }} - command: - - bash - - -ec - - | - # Execute entrypoint as usual after obtaining ZOO_SERVER_ID based on POD hostname - HOSTNAME=`hostname -s` - if [[ $HOSTNAME =~ (.*)-([0-9]+)$ ]]; then - ORD=${BASH_REMATCH[2]} - export ZOO_SERVER_ID=$((ORD+1)) - else - echo "Failed to get index from hostname $HOST" - exit 1 - fi - exec /entrypoint.sh /run.sh - {{- if .Values.resources }} - resources: {{- toYaml .Values.resources | nindent 12 }} - {{- end }} - env: - - name: ZOO_DATA_LOG_DIR - value: {{ .Values.dataLogDir | quote }} - - name: ZOO_PORT_NUMBER - value: {{ .Values.service.port | quote }} - - name: ZOO_TICK_TIME - value: {{ .Values.tickTime | quote }} - - name: ZOO_INIT_LIMIT - value: {{ .Values.initLimit | quote }} - - name: ZOO_SYNC_LIMIT - value: {{ .Values.syncLimit | quote }} - - name: ZOO_MAX_CLIENT_CNXNS - value: {{ .Values.maxClientCnxns | quote }} - - name: ZOO_4LW_COMMANDS_WHITELIST - value: {{ .Values.fourlwCommandsWhitelist | quote }} - - name: ZOO_LISTEN_ALLIPS_ENABLED - value: {{ ternary "yes" "no" .Values.listenOnAllIPs | quote }} - - name: ZOO_AUTOPURGE_INTERVAL - value: {{ .Values.autopurge.purgeInterval | quote }} - - name: ZOO_AUTOPURGE_RETAIN_COUNT - value: {{ .Values.autopurge.snapRetainCount | quote }} - - name: ZOO_MAX_SESSION_TIMEOUT - value: {{ .Values.maxSessionTimeout | quote }} - - name: ZOO_SERVERS - {{- $replicaCount := int .Values.replicaCount }} - {{- $followerPort := int .Values.service.followerPort }} - {{- $electionPort := int .Values.service.electionPort }} - {{- $releaseNamespace := .Release.Namespace }} - {{- $zookeeperFullname := include "zookeeper.fullname" . }} - {{- $zookeeperHeadlessServiceName := printf "%s-%s" $zookeeperFullname "headless" | trunc 63 }} - {{- $clusterDomain := .Values.clusterDomain }} - value: {{ range $i, $e := until $replicaCount }}{{ $zookeeperFullname }}-{{ $e }}.{{ $zookeeperHeadlessServiceName }}.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $followerPort }}:{{ $electionPort }} {{ end }} - - name: ZOO_ENABLE_AUTH - value: {{ ternary "yes" "no" .Values.auth.enabled | quote }} - {{- if .Values.auth.enabled }} - - name: ZOO_CLIENT_USER - value: {{ .Values.auth.clientUser | quote }} - - name: ZOO_CLIENT_PASSWORD - valueFrom: - secretKeyRef: - name: {{ if .Values.auth.existingSecret }}{{ .Values.auth.existingSecret }}{{ else }}{{ template "zookeeper.fullname" . }}{{ end }} - key: client-password - - name: ZOO_SERVER_USERS - value: {{ .Values.auth.serverUsers | quote }} - - name: ZOO_SERVER_PASSWORDS - valueFrom: - secretKeyRef: - name: {{ if .Values.auth.existingSecret }}{{ .Values.auth.existingSecret }}{{ else }}{{ template "zookeeper.fullname" . }}{{ end }} - key: server-password - {{- end }} - - name: ZOO_HEAP_SIZE - value: {{ .Values.heapSize | quote }} - - name: ZOO_LOG_LEVEL - value: {{ .Values.logLevel | quote }} - - name: ALLOW_ANONYMOUS_LOGIN - value: {{ ternary "yes" "no" .Values.allowAnonymousLogin | quote }} - {{- if .Values.jvmFlags }} - - name: JVMFLAGS - value: {{ .Values.jvmFlags | quote }} - {{- end }} - {{- if .Values.metrics.enabled }} - - name: ZOO_ENABLE_PROMETHEUS_METRICS - value: "yes" - - name: ZOO_PROMETHEUS_METRICS_PORT_NUMBER - value: {{ .Values.metrics.containerPort | quote }} - {{- end }} - {{- if .Values.service.tls.client_enable }} - - name: ZOO_TLS_CLIENT_ENABLE - value: {{ .Values.service.tls.client_enable | quote }} - - name: ZOO_TLS_CLIENT_KEYSTORE_FILE - value: {{ .Values.service.tls.client_keystore_path | quote }} - - name: ZOO_TLS_CLIENT_KEYSTORE_PASSWORD - value: {{ .Values.service.tls.client_keystore_password | quote }} - - name: ZOO_TLS_CLIENT_TRUSTSTORE_FILE - value: {{ .Values.service.tls.client_truststore_path | quote }} - - name: ZOO_TLS_CLIENT_TRUSTSTORE_PASSWORD - value: {{ .Values.service.tls.client_truststore_password | quote }} - {{ end }} - {{- if .Values.service.tls.quorum_enable }} - - name: ZOO_TLS_QUORUM_ENABLE - value: {{ .Values.service.tls.quorum_enable | quote }} - - name: ZOO_TLS_QUORUM_KEYSTORE_FILE - value: {{ .Values.service.tls.quorum_keystore_path | quote }} - - name: ZOO_TLS_QUORUM_KEYSTORE_PASSWORD - value: {{ .Values.service.tls.quorum_keystore_password | quote }} - - name: ZOO_TLS_QUORUM_TRUSTSTORE_FILE - value: {{ .Values.service.tls.quorum_truststore_path | quote }} - - name: ZOO_TLS_QUORUM_TRUSTSTORE_PASSWORD - value: {{ .Values.service.tls.quorum_truststore_password | quote }} - {{ end }} - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - {{- if .Values.extraEnvVars }} - {{- toYaml .Values.extraEnvVars | nindent 12 }} - {{- end }} - ports: - {{ if not .Values.service.tls.disable_base_client_port }} - - name: client - containerPort: {{ .Values.service.port }} - {{ end }} - {{ if .Values.service.tls.client_enable }} - - name: client-tls - containerPort: {{ .Values.service.tls.client_port }} - {{ end }} - - name: follower - containerPort: {{ .Values.service.followerPort }} - - name: election - containerPort: {{ .Values.service.electionPort }} - {{- if .Values.metrics.enabled }} - - name: metrics - containerPort: {{ .Values.metrics.containerPort }} - {{- end }} - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - exec: - {{- if not .Values.service.tls.disable_base_client_port }} - command: ['/bin/bash', '-c', 'echo "ruok" | timeout {{ .Values.livenessProbe.probeCommandTimeout }} nc -w {{ .Values.livenessProbe.probeCommandTimeout }} localhost {{ .Values.service.port }} | grep imok'] - {{- else }} - command: ['/bin/bash', '-c', 'echo "ruok" | timeout {{ .Values.livenessProbe.probeCommandTimeout }} openssl s_client -quiet -crlf -connect localhost:{{ .Values.service.tls.client_port }} | grep imok'] - {{- end }} - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - exec: - {{- if not .Values.service.tls.disable_base_client_port }} - command: ['/bin/bash', '-c', 'echo "ruok" | timeout {{ .Values.readinessProbe.probeCommandTimeout }} nc -w {{ .Values.readinessProbe.probeCommandTimeout }} localhost {{ .Values.service.port }} | grep imok'] - {{- else }} - command: ['/bin/bash', '-c', 'echo "ruok" | timeout {{ .Values.readinessProbe.probeCommandTimeout }} openssl s_client -quiet -crlf -connect localhost:{{ .Values.service.tls.client_port }} | grep imok'] - {{- end }} - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - {{- end }} - volumeMounts: - - name: data - mountPath: /bitnami/zookeeper - {{- if .Values.dataLogDir }} - - name: data-log - mountPath: {{ .Values.dataLogDir }} - {{- end }} - {{- if .Values.config }} - - name: config - mountPath: /opt/bitnami/zookeeper/conf/zoo.cfg - subPath: zoo.cfg - {{- end }} - {{- if .Values.extraVolumeMounts }} - {{- toYaml .Values.extraVolumeMounts | nindent 12 }} - {{- end }} - volumes: - {{- if .Values.config }} - - name: config - configMap: - name: {{ template "zookeeper.fullname" . }} - {{- end }} - {{- if and .Values.persistence.enabled .Values.persistence.existingClaim }} - - name: data - persistentVolumeClaim: - claimName: {{ printf "%s" (tpl .Values.persistence.existingClaim .) }} - {{- else if not .Values.persistence.enabled }} - - name: data - emptyDir: {} - {{- end }} - {{- if and .Values.persistence.enabled .Values.persistence.dataLogDir.existingClaim }} - - name: data-log - persistentVolumeClaim: - claimName: {{ printf "%s" (tpl .Values.persistence.dataLogDir.existingClaim .) }} - {{- else if and ( not .Values.persistence.enabled ) .Values.dataLogDir }} - - name: data-log - emptyDir: {} - {{- end }} - {{- if .Values.extraVolumes }} - {{- toYaml .Values.extraVolumes | nindent 8 }} - {{- end }} - {{- if and .Values.persistence.enabled (not (and .Values.persistence.existingClaim .Values.persistence.dataLogDir.existingClaim) )}} - volumeClaimTemplates: - {{- if not .Values.persistence.existingClaim }} - - metadata: - name: data - annotations: - {{- range $key, $value := .Values.persistence.annotations }} - {{ $key }}: {{ $value }} - {{- end }} - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{- include "zookeeper.storageClass" . | nindent 8 }} - {{- end }} - {{- if and (not .Values.persistence.dataLogDir.existingClaim) .Values.dataLogDir }} - - metadata: - name: data-log - annotations: - {{- range $key, $value := .Values.persistence.annotations }} - {{ $key }}: {{ $value }} - {{- end }} - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.dataLogDir.size | quote }} - {{- include "zookeeper.storageClass" . | nindent 8 }} - {{- end }} - {{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/svc-headless.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/svc-headless.yaml deleted file mode 100755 index 972efb51d..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/svc-headless.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "zookeeper.fullname" . }}-headless - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.commonAnnotations .Values.service.annotations }} - annotations: - {{- if .Values.service.headless.annotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.service.headless.annotations "context" $ ) | nindent 4 }}\ - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: ClusterIP - clusterIP: None - publishNotReadyAddresses: {{ .Values.service.publishNotReadyAddresses }} - ports: - {{ if not .Values.service.tls.disable_base_client_port }} - - name: tcp-client - port: 2181 - targetPort: client - {{ end }} - {{ if .Values.service.tls.client_enable }} - - name: tcp-client-tls - port: {{ .Values.service.tls.client_port }} - targetPort: client-tls - {{ end }} - - name: follower - port: 2888 - targetPort: follower - - name: tcp-election - port: 3888 - targetPort: election - selector: {{- include "zookeeper.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/svc.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/svc.yaml deleted file mode 100755 index da3a2895a..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/templates/svc.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "zookeeper.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "zookeeper.labels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper - {{- if .Values.commonLabels }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.commonAnnotations .Values.service.annotations }} - annotations: - {{- if .Values.service.annotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.service.annotations "context" $ ) | nindent 4 }}\ - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "zookeeper.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.service.type }} - ports: - {{ if not .Values.service.tls.disable_base_client_port }} - - name: tcp-client - port: 2181 - targetPort: client - {{ end }} - {{ if .Values.service.tls.client_enable }} - - name: tcp-client-tls - port: {{ .Values.service.tls.client_port }} - targetPort: client-tls - {{ end }} - - name: follower - port: 2888 - targetPort: follower - - name: tcp-election - port: 3888 - targetPort: election - selector: {{- include "zookeeper.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: zookeeper diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/values-production.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/values-production.yaml deleted file mode 100755 index 7d678603f..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/values-production.yaml +++ /dev/null @@ -1,430 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -# global: -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami Zookeeper image version -## ref: https://hub.docker.com/r/bitnami/zookeeper/tags/ -## -image: - registry: docker.io - repository: bitnami/zookeeper - tag: 3.6.2-debian-10-r10 - - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Set to true if you would like to see extra information on logs - ## It turns BASH and NAMI debugging in minideb - ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging - ## - debug: false - -## String to partially override zookeeper.fullname template (will maintain the release name) -# nameOverride: - -## String to fully override zookeeper.fullname template -# fullnameOverride: - -## Kubernetes Cluster Domain -## -clusterDomain: cluster.local - -## Add labels to all the deployed resources -## -commonLabels: {} - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -## Init containers parameters: -## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - resources: {} - -## extraVolumes and extraVolumeMounts allows you to mount other volumes -## Example Use Cases: -## mount certificates to enable tls -# extraVolumes: -# - name: zookeeper-keystore -# secret: -# defaultMode: 288 -# secretName: zookeeper-keystore -# - name: zookeeper-trustsore -# secret: -# defaultMode: 288 -# secretName: zookeeper-truststore -# extraVolumeMounts: -# - name: zookeeper-keystore -# mountPath: /certs/keystore -# readOnly: true -# - name: zookeeper-truststore -# mountPath: /certs/truststore -# readOnly: true - - -## StatefulSet controller supports automated updates. There are two valid update strategies: RollingUpdate and OnDelete -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets -## -updateStrategy: RollingUpdate - -## Limits the number of pods of the replicated application that are down simultaneously from voluntary disruptions -## The PDB will only be created if replicaCount is greater than 1 -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions -## -podDisruptionBudget: - maxUnavailable: 1 - -## Partition update strategy -## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -## -# rollingUpdatePartition: - -## StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: OrderedReady and Parallel -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy -## -podManagementPolicy: Parallel - -## Number of ZooKeeper nodes -## -replicaCount: 3 - -## Basic time unit in milliseconds used by ZooKeeper for heartbeats -## -tickTime: 2000 - -## ZooKeeper uses to limit the length of time the ZooKeeper servers in quorum have to connect to a leader -## -initLimit: 10 - -## How far out of date a server can be from a leader -## -syncLimit: 5 - -## Limits the number of concurrent connections that a single client may make to a single member of the ZooKeeper ensemble -## -maxClientCnxns: 60 - -## Maximum session timeout in milliseconds that the server will allow the client to negotiate. Defaults to 20 times the tickTime. -## -maxSessionTimeout: 40000 - -## A list of comma separated Four Letter Words commands to use -## -fourlwCommandsWhitelist: srvr, mntr, ruok - -## Allow zookeeper to listen for peers on all IPs -## -listenOnAllIPs: false - -## Allow to accept connections from unauthenticated users -## -allowAnonymousLogin: true - -autopurge: - ## Retains the snapRetainCount most recent snapshots and the corresponding transaction logs and deletes the rest - ## - snapRetainCount: 3 - ## The time interval in hours for which the purge task has to be triggered. Set to a positive integer (1 and above) to enable the auto purging. - ## - purgeInterval: 0 - -auth: - ## Use existing secret (ignores previous password) - ## - # existingSecret: - ## Enable Zookeeper auth. It uses SASL/Digest-MD5 - ## - enabled: false - ## User that will use Zookeeper clients to auth - ## - clientUser: - ## Password that will use Zookeeper clients to auth - ## - clientPassword: - ## Comma, semicolon or whitespace separated list of user to be created. Specify them as a string, for example: "user1,user2,admin" - ## - serverUsers: - ## Comma, semicolon or whitespace separated list of passwords to assign to users when created. Specify them as a string, for example: "pass4user1, pass4user2, pass4admin" - ## - serverPasswords: - -## Size in MB for the Java Heap options (Xmx and XMs). This env var is ignored if Xmx an Xms are configured via JVMFLAGS -## -heapSize: 1024 - -## Log level for the Zookeeper server. ERROR by default. Have in mind if you set it to INFO or WARN the ReadinessProve will produce a lot of logs. -## -logLevel: ERROR - -## Data log directory. Specifying this option will direct zookeeper to write the transaction log to the dataLogDir rather than the dataDir. -## This allows a dedicated log device to be used, and helps avoid competition between logging and snaphots. -## Example: -## dataLogDir: /bitnami/zookeeper/dataLog -## -dataLogDir: "" - -## Default JVMFLAGS for the ZooKeeper process -## -# jvmFlags: - -## Configure ZooKeeper with a custom zoo.cfg file -## -# config: - -## Kubernetes configuration -## For minikube, set this to NodePort, elsewhere use LoadBalancer -## -service: - type: ClusterIP - port: 2181 - followerPort: 2888 - electionPort: 3888 - publishNotReadyAddresses: true - tls: - client_enable: true - quorum_enable: true - disable_base_client_port: true - - client_port: 3181 - - client_keystore_path: /tls_key_store/key_store_file - client_keystore_password: "" - client_truststore_path: /tls_trust_store/trust_store_file - client_truststore_password: "" - - quorum_keystore_path: /tls_key_store/key_store_file - quorum_keystore_password: "" - quorum_truststore_path: /tls_trust_store/trust_store_file - quorum_truststore_password: "" - annotations: {} - headless: - annotations: {} - -## Service account for Zookeeper to use. -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: false - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the zookeeper.fullname template - # name: - -## Zookeeper Pod Security Context -securityContext: - enabled: true - fsGroup: 1001 - runAsUser: 1001 - -## Zookeeper data Persistent Volume Storage Class -## If defined, storageClassName: -## If set to "-", storageClassName: "", which disables dynamic provisioning -## If undefined (the default) or set to null, no storageClassName spec is -## set, choosing the default provisioner. (gp2 on AWS, standard on -## GKE, AWS & OpenStack) -## -persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - annotations: {} - dataLogDir: - size: 8Gi - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - -## Node labels for pod assignment -## Ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Labels -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -podLabels: {} - -## Annotations -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -podAnnotations: {} - -## Name of the priority class to be used by zookeeper pods, priority class needs to be created beforehand -## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ -priorityClassName: "" - -## Affinity for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Scheduler name -## https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: stork - -## Configure resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - requests: - memory: 256Mi - cpu: 250m - -## Configure extra options for liveness and readiness probes -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) -## -livenessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - probeCommandTimeout: 2 - -readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - probeCommandTimeout: 2 - -## Network policies -## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ -## -networkPolicy: - ## Specifies whether a NetworkPolicy should be created - ## - enabled: true - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port Redis is listening - ## on. When true, zookeeper accept connections from any source - ## (with the correct destination port). - ## - allowExternal: true - -## Zookeeper Prometheus Exporter configuration -## -metrics: - enabled: false - - ## Zookeeper Prometheus Exporter container port - ## - containerPort: 9141 - - ## Service configuration - ## - service: - ## Zookeeper Prometheus Exporter service type - ## - type: ClusterIP - ## Zookeeper Prometheus Exporter service port - ## - port: 9141 - ## Annotations for the Zookeeper Prometheus Exporter metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.service.port }}" - prometheus.io/path: "/metrics" - - ## Prometheus Operator ServiceMonitor configuration - ## - serviceMonitor: - enabled: false - ## Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) - ## - namespace: - - ## Interval at which metrics should be scraped. - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # interval: 10s - - ## Timeout after which the scrape is ended - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # scrapeTimeout: 10s - - ## ServiceMonitor selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - - ## Prometheus Operator PrometheusRule configuration - ## - prometheusRule: - enabled: false - ## Namespace for the PrometheusRule Resource (defaults to the Release Namespace) - ## - namespace: - - ## PrometheusRule selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - - ## Some example rules. - rules: [] - # - alert: ZookeeperSyncedFollowers - # annotations: - # message: The number of synced followers for the leader node in Zookeeper deployment my-release is less than 2. This usually means that some of the Zookeeper nodes aren't communicating properly. If it doesn't resolve itself you can try killing the pods (one by one). - # expr: max(synced_followers{service="my-release-metrics"}) < 2 - # for: 5m - # labels: - # severity: critical - # - alert: ZookeeperOutstandingRequests - # annotations: - # message: The number of outstanding requests for Zookeeper pod {{ $labels.pod }} is greater than 10. This can indicate a performance issue with the Pod or cluster a whole. - # expr: outstanding_requests{service="my-release-metrics"} > 10 - # for: 5m - # labels: - # severity: critical diff --git a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/values.yaml b/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/values.yaml deleted file mode 100755 index a40decb54..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/charts/zookeeper/values.yaml +++ /dev/null @@ -1,430 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -# global: -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami Zookeeper image version -## ref: https://hub.docker.com/r/bitnami/zookeeper/tags/ -## -image: - registry: docker.io - repository: bitnami/zookeeper - tag: 3.6.2-debian-10-r10 - - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Set to true if you would like to see extra information on logs - ## It turns BASH and NAMI debugging in minideb - ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging - ## - debug: false - -## String to partially override zookeeper.fullname template (will maintain the release name) -# nameOverride: - -## String to fully override zookeeper.fullname template -# fullnameOverride: - -## Kubernetes Cluster Domain -## -clusterDomain: cluster.local - -## Add labels to all the deployed resources -## -commonLabels: {} - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -## Init containers parameters: -## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - resources: {} - -## extraVolumes and extraVolumeMounts allows you to mount other volumes -## Example Use Cases: -## mount certificates to enable tls -# extraVolumes: -# - name: zookeeper-keystore -# secret: -# defaultMode: 288 -# secretName: zookeeper-keystore -# - name: zookeeper-trustsore -# secret: -# defaultMode: 288 -# secretName: zookeeper-truststore -# extraVolumeMounts: -# - name: zookeeper-keystore -# mountPath: /certs/keystore -# readOnly: true -# - name: zookeeper-truststore -# mountPath: /certs/truststore -# readOnly: true - -## StatefulSet controller supports automated updates. There are two valid update strategies: RollingUpdate and OnDelete -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets -## -updateStrategy: RollingUpdate - -## Limits the number of pods of the replicated application that are down simultaneously from voluntary disruptions -## The PDB will only be created if replicaCount is greater than 1 -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions -## -podDisruptionBudget: - maxUnavailable: 1 - -## Partition update strategy -## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -## -# rollingUpdatePartition: - -## StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: OrderedReady and Parallel -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy -## -podManagementPolicy: Parallel - -## Number of ZooKeeper nodes -## -replicaCount: 1 - -## Basic time unit in milliseconds used by ZooKeeper for heartbeats -## -tickTime: 2000 - -## ZooKeeper uses to limit the length of time the ZooKeeper servers in quorum have to connect to a leader -## -initLimit: 10 - -## How far out of date a server can be from a leader -## -syncLimit: 5 - -## Limits the number of concurrent connections that a single client may make to a single member of the ZooKeeper ensemble -## -maxClientCnxns: 60 - -## A list of comma separated Four Letter Words commands to use -## -fourlwCommandsWhitelist: srvr, mntr, ruok - -## Allow zookeeper to listen for peers on all IPs -## -listenOnAllIPs: false - -## Allow to accept connections from unauthenticated users -## -allowAnonymousLogin: true - -autopurge: - ## Retains the snapRetainCount most recent snapshots and the corresponding transaction logs and deletes the rest - ## - snapRetainCount: 3 - ## The time interval in hours for which the purge task has to be triggered. Set to a positive integer (1 and above) to enable the auto purging. - ## - purgeInterval: 0 - -## Maximum session timeout in milliseconds that the server will allow the client to negotiate. Defaults to 20 times the tickTime. -## -maxSessionTimeout: 40000 - -auth: - ## Use existing secret (ignores previous password) - ## - # existingSecret: - ## Enable Zookeeper auth. It uses SASL/Digest-MD5 - ## - enabled: false - ## User that will use Zookeeper clients to auth - ## - clientUser: - ## Password that will use Zookeeper clients to auth - ## - clientPassword: - ## Comma, semicolon or whitespace separated list of user to be created. Specify them as a string, for example: "user1,user2,admin" - ## - serverUsers: - ## Comma, semicolon or whitespace separated list of passwords to assign to users when created. Specify them as a string, for example: "pass4user1, pass4user2, pass4admin" - ## - serverPasswords: - -## Size in MB for the Java Heap options (Xmx and XMs). This env var is ignored if Xmx an Xms are configured via JVMFLAGS -## -heapSize: 1024 - -## Log level for the Zookeeper server. ERROR by default. Have in mind if you set it to INFO or WARN the ReadinessProve will produce a lot of logs. -## -logLevel: ERROR - -## Data log directory. Specifying this option will direct zookeeper to write the transaction log to the dataLogDir rather than the dataDir. -## This allows a dedicated log device to be used, and helps avoid competition between logging and snaphots. -## Example: -## dataLogDir: /bitnami/zookeeper/dataLog -## -dataLogDir: "" - -## Default JVMFLAGS for the ZooKeeper process -## -# jvmFlags: - -## Configure ZooKeeper with a custom zoo.cfg file -## -# config: - -## Kubernetes configuration -## For minikube, set this to NodePort, elsewhere use LoadBalancer -## -service: - type: ClusterIP - port: 2181 - followerPort: 2888 - electionPort: 3888 - publishNotReadyAddresses: true - tls: - client_enable: false - quorum_enable: false - disable_base_client_port: false - - client_port: 3181 - - client_keystore_path: /tls_key_store/key_store_file - client_keystore_password: "" - client_truststore_path: /tls_trust_store/trust_store_file - client_truststore_password: "" - - quorum_keystore_path: /tls_key_store/key_store_file - quorum_keystore_password: "" - quorum_truststore_path: /tls_trust_store/trust_store_file - quorum_truststore_password: "" - annotations: {} - headless: - annotations: {} - -## Service account for Zookeeper to use. -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: false - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the zookeeper.fullname template - # name: - -## Zookeeper Pod Security Context -securityContext: - enabled: true - fsGroup: 1001 - runAsUser: 1001 - -## Zookeeper data Persistent Volume Storage Class -## If defined, storageClassName: -## If set to "-", storageClassName: "", which disables dynamic provisioning -## If undefined (the default) or set to null, no storageClassName spec is -## set, choosing the default provisioner. (gp2 on AWS, standard on -## GKE, AWS & OpenStack) -## -persistence: - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - - enabled: true - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - annotations: {} - dataLogDir: - size: 8Gi - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - - -## Node labels for pod assignment -## Ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Labels -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -podLabels: {} - -## Annotations -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -podAnnotations: {} - -## Name of the priority class to be used by zookeeper pods, priority class needs to be created beforehand -## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ -priorityClassName: "" - -## Affinity for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Scheduler name -## https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: stork - -## Configure resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - requests: - memory: 256Mi - cpu: 250m - -## Configure extra options for liveness and readiness probes -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) -## -livenessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - probeCommandTimeout: 2 - -readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - probeCommandTimeout: 2 - -## Network policies -## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ -## -networkPolicy: - ## Specifies whether a NetworkPolicy should be created - ## - enabled: false - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port Redis is listening - ## on. When true, zookeeper accept connections from any source - ## (with the correct destination port). - ## - # allowExternal: true - -## Zookeeper Prometheus Exporter configuration -## -metrics: - enabled: false - - ## Zookeeper Prometheus Exporter container port - ## - containerPort: 9141 - - ## Service configuration - ## - service: - ## Zookeeper Prometheus Exporter service type - ## - type: ClusterIP - ## Zookeeper Prometheus Exporter service port - ## - port: 9141 - ## Annotations for the Zookeeper Prometheus Exporter metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.service.port }}" - prometheus.io/path: "/metrics" - - ## Prometheus Operator ServiceMonitor configuration - ## - serviceMonitor: - enabled: false - ## Namespace for the ServiceMonitor Resource (defaults to the Release Namespace) - ## - namespace: - - ## Interval at which metrics should be scraped. - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # interval: 10s - - ## Timeout after which the scrape is ended - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # scrapeTimeout: 10s - - ## ServiceMonitor selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - - ## Prometheus Operator PrometheusRule configuration - ## - prometheusRule: - enabled: false - ## Namespace for the PrometheusRule Resource (defaults to the Release Namespace) - ## - namespace: - - ## PrometheusRule selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - - ## Some example rules. - rules: [] - # - alert: ZookeeperSyncedFollowers - # annotations: - # message: The number of synced followers for the leader node in Zookeeper deployment my-release is less than 2. This usually means that some of the Zookeeper nodes aren't communicating properly. If it doesn't resolve itself you can try killing the pods (one by one). - # expr: max(synced_followers{service="my-release-metrics"}) < 2 - # for: 5m - # labels: - # severity: critical - # - alert: ZookeeperOutstandingRequests - # annotations: - # message: The number of outstanding requests for Zookeeper pod {{ $labels.pod }} is greater than 10. This can indicate a performance issue with the Pod or cluster a whole. - # expr: outstanding_requests{service="my-release-metrics"} > 10 - # for: 5m - # labels: - # severity: critical diff --git a/ee/scripts/helm/helm/databases/charts/kafka/files/jks/README.md b/ee/scripts/helm/helm/databases/charts/kafka/files/jks/README.md deleted file mode 100755 index e110a8825..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/files/jks/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Java Key Stores - -You can copy here your Java Key Stores (JKS) files so a secret is created including them. Remember to use a truststore (`kafka.truststore.jks`) and one keystore (`kafka.keystore.jks`) per Kafka broker you have in the cluster. For instance, if you have 3 brokers you need to copy here the following files: - -- kafka.truststore.jks -- kafka-0.keystore.jks -- kafka-1.keystore.jks -- kafka-2.keystore.jks - -Find more info in [this section](https://github.com/bitnami/charts/tree/master/bitnami/kafka#enable-security-for-kafka-and-zookeeper) of the README.md file. diff --git a/ee/scripts/helm/helm/databases/charts/kafka/kafka.yaml b/ee/scripts/helm/helm/databases/charts/kafka/kafka.yaml deleted file mode 100644 index acd718957..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/kafka.yaml +++ /dev/null @@ -1,521 +0,0 @@ ---- -# Source: kafka/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kafka - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka ---- -# Source: kafka/templates/scripts-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: kafka-scripts - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm -data: - setup.sh: |- - #!/bin/bash - - ID="${MY_POD_NAME#"kafka-"}" - export KAFKA_CFG_BROKER_ID="$ID" - - exec /entrypoint.sh /run.sh ---- -# Source: kafka/charts/zookeeper/templates/svc-headless.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka-zookeeper-headless - namespace: db - labels: - app.kubernetes.io/name: zookeeper - helm.sh/chart: zookeeper-5.21.9 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: zookeeper -spec: - type: ClusterIP - clusterIP: None - publishNotReadyAddresses: true - ports: - - - name: tcp-client - port: 2181 - targetPort: client - - - - name: follower - port: 2888 - targetPort: follower - - name: tcp-election - port: 3888 - targetPort: election - selector: - app.kubernetes.io/name: zookeeper - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: zookeeper ---- -# Source: kafka/charts/zookeeper/templates/svc.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka-zookeeper - namespace: db - labels: - app.kubernetes.io/name: zookeeper - helm.sh/chart: zookeeper-5.21.9 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: zookeeper -spec: - type: ClusterIP - ports: - - - name: tcp-client - port: 2181 - targetPort: client - - - - name: follower - port: 2888 - targetPort: follower - - name: tcp-election - port: 3888 - targetPort: election - selector: - app.kubernetes.io/name: zookeeper - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: zookeeper ---- -# Source: kafka/templates/kafka-metrics-svc.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka-metrics - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: metrics - annotations: - - prometheus.io/path: /metrics - prometheus.io/port: '9308' - prometheus.io/scrape: "true" -spec: - type: ClusterIP - ports: - - name: http-metrics - port: 9308 - protocol: TCP - targetPort: metrics - nodePort: null - selector: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: metrics ---- -# Source: kafka/templates/svc-headless.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka-headless - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka -spec: - type: ClusterIP - clusterIP: None - ports: - - name: tcp-client - port: 9092 - protocol: TCP - targetPort: kafka-client - - name: tcp-internal - port: 9093 - protocol: TCP - targetPort: kafka-internal - selector: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: kafka ---- -# Source: kafka/templates/svc.yaml -apiVersion: v1 -kind: Service -metadata: - name: kafka - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka -spec: - type: ClusterIP - ports: - - name: tcp-client - port: 9092 - protocol: TCP - targetPort: kafka-client - nodePort: null - selector: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: kafka ---- -# Source: kafka/templates/kafka-metrics-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: kafka-exporter - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: metrics -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: metrics - template: - metadata: - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: metrics - spec: - containers: - - name: kafka-exporter - image: docker.io/bitnami/kafka-exporter:1.2.0-debian-10-r220 - imagePullPolicy: "IfNotPresent" - command: - - /bin/bash - - -ec - - | - read -r -a sasl_passwords <<< "$(tr ',;' ' ' <<< "${SASL_USER_PASSWORD}")" - kafka_exporter \ - --kafka.server=kafka-0.kafka-headless.db.svc.cluster.local:9092 \ - --kafka.server=kafka-1.kafka-headless.db.svc.cluster.local:9092 \ - --web.listen-address=:9308 - ports: - - name: metrics - containerPort: 9308 - resources: - limits: {} - requests: {} ---- -# Source: kafka/charts/zookeeper/templates/statefulset.yaml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: kafka-zookeeper - namespace: db - labels: - app.kubernetes.io/name: zookeeper - helm.sh/chart: zookeeper-5.21.9 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: zookeeper - role: zookeeper -spec: - serviceName: kafka-zookeeper-headless - replicas: 1 - podManagementPolicy: Parallel - updateStrategy: - type: RollingUpdate - selector: - matchLabels: - app.kubernetes.io/name: zookeeper - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: zookeeper - template: - metadata: - name: kafka-zookeeper - labels: - app.kubernetes.io/name: zookeeper - helm.sh/chart: zookeeper-5.21.9 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: zookeeper - spec: - - serviceAccountName: default - securityContext: - fsGroup: 1001 - containers: - - name: zookeeper - image: docker.io/bitnami/zookeeper:3.6.2-debian-10-r10 - imagePullPolicy: "IfNotPresent" - securityContext: - runAsUser: 1001 - command: - - bash - - -ec - - | - # Execute entrypoint as usual after obtaining ZOO_SERVER_ID based on POD hostname - HOSTNAME=`hostname -s` - if [[ $HOSTNAME =~ (.*)-([0-9]+)$ ]]; then - ORD=${BASH_REMATCH[2]} - export ZOO_SERVER_ID=$((ORD+1)) - else - echo "Failed to get index from hostname $HOST" - exit 1 - fi - exec /entrypoint.sh /run.sh - resources: - requests: - cpu: 250m - memory: 256Mi - env: - - name: ZOO_DATA_LOG_DIR - value: "" - - name: ZOO_PORT_NUMBER - value: "2181" - - name: ZOO_TICK_TIME - value: "2000" - - name: ZOO_INIT_LIMIT - value: "10" - - name: ZOO_SYNC_LIMIT - value: "5" - - name: ZOO_MAX_CLIENT_CNXNS - value: "60" - - name: ZOO_4LW_COMMANDS_WHITELIST - value: "srvr, mntr, ruok" - - name: ZOO_LISTEN_ALLIPS_ENABLED - value: "no" - - name: ZOO_AUTOPURGE_INTERVAL - value: "0" - - name: ZOO_AUTOPURGE_RETAIN_COUNT - value: "3" - - name: ZOO_MAX_SESSION_TIMEOUT - value: "40000" - - name: ZOO_SERVERS - value: kafka-zookeeper-0.kafka-zookeeper-headless.db.svc.cluster.local:2888:3888 - - name: ZOO_ENABLE_AUTH - value: "no" - - name: ZOO_HEAP_SIZE - value: "1024" - - name: ZOO_LOG_LEVEL - value: "ERROR" - - name: ALLOW_ANONYMOUS_LOGIN - value: "yes" - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - ports: - - - name: client - containerPort: 2181 - - - - name: follower - containerPort: 2888 - - name: election - containerPort: 3888 - livenessProbe: - exec: - command: ['/bin/bash', '-c', 'echo "ruok" | timeout 2 nc -w 2 localhost 2181 | grep imok'] - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 6 - readinessProbe: - exec: - command: ['/bin/bash', '-c', 'echo "ruok" | timeout 2 nc -w 2 localhost 2181 | grep imok'] - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 6 - volumeMounts: - - name: data - mountPath: /bitnami/zookeeper - volumes: - volumeClaimTemplates: - - metadata: - name: data - annotations: - spec: - accessModes: - - "ReadWriteOnce" - resources: - requests: - storage: "8Gi" ---- -# Source: kafka/templates/statefulset.yaml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: kafka - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka -spec: - podManagementPolicy: Parallel - replicas: 2 - selector: - matchLabels: - app.kubernetes.io/name: kafka - app.kubernetes.io/instance: kafka - app.kubernetes.io/component: kafka - serviceName: kafka-headless - updateStrategy: - type: "RollingUpdate" - template: - metadata: - labels: - app.kubernetes.io/name: kafka - helm.sh/chart: kafka-11.8.6 - app.kubernetes.io/instance: kafka - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/component: kafka - spec: - securityContext: - fsGroup: 1001 - runAsUser: 1001 - serviceAccountName: kafka - containers: - - name: kafka - image: docker.io/bitnami/kafka:2.6.0-debian-10-r30 - imagePullPolicy: "IfNotPresent" - command: - - /scripts/setup.sh - env: - - name: BITNAMI_DEBUG - value: "false" - - name: MY_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: MY_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KAFKA_CFG_ZOOKEEPER_CONNECT - value: "kafka-zookeeper" - - name: KAFKA_INTER_BROKER_LISTENER_NAME - value: "INTERNAL" - - name: KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP - value: "INTERNAL:PLAINTEXT,CLIENT:PLAINTEXT" - - name: KAFKA_CFG_LISTENERS - value: "INTERNAL://:9093,CLIENT://:9092" - - name: KAFKA_CFG_ADVERTISED_LISTENERS - value: "INTERNAL://$(MY_POD_NAME).kafka-headless.db.svc.cluster.local:9093,CLIENT://$(MY_POD_NAME).kafka-headless.db.svc.cluster.local:9092" - - name: ALLOW_PLAINTEXT_LISTENER - value: "yes" - - name: KAFKA_CFG_DELETE_TOPIC_ENABLE - value: "false" - - name: KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE - value: "true" - - name: KAFKA_HEAP_OPTS - value: "-Xmx1024m -Xms1024m" - - name: KAFKA_CFG_LOG_FLUSH_INTERVAL_MESSAGES - value: "10000" - - name: KAFKA_CFG_LOG_FLUSH_INTERVAL_MS - value: "1000" - - name: KAFKA_CFG_LOG_RETENTION_BYTES - value: "1073741824" - - name: KAFKA_CFG_LOG_RETENTION_CHECK_INTERVALS_MS - value: "300000" - - name: KAFKA_CFG_LOG_RETENTION_HOURS - value: "168" - - name: KAFKA_CFG_MESSAGE_MAX_BYTES - value: "1000012" - - name: KAFKA_CFG_LOG_SEGMENT_BYTES - value: "1073741824" - - name: KAFKA_CFG_LOG_DIRS - value: "/bitnami/kafka/data" - - name: KAFKA_CFG_DEFAULT_REPLICATION_FACTOR - value: "1" - - name: KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR - value: "1" - - name: KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR - value: "1" - - name: KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR - value: "1" - - name: KAFKA_CFG_NUM_IO_THREADS - value: "8" - - name: KAFKA_CFG_NUM_NETWORK_THREADS - value: "3" - - name: KAFKA_CFG_NUM_PARTITIONS - value: "1" - - name: KAFKA_CFG_NUM_RECOVERY_THREADS_PER_DATA_DIR - value: "1" - - name: KAFKA_CFG_SOCKET_RECEIVE_BUFFER_BYTES - value: "102400" - - name: KAFKA_CFG_SOCKET_REQUEST_MAX_BYTES - value: "104857600" - - name: KAFKA_CFG_SOCKET_SEND_BUFFER_BYTES - value: "102400" - - name: KAFKA_CFG_ZOOKEEPER_CONNECTION_TIMEOUT_MS - value: "6000" - ports: - - name: kafka-client - containerPort: 9092 - - name: kafka-internal - containerPort: 9093 - livenessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: 10 - timeoutSeconds: 5 - failureThreshold: - periodSeconds: - successThreshold: - readinessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: 5 - timeoutSeconds: 5 - failureThreshold: 6 - periodSeconds: - successThreshold: - resources: - limits: {} - requests: {} - volumeMounts: - - name: data - mountPath: /bitnami/kafka - - name: scripts - mountPath: /scripts/setup.sh - subPath: setup.sh - volumes: - - name: scripts - configMap: - name: kafka-scripts - defaultMode: 0755 - volumeClaimTemplates: - - metadata: - name: data - spec: - accessModes: - - "ReadWriteOnce" - resources: - requests: - storage: "8Gi" diff --git a/ee/scripts/helm/helm/databases/charts/kafka/requirements.lock b/ee/scripts/helm/helm/databases/charts/kafka/requirements.lock deleted file mode 100755 index 115d0b229..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/requirements.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: zookeeper - repository: https://charts.bitnami.com/bitnami - version: 5.21.9 -digest: sha256:2f3c43ce02e3966648b8c89be121fe39537f62ea1d161ad908f51ddc90e4243e -generated: "2020-09-29T07:43:56.483358254Z" diff --git a/ee/scripts/helm/helm/databases/charts/kafka/requirements.yaml b/ee/scripts/helm/helm/databases/charts/kafka/requirements.yaml deleted file mode 100755 index 533875258..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/requirements.yaml +++ /dev/null @@ -1,5 +0,0 @@ -dependencies: - - name: zookeeper - version: 5.x.x - repository: https://charts.bitnami.com/bitnami - condition: zookeeper.enabled diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/NOTES.txt b/ee/scripts/helm/helm/databases/charts/kafka/templates/NOTES.txt deleted file mode 100755 index 0347c21c4..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/NOTES.txt +++ /dev/null @@ -1,181 +0,0 @@ -{{- $replicaCount := int .Values.replicaCount -}} -{{- $releaseNamespace := .Release.Namespace -}} -{{- $clusterDomain := .Values.clusterDomain -}} -{{- $fullname := include "kafka.fullname" . -}} -{{- $clientProtocol := include "kafka.listenerType" ( dict "protocol" .Values.auth.clientProtocol ) -}} -{{- $servicePort := int .Values.service.port -}} -{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs -}} -{{- if and .Values.externalAccess.enabled (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerIPListLength )) (eq .Values.externalAccess.service.type "LoadBalancer") }} - -############################################################################### -### ERROR: You enabled external access to Kafka brokers without specifying ### -### the array of load balancer IPs for Kafka brokers. ### -############################################################################### - -This deployment will be incomplete until you configure the array of load balancer -IPs for Kafka brokers. To complete your deployment follow the steps below: - -1. Wait for the load balancer IPs (it may take a few minutes for them to be available): - - kubectl get svc --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ template "kafka.name" . }},app.kubernetes.io/instance={{ .Release.Name }},app.kubernetes.io/component=kafka,pod" -w - -2. Obtain the load balancer IPs and upgrade your chart: - - {{- range $i, $e := until $replicaCount }} - LOAD_BALANCER_IP_{{ add $i 1 }}="$(kubectl get svc --namespace {{ $releaseNamespace }} {{ $fullname }}-{{ $i }}-external -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" - {{- end }} - -3. Upgrade you chart: - - helm upgrade {{ .Release.Name }} bitnami/{{ .Chart.Name }} \ - --set replicaCount={{ $replicaCount }} \ - --set externalAccess.enabled=true \ - {{- range $i, $e := until $replicaCount }} - --set externalAccess.service.loadBalancerIPs[{{ $i }}]=$LOAD_BALANCER_IP_{{ add $i 1 }} \ - {{- end }} - --set externalAccess.service.type=LoadBalancer - -{{- else }} - -{{- if and (or (eq .Values.service.type "LoadBalancer") .Values.externalAccess.enabled) (eq .Values.auth.clientProtocol "plaintext") }} ---------------------------------------------------------------------------------------------- - WARNING - - By specifying "serviceType=LoadBalancer" and not configuring the authentication - you have most likely exposed the Kafka service externally without any - authentication mechanism. - - For security reasons, we strongly suggest that you switch to "ClusterIP" or - "NodePort". As alternative, you can also configure the Kafka authentication. - ---------------------------------------------------------------------------------------------- -{{- end }} - -** Please be patient while the chart is being deployed ** - -Kafka can be accessed by consumers via port {{ $servicePort }} on the following DNS name from within your cluster: - - {{ $fullname }}.{{ $releaseNamespace }}.svc.{{ $clusterDomain }} - -Each Kafka broker can be accessed by producers via port {{ $servicePort }} on the following DNS name(s) from within your cluster: - -{{- $brokerList := list }} -{{- range $e, $i := until $replicaCount }} -{{- $brokerList = append $brokerList (printf "%s-%d.%s-headless.%s.svc.%s:%d" $fullname $i $fullname $releaseNamespace $clusterDomain $servicePort) }} -{{- end }} -{{ join "\n" $brokerList | nindent 4 }} - - -{{- if (include "kafka.client.saslAuthentication" .) }} - -You need to configure your Kafka client to access using SASL authentication. To do so, you need to create the 'kafka_jaas.conf' and 'client.properties' configuration files by executing these commands: - - - kafka_jaas.conf: - -cat > kafka_jaas.conf < client.properties <<>(Value) - name: kafka_controller_$1_$2_$4 - labels: - broker_id: "$3" - - pattern: kafka.controller<>(Value) - name: kafka_controller_$1_$2_$3 - - pattern: kafka.controller<>(Value) - name: kafka_controller_$1_$2_$3 - - pattern: kafka.controller<>(Count) - name: kafka_controller_$1_$2_$3 - - pattern: kafka.server<>(Value) - name: kafka_server_$1_$2_$4 - labels: - client_id: "$3" - - pattern : kafka.network<>(Value) - name: kafka_network_$1_$2_$4 - labels: - network_processor: $3 - - pattern : kafka.network<>(Count) - name: kafka_network_$1_$2_$4 - labels: - request: $3 - - pattern: kafka.server<>(Count|OneMinuteRate) - name: kafka_server_$1_$2_$4 - labels: - topic: $3 - - pattern: kafka.server<>(Value) - name: kafka_server_$1_$2_$3_$4 - - pattern: kafka.server<>(Count|Value|OneMinuteRate) - name: kafka_server_$1_total_$2_$3 - - pattern: kafka.server<>(queue-size) - name: kafka_server_$1_$2 - - pattern: java.lang<(.+)>(\w+) - name: java_lang_$1_$4_$3_$2 - - pattern: java.lang<>(\w+) - name: java_lang_$1_$3_$2 - - pattern : java.lang - - pattern: kafka.log<>Value - name: kafka_log_$1_$2 - labels: - topic: $3 - partition: $4 -{{- end -}} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/jmx-metrics-svc.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/jmx-metrics-svc.yaml deleted file mode 100755 index 83edd8422..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/jmx-metrics-svc.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{{- if .Values.metrics.jmx.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" . }}-jmx-metrics - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.metrics.jmx.service.annotations .Values.commonAnnotations }} - annotations: - {{- if .Values.metrics.jmx.service.annotations }} - {{ include "kafka.tplValue" ( dict "value" .Values.metrics.jmx.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.metrics.jmx.service.type }} - {{- if eq .Values.metrics.jmx.service.type "LoadBalancer" }} - {{- if .Values.metrics.jmx.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.metrics.jmx.service.loadBalancerIP }} - {{- end }} - {{- if .Values.metrics.jmx.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- toYaml .Values.metrics.jmx.service.loadBalancerSourceRanges | nindent 4 }} - {{- end }} - {{- end }} - {{- if and (eq .Values.metrics.jmx.service.type "ClusterIP") .Values.metrics.jmx.service.clusterIP }} - clusterIP: {{ .Values.metrics.jmx.service.clusterIP }} - {{- end }} - ports: - - name: http-metrics - port: {{ .Values.metrics.jmx.service.port }} - protocol: TCP - targetPort: metrics - {{- if and (or (eq .Values.metrics.jmx.service.type "NodePort") (eq .Values.metrics.jmx.service.type "LoadBalancer")) (not (empty .Values.metrics.jmx.service.nodePort)) }} - nodePort: {{ .Values.metrics.jmx.service.nodePort }} - {{- else if eq .Values.metrics.jmx.service.type "ClusterIP" }} - nodePort: null - {{- end }} - selector: {{- include "kafka.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: kafka -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/kafka-metrics-deployment.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/kafka-metrics-deployment.yaml deleted file mode 100755 index c547fbb39..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/kafka-metrics-deployment.yaml +++ /dev/null @@ -1,87 +0,0 @@ -{{- if .Values.metrics.kafka.enabled }} -{{- $replicaCount := int .Values.replicaCount -}} -{{- $releaseNamespace := .Release.Namespace -}} -{{- $clusterDomain := .Values.clusterDomain -}} -{{- $fullname := include "kafka.fullname" . -}} -{{- $servicePort := int .Values.service.port -}} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "kafka.fullname" . }}-exporter - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: metrics - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - replicas: 1 - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: metrics - template: - metadata: - labels: {{- include "kafka.labels" . | nindent 8 }} - app.kubernetes.io/component: metrics - spec: -{{- include "kafka.imagePullSecrets" . | indent 6 }} - containers: - - name: kafka-exporter - image: {{ include "kafka.metrics.kafka.image" . }} - imagePullPolicy: {{ .Values.metrics.kafka.image.pullPolicy | quote }} - command: - - /bin/bash - - -ec - - | - read -r -a sasl_passwords <<< "$(tr ',;' ' ' <<< "${SASL_USER_PASSWORD}")" - kafka_exporter \ - {{- range $i, $e := until $replicaCount }} - --kafka.server={{ $fullname }}-{{ $i }}.{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $servicePort }} \ - {{- end }} - {{- if (include "kafka.client.saslAuthentication" .) }} - --sasl.enabled \ - --sasl.username="$SASL_USERNAME" \ - --sasl.password="${sasl_passwords[0]}" \ - {{- end }} - {{- if (include "kafka.tlsEncryption" .) }} - --tls.enabled \ - {{- if .Values.metrics.kafka.certificatesSecret }} - --tls.ca-file="/opt/bitnami/kafka-exporter/certs/ca-file" \ - --tls.cert-file="/opt/bitnami/kafka-exporter/certs/cert-file" \ - --tls.key-file="/opt/bitnami/kafka-exporter/certs/key-file" \ - {{- end }} - {{- end }} - {{- range $key, $value := .Values.metrics.kafka.extraFlags }} - --{{ $key }}{{ if $value }}={{ $value }}{{ end }} \ - {{- end }} - --web.listen-address=:9308 - {{- if (include "kafka.client.saslAuthentication" .) }} - env: - - name: SASL_USERNAME - value: {{ index .Values.auth.jaas.clientUsers 0 | quote }} - - name: SASL_USER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "kafka.jaasSecretName" . }} - key: client-passwords - {{- end }} - ports: - - name: metrics - containerPort: 9308 - {{- if .Values.metrics.kafka.resources }} - resources: {{ toYaml .Values.metrics.kafka.resources | nindent 12 }} - {{- end }} - {{- if and (include "kafka.tlsEncryption" .) .Values.metrics.kafka.certificatesSecret }} - volumeMounts: - - name: kafka-exporter-certificates - mountPath: /opt/bitnami/kafka-exporter/certs/ - readOnly: true - volumes: - - name: kafka-exporter-certificates - secret: - secretName: {{ .Values.metrics.kafka.certificatesSecret }} - defaultMode: 0440 - {{- end }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/kafka-metrics-svc.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/kafka-metrics-svc.yaml deleted file mode 100755 index 54a4ccb0b..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/kafka-metrics-svc.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{{- if .Values.metrics.kafka.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" . }}-metrics - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: metrics - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.metrics.kafka.service.annotations .Values.commonAnnotations }} - annotations: - {{- if .Values.metrics.kafka.service.annotations }} - {{ include "kafka.tplValue" ( dict "value" .Values.metrics.kafka.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.metrics.kafka.service.type }} - {{- if eq .Values.metrics.kafka.service.type "LoadBalancer" }} - {{- if .Values.metrics.kafka.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.metrics.kafka.service.loadBalancerIP }} - {{- end }} - {{- if .Values.metrics.kafka.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- toYaml .Values.metrics.kafka.service.loadBalancerSourceRanges | nindent 4 }} - {{- end }} - {{- end }} - {{- if and (eq .Values.metrics.kafka.service.type "ClusterIP") .Values.metrics.kafka.service.clusterIP }} - clusterIP: {{ .Values.metrics.kafka.service.clusterIP }} - {{- end }} - ports: - - name: http-metrics - port: {{ .Values.metrics.kafka.service.port }} - protocol: TCP - targetPort: metrics - {{- if and (or (eq .Values.metrics.kafka.service.type "NodePort") (eq .Values.metrics.kafka.service.type "LoadBalancer")) (not (empty .Values.metrics.kafka.service.nodePort)) }} - nodePort: {{ .Values.metrics.kafka.service.nodePort }} - {{- else if eq .Values.metrics.kafka.service.type "ClusterIP" }} - nodePort: null - {{- end }} - selector: {{- include "kafka.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: metrics -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/log4j-configmap.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/log4j-configmap.yaml deleted file mode 100755 index 0a34d50dd..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/log4j-configmap.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if (include "kafka.log4j.createConfigMap" .) }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "kafka.log4j.configMapName" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: - log4j.properties: |- - {{ .Values.log4j | nindent 4 }} -{{- end -}} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/poddisruptionbudget.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/poddisruptionbudget.yaml deleted file mode 100755 index cf515becb..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- $replicaCount := int .Values.replicaCount }} -{{- if and .Values.pdb.create (gt $replicaCount 1) }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - {{- if .Values.pdb.minAvailable }} - minAvailable: {{ .Values.pdb.minAvailable }} - {{- end }} - {{- if .Values.pdb.maxUnavailable }} - maxUnavailable: {{ .Values.pdb.maxUnavailable }} - {{- end }} - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: kafka -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/role.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/role.yaml deleted file mode 100755 index 943c5bf3c..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/role.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -rules: - - apiGroups: - - "" - resources: - - services - verbs: - - get - - list - - watch -{{- end -}} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/rolebinding.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/rolebinding.yaml deleted file mode 100755 index 78f940f85..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/rolebinding.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if and .Values.serviceAccount.create .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -roleRef: - kind: Role - name: {{ template "kafka.fullname" . }} - apiGroup: rbac.authorization.k8s.io -subjects: - - kind: ServiceAccount - name: {{ template "kafka.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/scripts-configmap.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/scripts-configmap.yaml deleted file mode 100755 index 705545a61..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/scripts-configmap.yaml +++ /dev/null @@ -1,118 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "kafka.fullname" . }}-scripts - labels: {{- include "kafka.labels" . | nindent 4 }} - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: - {{- $fullname := include "kafka.fullname" . }} - {{- $releaseNamespace := .Release.Namespace }} - {{- $clusterDomain := .Values.clusterDomain }} - {{- $interBrokerPort := .Values.service.internalPort }} - {{- $clientPort := .Values.service.port }} - {{- if .Values.externalAccess.autoDiscovery.enabled }} - auto-discovery.sh: |- - #!/bin/bash - - SVC_NAME="${MY_POD_NAME}-external" - - {{- if eq .Values.externalAccess.service.type "LoadBalancer" }} - # Auxiliar functions - retry_while() { - local -r cmd="${1:?cmd is missing}" - local -r retries="${2:-12}" - local -r sleep_time="${3:-5}" - local return_value=1 - - read -r -a command <<< "$cmd" - for ((i = 1 ; i <= retries ; i+=1 )); do - "${command[@]}" && return_value=0 && break - sleep "$sleep_time" - done - return $return_value - } - k8s_svc_lb_ip() { - local namespace=${1:?namespace is missing} - local service=${2:?service is missing} - local service_ip=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].ip}") - local service_hostname=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].hostname}") - - if [[ -n ${service_ip} ]]; then - echo "${service_ip}" - else - echo "${service_hostname}" - fi - } - k8s_svc_lb_ip_ready() { - local namespace=${1:?namespace is missing} - local service=${2:?service is missing} - [[ -n "$(k8s_svc_lb_ip "$namespace" "$service")" ]] - } - # Wait until LoadBalancer IP is ready - retry_while "k8s_svc_lb_ip_ready {{ $releaseNamespace }} $SVC_NAME" || exit 1 - # Obtain LoadBalancer external IP - k8s_svc_lb_ip "{{ $releaseNamespace }}" "$SVC_NAME" | tee "$SHARED_FILE" - {{- else if eq .Values.externalAccess.service.type "NodePort" }} - k8s_svc_node_port() { - local namespace=${1:?namespace is missing} - local service=${2:?service is missing} - local index=${3:-0} - local node_port="$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.spec.ports[$index].nodePort}")" - echo "$node_port" - } - k8s_svc_node_port "{{ $releaseNamespace }}" "$SVC_NAME" | tee "$SHARED_FILE" - {{- end }} - {{- end }} - setup.sh: |- - #!/bin/bash - - ID="${MY_POD_NAME#"{{ $fullname }}-"}" - export KAFKA_CFG_BROKER_ID="$ID" - - {{- if .Values.externalAccess.enabled }} - # Configure external ip and port - {{- if eq .Values.externalAccess.service.type "LoadBalancer" }} - {{- if .Values.externalAccess.autoDiscovery.enabled }} - export EXTERNAL_ACCESS_IP="$(<${SHARED_FILE})" - {{- else }} - export EXTERNAL_ACCESS_IP=$(echo '{{ .Values.externalAccess.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") - {{- end }} - export EXTERNAL_ACCESS_PORT={{ .Values.externalAccess.service.port }} - {{- else if eq .Values.externalAccess.service.type "NodePort" }} - {{- if .Values.externalAccess.service.domain }} - export EXTERNAL_ACCESS_IP={{ .Values.externalAccess.service.domain }} - {{- else }} - export EXTERNAL_ACCESS_IP=$(curl -s https://ipinfo.io/ip) - {{- end }} - {{- if .Values.externalAccess.autoDiscovery.enabled }} - export EXTERNAL_ACCESS_PORT="$(<${SHARED_FILE})" - {{- else }} - export EXTERNAL_ACCESS_PORT=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))") - {{- end }} - {{- end }} - - # Configure Kafka advertised listeners - {{- if .Values.advertisedListeners }} - export KAFKA_CFG_ADVERTISED_LISTENERS={{ .Values.advertisedListeners }} - {{- else }} - export KAFKA_CFG_ADVERTISED_LISTENERS="INTERNAL://${MY_POD_NAME}.{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $interBrokerPort }},CLIENT://${MY_POD_NAME}.{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $clientPort }},EXTERNAL://${EXTERNAL_ACCESS_IP}:${EXTERNAL_ACCESS_PORT}" - {{- end }} - {{- end }} - - {{- if (include "kafka.tlsEncryption" .) }} - if [[ -f "/certs/kafka.truststore.jks" ]] && [[ -f "/certs/kafka-${ID}.keystore.jks" ]]; then - mkdir -p /opt/bitnami/kafka/config/certs - cp "/certs/kafka.truststore.jks" "/opt/bitnami/kafka/config/certs/kafka.truststore.jks" - cp "/certs/kafka-${ID}.keystore.jks" "/opt/bitnami/kafka/config/certs/kafka.keystore.jks" - else - echo "Couldn't find the expected Java Key Stores (JKS) files! They are mandatory when encryption via TLS is enabled." - exit 1 - fi - {{- end }} - - exec /entrypoint.sh /run.sh diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/serviceaccount.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/serviceaccount.yaml deleted file mode 100755 index 790790b3f..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/serviceaccount.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "kafka.serviceAccountName" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/servicemonitor-jmx-metrics.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/servicemonitor-jmx-metrics.yaml deleted file mode 100755 index 250bb5306..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/servicemonitor-jmx-metrics.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if and .Values.metrics.jmx.enabled .Values.metrics.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kafka.fullname" . }}-jmx-metrics - {{- if .Values.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.metrics.serviceMonitor.namespace }} - {{- end }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- range $key, $value := .Values.metrics.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: kafka - endpoints: - - port: http-metrics - path: "/" - {{- if .Values.metrics.serviceMonitor.interval }} - interval: {{ .Values.metrics.serviceMonitor.interval }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} - {{- end }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/servicemonitor-metrics.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/servicemonitor-metrics.yaml deleted file mode 100755 index 951bf7c41..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/servicemonitor-metrics.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if and .Values.metrics.kafka.enabled .Values.metrics.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kafka.fullname" . }}-metrics - {{- if .Values.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.metrics.serviceMonitor.namespace }} - {{- end }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: metrics - {{- range $key, $value := .Values.metrics.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: metrics - endpoints: - - port: http-metrics - path: "/metrics" - {{- if .Values.metrics.serviceMonitor.interval }} - interval: {{ .Values.metrics.serviceMonitor.interval }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} - {{- end }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/statefulset.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/statefulset.yaml deleted file mode 100755 index e9b5ce8f9..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/statefulset.yaml +++ /dev/null @@ -1,435 +0,0 @@ -{{- $replicaCount := int .Values.replicaCount }} -{{- $fullname := include "kafka.fullname" . }} -{{- $releaseNamespace := .Release.Namespace }} -{{- $clusterDomain := .Values.clusterDomain }} -{{- $interBrokerPort := .Values.service.internalPort }} -{{- $clientPort := .Values.service.port }} -{{- $interBrokerProtocol := include "kafka.listenerType" ( dict "protocol" .Values.auth.interBrokerProtocol ) -}} -{{- $clientProtocol := include "kafka.listenerType" ( dict "protocol" .Values.auth.clientProtocol ) -}} -{{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }} -{{- if not (and .Values.externalAccess.enabled (not .Values.externalAccess.autoDiscovery.enabled) (not (eq $replicaCount $loadBalancerIPListLength )) (eq .Values.externalAccess.service.type "LoadBalancer")) }} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ include "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - podManagementPolicy: Parallel - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: {{- include "kafka.matchLabels" . | nindent 6 }} - app.kubernetes.io/component: kafka - serviceName: {{ template "kafka.fullname" . }}-headless - updateStrategy: - type: {{ .Values.updateStrategy | quote }} - {{- if (eq "OnDelete" .Values.updateStrategy) }} - rollingUpdate: null - {{- else if .Values.rollingUpdatePartition }} - rollingUpdate: - partition: {{ .Values.rollingUpdatePartition }} - {{- end }} - template: - metadata: - labels: {{- include "kafka.labels" . | nindent 8 }} - app.kubernetes.io/component: kafka - {{- if .Values.podLabels }} - {{- include "kafka.tplValue" (dict "value" .Values.podLabels "context" $) | nindent 8 }} - {{- end }} - {{- if or (include "kafka.createConfigmap" .) (include "kafka.createJaasSecret" .) .Values.externalAccess.enabled (include "kafka.metrics.jmx.createConfigmap" .) .Values.podAnnotations }} - annotations: - {{- if (include "kafka.createConfigmap" .) }} - checksum/configuration: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - {{- end }} - {{- if (include "kafka.createJaasSecret" .) }} - checksum/secret: {{ include (print $.Template.BasePath "/jaas-secret.yaml") . | sha256sum }} - {{- end }} - {{- if .Values.externalAccess.enabled }} - checksum/scripts: {{ include (print $.Template.BasePath "/scripts-configmap.yaml") . | sha256sum }} - {{- end }} - {{- if (include "kafka.metrics.jmx.createConfigmap" .) }} - checksum/jmx-configuration: {{ include (print $.Template.BasePath "/jmx-configmap.yaml") . | sha256sum }} - {{- end }} - {{- if .Values.podAnnotations }} - {{- include "kafka.tplValue" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} - {{- end }} - {{- end }} - spec: -{{- include "kafka.imagePullSecrets" . | indent 6 }} - {{- if .Values.affinity }} - affinity: {{- include "kafka.tplValue" ( dict "value" .Values.affinity "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: {{- include "kafka.tplValue" ( dict "value" .Values.nodeSelector "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.tolerations }} - tolerations: {{- include "kafka.tplValue" ( dict "value" .Values.tolerations "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.priorityClassName }} - priorityClassName: {{ .Values.priorityClassName }} - {{- end }} - {{- if .Values.podSecurityContext }} - securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} - {{- end }} - {{- if .Values.serviceAccount.create }} - serviceAccountName: {{ template "kafka.serviceAccountName" . }} - {{- end }} - {{- if or (and .Values.volumePermissions.enabled .Values.persistence.enabled) (and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled) }} - initContainers: - {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} - - name: volume-permissions - image: {{ include "kafka.volumePermissions.image" . }} - imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} - command: - - /bin/bash - args: - - -ec - - | - mkdir -p /bitnami/kafka - chown -R "{{ .Values.podSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }}" "/bitnami/kafka" - securityContext: - runAsUser: 0 - {{- if .Values.volumePermissions.resources }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: data - mountPath: /bitnami/kafka - {{- end }} - {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled }} - - name: auto-discovery - image: {{ include "kafka.externalAccess.autoDiscovery.image" . }} - imagePullPolicy: {{ .Values.externalAccess.autoDiscovery.image.pullPolicy | quote }} - command: - - /scripts/auto-discovery.sh - env: - - name: MY_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: SHARED_FILE - value: "/shared/info.txt" - {{- if .Values.externalAccess.autoDiscovery.resources }} - resources: {{- toYaml .Values.externalAccess.autoDiscovery.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: shared - mountPath: /shared - - name: scripts - mountPath: /scripts/auto-discovery.sh - subPath: auto-discovery.sh - {{- end }} - {{- end }} - containers: - - name: kafka - image: {{ include "kafka.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - command: {{- include "kafka.tplValue" (dict "value" .Values.command "context" $) | nindent 12 }} - {{- if .Values.args }} - args: {{- include "kafka.tplValue" (dict "value" .Values.args "context" $) | nindent 12 }} - {{- end }} - env: - - name: BITNAMI_DEBUG - value: {{ ternary "true" "false" .Values.image.debug | quote }} - - name: MY_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: MY_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KAFKA_CFG_ZOOKEEPER_CONNECT - {{- if .Values.zookeeper.enabled }} - value: {{ include "kafka.zookeeper.fullname" . | quote }} - {{- else }} - value: {{ join "," .Values.externalZookeeper.servers | quote }} - {{- end }} - - name: KAFKA_INTER_BROKER_LISTENER_NAME - value: {{ .Values.interBrokerListenerName | quote }} - - name: KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP - {{- if .Values.listenerSecurityProtocolMap }} - value: {{ .Values.listenerSecurityProtocolMap | quote }} - {{- else if .Values.externalAccess.enabled }} - value: "INTERNAL:{{ $interBrokerProtocol }},CLIENT:{{ $clientProtocol }},EXTERNAL:{{ $clientProtocol }}" - {{- else }} - value: "INTERNAL:{{ $interBrokerProtocol }},CLIENT:{{ $clientProtocol }}" - {{- end }} - {{- if or ($clientProtocol | regexFind "SASL") ($interBrokerProtocol | regexFind "SASL") .Values.auth.jaas.zookeeperUser }} - - name: KAFKA_CFG_SASL_ENABLED_MECHANISMS - value: {{ include "kafka.auth.saslMechanisms" ( dict "type" .Values.auth.saslMechanisms ) }} - - name: KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL - value: {{ upper .Values.auth.saslInterBrokerMechanism | quote }} - {{- end }} - - name: KAFKA_CFG_LISTENERS - {{- if .Values.listeners }} - value: {{ .Values.listeners }} - {{- else if .Values.externalAccess.enabled }} - value: "INTERNAL://:{{ $interBrokerPort }},CLIENT://:9092,EXTERNAL://:9094" - {{- else }} - value: "INTERNAL://:{{ $interBrokerPort }},CLIENT://:9092" - {{- end }} - {{- if .Values.externalAccess.enabled }} - {{- if .Values.externalAccess.autoDiscovery.enabled }} - - name: SHARED_FILE - value: "/shared/info.txt" - {{- end }} - {{- else }} - - name: KAFKA_CFG_ADVERTISED_LISTENERS - {{- if .Values.advertisedListeners }} - value: {{ .Values.advertisedListeners }} - {{- else }} - value: "INTERNAL://$(MY_POD_NAME).{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $interBrokerPort }},CLIENT://$(MY_POD_NAME).{{ $fullname }}-headless.{{ $releaseNamespace }}.svc.{{ $clusterDomain }}:{{ $clientPort }}" - {{- end }} - {{- end }} - - name: ALLOW_PLAINTEXT_LISTENER - value: {{ ternary "yes" "no" (or .Values.auth.enabled .Values.allowPlaintextListener) | quote }} - {{- if or (include "kafka.client.saslAuthentication" .) (include "kafka.interBroker.saslAuthentication" .) }} - - name: KAFKA_OPTS - value: "-Djava.security.auth.login.config=/opt/bitnami/kafka/config/kafka_jaas.conf" - {{- if (include "kafka.client.saslAuthentication" .) }} - - name: KAFKA_CLIENT_USERS - value: {{ join "," .Values.auth.jaas.clientUsers | quote }} - - name: KAFKA_CLIENT_PASSWORDS - valueFrom: - secretKeyRef: - name: {{ include "kafka.jaasSecretName" . }} - key: client-passwords - {{- end }} - {{- if .Values.auth.jaas.zookeeperUser }} - - name: KAFKA_ZOOKEEPER_PROTOCOL - value: "SASL" - - name: KAFKA_ZOOKEEPER_USER - value: {{ .Values.auth.jaas.zookeeperUser | quote }} - - name: KAFKA_ZOOKEEPER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "kafka.jaasSecretName" . }} - key: zookeeper-password - {{- end }} - {{- if (include "kafka.interBroker.saslAuthentication" .) }} - - name: KAFKA_INTER_BROKER_USER - value: {{ .Values.auth.jaas.interBrokerUser | quote }} - - name: KAFKA_INTER_BROKER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "kafka.jaasSecretName" . }} - key: inter-broker-password - {{- end }} - {{- end }} - {{- if (include "kafka.tlsEncryption" .) }} - - name: KAFKA_CFG_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM - value: {{ .Values.auth.tlsEndpointIdentificationAlgorithm | quote }} - {{- if .Values.auth.jksPassword }} - - name: KAFKA_CERTIFICATE_PASSWORD - value: {{ .Values.auth.jksPassword | quote }} - {{- end }} - {{- end }} - {{- if .Values.metrics.jmx.enabled }} - - name: JMX_PORT - value: "5555" - {{- end }} - - name: KAFKA_CFG_DELETE_TOPIC_ENABLE - value: {{ .Values.deleteTopicEnable | quote }} - - name: KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE - value: {{ .Values.autoCreateTopicsEnable | quote }} - - name: KAFKA_HEAP_OPTS - value: {{ .Values.heapOpts | quote }} - - name: KAFKA_CFG_LOG_FLUSH_INTERVAL_MESSAGES - value: {{ .Values.logFlushIntervalMessages | quote }} - - name: KAFKA_CFG_LOG_FLUSH_INTERVAL_MS - value: {{ .Values.logFlushIntervalMs | quote }} - - name: KAFKA_CFG_LOG_RETENTION_BYTES - value: {{ .Values.logRetentionBytes | replace "_" "" | quote }} - - name: KAFKA_CFG_LOG_RETENTION_CHECK_INTERVALS_MS - value: {{ .Values.logRetentionCheckIntervalMs | quote }} - - name: KAFKA_CFG_LOG_RETENTION_HOURS - value: {{ .Values.logRetentionHours | quote }} - - name: KAFKA_CFG_MESSAGE_MAX_BYTES - value: {{ .Values.maxMessageBytes | replace "_" "" | quote }} - - name: KAFKA_CFG_LOG_SEGMENT_BYTES - value: {{ .Values.logSegmentBytes | replace "_" "" | quote }} - - name: KAFKA_CFG_LOG_DIRS - value: {{ .Values.logsDirs | quote }} - - name: KAFKA_CFG_DEFAULT_REPLICATION_FACTOR - value: {{ .Values.defaultReplicationFactor | quote }} - - name: KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR - value: {{ .Values.offsetsTopicReplicationFactor | quote }} - - name: KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR - value: {{ .Values.transactionStateLogReplicationFactor | quote }} - - name: KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR - value: {{ .Values.transactionStateLogMinIsr | quote }} - - name: KAFKA_CFG_NUM_IO_THREADS - value: {{ .Values.numIoThreads | quote }} - - name: KAFKA_CFG_NUM_NETWORK_THREADS - value: {{ .Values.numNetworkThreads | quote }} - - name: KAFKA_CFG_NUM_PARTITIONS - value: {{ .Values.numPartitions | quote }} - - name: KAFKA_CFG_NUM_RECOVERY_THREADS_PER_DATA_DIR - value: {{ .Values.numRecoveryThreadsPerDataDir | quote }} - - name: KAFKA_CFG_SOCKET_RECEIVE_BUFFER_BYTES - value: {{ .Values.socketReceiveBufferBytes | quote }} - - name: KAFKA_CFG_SOCKET_REQUEST_MAX_BYTES - value: {{ .Values.socketRequestMaxBytes | replace "_" "" | quote }} - - name: KAFKA_CFG_SOCKET_SEND_BUFFER_BYTES - value: {{ .Values.socketSendBufferBytes | quote }} - - name: KAFKA_CFG_ZOOKEEPER_CONNECTION_TIMEOUT_MS - value: {{ .Values.zookeeperConnectionTimeoutMs | quote }} - {{- if .Values.extraEnvVars }} - {{ include "kafka.tplValue" ( dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} - {{- end }} - ports: - - name: kafka-client - containerPort: 9092 - - name: kafka-internal - containerPort: {{ $interBrokerPort }} - {{- if .Values.externalAccess.enabled }} - - name: kafka-external - containerPort: 9094 - {{- end }} - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - {{- else if .Values.customLivenessProbe }} - livenessProbe: {{- include "kafka.tplValue" (dict "value" .Values.customlivenessProbe "context" $) | nindent 12 }} - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - successThreshold: {{ .Values.readinessProbe.successThreshold }} - {{- else if .Values.customReadinessProbe }} - readinessProbe: {{- include "kafka.tplValue" (dict "value" .Values.customreadinessProbe "context" $) | nindent 12 }} - {{- end }} - {{- if .Values.resources }} - resources: {{- toYaml .Values.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: data - mountPath: /bitnami/kafka - {{- if or .Values.config .Values.existingConfigmap }} - - name: kafka-config - mountPath: /bitnami/kafka/config/server.properties - subPath: server.properties - {{- end }} - {{- if or .Values.log4j .Values.existingLog4jConfigMap }} - - name: log4j-config - mountPath: /bitnami/kafka/config/log4j.properties - subPath: log4j.properties - {{- end }} - - name: scripts - mountPath: /scripts/setup.sh - subPath: setup.sh - {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled }} - - name: shared - mountPath: /shared - {{- end }} - {{- if (include "kafka.tlsEncryption" .) }} - - name: kafka-certificates - mountPath: /certs - readOnly: true - {{- end }} - {{- if .Values.extraVolumeMounts }} - {{- toYaml .Values.extraVolumeMounts | nindent 12 }} - {{- end }} - {{- if .Values.metrics.jmx.enabled }} - - name: jmx-exporter - image: {{ template "kafka.metrics.jmx.image" . }} - imagePullPolicy: {{ .Values.metrics.jmx.image.pullPolicy | quote }} - command: - - java - - -XX:+UnlockExperimentalVMOptions - - -XX:+UseCGroupMemoryLimitForHeap - - -XX:MaxRAMFraction=1 - - -XshowSettings:vm - - -jar - - jmx_prometheus_httpserver.jar - - "5556" - - /etc/jmx-kafka/jmx-kafka-prometheus.yml - ports: - - name: metrics - containerPort: 5556 - {{- if .Values.metrics.jmx.resources }} - resources: {{- toYaml .Values.metrics.jmx.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: jmx-config - mountPath: /etc/jmx-kafka - {{- end }} - {{- if .Values.sidecars }} - {{- include "kafka.tplValue" (dict "value" .Values.sidecars "context" $) | nindent 8 }} - {{- end }} - volumes: - {{- if or .Values.config .Values.existingConfigmap }} - - name: kafka-config - configMap: - name: {{ include "kafka.configmapName" . }} - {{- end }} - {{- if or .Values.log4j .Values.existingLog4jConfigMap }} - - name: log4j-config - configMap: - name: {{ include "kafka.log4j.configMapName" . }} - {{ end }} - - name: scripts - configMap: - name: {{ include "kafka.fullname" . }}-scripts - defaultMode: 0755 - {{- if and .Values.externalAccess.enabled .Values.externalAccess.autoDiscovery.enabled }} - - name: shared - emptyDir: {} - {{- end }} - {{- if .Values.metrics.jmx.enabled }} - - name: jmx-config - configMap: - name: {{ include "kafka.metrics.jmx.configmapName" . }} - {{- end }} - {{- if (include "kafka.tlsEncryption" .) }} - - name: kafka-certificates - secret: - secretName: {{ include "kafka.jksSecretName" . }} - defaultMode: 256 - {{- end }} - {{- if .Values.extraVolumes }} - {{- toYaml .Values.extraVolumes | nindent 8 }} - {{- end }} -{{- if not .Values.persistence.enabled }} - - name: data - emptyDir: {} -{{- else if .Values.persistence.existingClaim }} - - name: data - persistentVolumeClaim: - claimName: {{ printf "%s" (tpl .Values.persistence.existingClaim .) }} -{{- else }} - volumeClaimTemplates: - - metadata: - name: data - {{- if .Values.persistence.annotations }} - annotations: {{- include "kafka.tplValue" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} - {{- end }} - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{ include "kafka.storageClass" . | nindent 8 }} -{{- end }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/svc-external-access.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/svc-external-access.yaml deleted file mode 100755 index eefe0046d..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/svc-external-access.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if .Values.externalAccess.enabled }} -{{- $fullName := include "kafka.fullname" . }} -{{- $replicaCount := .Values.replicaCount | int }} -{{- $root := . }} - -{{- range $i, $e := until $replicaCount }} -{{- $targetPod := printf "%s-%d" (printf "%s" $fullName) $i }} ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" $ }}-{{ $i }}-external - labels: {{- include "kafka.labels" $ | nindent 4 }} - app.kubernetes.io/component: kafka - pod: {{ $targetPod }} - {{- if $root.Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" $root.Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or $root.Values.externalAccess.service.annotations $root.Values.commonAnnotations }} - annotations: - {{- if $root.Values.externalAccess.service.annotations }} - {{ include "kafka.tplValue" ( dict "value" $root.Values.externalAccess.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if $root.Values.commonAnnotations }} - {{- include "kafka.tplValue" ( dict "value" $root.Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ $root.Values.externalAccess.service.type }} - {{- if eq $root.Values.externalAccess.service.type "LoadBalancer" }} - {{- if not (empty $root.Values.externalAccess.service.loadBalancerIPs) }} - loadBalancerIP: {{ index $root.Values.externalAccess.service.loadBalancerIPs $i }} - {{- end }} - {{- if $root.Values.externalAccess.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- toYaml $root.Values.externalAccess.service.loadBalancerSourceRanges | nindent 4 }} - {{- end }} - {{- end }} - ports: - - name: tcp-kafka - port: {{ $root.Values.externalAccess.service.port }} - {{- if not (empty $root.Values.externalAccess.service.nodePorts) }} - nodePort: {{ index $root.Values.externalAccess.service.nodePorts $i }} - {{- else }} - nodePort: null - {{- end }} - targetPort: kafka-external - selector: {{- include "kafka.matchLabels" $ | nindent 4 }} - app.kubernetes.io/component: kafka - statefulset.kubernetes.io/pod-name: {{ $targetPod }} ---- -{{- end }} -{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/svc-headless.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/svc-headless.yaml deleted file mode 100755 index e7c2e5e6e..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/svc-headless.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" . }}-headless - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - type: ClusterIP - clusterIP: None - ports: - - name: tcp-client - port: {{ .Values.service.port }} - protocol: TCP - targetPort: kafka-client - - name: tcp-internal - port: {{ .Values.service.internalPort }} - protocol: TCP - targetPort: kafka-internal - selector: {{- include "kafka.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: kafka diff --git a/ee/scripts/helm/helm/databases/charts/kafka/templates/svc.yaml b/ee/scripts/helm/helm/databases/charts/kafka/templates/svc.yaml deleted file mode 100755 index 189cb9ffd..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/templates/svc.yaml +++ /dev/null @@ -1,49 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kafka.fullname" . }} - labels: {{- include "kafka.labels" . | nindent 4 }} - app.kubernetes.io/component: kafka - {{- if .Values.commonLabels }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} - {{- end }} - {{- if or .Values.service.annotations .Values.commonAnnotations }} - annotations: - {{- if .Values.service.annotations }} - {{ include "kafka.tplValue" ( dict "value" .Values.service.annotations "context" $) | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - {{- include "kafka.tplValue" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- end }} -spec: - type: {{ .Values.service.type }} - {{- if eq .Values.service.type "LoadBalancer" }} - {{- if .Values.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.service.loadBalancerIP }} - {{- end }} - {{- if .Values.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} - {{- end }} - {{- end }} - ports: - - name: tcp-client - port: {{ .Values.service.port }} - protocol: TCP - targetPort: kafka-client - {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.client)) }} - nodePort: {{ .Values.service.nodePorts.client }} - {{- else if eq .Values.service.type "ClusterIP" }} - nodePort: null - {{- end }} - {{- if and .Values.externalAccess.enabled (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) }} - - name: tcp-external - port: {{ .Values.service.externalPort }} - protocol: TCP - targetPort: kafka-external - {{- if (not (empty .Values.service.nodePorts.external)) }} - nodePort: {{ .Values.service.nodePorts.external }} - {{- end }} - {{- end }} - selector: {{- include "kafka.matchLabels" . | nindent 4 }} - app.kubernetes.io/component: kafka diff --git a/ee/scripts/helm/helm/databases/charts/kafka/values-production.yaml b/ee/scripts/helm/helm/databases/charts/kafka/values-production.yaml deleted file mode 100755 index af6f43dba..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/values-production.yaml +++ /dev/null @@ -1,931 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -# global: -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami Kafka image version -## ref: https://hub.docker.com/r/bitnami/kafka/tags/ -## -image: - registry: docker.io - repository: bitnami/kafka - tag: 2.6.0-debian-10-r30 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Set to true if you would like to see extra information on logs - ## - debug: false - -## String to partially override kafka.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override kafka.fullname template -## -# fullnameOverride: - -## Kubernetes Cluster Domain -## -clusterDomain: cluster.local - -## Add labels to all the deployed resources -## -commonLabels: {} - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -## Kafka Configuration -## Specify content for server.properties -## The server.properties is auto-generated based on other parameters when this paremeter is not specified -## -## Example: -## config: |- -## broker.id=-1 -## listeners=PLAINTEXT://:9092 -## advertised.listeners=PLAINTEXT://KAFKA_IP:9092 -## num.network.threads=3 -## num.io.threads=8 -## socket.send.buffer.bytes=102400 -## socket.receive.buffer.bytes=102400 -## socket.request.max.bytes=104857600 -## log.dirs=/bitnami/kafka/data -## num.partitions=1 -## num.recovery.threads.per.data.dir=1 -## offsets.topic.replication.factor=1 -## transaction.state.log.replication.factor=1 -## transaction.state.log.min.isr=1 -## log.flush.interval.messages=10000 -## log.flush.interval.ms=1000 -## log.retention.hours=168 -## log.retention.bytes=1073741824 -## log.segment.bytes=1073741824 -## log.retention.check.interval.ms=300000 -## zookeeper.connect=ZOOKEEPER_SERVICE_NAME -## zookeeper.connection.timeout.ms=6000 -## group.initial.rebalance.delay.ms=0 -## -# config: - -## ConfigMap with Kafka Configuration -## NOTE: This will override config -## -# existingConfigmap: - -## Kafka Log4J Configuration -## An optional log4j.properties file to overwrite the default of the Kafka brokers. -## See an example log4j.properties at: -## https://github.com/apache/kafka/blob/trunk/config/log4j.properties -## -# log4j: - -## Kafka Log4j ConfigMap -## The name of an existing ConfigMap containing a log4j.properties file. -## NOTE: this will override log4j. -## -# existingLog4jConfigMap: - -## Kafka's Java Heap size -## -heapOpts: -Xmx1024m -Xms1024m - -## Switch to enable topic deletion or not. -## -deleteTopicEnable: false - -## Switch to enable auto creation of topics. -## Enabling auto creation of topics not recommended for production or similar environments. -## -autoCreateTopicsEnable: false - -## The number of messages to accept before forcing a flush of data to disk. -## -logFlushIntervalMessages: 10000 - -## The maximum amount of time a message can sit in a log before we force a flush. -## -logFlushIntervalMs: 1000 - -## A size-based retention policy for logs. -## -logRetentionBytes: _1073741824 - -## The interval at which log segments are checked to see if they can be deleted. -## -logRetentionCheckIntervalMs: 300000 - -## The minimum age of a log file to be eligible for deletion due to age. -## -logRetentionHours: 168 - -## The maximum size of a log segment file. When this size is reached a new log segment will be created. -## -logSegmentBytes: _1073741824 - -## A comma separated list of directories under which to store log files. -## -logsDirs: /bitnami/kafka/data - -## The largest record batch size allowed by Kafka -## -maxMessageBytes: _1000012 - -## Default replication factors for automatically created topics -## -defaultReplicationFactor: 3 - -## The replication factor for the offsets topic -## -offsetsTopicReplicationFactor: 3 - -## The replication factor for the transaction topic -## -transactionStateLogReplicationFactor: 3 - -## Overridden min.insync.replicas config for the transaction topic -## -transactionStateLogMinIsr: 3 - -## The number of threads doing disk I/O. -## -numIoThreads: 8 - -## The number of threads handling network requests. -## -numNetworkThreads: 3 - -## The default number of log partitions per topic. -## -numPartitions: 1 - -## The number of threads per data directory to be used for log recovery at startup and flushing at shutdown. -## -numRecoveryThreadsPerDataDir: 1 - -## The receive buffer (SO_RCVBUF) used by the socket server. -## -socketReceiveBufferBytes: 102400 - -## The maximum size of a request that the socket server will accept (protection against OOM). -## -socketRequestMaxBytes: _104857600 - -## The send buffer (SO_SNDBUF) used by the socket server. -## -socketSendBufferBytes: 102400 - -## Timeout in ms for connecting to zookeeper. -## -zookeeperConnectionTimeoutMs: 6000 - -## Command and args for running the container. Use array form -## -command: - - /scripts/setup.sh -args: - -## All the parameters from the configuration file can be overwritten by using environment variables with this format: KAFKA_CFG_{KEY} -## ref: https://github.com/bitnami/bitnami-docker-kafka#configuration -## Example: -## extraEnvVars: -## - name: KAFKA_CFG_BACKGROUND_THREADS -## value: "10" -## -extraEnvVars: [] - -## extraVolumes and extraVolumeMounts allows you to mount other volumes -## Examples: -# extraVolumes: -# - name: kafka-jaas -# secret: -# secretName: kafka-jaas -# extraVolumeMounts: -# - name: kafka-jaas -# mountPath: /bitnami/kafka/config/kafka_jaas.conf -# subPath: kafka_jaas.conf -extraVolumes: [] -extraVolumeMounts: [] - -## Extra objects to deploy (value evaluated as a template) -## -extraDeploy: [] - -## Authentication parameteres -## https://github.com/bitnami/bitnami-docker-kafka#security -## -auth: - ## Authentication protocol for client and inter-broker communications - ## Supported values: 'plaintext', 'tls', 'mtls', 'sasl' and 'sasl_tls' - ## This table shows the security provided on each protocol: - ## | Method | Authentication | Encryption via TLS | - ## | plaintext | None | No | - ## | tls | None | Yes | - ## | mtls | Yes (two-way authentication) | Yes | - ## | sasl | Yes (via SASL) | No | - ## | sasl_tls | Yes (via SASL) | Yes | - ## - clientProtocol: sasl - interBrokerProtocol: sasl - - ## Allowed SASL mechanisms when clientProtocol or interBrokerProtocol are using either sasl or sasl_tls - ## - saslMechanisms: plain,scram-sha-256,scram-sha-512 - ## SASL mechanism for inter broker communication - ## - saslInterBrokerMechanism: plain - - ## Name of the existing secret containing the truststore and - ## one keystore per Kafka broker you have in the Kafka cluster. - ## MANDATORY when 'tls', 'mtls', or 'sasl_tls' authentication protocols are used. - ## Create this secret following the steps below: - ## 1) Generate your trustore and keystore files. Helpful script: https://raw.githubusercontent.com/confluentinc/confluent-platform-security-tools/master/kafka-generate-ssl.sh - ## 2) Rename your truststore to `kafka.truststore.jks`. - ## 3) Rename your keystores to `kafka-X.keystore.jks` where X is the ID of each Kafka broker. - ## 4) Run the command below where SECRET_NAME is the name of the secret you want to create: - ## kubectl create secret generic SECRET_NAME --from-file=./kafka.truststore.jks --from-file=./kafka-0.keystore.jks --from-file=./kafka-1.keystore.jks ... - ## Alternatively, you can put your JKS files under the files/jks directory - ## - # jksSecret: - - ## Password to access the JKS files when they are password-protected. - ## - # jksPassword: - - ## The endpoint identification algorithm used by clients to validate server host name. - ## Disable server host name verification by setting it to an empty string - ## See: https://docs.confluent.io/current/kafka/authentication_ssl.html#optional-settings - ## - tlsEndpointIdentificationAlgorithm: https - - ## JAAS configuration for SASL authentication - ## MANDATORY when method is 'sasl', or 'sasl_tls' - ## - jaas: - ## Kafka client user list - ## - ## clientUsers: - ## - user1 - ## - user2 - ## - clientUsers: - - user - - ## Kafka client passwords - ## - ## clientPasswords: - ## - password1 - ## - password2 - ## - clientPasswords: [] - - ## Kafka inter broker communication user - ## - interBrokerUser: admin - - ## Kafka inter broker communication password - ## - interBrokerPassword: "" - - ## Kafka Zookeeper user - ## - zookeeperUser: zookeeperUser - - ## Kafka Zookeeper password - ## - zookeeperPassword: zookeeperPassword - - ## Name of the existing secret containing credentials for clientUsers, interBrokerUser and zookeeperUser. - ## Create this secret running the command below where SECRET_NAME is the name of the secret you want to create: - ## kubectl create secret generic SECRET_NAME --from-literal=client-password=CLIENT_PASSWORD1,CLIENT_PASSWORD2 --from-literal=inter-broker-password=INTER_BROKER_PASSWORD --from-literal=zookeeper-password=ZOOKEEPER_PASSWORD - ## - # existingSecret: - -## The address(es) the socket server listens on. -## When it's set to an empty array, the listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -listeners: [] - -## The address(es) (hostname:port) the brokers will advertise to producers and consumers. -## When it's set to an empty array, the advertised listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -advertisedListeners: [] - -## The listener->protocol mapping -## When it's nil, the listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -# listenerSecurityProtocolMap: - -## Allow to use the PLAINTEXT listener. -## -allowPlaintextListener: false - -## Name of listener used for communication between brokers. -## -interBrokerListenerName: INTERNAL - -## Number of Kafka brokers to deploy -## -replicaCount: 3 - -## StrategyType, can be set to RollingUpdate or OnDelete by default. -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets -## -updateStrategy: RollingUpdate - -## Partition update strategy -## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -## -# rollingUpdatePartition: - -## Pod labels. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -podLabels: {} - -## Pod annotations. Evaluated as a template -## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -## -podAnnotations: {} - -## Name of the priority class to be used by kafka pods, priority class needs to be created beforehand -## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ -priorityClassName: "" - -## Affinity for pod assignment. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Node labels for pod assignment. Evaluated as a template -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Kafka pods' Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod -## -podSecurityContext: - fsGroup: 1001 - runAsUser: 1001 - -## Kafka containers' Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container -## Example: -## containerSecurityContext: -## capabilities: -## drop: ["NET_RAW"] -## readOnlyRootFilesystem: true -## -containerSecurityContext: {} - -## Kafka containers' resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 250m - # memory: 1Gi - requests: {} - # cpu: 250m - # memory: 256Mi - -## Kafka containers' liveness and readiness probes. Evaluated as a template. -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes -## -livenessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: 10 - timeoutSeconds: 5 - # failureThreshold: 3 - # periodSeconds: 10 - # successThreshold: 1 -readinessProbe: - tcpSocket: - port: kafka-client - initialDelaySeconds: 5 - failureThreshold: 6 - timeoutSeconds: 5 - # periodSeconds: 10 - # successThreshold: 1 - -## Pod Disruption Budget configuration -## The PDB will only be created if replicaCount is greater than 1 -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions -## -pdb: - create: true - ## Min number of pods that must still be available after the eviction - ## - # minAvailable: 1 - ## Max number of pods that can be unavailable after the eviction - ## - maxUnavailable: 1 - -## Add sidecars to the pod. -## Example: -## sidecars: -## - name: your-image-name -## image: your-image -## imagePullPolicy: Always -## ports: -## - name: portname -## containerPort: 1234 -## -sidecars: {} - -## Service parameters -## -service: - ## Service type - ## - type: ClusterIP - ## Kafka port for client connections - ## - port: 9092 - ## Kafka port for inter-broker connections - ## - internalPort: 9093 - ## Kafka port for external connections - ## - externalPort: 9094 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePorts: - client: "" - external: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Provide any additional annotations which may be required. Evaluated as a template - ## - annotations: {} - -## External Access to Kafka brokers configuration -## -externalAccess: - ## Enable Kubernetes external cluster access to Kafka brokers - ## - enabled: false - - ## External IPs auto-discovery configuration - ## An init container is used to auto-detect LB IPs or node ports by querying the K8s API - ## Note: RBAC might be required - ## - autoDiscovery: - ## Enable external IP/ports auto-discovery - ## - enabled: false - ## Bitnami Kubectl image - ## ref: https://hub.docker.com/r/bitnami/kubectl/tags/ - ## - image: - registry: docker.io - repository: bitnami/kubectl - tag: 1.17.12-debian-10-r3 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## Init Container resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Parameters to configure K8s service(s) used to externally access Kafka brokers - ## A new service per broker will be created - ## - service: - ## Service type. Allowed values: LoadBalancer or NodePort - ## - type: LoadBalancer - ## Port used when service type is LoadBalancer - ## - port: 9094 - ## Array of load balancer IPs for each Kafka broker. Length must be the same as replicaCount - ## Example: - ## loadBalancerIPs: - ## - X.X.X.X - ## - Y.Y.Y.Y - ## - loadBalancerIPs: [] - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Array of node ports used for each Kafka broker. Length must be the same as replicaCount - ## Example: - ## nodePorts: - ## - 30001 - ## - 30002 - ## - nodePorts: [] - ## When service type is NodePort, you can specify the domain used for Kafka advertised listeners. - ## If not specified, the container will try to get the kubernetes node external IP - ## - # domain: mydomain.com - ## Provide any additional annotations which may be required. Evaluated as a template - ## - annotations: {} - -## Persistence paramaters -## -persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - ## PV Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. - ## - # storageClass: "-" - ## PV Access Mode - ## - accessModes: - - ReadWriteOnce - ## PVC size - ## - size: 8Gi - ## PVC annotations - ## - annotations: {} - -## Init Container paramaters -## Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each component -## values from the securityContext section of the component -## -volumePermissions: - enabled: false - ## Bitnami Minideb image - ## ref: https://hub.docker.com/r/bitnami/minideb/tags/ - ## - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## Init Container resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - -## Kafka pods ServiceAccount -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: true - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the fluentd.fullname template - ## - # name: - -## Role Based Access -## ref: https://kubernetes.io/docs/admin/authorization/rbac/ -## -rbac: - ## Specifies whether RBAC rules should be created - ## binding Kafka ServiceAccount to a role - ## that allows Kafka pods querying the K8s API - ## - create: false - -## Prometheus Exporters / Metrics -## -metrics: - ## Prometheus Kafka Exporter: exposes complimentary metrics to JMX Exporter - ## - kafka: - enabled: true - - ## Bitnami Kafka exporter image - ## ref: https://hub.docker.com/r/bitnami/kafka-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/kafka-exporter - tag: 1.2.0-debian-10-r220 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Extra flags to be passed to Kafka exporter - ## Example: - ## extraFlags: - ## tls.insecure-skip-tls-verify: "" - ## web.telemetry-path: "/metrics" - ## - extraFlags: {} - - ## Name of the existing secret containing the optional certificate and key files - ## for Kafka Exporter client authentication - ## - # certificatesSecret: - - ## Prometheus Kafka Exporter' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Service configuration - ## - service: - ## Kafka Exporter Service type - ## - type: ClusterIP - ## Kafka Exporter Prometheus port - ## - port: 9308 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePort: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Set the Cluster IP to use - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address - ## - # clusterIP: None - ## Annotations for the Kafka Exporter Prometheus metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.kafka.service.port }}" - prometheus.io/path: "/metrics" - - ## Prometheus JMX Exporter: exposes the majority of Kafkas metrics - ## - jmx: - enabled: true - - ## Bitnami JMX exporter image - ## ref: https://hub.docker.com/r/bitnami/jmx-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/jmx-exporter - tag: 0.14.0-debian-10-r15 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Prometheus JMX Exporter' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Service configuration - ## - service: - ## JMX Exporter Service type - ## - type: ClusterIP - ## JMX Exporter Prometheus port - ## - port: 5556 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePort: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Set the Cluster IP to use - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address - ## - # clusterIP: None - ## Annotations for the JMX Exporter Prometheus metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.jmx.service.port }}" - prometheus.io/path: "/" - - ## JMX Whitelist Objects, can be set to control which JMX metrics are exposed. Only whitelisted - ## values will be exposed via JMX Exporter. They must also be exposed via Rules. To expose all metrics - ## (warning its crazy excessive and they aren't formatted in a prometheus style) (1) `whitelistObjectNames: []` - ## (2) commented out above `overrideConfig`. - ## - whitelistObjectNames: - - kafka.controller:* - - kafka.server:* - - java.lang:* - - kafka.network:* - - kafka.log:* - - ## Prometheus JMX exporter configuration - ## Specify content for jmx-kafka-prometheus.yml. Evaluated as a template - ## - ## Credits to the incubator/kafka chart for the JMX configuration. - ## https://github.com/helm/charts/tree/master/incubator/kafka - ## - config: |- - jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:5555/jmxrmi - lowercaseOutputName: true - lowercaseOutputLabelNames: true - ssl: false - {{- if .Values.metrics.jmx.whitelistObjectNames }} - whitelistObjectNames: ["{{ join "\",\"" .Values.metrics.jmx.whitelistObjectNames }}"] - {{- end }} - - ## ConfigMap with Prometheus JMX exporter configuration - ## NOTE: This will override metrics.jmx.config - ## - # existingConfigmap: - - ## Prometheus Operator ServiceMonitor configuration - ## - serviceMonitor: - enabled: false - ## Namespace in which Prometheus is running - ## - # namespace: monitoring - - ## Interval at which metrics should be scraped. - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # interval: 10s - - ## Timeout after which the scrape is ended - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # scrapeTimeout: 10s - - ## ServiceMonitor selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - -## -## Zookeeper chart configuration -## -## https://github.com/bitnami/charts/blob/master/bitnami/zookeeper/values.yaml -## -zookeeper: - enabled: true - auth: - ## Enable Zookeeper auth - ## - enabled: true - ## User that will use Zookeeper clients to auth - ## - clientUser: zookeeperUser - ## Password that will use Zookeeper clients to auth - ## - clientPassword: zookeeperPassword - ## Comma, semicolon or whitespace separated list of user to be created. Specify them as a string, for example: "user1,user2,admin" - ## - serverUsers: zookeeperUser - ## Comma, semicolon or whitespace separated list of passwords to assign to users when created. Specify them as a string, for example: "pass4user1, pass4user2, pass4admin" - ## - serverPasswords: zookeeperPassword - metrics: - enabled: true - -## This value is only used when zookeeper.enabled is set to false -## -externalZookeeper: - ## Server or list of external zookeeper servers to use. - ## - servers: [] diff --git a/ee/scripts/helm/helm/databases/charts/kafka/values.yaml b/ee/scripts/helm/helm/databases/charts/kafka/values.yaml deleted file mode 100755 index 154d71bd5..000000000 --- a/ee/scripts/helm/helm/databases/charts/kafka/values.yaml +++ /dev/null @@ -1,934 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -# global: -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami Kafka image version -## ref: https://hub.docker.com/r/bitnami/kafka/tags/ -## -image: - registry: docker.io - repository: bitnami/kafka - tag: 2.6.0-debian-10-r30 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Set to true if you would like to see extra information on logs - ## - debug: false - -## String to partially override kafka.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override kafka.fullname template -## -# fullnameOverride: - -## Kubernetes Cluster Domain -## -clusterDomain: cluster.local - -## Add labels to all the deployed resources -## -commonLabels: {} - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -## Kafka Configuration -## Specify content for server.properties -## The server.properties is auto-generated based on other parameters when this paremeter is not specified -## -## Example: -## config: |- -## broker.id=-1 -## listeners=PLAINTEXT://:9092 -## advertised.listeners=PLAINTEXT://KAFKA_IP:9092 -## num.network.threads=3 -## num.io.threads=8 -## socket.send.buffer.bytes=102400 -## socket.receive.buffer.bytes=102400 -## socket.request.max.bytes=104857600 -## log.dirs=/bitnami/kafka/data -## num.partitions=1 -## num.recovery.threads.per.data.dir=1 -## offsets.topic.replication.factor=1 -## transaction.state.log.replication.factor=1 -## transaction.state.log.min.isr=1 -## log.flush.interval.messages=10000 -## log.flush.interval.ms=1000 -## log.retention.hours=168 -## log.retention.bytes=1073741824 -## log.segment.bytes=1073741824 -## log.retention.check.interval.ms=300000 -## zookeeper.connect=ZOOKEEPER_SERVICE_NAME -## zookeeper.connection.timeout.ms=6000 -## group.initial.rebalance.delay.ms=0 -## -# config: - -## ConfigMap with Kafka Configuration -## NOTE: This will override config -## -# existingConfigmap: - -## Kafka Log4J Configuration -## An optional log4j.properties file to overwrite the default of the Kafka brokers. -## See an example log4j.properties at: -## https://github.com/apache/kafka/blob/trunk/config/log4j.properties -## -# log4j: - -## Kafka Log4j ConfigMap -## The name of an existing ConfigMap containing a log4j.properties file. -## NOTE: this will override log4j. -## -# existingLog4jConfigMap: - -## Kafka's Java Heap size -## -heapOpts: -Xmx1024m -Xms1024m - -## Switch to enable topic deletion or not. -## -deleteTopicEnable: false - -## Switch to enable auto creation of topics. -## Enabling auto creation of topics not recommended for production or similar environments. -## -autoCreateTopicsEnable: true - -## The number of messages to accept before forcing a flush of data to disk. -## -logFlushIntervalMessages: 10000 - -## The maximum amount of time a message can sit in a log before we force a flush. -## -logFlushIntervalMs: 1000 - -## A size-based retention policy for logs. -## -logRetentionBytes: _1073741824 - -## The interval at which log segments are checked to see if they can be deleted. -## -logRetentionCheckIntervalMs: 300000 - -## The minimum age of a log file to be eligible for deletion due to age. -## -logRetentionHours: 168 - -## The maximum size of a log segment file. When this size is reached a new log segment will be created. -## -logSegmentBytes: _1073741824 - -## A comma separated list of directories under which to store log files. -## -logsDirs: /bitnami/kafka/data - -## The largest record batch size allowed by Kafka -## -maxMessageBytes: _1000012 - -## Default replication factors for automatically created topics -## -defaultReplicationFactor: 1 - -## The replication factor for the offsets topic -## -offsetsTopicReplicationFactor: 1 - -## The replication factor for the transaction topic -## -transactionStateLogReplicationFactor: 1 - -## Overridden min.insync.replicas config for the transaction topic -## -transactionStateLogMinIsr: 1 - -## The number of threads doing disk I/O. -## -numIoThreads: 8 - -## The number of threads handling network requests. -## -numNetworkThreads: 3 - -## The default number of log partitions per topic. -## -numPartitions: 1 - -## The number of threads per data directory to be used for log recovery at startup and flushing at shutdown. -## -numRecoveryThreadsPerDataDir: 1 - -## The receive buffer (SO_RCVBUF) used by the socket server. -## -socketReceiveBufferBytes: 102400 - -## The maximum size of a request that the socket server will accept (protection against OOM). -## -socketRequestMaxBytes: _104857600 - -## The send buffer (SO_SNDBUF) used by the socket server. -## -socketSendBufferBytes: 102400 - -## Timeout in ms for connecting to zookeeper. -## -zookeeperConnectionTimeoutMs: 6000 - -## Command and args for running the container. Use array form -## -command: - - /scripts/setup.sh -args: - -## All the parameters from the configuration file can be overwritten by using environment variables with this format: KAFKA_CFG_{KEY} -## ref: https://github.com/bitnami/bitnami-docker-kafka#configuration -## Example: -## extraEnvVars: -## - name: KAFKA_CFG_BACKGROUND_THREADS -## value: "10" -## -extraEnvVars: [] - -## extraVolumes and extraVolumeMounts allows you to mount other volumes -## Examples: -# extraVolumes: -# - name: kafka-jaas -# secret: -# secretName: kafka-jaas -# extraVolumeMounts: -# - name: kafka-jaas -# mountPath: /bitnami/kafka/config/kafka_jaas.conf -# subPath: kafka_jaas.conf -extraVolumes: [] -extraVolumeMounts: [] - -## Extra objects to deploy (value evaluated as a template) -## -extraDeploy: [] - -## Authentication parameteres -## https://github.com/bitnami/bitnami-docker-kafka#security -## -auth: - ## Authentication protocol for client and inter-broker communications - ## Supported values: 'plaintext', 'tls', 'mtls', 'sasl' and 'sasl_tls' - ## This table shows the security provided on each protocol: - ## | Method | Authentication | Encryption via TLS | - ## | plaintext | None | No | - ## | tls | None | Yes | - ## | mtls | Yes (two-way authentication) | Yes | - ## | sasl | Yes (via SASL) | No | - ## | sasl_tls | Yes (via SASL) | Yes | - ## - clientProtocol: plaintext - interBrokerProtocol: plaintext - - ## Allowed SASL mechanisms when clientProtocol or interBrokerProtocol are using either sasl or sasl_tls - ## - saslMechanisms: plain,scram-sha-256,scram-sha-512 - ## SASL mechanism for inter broker communication - ## - saslInterBrokerMechanism: plain - - ## Name of the existing secret containing the truststore and - ## one keystore per Kafka broker you have in the Kafka cluster. - ## MANDATORY when 'tls', 'mtls', or 'sasl_tls' authentication protocols are used. - ## Create this secret following the steps below: - ## 1) Generate your trustore and keystore files. Helpful script: https://raw.githubusercontent.com/confluentinc/confluent-platform-security-tools/master/kafka-generate-ssl.sh - ## 2) Rename your truststore to `kafka.truststore.jks`. - ## 3) Rename your keystores to `kafka-X.keystore.jks` where X is the ID of each Kafka broker. - ## 4) Run the command below where SECRET_NAME is the name of the secret you want to create: - ## kubectl create secret generic SECRET_NAME --from-file=./kafka.truststore.jks --from-file=./kafka-0.keystore.jks --from-file=./kafka-1.keystore.jks ... - ## Alternatively, you can put your JKS files under the files/jks directory - ## - # jksSecret: - - ## Password to access the JKS files when they are password-protected. - ## - # jksPassword: - - ## The endpoint identification algorithm used by clients to validate server host name. - ## Disable server host name verification by setting it to an empty string - ## See: https://docs.confluent.io/current/kafka/authentication_ssl.html#optional-settings - ## - tlsEndpointIdentificationAlgorithm: https - - ## JAAS configuration for SASL authentication - ## MANDATORY when method is 'sasl', or 'sasl_tls' - ## - jaas: - ## Kafka client user list - ## - ## clientUsers: - ## - user1 - ## - user2 - ## - clientUsers: - - user - - ## Kafka client passwords. This is mandatory if more than one user is specified in clientUsers. - ## - ## clientPasswords: - ## - password1 - ## - password2" - ## - clientPasswords: [] - - ## Kafka inter broker communication user - ## - interBrokerUser: admin - - ## Kafka inter broker communication password - ## - interBrokerPassword: "" - - ## Kafka Zookeeper user - ## - # zookeeperUser: - - ## Kafka Zookeeper password - ## - # zookeeperPassword: - - ## Name of the existing secret containing credentials for clientUsers, interBrokerUser and zookeeperUser. - ## Create this secret running the command below where SECRET_NAME is the name of the secret you want to create: - ## kubectl create secret generic SECRET_NAME --from-literal=client-passwords=CLIENT_PASSWORD1,CLIENT_PASSWORD2 --from-literal=inter-broker-password=INTER_BROKER_PASSWORD --from-literal=zookeeper-password=ZOOKEEPER_PASSWORD - ## - # existingSecret: - -## The address(es) the socket server listens on. -## When it's set to an empty array, the listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -listeners: [] - -## The address(es) (hostname:port) the brokers will advertise to producers and consumers. -## When it's set to an empty array, the advertised listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -advertisedListeners: [] - -## The listener->protocol mapping -## When it's nil, the listeners will be configured -## based on the authentication protocols (auth.clientProtocol and auth.interBrokerProtocol parameters) -## -# listenerSecurityProtocolMap: - -## Allow to use the PLAINTEXT listener. -## -allowPlaintextListener: true - -## Name of listener used for communication between brokers. -## -interBrokerListenerName: INTERNAL - -## Number of Kafka brokers to deploy -## -replicaCount: 2 - -## StrategyType, can be set to RollingUpdate or OnDelete by default. -## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets -## -updateStrategy: RollingUpdate - -## Partition update strategy -## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions -## -# rollingUpdatePartition: - -## Pod labels. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -## -podLabels: {} - -## Pod annotations. Evaluated as a template -## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -## -podAnnotations: {} - -## Name of the priority class to be used by kafka pods, priority class needs to be created beforehand -## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ -## -priorityClassName: "" - -## Affinity for pod assignment. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Node labels for pod assignment. Evaluated as a template -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment. Evaluated as a template -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Kafka pods' Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod -## -podSecurityContext: - fsGroup: 1001 - runAsUser: 1001 - -## Kafka containers' Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container -## Example: -## containerSecurityContext: -## capabilities: -## drop: ["NET_RAW"] -## readOnlyRootFilesystem: true -## -containerSecurityContext: {} - -## Kafka containers' resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 250m - # memory: 1Gi - requests: {} - # cpu: 250m - # memory: 256Mi - -## Kafka containers' liveness and readiness probes. Evaluated as a template. -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes -## -livenessProbe: - enabled: true - initialDelaySeconds: 10 - timeoutSeconds: 5 - # failureThreshold: 3 - # periodSeconds: 10 - # successThreshold: 1 -readinessProbe: - enabled: true - initialDelaySeconds: 5 - failureThreshold: 6 - timeoutSeconds: 5 - # periodSeconds: 10 - # successThreshold: 1 - -## Custom liveness/readiness probes that will override the default ones -## -customLivenessProbe: {} -customReadinessProbe: {} - -## Pod Disruption Budget configuration -## The PDB will only be created if replicaCount is greater than 1 -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions -## -pdb: - create: true - ## Min number of pods that must still be available after the eviction - ## - # minAvailable: 1 - ## Max number of pods that can be unavailable after the eviction - ## - maxUnavailable: 1 - -## Add sidecars to the pod. -## Example: -## sidecars: -## - name: your-image-name -## image: your-image -## imagePullPolicy: Always -## ports: -## - name: portname -## containerPort: 1234 -## -sidecars: {} - -## Service parameters -## -service: - ## Service type - ## - type: ClusterIP - ## Kafka port for client connections - ## - port: 9092 - ## Kafka port for inter-broker connections - ## - internalPort: 9093 - ## Kafka port for external connections - ## - externalPort: 9094 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePorts: - client: "" - external: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Provide any additional annotations which may be required. Evaluated as a template - ## - annotations: {} - -## External Access to Kafka brokers configuration -## -externalAccess: - ## Enable Kubernetes external cluster access to Kafka brokers - ## - enabled: false - - ## External IPs auto-discovery configuration - ## An init container is used to auto-detect LB IPs or node ports by querying the K8s API - ## Note: RBAC might be required - ## - autoDiscovery: - ## Enable external IP/ports auto-discovery - ## - enabled: false - ## Bitnami Kubectl image - ## ref: https://hub.docker.com/r/bitnami/kubectl/tags/ - ## - image: - registry: docker.io - repository: bitnami/kubectl - tag: 1.17.12-debian-10-r3 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## Init Container resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Parameters to configure K8s service(s) used to externally access Kafka brokers - ## A new service per broker will be created - ## - service: - ## Service type. Allowed values: LoadBalancer or NodePort - ## - type: LoadBalancer - ## Port used when service type is LoadBalancer - ## - port: 9094 - ## Array of load balancer IPs for each Kafka broker. Length must be the same as replicaCount - ## Example: - ## loadBalancerIPs: - ## - X.X.X.X - ## - Y.Y.Y.Y - ## - loadBalancerIPs: [] - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Array of node ports used for each Kafka broker. Length must be the same as replicaCount - ## Example: - ## nodePorts: - ## - 30001 - ## - 30002 - ## - nodePorts: [] - ## When service type is NodePort, you can specify the domain used for Kafka advertised listeners. - ## If not specified, the container will try to get the kubernetes node external IP - ## - # domain: mydomain.com - ## Provide any additional annotations which may be required. Evaluated as a template - ## - annotations: {} - -## Persistence paramaters -## -persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template - ## - # existingClaim: - ## PV Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. - ## - # storageClass: "-" - ## PV Access Mode - ## - accessModes: - - ReadWriteOnce - ## PVC size - ## - size: 8Gi - ## PVC annotations - ## - annotations: {} - -## Init Container paramaters -## Change the owner and group of the persistent volume(s) mountpoint(s) to 'runAsUser:fsGroup' on each component -## values from the securityContext section of the component -## -volumePermissions: - enabled: false - ## Bitnami Minideb image - ## ref: https://hub.docker.com/r/bitnami/minideb/tags/ - ## - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - ## Init Container resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - -## Kafka pods ServiceAccount -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: true - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the fluentd.fullname template - ## - # name: - -## Role Based Access -## ref: https://kubernetes.io/docs/admin/authorization/rbac/ -## -rbac: - ## Specifies whether RBAC rules should be created - ## binding Kafka ServiceAccount to a role - ## that allows Kafka pods querying the K8s API - ## - create: false - -## Prometheus Exporters / Metrics -## -metrics: - ## Prometheus Kafka Exporter: exposes complimentary metrics to JMX Exporter - ## - kafka: - enabled: false - - ## Bitnami Kafka exporter image - ## ref: https://hub.docker.com/r/bitnami/kafka-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/kafka-exporter - tag: 1.2.0-debian-10-r220 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Extra flags to be passed to Kafka exporter - ## Example: - ## extraFlags: - ## tls.insecure-skip-tls-verify: "" - ## web.telemetry-path: "/metrics" - ## - extraFlags: {} - - ## Name of the existing secret containing the optional certificate and key files - ## for Kafka Exporter client authentication - ## - # certificatesSecret: - - ## Prometheus Kafka Exporter' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Service configuration - ## - service: - ## Kafka Exporter Service type - ## - type: ClusterIP - ## Kafka Exporter Prometheus port - ## - port: 9308 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePort: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Set the Cluster IP to use - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address - ## - # clusterIP: None - ## Annotations for the Kafka Exporter Prometheus metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.kafka.service.port }}" - prometheus.io/path: "/metrics" - - ## Prometheus JMX Exporter: exposes the majority of Kafkas metrics - ## - jmx: - enabled: false - - ## Bitnami JMX exporter image - ## ref: https://hub.docker.com/r/bitnami/jmx-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/jmx-exporter - tag: 0.14.0-debian-10-r15 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## Example: - ## pullSecrets: - ## - myRegistryKeySecretName - ## - pullSecrets: [] - - ## Prometheus JMX Exporter' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - - ## Service configuration - ## - service: - ## JMX Exporter Service type - ## - type: ClusterIP - ## JMX Exporter Prometheus port - ## - port: 5556 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - nodePort: "" - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## Example: - ## loadBalancerSourceRanges: - ## - 10.10.10.0/24 - ## - loadBalancerSourceRanges: [] - ## Set the Cluster IP to use - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#choosing-your-own-ip-address - ## - # clusterIP: None - ## Annotations for the JMX Exporter Prometheus metrics service - ## - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.metrics.jmx.service.port }}" - prometheus.io/path: "/" - - ## JMX Whitelist Objects, can be set to control which JMX metrics are exposed. Only whitelisted - ## values will be exposed via JMX Exporter. They must also be exposed via Rules. To expose all metrics - ## (warning its crazy excessive and they aren't formatted in a prometheus style) (1) `whitelistObjectNames: []` - ## (2) commented out above `overrideConfig`. - ## - whitelistObjectNames: - - kafka.controller:* - - kafka.server:* - - java.lang:* - - kafka.network:* - - kafka.log:* - - ## Prometheus JMX exporter configuration - ## Specify content for jmx-kafka-prometheus.yml. Evaluated as a template - ## - ## Credits to the incubator/kafka chart for the JMX configuration. - ## https://github.com/helm/charts/tree/master/incubator/kafka - ## - config: |- - jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:5555/jmxrmi - lowercaseOutputName: true - lowercaseOutputLabelNames: true - ssl: false - {{- if .Values.metrics.jmx.whitelistObjectNames }} - whitelistObjectNames: ["{{ join "\",\"" .Values.metrics.jmx.whitelistObjectNames }}"] - {{- end }} - - ## ConfigMap with Prometheus JMX exporter configuration - ## NOTE: This will override metrics.jmx.config - ## - # existingConfigmap: - - ## Prometheus Operator ServiceMonitor configuration - ## - serviceMonitor: - enabled: false - ## Namespace in which Prometheus is running - ## - # namespace: monitoring - - ## Interval at which metrics should be scraped. - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # interval: 10s - - ## Timeout after which the scrape is ended - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint - ## - # scrapeTimeout: 10s - - ## ServiceMonitor selector labels - ## ref: https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-configuration - ## - # selector: - # prometheus: my-prometheus - -## -## Zookeeper chart configuration -## -## https://github.com/bitnami/charts/blob/master/bitnami/zookeeper/values.yaml -## -zookeeper: - enabled: true - auth: - ## Enable Zookeeper auth - ## - enabled: false - ## User that will use Zookeeper clients to auth - ## - # clientUser: - ## Password that will use Zookeeper clients to auth - ## - # clientPassword: - ## Comma, semicolon or whitespace separated list of user to be created. Specify them as a string, for example: "user1,user2,admin" - ## - # serverUsers: - ## Comma, semicolon or whitespace separated list of passwords to assign to users when created. Specify them as a string, for example: "pass4user1, pass4user2, pass4admin" - ## - # serverPasswords: - -## This value is only used when zookeeper.enabled is set to false -## -externalZookeeper: - ## Server or list of external zookeeper servers to use. - ## - servers: [] diff --git a/ee/scripts/helm/roles/openreplay/defaults/main.yaml b/ee/scripts/helm/roles/openreplay/defaults/main.yaml deleted file mode 100644 index 5199a0a19..000000000 --- a/ee/scripts/helm/roles/openreplay/defaults/main.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -# defaults file for openreplay -app_name: "" -db_name: "" -db_list: - - "minio" - - "postgresql" - - "redis" - - "clickhouse" - - "kafka" - -env: - alerts: - ch_host: "clickhouse.db.svc.cluster.local" - ch_port: "9000" - chalice: - ch_host: "clickhouse.db.svc.cluster.local" - ch_port: "9000" - LICENSE_KEY: "{{ enterprise_edition_license }}" diff --git a/ee/scripts/helm/db/init_dbs/clickhouse/1.3.6/1.3.6.sql b/ee/scripts/schema/db/init_dbs/clickhouse/1.3.6/1.3.6.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/clickhouse/1.3.6/1.3.6.sql rename to ee/scripts/schema/db/init_dbs/clickhouse/1.3.6/1.3.6.sql diff --git a/ee/scripts/helm/db/init_dbs/clickhouse/1.4.0/1.4.0.sql b/ee/scripts/schema/db/init_dbs/clickhouse/1.4.0/1.4.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/clickhouse/1.4.0/1.4.0.sql rename to ee/scripts/schema/db/init_dbs/clickhouse/1.4.0/1.4.0.sql diff --git a/ee/scripts/helm/db/init_dbs/clickhouse/1.5.0/1.5.0.sql b/ee/scripts/schema/db/init_dbs/clickhouse/1.5.0/1.5.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/clickhouse/1.5.0/1.5.0.sql rename to ee/scripts/schema/db/init_dbs/clickhouse/1.5.0/1.5.0.sql diff --git a/ee/scripts/helm/db/init_dbs/clickhouse/1.8.0/1.8.0.sql b/ee/scripts/schema/db/init_dbs/clickhouse/1.8.0/1.8.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/clickhouse/1.8.0/1.8.0.sql rename to ee/scripts/schema/db/init_dbs/clickhouse/1.8.0/1.8.0.sql diff --git a/ee/scripts/schema/db/init_dbs/clickhouse/1.9.0/1.9.0.sql b/ee/scripts/schema/db/init_dbs/clickhouse/1.9.0/1.9.0.sql new file mode 100644 index 000000000..134ec3af6 --- /dev/null +++ b/ee/scripts/schema/db/init_dbs/clickhouse/1.9.0/1.9.0.sql @@ -0,0 +1,59 @@ +ALTER TABLE experimental.events + ADD COLUMN IF NOT EXISTS error_tags_keys Array(String); +ALTER TABLE experimental.events + ADD COLUMN IF NOT EXISTS error_tags_values Array(Nullable(String)); + +ALTER TABLE experimental.events + ADD COLUMN IF NOT EXISTS issue_type Nullable(Enum8('click_rage'=1,'dead_click'=2,'excessive_scrolling'=3,'bad_request'=4,'missing_resource'=5,'memory'=6,'cpu'=7,'slow_resource'=8,'slow_page_load'=9,'crash'=10,'ml_cpu'=11,'ml_memory'=12,'ml_dead_click'=13,'ml_click_rage'=14,'ml_mouse_thrashing'=15,'ml_excessive_scrolling'=16,'ml_slow_resources'=17,'custom'=18,'js_exception'=19)); +ALTER TABLE experimental.events + ADD COLUMN IF NOT EXISTS issue_id Nullable(String); +ALTER TABLE experimental.events + MODIFY COLUMN event_type Enum8('CLICK'=0, 'INPUT'=1, 'LOCATION'=2,'REQUEST'=3,'PERFORMANCE'=4,'ERROR'=5,'CUSTOM'=6, 'GRAPHQL'=7, 'STATEACTION'=8, 'ISSUE'=9); + + +CREATE TABLE IF NOT EXISTS experimental.issues +( + project_id UInt16, + issue_id String, + type Enum8('click_rage'=1,'dead_click'=2,'excessive_scrolling'=3,'bad_request'=4,'missing_resource'=5,'memory'=6,'cpu'=7,'slow_resource'=8,'slow_page_load'=9,'crash'=10,'ml_cpu'=11,'ml_memory'=12,'ml_dead_click'=13,'ml_click_rage'=14,'ml_mouse_thrashing'=15,'ml_excessive_scrolling'=16,'ml_slow_resources'=17,'custom'=18,'js_exception'=19), + context_string String, + context_keys Array(String), + context_values Array(Nullable(String)), + _timestamp DateTime DEFAULT now() +) ENGINE = ReplacingMergeTree(_timestamp) + PARTITION BY toYYYYMM(_timestamp) + ORDER BY (project_id, issue_id, type) + TTL _timestamp + INTERVAL 3 MONTH; + +CREATE MATERIALIZED VIEW IF NOT EXISTS experimental.js_errors_sessions_mv + ENGINE = ReplacingMergeTree(_timestamp) + PARTITION BY toYYYYMM(datetime) + ORDER BY (project_id, datetime, event_type, error_id, session_id) + TTL _timestamp + INTERVAL 35 DAY + POPULATE +AS +SELECT session_id, + project_id, + events.datetime AS datetime, + event_type, + assumeNotNull(error_id) AS error_id, + source, + name, + message, + error_tags_keys, + error_tags_values, + message_id, + user_browser, + user_browser_version, + user_os, + user_os_version, + user_device_type, + user_device, + user_country, + _timestamp +FROM experimental.events + INNER JOIN experimental.sessions USING (session_id) +WHERE event_type = 'ERROR' + AND source = 'js_exception'; + +-- TODO: find a way to update materialized views; or drop and re-create them diff --git a/ee/scripts/helm/db/init_dbs/clickhouse/create/init_schema.sql b/ee/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql similarity index 86% rename from ee/scripts/helm/db/init_dbs/clickhouse/create/init_schema.sql rename to ee/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql index 01f3a9968..b172c0080 100644 --- a/ee/scripts/helm/db/init_dbs/clickhouse/create/init_schema.sql +++ b/ee/scripts/schema/db/init_dbs/clickhouse/create/init_schema.sql @@ -15,7 +15,7 @@ CREATE TABLE IF NOT EXISTS experimental.events ( session_id UInt64, project_id UInt16, - event_type Enum8('CLICK'=0, 'INPUT'=1, 'LOCATION'=2,'REQUEST'=3,'PERFORMANCE'=4,'ERROR'=5,'CUSTOM'=6, 'GRAPHQL'=7, 'STATEACTION'=8), + event_type Enum8('CLICK'=0, 'INPUT'=1, 'LOCATION'=2,'REQUEST'=3,'PERFORMANCE'=4,'ERROR'=5,'CUSTOM'=6, 'GRAPHQL'=7, 'STATEACTION'=8, 'ISSUE'=9), datetime DateTime, label Nullable(String), hesitation_time Nullable(UInt32), @@ -78,6 +78,10 @@ CREATE TABLE IF NOT EXISTS experimental.events success Nullable(UInt8), request_body Nullable(String), response_body Nullable(String), + issue_type Nullable(Enum8('click_rage'=1,'dead_click'=2,'excessive_scrolling'=3,'bad_request'=4,'missing_resource'=5,'memory'=6,'cpu'=7,'slow_resource'=8,'slow_page_load'=9,'crash'=10,'ml_cpu'=11,'ml_memory'=12,'ml_dead_click'=13,'ml_click_rage'=14,'ml_mouse_thrashing'=15,'ml_excessive_scrolling'=16,'ml_slow_resources'=17,'custom'=18,'js_exception'=19)), + issue_id Nullable(String), + error_tags_keys Array(String), + error_tags_values Array(Nullable(String)), message_id UInt64 DEFAULT 0, _timestamp DateTime DEFAULT now() ) ENGINE = ReplacingMergeTree(_timestamp) @@ -192,6 +196,20 @@ CREATE TABLE IF NOT EXISTS experimental.user_viewed_errors ORDER BY (project_id, user_id, error_id) TTL _timestamp + INTERVAL 3 MONTH; +CREATE TABLE IF NOT EXISTS experimental.issues +( + project_id UInt16, + issue_id String, + type Enum8('click_rage'=1,'dead_click'=2,'excessive_scrolling'=3,'bad_request'=4,'missing_resource'=5,'memory'=6,'cpu'=7,'slow_resource'=8,'slow_page_load'=9,'crash'=10,'ml_cpu'=11,'ml_memory'=12,'ml_dead_click'=13,'ml_click_rage'=14,'ml_mouse_thrashing'=15,'ml_excessive_scrolling'=16,'ml_slow_resources'=17,'custom'=18,'js_exception'=19), + context_string String, + context_keys Array(String), + context_values Array(Nullable(String)), + _timestamp DateTime DEFAULT now() +) ENGINE = ReplacingMergeTree(_timestamp) + PARTITION BY toYYYYMM(_timestamp) + ORDER BY (project_id, issue_id, type) + TTL _timestamp + INTERVAL 3 MONTH; + CREATE MATERIALIZED VIEW IF NOT EXISTS experimental.events_l7d_mv ENGINE = ReplacingMergeTree(_timestamp) PARTITION BY toYYYYMM(datetime) @@ -256,6 +274,10 @@ SELECT session_id, success, request_body, response_body, + issue_type, + issue_id, + error_tags_keys, + error_tags_values, message_id, _timestamp FROM experimental.events @@ -338,4 +360,36 @@ SELECT session_id, FROM experimental.sessions WHERE datetime >= now() - INTERVAL 7 DAY AND isNotNull(duration) - AND duration > 0; \ No newline at end of file + AND duration > 0; + +CREATE MATERIALIZED VIEW IF NOT EXISTS experimental.js_errors_sessions_mv + ENGINE = ReplacingMergeTree(_timestamp) + PARTITION BY toYYYYMM(datetime) + ORDER BY (project_id, datetime, event_type, error_id, session_id) + TTL _timestamp + INTERVAL 35 DAY + POPULATE +AS +SELECT session_id, + project_id, + events.datetime AS datetime, + event_type, + assumeNotNull(error_id) AS error_id, + source, + name, + message, + error_tags_keys, + error_tags_values, + message_id, + user_id, + user_browser, + user_browser_version, + user_os, + user_os_version, + user_device_type, + user_device, + user_country, + _timestamp +FROM experimental.events + INNER JOIN experimental.sessions USING (session_id) +WHERE event_type = 'ERROR' + AND source = 'js_exception'; \ No newline at end of file diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.2.0/1.2.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.2.0/1.2.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.2.0/1.2.0.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.2.0/1.2.0.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.3.0/1.3.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.3.0/1.3.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.3.0/1.3.0.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.3.0/1.3.0.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.3.5/1.3.5.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.3.5/1.3.5.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.3.5/1.3.5.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.3.5/1.3.5.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.3.6/1.3.6.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.3.6/1.3.6.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.3.6/1.3.6.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.3.6/1.3.6.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.4.0/1.4.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.4.0/1.4.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.4.0/1.4.0.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.4.0/1.4.0.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.5.0/1.5.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.5.0/1.5.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.5.0/1.5.0.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.5.0/1.5.0.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.5.1/1.5.1.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.5.1/1.5.1.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.5.1/1.5.1.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.5.1/1.5.1.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.5.2/1.5.2.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.5.2/1.5.2.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.5.2/1.5.2.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.5.2/1.5.2.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.5.3/1.5.3.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.5.3/1.5.3.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.5.4/1.5.4.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.5.4/1.5.4.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.5.4/1.5.4.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.5.4/1.5.4.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.6.0/1.6.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.6.0/1.6.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.6.0/1.6.0.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.6.0/1.6.0.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.7.0/1.7.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.7.0/1.7.0.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.8.0/1.8.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.8.0/1.8.0.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.8.0/1.8.0.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.8.0/1.8.0.sql diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.8.1/1.8.1.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.8.1/1.8.1.sql similarity index 100% rename from ee/scripts/helm/db/init_dbs/postgresql/1.8.1/1.8.1.sql rename to ee/scripts/schema/db/init_dbs/postgresql/1.8.1/1.8.1.sql diff --git a/ee/scripts/schema/db/init_dbs/postgresql/1.9.0/1.9.0.sql b/ee/scripts/schema/db/init_dbs/postgresql/1.9.0/1.9.0.sql new file mode 100644 index 000000000..05878ddba --- /dev/null +++ b/ee/scripts/schema/db/init_dbs/postgresql/1.9.0/1.9.0.sql @@ -0,0 +1,82 @@ +BEGIN; +CREATE OR REPLACE FUNCTION openreplay_version() + RETURNS text AS +$$ +SELECT 'v1.9.0-ee' +$$ LANGUAGE sql IMMUTABLE; + +ALTER TABLE IF EXISTS public.tenants + ADD COLUMN IF NOT EXISTS last_telemetry bigint NOT NULL DEFAULT CAST(EXTRACT(epoch FROM date_trunc('day', now())) * 1000 AS BIGINT), + DROP COLUMN IF EXISTS version_number; + +CREATE TABLE IF NOT EXISTS sessions_notes +( + note_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, + message text NOT NULL, + created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), + user_id integer NULL REFERENCES users (user_id) ON DELETE SET NULL, + deleted_at timestamp without time zone NULL DEFAULT NULL, + tag text NULL, + session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, + project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, + timestamp integer NOT NULL DEFAULT -1, + is_public boolean NOT NULL DEFAULT FALSE +); + +CREATE TABLE IF NOT EXISTS errors_tags +( + key text NOT NULL, + value text NOT NULL, + created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), + error_id text NOT NULL REFERENCES errors (error_id) ON DELETE CASCADE, + session_id bigint NOT NULL, + message_id bigint NOT NULL, + FOREIGN KEY (session_id, message_id) REFERENCES events.errors (session_id, message_id) ON DELETE CASCADE +); + +CREATE INDEX IF NOT EXISTS errors_tags_error_id_idx ON errors_tags (error_id); +CREATE INDEX IF NOT EXISTS errors_tags_session_id_idx ON errors_tags (session_id); +CREATE INDEX IF NOT EXISTS errors_tags_message_id_idx ON errors_tags (message_id); + +UPDATE metrics +SET default_config=default_config || '{"col":4}' +WHERE metric_type = 'funnel'; + +UPDATE dashboard_widgets +SET config=config || '{"col":4}' +WHERE metric_id IN (SELECT metric_id FROM metrics WHERE metric_type = 'funnel'); + +CREATE OR REPLACE FUNCTION notify_integration() RETURNS trigger AS +$$ +BEGIN + IF NEW IS NULL THEN + PERFORM pg_notify('integration', + jsonb_build_object('project_id', OLD.project_id, 'provider', OLD.provider, 'options', + null)::text); + ELSIF (OLD IS NULL) OR (OLD.options <> NEW.options) THEN + PERFORM pg_notify('integration', row_to_json(NEW)::text); + END IF; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +ALTER TABLE IF EXISTS sessions + ADD COLUMN IF NOT EXISTS file_key BYTEA DEFAULT NULL; + +UPDATE users +SET role_id=NULL +WHERE deleted_at IS NOT NULL; + +UPDATE roles +SET permissions=array_remove(permissions, 'ERRORS'); + +DROP INDEX IF EXISTS events_common.requests_url_idx; +DROP INDEX IF EXISTS events_common.requests_url_gin_idx; +DROP INDEX IF EXISTS events_common.requests_url_gin_idx2; + +DROP INDEX IF EXISTS events.resources_url_gin_idx; +DROP INDEX IF EXISTS events.resources_url_idx; + +COMMIT; + +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_session_id_status_code_nn_idx ON events_common.requests (session_id, status_code) WHERE status_code IS NOT NULL; \ No newline at end of file diff --git a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/ee/scripts/schema/db/init_dbs/postgresql/init_schema.sql similarity index 96% rename from ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql rename to ee/scripts/schema/db/init_dbs/postgresql/init_schema.sql index 723b8eb09..e864f3664 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/ee/scripts/schema/db/init_dbs/postgresql/init_schema.sql @@ -7,7 +7,7 @@ CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE OR REPLACE FUNCTION openreplay_version() RETURNS text AS $$ -SELECT 'v1.8.1-ee' +SELECT 'v1.9.0-ee' $$ LANGUAGE sql IMMUTABLE; @@ -61,7 +61,8 @@ $$ BEGIN IF NEW IS NULL THEN PERFORM pg_notify('integration', - (row_to_json(OLD)::text || '{"options": null, "request_data": null}'::text)); + jsonb_build_object('project_id', OLD.project_id, 'provider', OLD.provider, 'options', + null)::text); ELSIF (OLD IS NULL) OR (OLD.options <> NEW.options) THEN PERFORM pg_notify('integration', row_to_json(NEW)::text); END IF; @@ -129,7 +130,8 @@ $$ ('user_viewed_errors'), ('user_viewed_sessions'), ('users'), - ('webhooks')) + ('webhooks'), + ('sessions_notes')) select bool_and(exists(select * from information_schema.tables t where table_schema = 'public' @@ -147,13 +149,13 @@ $$ api_key text UNIQUE default generate_api_key(20) not null, created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'), deleted_at timestamp without time zone NULL DEFAULT NULL, - version_number text NOT NULL, license text NULL, opt_out bool NOT NULL DEFAULT FALSE, t_projects integer NOT NULL DEFAULT 1, t_sessions bigint NOT NULL DEFAULT 0, t_users integer NOT NULL DEFAULT 1, - t_integrations integer NOT NULL DEFAULT 0 + t_integrations integer NOT NULL DEFAULT 0, + last_telemetry bigint NOT NULL DEFAULT CAST(EXTRACT(epoch FROM date_trunc('day', now())) * 1000 AS BIGINT) ); @@ -223,7 +225,7 @@ $$ provider_user_id text NOT NULL, token text NOT NULL ); - CREATE UNIQUE INDEX IF NOT EXISTS oauth_authentication_unique_user_id_provider_idx ON oauth_authentication(user_id,provider); + CREATE UNIQUE INDEX IF NOT EXISTS oauth_authentication_unique_user_id_provider_idx ON oauth_authentication (user_id, provider); CREATE TABLE IF NOT EXISTS projects ( @@ -543,11 +545,12 @@ $$ watchdogs_score bigint NOT NULL DEFAULT 0, issue_score bigint NOT NULL DEFAULT 0, issue_types issue_type[] NOT NULL DEFAULT '{}'::issue_type[], - utm_source text NULL DEFAULT NULL, - utm_medium text NULL DEFAULT NULL, - utm_campaign text NULL DEFAULT NULL, - referrer text NULL DEFAULT NULL, - base_referrer text NULL DEFAULT NULL, + utm_source text DEFAULT NULL, + utm_medium text DEFAULT NULL, + utm_campaign text DEFAULT NULL, + referrer text DEFAULT NULL, + base_referrer text DEFAULT NULL, + file_key bytea DEFAULT NULL, metadata_1 text DEFAULT NULL, metadata_2 text DEFAULT NULL, metadata_3 text DEFAULT NULL, @@ -856,6 +859,20 @@ $$ FOR EACH ROW EXECUTE PROCEDURE notify_alert(); + CREATE TABLE IF NOT EXISTS sessions_notes + ( + note_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, + message text NOT NULL, + created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), + user_id integer NULL REFERENCES users (user_id) ON DELETE SET NULL, + deleted_at timestamp without time zone NULL DEFAULT NULL, + tag text NULL, + session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, + project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, + timestamp integer NOT NULL DEFAULT -1, + is_public boolean NOT NULL DEFAULT FALSE + ); + RAISE NOTICE 'Created missing public schema tables'; END IF; END; @@ -1002,6 +1019,21 @@ $$ CREATE INDEX IF NOT EXISTS errors_error_id_timestamp_session_id_idx ON events.errors (error_id, timestamp, session_id); CREATE INDEX IF NOT EXISTS errors_error_id_idx ON events.errors (error_id); + CREATE TABLE IF NOT EXISTS errors_tags + ( + key text NOT NULL, + value text NOT NULL, + created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), + error_id text NOT NULL REFERENCES errors (error_id) ON DELETE CASCADE, + session_id bigint NOT NULL, + message_id bigint NOT NULL, + FOREIGN KEY (session_id, message_id) REFERENCES events.errors (session_id, message_id) ON DELETE CASCADE + ); + + CREATE INDEX IF NOT EXISTS errors_tags_error_id_idx ON errors_tags (error_id); + CREATE INDEX IF NOT EXISTS errors_tags_session_id_idx ON errors_tags (session_id); + CREATE INDEX IF NOT EXISTS errors_tags_message_id_idx ON errors_tags (message_id); + IF NOT EXISTS(SELECT * FROM pg_type typ WHERE typ.typname = 'http_method') THEN @@ -1189,23 +1221,14 @@ $$ query text NULL, PRIMARY KEY (session_id, timestamp, seq_index) ); - CREATE INDEX IF NOT EXISTS requests_url_idx ON events_common.requests (url); + CREATE INDEX IF NOT EXISTS requests_duration_idx ON events_common.requests (duration); - CREATE INDEX IF NOT EXISTS requests_url_gin_idx ON events_common.requests USING GIN (url gin_trgm_ops); CREATE INDEX IF NOT EXISTS requests_timestamp_idx ON events_common.requests (timestamp); - CREATE INDEX IF NOT EXISTS requests_url_gin_idx2 ON events_common.requests USING GIN (RIGHT(url, - length(url) - - (CASE - WHEN url LIKE 'http://%' - THEN 7 - WHEN url LIKE 'https://%' - THEN 8 - ELSE 0 END)) - gin_trgm_ops); CREATE INDEX IF NOT EXISTS requests_timestamp_session_id_failed_idx ON events_common.requests (timestamp, session_id) WHERE success = FALSE; CREATE INDEX IF NOT EXISTS requests_request_body_nn_gin_idx ON events_common.requests USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; CREATE INDEX IF NOT EXISTS requests_response_body_nn_gin_idx ON events_common.requests USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; CREATE INDEX IF NOT EXISTS requests_status_code_nn_idx ON events_common.requests (status_code) WHERE status_code IS NOT NULL; + CREATE INDEX IF NOT EXISTS requests_session_id_status_code_nn_idx ON events_common.requests (session_id, status_code) WHERE status_code IS NOT NULL; CREATE INDEX IF NOT EXISTS requests_host_nn_idx ON events_common.requests (host) WHERE host IS NOT NULL; CREATE INDEX IF NOT EXISTS requests_host_nn_gin_idx ON events_common.requests USING GIN (host gin_trgm_ops) WHERE host IS NOT NULL; CREATE INDEX IF NOT EXISTS requests_path_nn_idx ON events_common.requests (path) WHERE path IS NOT NULL; diff --git a/ee/api/auth/__init__.py b/ee/sourcemap-reader/Readme.md similarity index 100% rename from ee/api/auth/__init__.py rename to ee/sourcemap-reader/Readme.md diff --git a/ee/utilities/.gitignore b/ee/utilities/.gitignore index a11e6be97..8c9dca279 100644 --- a/ee/utilities/.gitignore +++ b/ee/utilities/.gitignore @@ -15,3 +15,5 @@ servers/sourcemaps-server.js /utils/helper.js /utils/assistHelper.js .local +run-dev.sh +*.mmdb diff --git a/ee/utilities/Dockerfile b/ee/utilities/Dockerfile index e3d5d4a0a..08ccba56f 100644 --- a/ee/utilities/Dockerfile +++ b/ee/utilities/Dockerfile @@ -5,6 +5,7 @@ RUN apk add --no-cache tini git libc6-compat && ln -s /lib/libc.musl-x86_64.so.1 ARG envarg ENV ENTERPRISE_BUILD=${envarg} \ MAXMINDDB_FILE=/home/openreplay/geoip.mmdb \ + PRIVATE_ENDPOINTS=false \ LISTEN_PORT=9001 WORKDIR /work COPY package.json . diff --git a/ee/utilities/package-lock.json b/ee/utilities/package-lock.json index 1c14c5f25..ace7a2109 100644 --- a/ee/utilities/package-lock.json +++ b/ee/utilities/package-lock.json @@ -12,6 +12,7 @@ "@maxmind/geoip2-node": "^3.4.0", "@socket.io/redis-adapter": "^7.2.0", "express": "^4.18.1", + "jsonwebtoken": "^8.5.1", "redis": "^4.2.0", "socket.io": "^4.5.1", "ua-parser-js": "^1.0.2", @@ -185,6 +186,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -328,6 +334,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -599,6 +613,27 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, "node_modules/jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -613,6 +648,60 @@ "verror": "1.10.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -856,6 +945,14 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -1241,6 +1338,11 @@ } } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1336,6 +1438,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1559,6 +1669,23 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + } + }, "jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -1570,6 +1697,60 @@ "verror": "1.10.0" } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -1731,6 +1912,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, "send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", diff --git a/ee/utilities/package.json b/ee/utilities/package.json index ba3997a90..5dfd325af 100644 --- a/ee/utilities/package.json +++ b/ee/utilities/package.json @@ -21,6 +21,7 @@ "@maxmind/geoip2-node": "^3.4.0", "@socket.io/redis-adapter": "^7.2.0", "express": "^4.18.1", + "jsonwebtoken": "^8.5.1", "redis": "^4.2.0", "socket.io": "^4.5.1", "ua-parser-js": "^1.0.2", diff --git a/ee/utilities/server.js b/ee/utilities/server.js index 48799e279..482ddcd17 100644 --- a/ee/utilities/server.js +++ b/ee/utilities/server.js @@ -31,6 +31,14 @@ if (process.env.uws !== "true") { ); heapdump && wsapp.use(`${PREFIX}/${P_KEY}/heapdump`, dumps.router); wsapp.use(`${PREFIX}/${P_KEY}`, socket.wsRouter); + wsapp.get('/private/shutdown', (req, res) => { + console.log("Requested shutdown"); + res.statusCode = 200; + res.end("ok!"); + process.kill(1, "SIGTERM"); + } + ); + wsapp.enable('trust proxy'); const wsserver = wsapp.listen(PORT, HOST, () => { console.log(`WS App listening on http://${HOST}:${PORT}`); @@ -94,6 +102,12 @@ if (process.env.uws !== "true") { uapp.post(`${PREFIX}/${P_KEY}/sockets-live/:projectKey`, uWrapper(socket.handlers.socketsLiveByProject)); uapp.get(`${PREFIX}/${P_KEY}/sockets-live/:projectKey/:sessionId`, uWrapper(socket.handlers.socketsLiveByProject)); + uapp.get('/private/shutdown', (res, req) => { + console.log("Requested shutdown"); + res.writeStatus('200 OK').end("ok!"); + process.kill(1, "SIGTERM"); + } + ); socket.start(uapp); diff --git a/ee/utilities/servers/websocket-cluster.js b/ee/utilities/servers/websocket-cluster.js index ab3d3ea59..6aa2bade5 100644 --- a/ee/utilities/servers/websocket-cluster.js +++ b/ee/utilities/servers/websocket-cluster.js @@ -13,7 +13,8 @@ const { EVENTS_DEFINITION, extractSessionInfo, socketConnexionTimeout, - errorHandler + errorHandler, + authorizer } = require('../utils/assistHelper'); const { extractProjectKeyFromRequest, @@ -282,6 +283,7 @@ module.exports = { wsRouter, start: (server, prefix) => { createSocketIOServer(server, prefix); + io.use(async (socket, next) => await authorizer.check(socket, next)); io.on('connection', async (socket) => { socket.on(EVENTS_DEFINITION.listen.ERROR, err => errorHandler(EVENTS_DEFINITION.listen.ERROR, err)); debug && console.log(`WS started:${socket.id}, Query:${JSON.stringify(socket.handshake.query)}`); diff --git a/ee/utilities/servers/websocket.js b/ee/utilities/servers/websocket.js index 259838fb1..bf65789f2 100644 --- a/ee/utilities/servers/websocket.js +++ b/ee/utilities/servers/websocket.js @@ -13,7 +13,8 @@ const { EVENTS_DEFINITION, extractSessionInfo, socketConnexionTimeout, - errorHandler + errorHandler, + authorizer } = require('../utils/assistHelper'); const { extractProjectKeyFromRequest, @@ -260,6 +261,7 @@ module.exports = { wsRouter, start: (server, prefix) => { createSocketIOServer(server, prefix); + io.use(async (socket, next) => await authorizer.check(socket, next)); io.on('connection', async (socket) => { socket.on(EVENTS_DEFINITION.listen.ERROR, err => errorHandler(EVENTS_DEFINITION.listen.ERROR, err)); debug && console.log(`WS started:${socket.id}, Query:${JSON.stringify(socket.handshake.query)}`); diff --git a/frontend/.env.sample b/frontend/.env.sample index 3c8da9433..33c67be52 100644 --- a/frontend/.env.sample +++ b/frontend/.env.sample @@ -22,5 +22,5 @@ MINIO_ACCESS_KEY = '' MINIO_SECRET_KEY = '' # APP and TRACKER VERSIONS -VERSION = '1.8.1' -TRACKER_VERSION = '4.1.0' +VERSION = '1.9.0' +TRACKER_VERSION = '4.1.7' diff --git a/frontend/README.md b/frontend/README.md index e2b4a3898..3eb54ede6 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,7 +1,7 @@ # openreplay-ui OpenReplay prototype UI -On new icon addition: +On new icon addition: `yarn gen:icons` ## Documentation @@ -14,3 +14,7 @@ On new icon addition: Labels in comments: TEMP = temporary code TODO = things to implement + +## Contributing notes + +Please use `dev` branch as base and target branch. diff --git a/frontend/app/Router.js b/frontend/app/Router.js index 4d6c9f941..6a4aea446 100644 --- a/frontend/app/Router.js +++ b/frontend/app/Router.js @@ -20,7 +20,7 @@ import Signup from './components/Signup/Signup'; import { fetchTenants } from 'Duck/user'; import { setSessionPath } from 'Duck/sessions'; import { ModalProvider } from './components/Modal'; -import { GLOBAL_DESTINATION_PATH } from 'App/constants/storageKeys'; +import { GLOBAL_DESTINATION_PATH, GLOBAL_HAS_NO_RECORDINGS } from 'App/constants/storageKeys'; import SupportCallout from 'Shared/SupportCallout'; const Login = lazy(() => import('Components/Login/Login')); @@ -126,8 +126,9 @@ class Router extends React.Component { } fetchInitialData = async () => { + const siteIdFromPath = parseInt(window.location.pathname.split("/")[1]) await this.props.fetchUserInfo() - await this.props.fetchSiteList() + await this.props.fetchSiteList(siteIdFromPath) const { mstore } = this.props; mstore.initClient(); }; @@ -171,6 +172,7 @@ class Router extends React.Component { const siteIdList = sites.map(({ id }) => id).toJS(); const hideHeader = (location.pathname && location.pathname.includes('/session/')) || location.pathname.includes('/assist/'); const isPlayer = isRoute(SESSION_PATH, location.pathname) || isRoute(LIVE_SESSION_PATH, location.pathname); + const redirectToOnboarding = !onboarding && localStorage.getItem(GLOBAL_HAS_NO_RECORDINGS) === 'true' return isLoggedIn ? ( @@ -196,7 +198,7 @@ class Router extends React.Component { return ; }} /> - {onboarding && } + {redirectToOnboarding && } {/* DASHBOARD and Metrics */} diff --git a/frontend/app/api_client.js b/frontend/app/api_client.js index 33f7ffe66..0e4699359 100644 --- a/frontend/app/api_client.js +++ b/frontend/app/api_client.js @@ -26,6 +26,7 @@ const siteIdRequiredPaths = [ '/dashboards', '/metrics', '/unprocessed', + '/notes', // '/custom_metrics/sessions', ]; @@ -37,7 +38,7 @@ const noStoringFetchPathStarts = [ // null? export const clean = (obj, forbidenValues = [ undefined, '' ]) => { - const keys = Array.isArray(obj) + const keys = Array.isArray(obj) ? new Array(obj.length).fill().map((_, i) => i) : Object.keys(obj); const retObj = Array.isArray(obj) ? [] : {}; @@ -49,7 +50,7 @@ export const clean = (obj, forbidenValues = [ undefined, '' ]) => { retObj[key] = value; } }); - + return retObj; } @@ -70,7 +71,7 @@ export default class APIClient { this.siteId = siteId; } - fetch(path, params, options = { clean: true }) { + fetch(path, params, options = { clean: true }) { if (params !== undefined) { const cleanedParams = options.clean ? clean(params) : params; this.init.body = JSON.stringify(cleanedParams); diff --git a/frontend/app/api_middleware.js b/frontend/app/api_middleware.js index 783ebe8c3..1846a9dbc 100644 --- a/frontend/app/api_middleware.js +++ b/frontend/app/api_middleware.js @@ -2,27 +2,27 @@ import logger from 'App/logger'; import APIClient from './api_client'; import { UPDATE, DELETE } from './duck/jwt'; -export default store => next => (action) => { +export default (store) => (next) => (action) => { const { types, call, ...rest } = action; if (!call) { return next(action); } - const [ REQUEST, SUCCESS, FAILURE ] = types; + const [REQUEST, SUCCESS, FAILURE] = types; next({ ...rest, type: REQUEST }); const client = new APIClient(); return call(client) - .then(async response => { + .then(async (response) => { if (response.status === 403) { next({ type: DELETE }); } if (!response.ok) { - const text = await response.text() + const text = await response.text(); return Promise.reject(text); } - return response.json() + return response.json(); }) - .then(json => json || {}) // TEMP TODO on server: no empty responces + .then((json) => json || {}) // TEMP TODO on server: no empty responces .then(({ jwt, errors, data }) => { if (errors) { next({ type: FAILURE, errors, data }); @@ -34,14 +34,22 @@ export default store => next => (action) => { } }) .catch((e) => { - logger.error("Error during API request. ", e) - return next({ type: FAILURE, errors: JSON.parse(e).errors || [] }); + logger.error('Error during API request. ', e); + return next({ type: FAILURE, errors: parseError(e) }); }); }; +function parseError(e) { + try { + return JSON.parse(e).errors || []; + } catch { + return e; + } +} + function jwtExpired(token) { try { - const base64Url = token.split('.')[ 1 ]; + const base64Url = token.split('.')[1]; const base64 = base64Url.replace('-', '+').replace('_', '/'); const tokenObj = JSON.parse(window.atob(base64)); return tokenObj.exp * 1000 < Date.now(); // exp in Unix time (sec) diff --git a/frontend/app/assets/img/report-head.png b/frontend/app/assets/img/report-head.png new file mode 100644 index 000000000..2164cadba Binary files /dev/null and b/frontend/app/assets/img/report-head.png differ diff --git a/frontend/app/components/Alerts/Notifications/Notifications.tsx b/frontend/app/components/Alerts/Notifications/Notifications.tsx index d6327d530..05bcea06b 100644 --- a/frontend/app/components/Alerts/Notifications/Notifications.tsx +++ b/frontend/app/components/Alerts/Notifications/Notifications.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from 'react'; import stl from './notifications.module.css'; import { connect } from 'react-redux'; -import { Icon, Popup } from 'UI'; +import { Icon, Tooltip } from 'UI'; import { fetchList, setViewed, clearAll } from 'Duck/notifications'; import { setLastRead } from 'Duck/announcements'; import { useModal } from 'App/components/Modal'; @@ -22,24 +22,30 @@ function Notifications(props: Props) { useEffect(() => { const interval = setInterval(() => { - notificationStore.fetchNotificationsCount() + notificationStore.fetchNotificationsCount(); }, AUTOREFRESH_INTERVAL); return () => clearInterval(interval); }, []); return useObserver(() => ( - -
showModal(, { right: true }) }> -
- { count } -
- + +
showModal(, { right: true })} + > +
+ {count}
- + +
+
)); } -export default connect((state: any) => ({ - notifications: state.getIn(['notifications', 'list']), -}), { fetchList, setLastRead, setViewed, clearAll })(Notifications); \ No newline at end of file +export default connect( + (state: any) => ({ + notifications: state.getIn(['notifications', 'list']), + }), + { fetchList, setLastRead, setViewed, clearAll } +)(Notifications); diff --git a/frontend/app/components/Alerts/Notifications/notifications.module.css b/frontend/app/components/Alerts/Notifications/notifications.module.css index 3e4101502..f88767b36 100644 --- a/frontend/app/components/Alerts/Notifications/notifications.module.css +++ b/frontend/app/components/Alerts/Notifications/notifications.module.css @@ -9,16 +9,16 @@ display: flex; align-items: center; padding: 0 15px; - height: 50px; + height: 49px; transition: all 0.3s; &:hover { - background-color: $gray-lightest; + background-color: $active-blue; transition: all 0.2s; } &[data-active=true] { - background-color: $gray-lightest; + background-color: $active-blue; } } diff --git a/frontend/app/components/Announcements/Announcements.js b/frontend/app/components/Announcements/Announcements.js index b17e44982..55306e643 100644 --- a/frontend/app/components/Announcements/Announcements.js +++ b/frontend/app/components/Announcements/Announcements.js @@ -2,7 +2,7 @@ import React from 'react'; import stl from './announcements.module.css'; import ListItem from './ListItem'; import { connect } from 'react-redux'; -import { SlideModal, Icon, NoContent, Popup } from 'UI'; +import { SlideModal, Icon, NoContent, Tooltip } from 'UI'; import { fetchList, setLastRead } from 'Duck/announcements'; import withToggle from 'Components/hocs/withToggle'; import { withRouter } from 'react-router-dom'; @@ -45,14 +45,14 @@ class Announcements extends React.Component { return (
- +
{ unReadNotificationsCount }
-
+ { if (!stream) { return; } stream.toggleVideo() - .then(setVideoEnabled) + .then((v) => setVideoEnabled(v)) } /** muting user if he is auto connected to the call */ diff --git a/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx b/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx index c070c3b50..167db8281 100644 --- a/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx +++ b/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx @@ -1,27 +1,35 @@ -import React, { useState, useEffect } from 'react' -import VideoContainer from '../components/VideoContainer' -import cn from 'classnames' -import Counter from 'App/components/shared/SessionItem/Counter' -import stl from './chatWindow.module.css' -import ChatControls from '../ChatControls/ChatControls' +import React, { useState, useEffect } from 'react'; +import VideoContainer from '../components/VideoContainer'; +import cn from 'classnames'; +import Counter from 'App/components/shared/SessionItem/Counter'; +import stl from './chatWindow.module.css'; +import ChatControls from '../ChatControls/ChatControls'; import Draggable from 'react-draggable'; -import type { LocalStream } from 'Player/MessageDistributor/managers/LocalStream'; +import type { LocalStream } from 'Player'; +import { toggleVideoLocalStream } from 'Player' export interface Props { - incomeStream: MediaStream[] | null, - localStream: LocalStream | null, - userId: string, + incomeStream: MediaStream[] | null; + localStream: LocalStream | null; + userId: string; isPrestart?: boolean; - endCall: () => void + endCall: () => void; } function ChatWindow({ userId, incomeStream, localStream, endCall, isPrestart }: Props) { - const [localVideoEnabled, setLocalVideoEnabled] = useState(false) + const [localVideoEnabled, setLocalVideoEnabled] = useState(false); + const [anyRemoteEnabled, setRemoteEnabled] = useState(false); + + const onlyLocalEnabled = localVideoEnabled && !anyRemoteEnabled; + + useEffect(() => { + toggleVideoLocalStream(localVideoEnabled) + }, [localVideoEnabled]) return ( - +
@@ -30,21 +38,39 @@ function ChatWindow({ userId, incomeStream, localStream, endCall, isPrestart }:
{incomeStream && incomeStream.length > 2 ? ' (+ other agents in the call)' : ''}
- +
-
- {incomeStream - ? incomeStream.map(stream => ) : ( +
+ {incomeStream ? ( + incomeStream.map((stream) => ( + + + + )) + ) : (
Error obtaining incoming streams
)} -
- +
+
- +
- ) + ); } -export default ChatWindow +export default ChatWindow; diff --git a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx index 85c2f6ad3..e377cd3ba 100644 --- a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx +++ b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx @@ -1,9 +1,9 @@ import React, { useState, useEffect } from 'react'; -import { Popup, Button } from 'UI'; +import { Button, Tooltip } from 'UI'; import { connect } from 'react-redux'; import cn from 'classnames'; import { toggleChatWindow } from 'Duck/sessions'; -import { connectPlayer } from 'Player/store'; +import { connectPlayer } from 'Player'; import ChatWindow from '../../ChatWindow'; import { callPeer, @@ -16,10 +16,9 @@ import { CallingState, ConnectionStatus, RemoteControlStatus, -} from 'Player/MessageDistributor/managers/AssistManager'; -import RequestLocalStream from 'Player/MessageDistributor/managers/LocalStream'; -import type { LocalStream } from 'Player/MessageDistributor/managers/LocalStream'; -import { Tooltip } from 'react-tippy'; + RequestLocalStream, +} from 'Player'; +import type { LocalStream } from 'Player'; import { toast } from 'react-toastify'; import { confirm } from 'UI'; import stl from './AassistActions.module.css'; @@ -95,7 +94,10 @@ function AssistActions({ if (remoteActive) { toggleUserName(userDisplayName); } else { - toggleUserName(); + // higher than waiting for messages + if (peerConnectionStatus > 1) { + toggleUserName(); + } } }, [remoteActive]); @@ -193,8 +195,8 @@ function AssistActions({
-
- +
{onCall && callObject && ( diff --git a/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx b/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx index bff02fb0c..97b8c9f9e 100644 --- a/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx +++ b/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx @@ -1,12 +1,13 @@ -import React, { useEffect, useRef } from 'react' +import React, { useEffect, useRef } from 'react'; interface Props { - stream: MediaStream | null - muted?: boolean, - height?: number + stream: MediaStream | null; + muted?: boolean; + height?: number | string; + setRemoteEnabled?: (isEnabled: boolean) => void; } -function VideoContainer({ stream, muted = false, height = 280 }: Props) { +function VideoContainer({ stream, muted = false, height = 280, setRemoteEnabled }: Props) { const ref = useRef(null); const [isEnabled, setEnabled] = React.useState(false); @@ -14,24 +15,43 @@ function VideoContainer({ stream, muted = false, height = 280 }: Props) { if (ref.current) { ref.current.srcObject = stream; } - }, [ ref.current, stream, stream.getVideoTracks()[0]?.getSettings().width ]) + }, [ref.current, stream, stream.getVideoTracks()[0]?.getSettings().width]); useEffect(() => { - if (!stream) { return } + if (!stream) { + return; + } const iid = setInterval(() => { - const settings = stream.getVideoTracks()[0]?.getSettings() - const isDummyVideoTrack = settings ? (settings.width === 2 || settings.frameRate === 0 || !settings.frameRate && !settings.width) : true - const shouldBeEnabled = !isDummyVideoTrack - isEnabled !== shouldBeEnabled ? setEnabled(shouldBeEnabled) : null; - }, 500) - return () => clearInterval(iid) - }, [ stream, isEnabled ]) + const track = stream.getVideoTracks()[0] + const settings = track?.getSettings(); + const isDummyVideoTrack = settings + ? settings.width === 2 || + settings.frameRate === 0 || + (!settings.frameRate && !settings.width) + : true; + const shouldBeEnabled = track.enabled && !isDummyVideoTrack; + + if (isEnabled !== shouldBeEnabled) { + setEnabled(shouldBeEnabled); + setRemoteEnabled?.(shouldBeEnabled); + } + }, 500); + return () => clearInterval(iid); + }, [stream, isEnabled]); return ( -
-
showModal(, { right: true })}> - Configure the percentage of sessions
to be captured, timezone and more.
} + Configure the percentage of sessions
to be captured, timezone and more.} > Settings - +
diff --git a/frontend/app/components/Client/Client.js b/frontend/app/components/Client/Client.js index 97d8e5aab..b2a6d8f7f 100644 --- a/frontend/app/components/Client/Client.js +++ b/frontend/app/components/Client/Client.js @@ -52,7 +52,7 @@ export default class Client extends React.PureComponent {
-
+
{ activeTab && this.renderActiveTab() }
diff --git a/frontend/app/components/Client/CustomFields/CustomFields.js b/frontend/app/components/Client/CustomFields/CustomFields.js index 0964ff7b8..5f2645fc8 100644 --- a/frontend/app/components/Client/CustomFields/CustomFields.js +++ b/frontend/app/components/Client/CustomFields/CustomFields.js @@ -71,7 +71,7 @@ function CustomFields(props) {
- +
diff --git a/frontend/app/components/Client/Integrations/IntegrationItem.tsx b/frontend/app/components/Client/Integrations/IntegrationItem.tsx index ec730e7c1..d04ac3b7e 100644 --- a/frontend/app/components/Client/Integrations/IntegrationItem.tsx +++ b/frontend/app/components/Client/Integrations/IntegrationItem.tsx @@ -1,6 +1,6 @@ import React from 'react'; import cn from 'classnames'; -import { Icon, Popup } from 'UI'; +import { Icon, Tooltip } from 'UI'; import stl from './integrationItem.module.css'; import { connect } from 'react-redux'; @@ -17,9 +17,9 @@ const IntegrationItem = (props: Props) => {
props.onClick(e)}> {integrated && (
- + - +
)} {integration.icon.length ? integration : ( @@ -33,9 +33,4 @@ const IntegrationItem = (props: Props) => { ); }; -export default connect((state: any, props: Props) => { - const list = state.getIn([props.integration.slug, 'list']) || []; - return { - // integrated: props.integration.slug === 'issues' ? !!(list.first() && list.first().token) : list.size > 0, - }; -})(IntegrationItem); +export default IntegrationItem; diff --git a/frontend/app/components/Client/Integrations/Integrations.js_ b/frontend/app/components/Client/Integrations/Integrations.js_ deleted file mode 100644 index b4a421980..000000000 --- a/frontend/app/components/Client/Integrations/Integrations.js_ +++ /dev/null @@ -1,633 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import withPageTitle from "HOCs/withPageTitle"; -import { Loader, IconButton, SlideModal } from "UI"; -import { fetchList as fetchListSlack } from "Duck/integrations/slack"; -import { remove as removeIntegrationConfig } from "Duck/integrations/actions"; -import { fetchList, init } from "Duck/integrations/actions"; -import cn from "classnames"; - -import IntegrationItem from "./IntegrationItem"; -import SentryForm from "./SentryForm"; -import GithubForm from "./GithubForm"; -import SlackForm from "./SlackForm"; -import DatadogForm from "./DatadogForm"; -import StackdriverForm from "./StackdriverForm"; -import RollbarForm from "./RollbarForm"; -import NewrelicForm from "./NewrelicForm"; -import BugsnagForm from "./BugsnagForm"; -import CloudwatchForm from "./CloudwatchForm"; -import ElasticsearchForm from "./ElasticsearchForm"; -import SumoLogicForm from "./SumoLogicForm"; -import JiraForm from "./JiraForm"; -import styles from "./integrations.module.css"; -import ReduxDoc from "./ReduxDoc"; -import VueDoc from "./VueDoc"; -import GraphQLDoc from "./GraphQLDoc"; -import NgRxDoc from "./NgRxDoc/NgRxDoc"; -import SlackAddForm from "./SlackAddForm"; -import FetchDoc from "./FetchDoc"; -import MobxDoc from "./MobxDoc"; -import ProfilerDoc from "./ProfilerDoc"; -import AssistDoc from "./AssistDoc"; -import AxiosDoc from "./AxiosDoc/AxiosDoc"; - -const NONE = -1; -const SENTRY = 0; -const DATADOG = 1; -const STACKDRIVER = 2; -const ROLLBAR = 3; -const NEWRELIC = 4; -const BUGSNAG = 5; -const CLOUDWATCH = 6; -const ELASTICSEARCH = 7; -const SUMOLOGIC = 8; -const JIRA = 9; -const GITHUB = 10; -const REDUX = 11; -const VUE = 12; -const GRAPHQL = 13; -const NGRX = 14; -const SLACK = 15; -const FETCH = 16; -const MOBX = 17; -const PROFILER = 18; -const ASSIST = 19; -const AXIOS = 20; - -const TITLE = { - [SENTRY]: "Sentry", - [SLACK]: "Slack", - [DATADOG]: "Datadog", - [STACKDRIVER]: "Stackdriver", - [ROLLBAR]: "Rollbar", - [NEWRELIC]: "New Relic", - [BUGSNAG]: "Bugsnag", - [CLOUDWATCH]: "CloudWatch", - [ELASTICSEARCH]: "Elastic Search", - [SUMOLOGIC]: "Sumo Logic", - [JIRA]: "Jira", - [GITHUB]: "Github", - [REDUX]: "Redux", - [VUE]: "VueX", - [GRAPHQL]: "GraphQL", - [NGRX]: "NgRx", - [FETCH]: "Fetch", - [MOBX]: "MobX", - [PROFILER]: "Profiler", - [ASSIST]: "Assist", - [AXIOS]: "Axios", -}; - -const DOCS = [REDUX, VUE, GRAPHQL, NGRX, FETCH, MOBX, PROFILER, ASSIST]; - -const integrations = [ - "sentry", - "datadog", - "stackdriver", - "rollbar", - "newrelic", - "bugsnag", - "cloudwatch", - "elasticsearch", - "sumologic", - "issues", -]; - -@connect( - (state) => { - const props = {}; - integrations.forEach((name) => { - props[`${name}Integrated`] = - name === "issues" - ? !!( - state.getIn([name, "list"]).first() && - state.getIn([name, "list"]).first().token - ) - : state.getIn([name, "list"]).size > 0; - props.loading = - props.loading || state.getIn([name, "fetchRequest", "loading"]); - }); - const site = state.getIn(["site", "instance"]); - return { - ...props, - issues: state.getIn(["issues", "list"]).first() || {}, - slackChannelListExists: state.getIn(["slack", "list"]).size > 0, - tenantId: state.getIn(["user", "account", "tenantId"]), - jwt: state.get("jwt"), - projectKey: site ? site.projectKey : "", - }; - }, - { - fetchList, - init, - fetchListSlack, - removeIntegrationConfig, - } -) -@withPageTitle("Integrations - OpenReplay Preferences") -export default class Integrations extends React.PureComponent { - state = { - modalContent: NONE, - showDetailContent: false, - }; - - componentWillMount() { - integrations.forEach((name) => this.props.fetchList(name)); - this.props.fetchListSlack(); - } - - onClickIntegrationItem = (e, url) => { - e.preventDefault(); - window.open(url); - }; - - closeModal = () => - this.setState({ modalContent: NONE, showDetailContent: false }); - - onOauthClick = (source) => { - if (source === GITHUB) { - const githubUrl = `https://auth.openreplay.com/oauth/login?provider=github&back_url=${document.location.href}`; - const options = { - method: "GET", - credentials: "include", - headers: new Headers({ - Authorization: "Bearer " + this.props.jwt.toString(), - }), - }; - fetch(githubUrl, options).then((resp) => - resp.text().then((txt) => window.open(txt, "_self")) - ); - } - }; - - renderDetailContent() { - switch (this.state.modalContent) { - case SLACK: - return ( - - this.setState({ showDetailContent: false }) - } - /> - ); - } - } - - renderModalContent() { - const { projectKey } = this.props; - - switch (this.state.modalContent) { - case SENTRY: - return ; - case GITHUB: - return ; - case SLACK: - return ( - - this.setState({ showDetailContent: true }) - } - /> - ); - case DATADOG: - return ; - case STACKDRIVER: - return ; - case ROLLBAR: - return ; - case NEWRELIC: - return ; - case BUGSNAG: - return ; - case CLOUDWATCH: - return ; - case ELASTICSEARCH: - return ; - case SUMOLOGIC: - return ; - case JIRA: - return ; - case REDUX: - return ( - - ); - case VUE: - return ( - - ); - case GRAPHQL: - return ( - - ); - case NGRX: - return ( - - ); - case FETCH: - return ( - - ); - case MOBX: - return ( - - ); - case PROFILER: - return ( - - ); - case ASSIST: - return ( - - ); - case AXIOS: - return ( - - ); - default: - return null; - } - } - - deleteHandler = (name) => { - this.props.removeIntegrationConfig(name, null).then( - function () { - this.props.fetchList(name); - }.bind(this) - ); - }; - - showIntegrationConfig = (type) => { - this.setState({ modalContent: type }); - }; - - render() { - const { - loading, - sentryIntegrated, - stackdriverIntegrated, - datadogIntegrated, - rollbarIntegrated, - newrelicIntegrated, - bugsnagIntegrated, - cloudwatchIntegrated, - elasticsearchIntegrated, - sumologicIntegrated, - hideHeader = false, - plugins = false, - jiraIntegrated, - issuesIntegrated, - tenantId, - slackChannelListExists, - issues, - } = this.props; - const { modalContent, showDetailContent } = this.state; - return ( -
- -
{TITLE[modalContent]}
- {modalContent === SLACK && ( - - this.setState({ - showDetailContent: true, - }) - } - /> - )} -
- } - isDisplayed={modalContent !== NONE} - onClose={this.closeModal} - size={ - DOCS.includes(this.state.modalContent) - ? "middle" - : "small" - } - content={this.renderModalContent()} - detailContent={ - showDetailContent && this.renderDetailContent() - } - /> - - {!hideHeader && ( -
-

- {"Integrations"} -

-

- Power your workflow with your favourite tools. -

-
-
- )} - - {plugins && ( -
-
- Use plugins to better debug your application's - store, monitor queries and track performance issues. -
-
- - this.showIntegrationConfig(REDUX) - } - // integrated={ sentryIntegrated } - /> - this.showIntegrationConfig(VUE)} - // integrated={ sentryIntegrated } - /> - - this.showIntegrationConfig(GRAPHQL) - } - // integrated={ sentryIntegrated } - /> - this.showIntegrationConfig(NGRX)} - // integrated={ sentryIntegrated } - /> - this.showIntegrationConfig(MOBX)} - // integrated={ sentryIntegrated } - /> - - this.showIntegrationConfig(FETCH) - } - // integrated={ sentryIntegrated } - /> - - this.showIntegrationConfig(PROFILER) - } - // integrated={ sentryIntegrated } - /> - - this.showIntegrationConfig(AXIOS) - } - // integrated={ sentryIntegrated } - /> - - this.showIntegrationConfig(ASSIST) - } - // integrated={ sentryIntegrated } - /> -
-
- )} - - {!plugins && ( - -
-
-
- How are you monitoring errors and crash - reporting? -
-
- {(!issues.token || - issues.provider !== "github") && ( - - this.showIntegrationConfig(JIRA) - } - integrated={issuesIntegrated} - /> - )} - {(!issues.token || - issues.provider !== "jira") && ( - - this.showIntegrationConfig( - GITHUB - ) - } - integrated={issuesIntegrated} - deleteHandler={ - issuesIntegrated - ? () => - this.deleteHandler( - "issues" - ) - : null - } - /> - )} - - - this.showIntegrationConfig(SLACK) - } - integrated={sentryIntegrated} - /> - - this.showIntegrationConfig(SENTRY) - } - integrated={sentryIntegrated} - /> - - - this.showIntegrationConfig(BUGSNAG) - } - integrated={bugsnagIntegrated} - /> - - - this.showIntegrationConfig(ROLLBAR) - } - integrated={rollbarIntegrated} - /> - - - this.showIntegrationConfig( - ELASTICSEARCH - ) - } - integrated={elasticsearchIntegrated} - /> - - - this.showIntegrationConfig(DATADOG) - } - integrated={datadogIntegrated} - /> - - this.showIntegrationConfig( - SUMOLOGIC - ) - } - integrated={sumologicIntegrated} - /> - - this.showIntegrationConfig( - STACKDRIVER - ) - } - integrated={stackdriverIntegrated} - /> - - - this.showIntegrationConfig( - CLOUDWATCH - ) - } - integrated={cloudwatchIntegrated} - /> - - - this.showIntegrationConfig(NEWRELIC) - } - integrated={newrelicIntegrated} - /> -
-
-
-
- )} -
- ); - } -} diff --git a/frontend/app/components/Client/Integrations/PiniaDoc/PiniaDoc.tsx b/frontend/app/components/Client/Integrations/PiniaDoc/PiniaDoc.tsx index 8a2033a2d..171aa1d50 100644 --- a/frontend/app/components/Client/Integrations/PiniaDoc/PiniaDoc.tsx +++ b/frontend/app/components/Client/Integrations/PiniaDoc/PiniaDoc.tsx @@ -87,7 +87,7 @@ piniaStorePlugin(examplePiniaStore)
diff --git a/frontend/app/components/Client/Integrations/ZustandDoc/ZustandDoc.js b/frontend/app/components/Client/Integrations/ZustandDoc/ZustandDoc.js index 35ff5ecdf..5944e3836 100644 --- a/frontend/app/components/Client/Integrations/ZustandDoc/ZustandDoc.js +++ b/frontend/app/components/Client/Integrations/ZustandDoc/ZustandDoc.js @@ -81,7 +81,7 @@ const useBearStore = create( } /> - +
); diff --git a/frontend/app/components/Client/ManageUsers/ManageUsers.js b/frontend/app/components/Client/ManageUsers/ManageUsers.js deleted file mode 100644 index dd703813e..000000000 --- a/frontend/app/components/Client/ManageUsers/ManageUsers.js +++ /dev/null @@ -1,273 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import cn from 'classnames'; -import withPageTitle from 'HOCs/withPageTitle'; -import { - Form, IconButton, SlideModal, Input, Button, Loader, - NoContent, Popup, CopyButton } from 'UI'; -import Select from 'Shared/Select'; -import { init, save, edit, remove as deleteMember, fetchList, generateInviteLink } from 'Duck/member'; -import { fetchList as fetchRoles } from 'Duck/roles'; -import styles from './manageUsers.module.css'; -import UserItem from './UserItem'; -import { confirm } from 'UI'; -import { toast } from 'react-toastify'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; - -const PERMISSION_WARNING = 'You don’t have the permissions to perform this action.'; -const LIMIT_WARNING = 'You have reached users limit.'; - -@connect(state => ({ - account: state.getIn([ 'user', 'account' ]), - members: state.getIn([ 'members', 'list' ]).filter(u => u.id), - member: state.getIn([ 'members', 'instance' ]), - errors: state.getIn([ 'members', 'saveRequest', 'errors' ]), - loading: state.getIn([ 'members', 'loading' ]), - saving: state.getIn([ 'members', 'saveRequest', 'loading' ]), - roles: state.getIn(['roles', 'list']).filter(r => !r.protected).map(r => ({ label: r.name, value: r.roleId })).toJS(), - isEnterprise: state.getIn([ 'user', 'account', 'edition' ]) === 'ee', -}), { - init, - save, - edit, - deleteMember, - fetchList, - generateInviteLink, - fetchRoles -}) -@withPageTitle('Team - OpenReplay Preferences') -class ManageUsers extends React.PureComponent { - state = { showModal: false, remaining: this.props.account.limits.teamMember.remaining, invited: false } - - // writeOption = (e, { name, value }) => this.props.edit({ [ name ]: value }); - onChange = ({ name, value }) => this.props.edit({ [ name ]: value.value }); - onChangeCheckbox = ({ target: { checked, name } }) => this.props.edit({ [ name ]: checked }); - setFocus = () => this.focusElement && this.focusElement.focus(); - closeModal = () => this.setState({ showModal: false }); - componentWillMount = () => { - this.props.fetchList(); - if (this.props.isEnterprise) { - this.props.fetchRoles(); - } - } - - adminLabel = (user) => { - if (user.superAdmin) return null; - return user.admin ? 'Admin' : ''; - }; - - editHandler = user => { - this.init(user) - } - - deleteHandler = async (user) => { - if (await confirm({ - header: 'Users', - confirmation: `Are you sure you want to remove this user?` - })) { - this.props.deleteMember(user.id).then(() => { - const { remaining } = this.state; - if (remaining <= 0) return; - this.setState({ remaining: remaining - 1 }) - }); - } - } - - save = (e) => { - e.preventDefault(); - this.props.save(this.props.member) - .then(() => { - const { errors } = this.props; - if (errors && errors.size > 0) { - errors.forEach(e => { - toast.error(e); - }) - } - this.setState({ invited: true }) - // this.closeModal() - }); - } - - formContent = () => { - const { member, account, isEnterprise, roles } = this.props; - - return ( -
-
-
- - { this.focusElement = ref; } } - name="name" - value={ member.name } - onChange={ this.onChange } - className={ styles.input } - id="name-field" - /> -
- - - - - - { !account.smtp && -
- SMTP is not configured (see here how to set it up). You can still add new users, but you’d have to manually copy then send them the invitation link. -
- } - - -
{ 'Can manage Projects and team members.' }
-
- - { isEnterprise && ( - - - this.setState({ autoScroll: !this.state.autoScroll })} /> Autoscroll */} + {/*
+ {navigation && ( <> )} -
+
*/}
); diff --git a/frontend/app/components/Session_/BottomBlock/Header.js b/frontend/app/components/Session_/BottomBlock/Header.js index 15dd7a0c9..15cdf3365 100644 --- a/frontend/app/components/Session_/BottomBlock/Header.js +++ b/frontend/app/components/Session_/BottomBlock/Header.js @@ -11,9 +11,10 @@ const Header = ({ closeBottomBlock, onFilterChange, showClose = true, + customStyle, ...props }) => ( -
+
{ children }
{ showClose && } diff --git a/frontend/app/components/Session_/BottomBlock/infoLine.module.css b/frontend/app/components/Session_/BottomBlock/infoLine.module.css index b6798d1bf..37e47f013 100644 --- a/frontend/app/components/Session_/BottomBlock/infoLine.module.css +++ b/frontend/app/components/Session_/BottomBlock/infoLine.module.css @@ -6,7 +6,7 @@ display: flex; align-items: center; & >.infoPoint { - font-size: 12px; + font-size: 14px; display: flex; align-items: center; &:not(:last-child):after { diff --git a/frontend/app/components/Session_/BugReport/BugReportModal.tsx b/frontend/app/components/Session_/BugReport/BugReportModal.tsx new file mode 100644 index 000000000..da4fa64b7 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/BugReportModal.tsx @@ -0,0 +1,226 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { countries } from 'App/constants'; +import { useStore } from 'App/mstore'; +import { Button } from 'UI'; +import { session as sessionRoute } from 'App/routes'; +import { ReportDefaults, EnvData, Activity } from './types'; +import Session from './components/Session'; +import MetaInfo from './components/MetaInfo'; +import Title from './components/Title'; +import Comments from './components/Comments'; +import Steps from './components/Steps'; +import { mapEvents } from './utils'; +import { fetchList as fetchMembers } from 'Duck/member'; + +interface Props { + hideModal: () => void; + session: Record; + account: Record; + width: number; + height: number; + xrayProps: { + currentLocation: Record[]; + resourceList: Record[]; + exceptionsList: Record[]; + eventsList: Record[]; + endTime: number; + }; + fetchMembers: () => void + members: any; +} + +function BugReportModal({ hideModal, session, width, height, account, xrayProps, fetchMembers, members }: Props) { + const reportRef = React.createRef(); + const [isRendering, setRendering] = React.useState(false); + + const { bugReportStore } = useStore(); + const { + userBrowser, + userDevice, + userCountry, + userBrowserVersion, + userOs, + userOsVersion, + userDisplayName, + userDeviceType, + revId, + metadata, + sessionId, + events, + notes, + } = session; + + const envObject: EnvData = { + Device: `${userDevice}${userDeviceType !== userDevice ? ` ${userDeviceType}` : ''}`, + Resolution: `${width}x${height}`, + Browser: `${userBrowser} v${userBrowserVersion}`, + OS: `${userOs} v${userOsVersion}`, + // @ts-ignore + Country: countries[userCountry], + }; + if (revId) { + Object.assign(envObject, { Rev: revId }); + } + + const sessionUrl = `${window.location.origin}/${ + window.location.pathname.split('/')[1] + }${sessionRoute(sessionId)}`; + + const defaults: ReportDefaults = { + author: account.name, + env: envObject, + meta: metadata, + session: { + user: userDisplayName, + id: sessionId, + url: sessionUrl, + }, + }; + + React.useEffect(() => { + fetchMembers() + bugReportStore.updateReportDefaults(defaults); + bugReportStore.setDefaultSteps(mapEvents(events)); + }, []); + + const onClose = () => { + hideModal(); + return bugReportStore.clearStore(); + } + + const onGen = () => { + // @ts-ignore + import('html2canvas').then(({ default: html2canvas }) => { + // @ts-ignore + window.html2canvas = html2canvas; + + // @ts-ignore + import('jspdf').then(({ jsPDF }) => { + setRendering(true); + const doc = new jsPDF('p', 'mm', 'a4'); + const now = new Date().toISOString(); + + doc.addMetadata('Author', account.name); + doc.addMetadata('Title', 'OpenReplay Bug Report'); + doc.addMetadata('Subject', 'OpenReplay Bug Report'); + doc.addMetadata('Keywords', 'OpenReplay Bug Report'); + doc.addMetadata('Creator', 'OpenReplay'); + doc.addMetadata('Producer', 'OpenReplay'); + doc.addMetadata('CreationDate', now); + + // DO NOT DELETE UNUSED RENDER FUNCTION + // REQUIRED FOR FUTURE USAGE AND AS AN EXAMPLE OF THE FUNCTIONALITY + + function buildPng() { + html2canvas(reportRef.current, { + scale: 2, + ignoreElements: (e) => e.id.includes('pdf-ignore'), + }).then((canvas) => { + const imgData = canvas.toDataURL('img/png'); + + var imgWidth = 200; + var pageHeight = 295; + var imgHeight = (canvas.height * imgWidth) / canvas.width; + var heightLeft = imgHeight; + var position = 0; + + + doc.addImage(imgData, 'PNG', 5, 5, imgWidth, imgHeight); + + doc.addImage('/assets/img/report-head.png', 'png', 210/2 - 40/2, 2, 45, 5); + + heightLeft -= pageHeight - 7; + + while (heightLeft >= 0) { + position = heightLeft - imgHeight + 10; + doc.addPage(); + doc.addImage(imgData, 'PNG', 5, position, imgWidth, imgHeight); + doc.addImage('/assets/img/report-head.png', 'png', 210/2 - 40/2, pageHeight - 5, 45, 5); + heightLeft -= pageHeight; + } + + doc.link(5, 295 - Math.abs(heightLeft) - 25, 200, 30, { url: sessionUrl }); + if (position === 0) doc.addImage('/assets/img/report-head.png', 'png', 210/2 - 40/2, pageHeight - 5, 45, 5); + + doc.save('Bug Report: ' + sessionId + '.pdf'); + setRendering(false); + }); + } + function buildText() { + doc + .html(reportRef.current, { + x: 0, + y: 0, + width: 210, + windowWidth: reportRef.current.getBoundingClientRect().width, + autoPaging: 'text', + html2canvas: { + ignoreElements: (e) => e.id.includes('pdf-ignore') || e instanceof SVGElement, + }, + }) + .save('html.pdf') + .then(() => { + setRendering(false); + }) + .catch((e) => { + console.error(e); + setRendering(false); + }); + } + // buildText(); + buildPng(); + + const activity = { + network: xrayProps.resourceList, + console: xrayProps.exceptionsList, + clickRage: xrayProps.eventsList.filter((item: any) => item.type === 'CLICKRAGE'), + } + bugReportStore.composeReport(activity as unknown as Activity) + }); + }); + }; + + return ( +
+
+ + <MetaInfo envObject={envObject} metadata={metadata} /> + <Steps xrayProps={xrayProps} notes={notes} members={members} /> + <Comments /> + <Session user={userDisplayName} sessionUrl={sessionUrl} /> + <div id="pdf-ignore" className="flex items-center gap-2 mt-4"> + <Button icon="file-pdf" variant="primary" onClick={onGen} loading={isRendering}> + Download Bug Report + </Button> + <Button variant="text-primary" onClick={onClose}> + Close + </Button> + </div> + </div> + {isRendering ? ( + <div + className="fixed min-h-screen flex text-xl items-center justify-center top-0 right-0 cursor-wait" + style={{ background: 'rgba(0,0,0, 0.2)', zIndex: 9999, width: 620, maxWidth: '70vw' }} + id="pdf-ignore" + > + <div>Rendering PDF Report</div> + </div> + ) : null} + </div> + ); +} + +const WithUIState = connect((state) => ({ + // @ts-ignore + session: state.getIn(['sessions', 'current']), + // @ts-ignore + account: state.getIn(['user', 'account']), + // @ts-ignore + members: state.getIn(['members', 'list']), +}), { fetchMembers })(BugReportModal); + +export default WithUIState; diff --git a/frontend/app/components/Session_/BugReport/components/Comments.tsx b/frontend/app/components/Session_/BugReport/components/Comments.tsx new file mode 100644 index 000000000..cb8a57b18 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/Comments.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import cn from 'classnames'; +import SectionTitle from './SectionTitle'; + +function Comments() { + const { bugReportStore } = useStore(); + const inputRef = React.createRef<HTMLTextAreaElement>(); + + const toggleEdit = () => { + bugReportStore.toggleCommentEditing(true); + }; + + React.useEffect(() => { + if (inputRef.current && bugReportStore.isCommentEdit) { + inputRef.current?.focus(); + } + }, [bugReportStore.isCommentEdit]); + + const commentsEnabled = bugReportStore.comment.length > 0; + const commentStr = commentsEnabled + ? bugReportStore.comment + : 'Expected results, additional steps or any other useful information for debugging.'; + + return ( + <div className="w-full" id={commentsEnabled ? '' : 'pdf-ignore'}> + <div className="flex items-center gap-2"> + <SectionTitle>Comments</SectionTitle> + <div className="text-disabled-text mb-2">(Optional)</div> + </div> + {bugReportStore.isCommentEdit ? ( + <textarea + ref={inputRef} + name="reportComments" + placeholder="Comment..." + rows={3} + autoFocus + className="rounded fluid border -mx-2 px-2 py-1 w-full -mt-2" + value={bugReportStore.comment} + onChange={(e) => bugReportStore.setComment(e.target.value)} + onBlur={() => bugReportStore.toggleCommentEditing(false)} + onFocus={() => bugReportStore.toggleCommentEditing(true)} + /> + ) : ( + <div + onClick={toggleEdit} + className={cn( + !commentsEnabled + ? 'text-disabled-text border-dotted border-gray-medium' + : 'border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium', + 'pt-1 w-fit -mt-2', + 'cursor-pointer select-none border-b' + )} + > + {commentStr} + </div> + )} + </div> + ); +} + +export default observer(Comments); diff --git a/frontend/app/components/Session_/BugReport/components/MetaInfo.tsx b/frontend/app/components/Session_/BugReport/components/MetaInfo.tsx new file mode 100644 index 000000000..09746dcfb --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/MetaInfo.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import SectionTitle from './SectionTitle'; + +interface EnvObj { + Device: string; + Resolution: string; + Browser: string; + OS: string; + Country: string; + Rev?: string; +} + +export default function MetaInfo({ + envObject, + metadata, +}: { + envObject: EnvObj; + metadata: Record<string, any>; +}) { + return ( + <div className="flex gap-8"> + <div className="flex flex-col gap-2"> + <SectionTitle>Environment</SectionTitle> + {Object.keys(envObject).map((envTag) => ( + <div key={envTag} className="flex items-center"> + <div className="py-1 px-2 font-medium">{envTag}</div> + <div className="rounded bg-active-blue px-2 py-1 whitespace-nowrap overflow-hidden text-clip"> + <span className="text-base"> + {/* @ts-ignore */} + {envObject[envTag]} + </span> + </div> + </div> + ))} + </div> + + {Object.keys(metadata).length > 0 ? ( + <div className="flex flex-col gap-2"> + <SectionTitle>Metadata</SectionTitle> + {Object.keys(metadata).map((meta) => ( + <div key={meta} className="flex items-center rounded overflow-hidden bg-gray-lightest"> + <div className="bg-gray-light-shade py-1 px-2">{meta}</div> + <div className="py-1 px-2 text-gray-medium">{metadata[meta]}</div> + </div> + ))} + </div> + ) : null} + </div> + ); +} diff --git a/frontend/app/components/Session_/BugReport/components/ReportTitle.tsx b/frontend/app/components/Session_/BugReport/components/ReportTitle.tsx new file mode 100644 index 000000000..6e00d397a --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/ReportTitle.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import cn from 'classnames'; +import { Tooltip } from 'UI'; + +function ReportTitle() { + const { bugReportStore } = useStore(); + const inputRef = React.createRef<HTMLInputElement>(); + + const toggleEdit = () => { + bugReportStore.toggleTitleEdit(true); + }; + + React.useEffect(() => { + const handler = (e: KeyboardEvent) => { + if (bugReportStore.isTitleEdit && e.key === 'Enter') { + inputRef.current?.blur(); + bugReportStore.toggleTitleEdit(false); + } + } + + document.addEventListener('keydown', handler, false) + + return () => document.removeEventListener('keydown', handler) + }) + + React.useEffect(() => { + if (inputRef.current && bugReportStore.isTitleEdit) { + inputRef.current?.focus(); + } + }, [bugReportStore.isTitleEdit]) + + return ( + <div> + {bugReportStore.isTitleEdit ? ( + <input + ref={inputRef} + name="reportTitle" + className="rounded fluid border-0 -mx-2 px-2 h-8 text-2xl" + value={bugReportStore.reportTitle} + onChange={(e) => bugReportStore.setTitle(e.target.value)} + onBlur={() => bugReportStore.toggleTitleEdit(false)} + onFocus={() => bugReportStore.toggleTitleEdit(true)} + /> + ) : ( + // @ts-ignore + <Tooltip title="Double click to rename"> + <div + onDoubleClick={toggleEdit} + className={cn( + 'text-blue text-2xl h-8 flex items-center border-transparent', + 'cursor-pointer select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium' + )} + > + {bugReportStore.reportTitle} + </div> + </Tooltip> + )} + </div> + ); +} + +export default observer(ReportTitle); diff --git a/frontend/app/components/Session_/BugReport/components/SectionTitle.tsx b/frontend/app/components/Session_/BugReport/components/SectionTitle.tsx new file mode 100644 index 000000000..60306ca88 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/SectionTitle.tsx @@ -0,0 +1,5 @@ +import React from 'react' + +export default function SectionTitle({ children }: { children: React.ReactNode }) { + return <div className="text-xl font-semibold mb-2">{children}</div>; +} diff --git a/frontend/app/components/Session_/BugReport/components/Session.tsx b/frontend/app/components/Session_/BugReport/components/Session.tsx new file mode 100644 index 000000000..11dfffbfb --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/Session.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import SectionTitle from './SectionTitle'; +import { Icon, Tooltip } from 'UI' + +export default function Session({ user, sessionUrl }: { user: string, sessionUrl: string }) { + + const onSessionClick = () => { + window.open(sessionUrl, '_blank').focus(); + } + + return ( + <div> + <SectionTitle>Session recording</SectionTitle> + {/* @ts-ignore */} + <Tooltip title="Play session in new tab"> + <div className="border hover:border-main hover:bg-active-blue cursor-pointer rounded flex items-center justify-between p-2" onClick={onSessionClick}> + <div className="flex flex-col"> + <div className="text-lg">{user}</div> + <div className="text-disabled-text"> + {sessionUrl} + </div> + </div> + <Icon name="play-fill" size={38} color="teal" /> + </div> + </Tooltip> + </div> + ); +} diff --git a/frontend/app/components/Session_/BugReport/components/Steps.tsx b/frontend/app/components/Session_/BugReport/components/Steps.tsx new file mode 100644 index 000000000..8307eea47 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/Steps.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { Button } from 'UI' +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import { RADIUS } from '../utils'; +import SectionTitle from './SectionTitle'; +import XRay from './StepsComponents/XRay'; +import StepRenderer from './StepsComponents/StepRenderer'; +import StepRadius from './StepsComponents/StepRadius'; +import SubModal from './StepsComponents/SubModal'; +import { Note } from 'App/services/NotesService'; + +interface Props { + xrayProps: { + currentLocation: Record<string, any>[]; + resourceList: Record<string, any>[]; + exceptionsList: Record<string, any>[]; + eventsList: Record<string, any>[]; + endTime: number; + }; + notes: Note[]; + members: Record<string, any>[]; +} + +function Steps({ xrayProps, notes, members }: Props) { + const { bugReportStore } = useStore(); + const [stepPickRadius, setRadius] = React.useState(RADIUS); + const [timePointer, setPointer] = React.useState(0); + + const shouldShowEventReset = bugReportStore.chosenEventSteps.length > 0; + + const handleStepsSelection = () => { + if (shouldShowEventReset) { + return clearEventSelection(); + } + if (timePointer > 0) { + // temp ? + return bugReportStore.setSteps(bugReportStore.sessionEventSteps); + } else { + bugReportStore.setSteps(bugReportStore.sessionEventSteps); + } + }; + + const clearEventSelection = () => { + setPointer(0); + bugReportStore.resetSteps(); + }; + + return ( + <div> + <SectionTitle>Steps to reproduce</SectionTitle> + + <XRay + xrayProps={xrayProps} + timePointer={timePointer} + clearEventSelection={clearEventSelection} + setPointer={setPointer} + stepPickRadius={stepPickRadius} + /> + + <div className="flex items-center justify-between"> + <div className="mt-4 mb-2 text-gray-dark flex items-center gap-4"> + STEPS + <div id="pdf-ignore"> + {timePointer > 0 ? ( + <StepRadius pickRadius={stepPickRadius} setRadius={setRadius} /> + ) : null} + </div> + </div> + <Button id="pdf-ignore" variant="text-primary" onClick={handleStepsSelection}> + {!shouldShowEventReset ? ( + <span>Add {timePointer > 0 ? '' : 'All'} Steps</span> + ) : ( + <span>Reset</span> + )} + </Button> + </div> + <StepRenderer + isDefault={bugReportStore.chosenEventSteps.length === 0} + steps={ + bugReportStore.chosenEventSteps.length === 0 + ? bugReportStore.sessionEventSteps + : bugReportStore.chosenEventSteps + } + /> + {bugReportStore.isSubStepModalOpen ? ( + <SubModal + members={members} + type={bugReportStore.subModalType} + notes={notes} + xrayProps={xrayProps} + /> + ) : null} + </div> + ); +} + +export default observer(Steps); diff --git a/frontend/app/components/Session_/BugReport/components/StepsComponents/EventStep.tsx b/frontend/app/components/Session_/BugReport/components/StepsComponents/EventStep.tsx new file mode 100644 index 000000000..255cac92b --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/StepsComponents/EventStep.tsx @@ -0,0 +1,126 @@ +import React from 'react'; +import { Icon, ItemMenu, Tooltip } from 'UI'; +import { observer } from 'mobx-react-lite'; +import { Step as IStep } from '../../types'; +const STEP_NAMES = { CLICKRAGE: 'Multiple click', CLICK: 'Clicked', LOCATION: 'Visited' }; +import { useStore } from 'App/mstore'; +import cn from 'classnames'; +import { ErrorComp, NetworkComp, NoteComp } from './SubModalItems'; +import { durationFromMs } from 'App/date'; + +const SUBSTEP = { + network: NetworkComp, + note: NoteComp, + error: ErrorComp, +}; + +function Step({ step, ind, isDefault }: { step: IStep; ind: number; isDefault?: boolean }) { + const { bugReportStore } = useStore(); + const [menuOpen, setMenu] = React.useState(false); + + const menuItems = [ + { + icon: 'quotes', + text: 'Add/Remove Note', + onClick: () => bugReportStore.toggleSubStepModal(true, 'note', step.key), + }, + { + icon: 'info-circle', + text: `Add/Remove Error`, + onClick: () => bugReportStore.toggleSubStepModal(true, 'error', step.key), + }, + { + icon: 'network', + text: 'Add/Remove Network Request', + onClick: () => bugReportStore.toggleSubStepModal(true, 'network', step.key), + }, + ]; + + return ( + <div className="flex flex-col w-full"> + <div + className={cn( + 'py-1 px-2 flex items-start gap-2 w-full rounded', + menuOpen + ? 'bg-figmaColors-secondary-outlined-hover-background' + : isDefault + ? '' + : 'hover:bg-figmaColors-secondary-outlined-hover-background group' + )} + > + <div className="rounded-3xl px-4 bg-gray-lightest relative z-10">{ind + 1}</div> + <div className="w-full"> + <div className="flex items-start w-full gap-2"> + <div className="px-1 text-disabled-text">{durationFromMs(step.time)}</div> + {/* @ts-ignore */} + <Icon name={step.icon} size={16} color="gray-darkest" className="relative z-10" /> + {/* @ts-ignore */} + <div className="font-semibold">{STEP_NAMES[step.type]}</div> + <div className="text-gray-medium">{step.details}</div> + <div + className={cn( + 'group-hover:flex items-center ml-auto gap-4', + menuOpen ? 'flex' : 'hidden' + )} + > + {/* @ts-ignore */} + <Tooltip title="Add Note, Error or Network Request" className="!flex items-center"> + <ItemMenu + label={ + <Icon + name="plus" + size={16} + className="cursor-pointer hover:fill-gray-darkest" + /> + } + items={menuItems} + flat + onToggle={(isOpen) => setMenu(isOpen)} + /> + </Tooltip> + {/* @ts-ignore */} + <Tooltip title="Delete Step" className="whitespace-nowrap"> + <div onClick={() => bugReportStore.removeStep(step)}> + <Icon name="trash" size={16} className="cursor-pointer hover:fill-gray-darkest" /> + </div> + </Tooltip> + </div> + </div> + {step.substeps?.length ? ( + <div className="flex flex-col gap-2 w-full mt-2 relative"> + {step.substeps.map((subStep) => { + const Component = SUBSTEP[subStep.type]; + return ( + <div className="relative" key={subStep.key}> + <div + className="rounded border py-1 px-2 w-full flex flex-col relative z-10" + style={{ background: subStep.type === 'note' ? '#FFFEF5' : 'white' }} + > + {/* @ts-ignore */} + <Component item={subStep} /> + </div> + <div + style={{ + borderBottom: '1px solid #DDDDDD', + borderLeft: '1px solid #DDDDDD', + borderBottomLeftRadius: 6, + position: 'absolute', + zIndex: 1, + left: -25, + bottom: 10, + height: '120%', + width: 50, + }} + /> + </div> + ); + })} + </div> + ) : null} + </div> + </div> + </div> + ); +} + +export default observer(Step); diff --git a/frontend/app/components/Session_/BugReport/components/StepsComponents/StepRadius.tsx b/frontend/app/components/Session_/BugReport/components/StepsComponents/StepRadius.tsx new file mode 100644 index 000000000..543d2c803 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/StepsComponents/StepRadius.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Tooltip } from 'UI' + +interface Props { + pickRadius: number; + setRadius: (v: number) => void; +} + +function StepRadius({ pickRadius, setRadius }: Props) { + return ( + <div className="w-full flex items-center gap-4"> + <div className="border-b border-dotted border-gray-medium cursor-help"> + {/* @ts-ignore */} + <Tooltip title={<span>Closest step to the selected timestamp ± {pickRadius}.</span>}> + <span>± {pickRadius}</span> + </Tooltip> + </div> + <div className="flex items-center gap-1"> + <div + className="rounded px-2 bg-light-blue-bg cursor-pointer hover:bg-teal-light" + onClick={() => setRadius(pickRadius + 1)} + > + +1 + </div> + <div + className="rounded px-2 bg-light-blue-bg cursor-pointer hover:bg-teal-light" + onClick={() => (pickRadius > 1 ? setRadius(pickRadius - 1) : null)} + > + -1 + </div> + </div> + </div> + ); +} + +export default StepRadius; diff --git a/frontend/app/components/Session_/BugReport/components/StepsComponents/StepRenderer.tsx b/frontend/app/components/Session_/BugReport/components/StepsComponents/StepRenderer.tsx new file mode 100644 index 000000000..569a794d0 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/StepsComponents/StepRenderer.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import Step from './EventStep'; +import { Step as IStep } from '../../types'; + +function StepRenderer(props: { steps: IStep[]; isDefault: boolean }) { + const stepAmount = props.steps.length; + const shouldSkip = stepAmount > 2; + if (props.isDefault && shouldSkip) { + return ( + <div className="flex flex-col gap-4 opacity-50"> + <Step step={props.steps[0]} ind={1} isDefault /> + <div className="ml-4"> + {stepAmount - 2} Steps</div> + <Step step={props.steps[stepAmount - 1]} ind={stepAmount} isDefault /> + </div> + ); + } + return ( + <div className="flex flex-col gap-4"> + {props.steps.map((step, ind) => ( + <React.Fragment key={step.key}> + <Step step={step} ind={ind} /> + </React.Fragment> + ))} + </div> + ); +} + +export default StepRenderer diff --git a/frontend/app/components/Session_/BugReport/components/StepsComponents/SubModal.tsx b/frontend/app/components/Session_/BugReport/components/StepsComponents/SubModal.tsx new file mode 100644 index 000000000..e70f19150 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/StepsComponents/SubModal.tsx @@ -0,0 +1,179 @@ +import React from 'react'; +import { Icon, Button } from 'UI'; +import { observer } from 'mobx-react-lite'; +import { Note } from 'App/services/NotesService'; +import { NoteItem, ErrorItem, NetworkReq, SubItem } from './SubModalItems'; +import { filterList, debounce } from 'App/utils'; +import { useStore } from 'App/mstore'; + +const Titles = { + note: 'Note', + network: 'Fetch/XHR', + error: 'Console Error', +}; +const Icons = { + note: 'quotes' as const, + network: 'network' as const, + error: 'info-circle' as const +} +const Filters = { + note: 'note message or author', + network: 'url', + error: 'error name or message', +}; + +interface Props { + type: 'note' | 'network' | 'error'; + items: SubItem[]; +} + +let debounceUpdate: any = () => {}; + +const SUB_ITEMS = { + note: NoteItem, + error: ErrorItem, + network: NetworkReq, +}; + +function ModalContent(props: Props) { + const [searchStr, setSearch] = React.useState(''); + const list = + searchStr !== '' + ? filterList(props.items, searchStr, ['url', 'name', 'title', 'message']) + : props.items; + + React.useEffect(() => { + debounceUpdate = debounce((val: string) => setSearch(val), 250); + }, []); + + const SubItem = SUB_ITEMS[props.type]; + + return ( + <div className="flex flex-col p-4 bg-white gap-4 w-full"> + <div className="flex items-center gap-2"> + <div className="p-2 rounded-full bg-light-blue-bg"> + <Icon name={Icons[props.type]} size={18} /> + </div> + <div className="text-2xl font-semibold">{`Select ${Titles[props.type]}`}</div> + <div className="ml-auto"> + <input + onChange={(e) => debounceUpdate(e.target.value)} + className="bg-white p-2 border border-borderColor-gray-light-shade rounded" + placeholder={`Filter by ${Filters[props.type]}`} + style={{ width: 250 }} + /> + </div> + </div> + <div + className="flex flex-col rounded -mx-4 px-4 py-2 bg-white" + style={{ height: 'calc(100vh - 130px)', overflowY: 'scroll', maxWidth: '70vw', width: 620 }} + > + {list.length > 0 ? ( + list.map((item) => ( + <React.Fragment key={item.key}> + {/* @ts-ignore */} + <SubItem item={item} /> + </React.Fragment> + )) + ) : ( + <div className="text-2xl font-semibold text-center">No items to show.</div> + )} + </div> + + <ModalActionsObs /> + </div> + ); +} + +function ModalActions() { + const { bugReportStore } = useStore(); + + const removeModal = () => { + bugReportStore.toggleSubStepModal(false, bugReportStore.subModalType, undefined); + }; + const saveChoice = () => { + bugReportStore.saveSubItems(); + removeModal(); + }; + return ( + <div className="flex items-center gap-2"> + <Button + disabled={bugReportStore.pickedSubItems[bugReportStore.targetStep].size === 0} + variant="primary" + onClick={saveChoice} + > + Add Selected + </Button> + <Button variant="text-primary" onClick={removeModal}> + Cancel + </Button> + </div> + ); +} + +const ModalActionsObs = observer(ModalActions); + +interface ModalProps { + xrayProps: { + currentLocation: Record<string, any>[]; + resourceList: Record<string, any>[]; + exceptionsList: Record<string, any>[]; + eventsList: Record<string, any>[]; + endTime: number; + }; + type: 'note' | 'network' | 'error'; + notes: Note[]; + members: Record<string, any>[]; +} + +function SubModal(props: ModalProps) { + let items; + if (props.type === 'note') { + items = props.notes.map((note) => ({ + type: 'note' as const, + title: props.members.find((m) => m.id === note.userId)?.email || note.userId, + message: note.message, + time: 0, + key: note.noteId as unknown as string, + })); + } + if (props.type === 'error') { + items = props.xrayProps.exceptionsList.map((error) => ({ + type: 'error' as const, + time: error.time, + message: error.message, + name: error.name, + key: error.key, + })); + } + if (props.type === 'network') { + items = props.xrayProps.resourceList.map((fetch) => ({ + type: 'network' as const, + time: fetch.time, + url: fetch.url, + status: fetch.status, + success: fetch.success, + message: fetch.name, + key: fetch.key, + })); + } + + return ( + <div + className="bg-white fixed" + style={{ + maxWidth: '70vw', + overflow: 'hidden', + width: 620, + height: '100vh', + top: 0, + right: 0, + zIndex: 999, + }} + > + <ModalContent type={props.type} items={items} /> + </div> + ); +} + +export default SubModal; diff --git a/frontend/app/components/Session_/BugReport/components/StepsComponents/SubModalItems.tsx b/frontend/app/components/Session_/BugReport/components/StepsComponents/SubModalItems.tsx new file mode 100644 index 000000000..136bfe0fc --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/StepsComponents/SubModalItems.tsx @@ -0,0 +1,125 @@ +import React from 'react'; +import { Checkbox } from 'UI'; +import { observer } from 'mobx-react-lite'; +import { useStore } from 'App/mstore'; +import { durationFromMs } from 'App/date' +import cn from 'classnames' + +interface Item { + time: number; + message: string; + type: 'note' | 'network' | 'error'; + key: string; +} + +export interface INoteItem extends Item { + title: string; +} + +export interface IError extends Item { + name?: string; +} + +export interface INetworkReq extends Item { + url: string; + status: string; + success: boolean; +} + +export type SubItem = INoteItem | IError | INetworkReq; + +const safeStr = (ogStr: string) => (ogStr.length > 60 ? ogStr.slice(0, 60) + '...' : ogStr); + +export const NetworkComp = ({ item }: { item: INetworkReq }) => ( + <div className="flex items-start flex-col z-10"> + <div className="flex items-center gap-2 text-disabled-text"> + <div>{durationFromMs(item.time)}</div> + <div>{safeStr(item.url)}</div> + </div> + <div className="flex items-center gap-2"> + <div className="rounded bg-active-blue px-2 whitespace-nowrap overflow-hidden text-clip font-mono">{item.status}</div> + <div className={item.success ? '' : 'text-red'}>{safeStr(item.message)}</div> + </div> + </div> +); + +export const NetworkReq = observer(({ item }: { item: INetworkReq }) => { + const { bugReportStore } = useStore(); + return ( + <SubModalItemContainer + isChecked={bugReportStore.isSubItemChecked(item)} + onChange={(isChecked) => bugReportStore.toggleSubItem(isChecked, item)} + > + <NetworkComp item={item} /> + </SubModalItemContainer> + ); +}); + +export const NoteComp = ({ item }: { item: INoteItem }) => ( + <div className="flex items-start flex-col z-10"> + <div>{item.message}</div> + <div className="text-disabled-text text-sm">{item.title}</div> + </div> +); + +export const NoteItem = observer(({ item }: { item: INoteItem }) => { + const { bugReportStore } = useStore(); + return ( + <SubModalItemContainer + isChecked={bugReportStore.isSubItemChecked(item)} + onChange={(isChecked) => bugReportStore.toggleSubItem(isChecked, item)} + isNote + > + <NoteComp item={item} /> + </SubModalItemContainer> + ); +}); + +export const ErrorComp = ({ item }: { item: IError }) => ( + <div className="flex items-start flex-col z-10"> + <div className="text-disabled-text">{durationFromMs(item.time)}</div> + {item.name ? <div className="text-red">{item.name}</div> : null} + <div className="text-secondary">{safeStr(item.message)}</div> + </div> +); + +export const ErrorItem = observer(({ item }: { item: IError }) => { + const { bugReportStore } = useStore(); + return ( + <SubModalItemContainer + isChecked={bugReportStore.isSubItemChecked(item)} + onChange={(isChecked) => bugReportStore.toggleSubItem(isChecked, item)} + > + <ErrorComp item={item} /> + </SubModalItemContainer> + ); +}); + +export function SubModalItemContainer({ + children, + isChecked, + onChange, + isNote, +}: { + children: React.ReactNode; + isChecked: boolean; + onChange: (arg: any) => void; + isNote?: boolean; +}) { + return ( + <div + className={cn("flex items-start p-2 gap-2 border-t last:border-b cursor-pointer", isNote ? 'note-hover-bg' : 'hover:bg-active-blue')} + // style={{ background: isNote ? '#FFFEF5' : undefined }} + onClick={() => onChange(!isChecked)} + > + <Checkbox + name="isIncluded" + type="checkbox" + checked={isChecked} + onChange={(e: any) => onChange(e.target.checked)} + className="pt-1" + /> + {children} + </div> + ); +} diff --git a/frontend/app/components/Session_/BugReport/components/StepsComponents/XRay.tsx b/frontend/app/components/Session_/BugReport/components/StepsComponents/XRay.tsx new file mode 100644 index 000000000..61c2fb9da --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/StepsComponents/XRay.tsx @@ -0,0 +1,155 @@ +import React from 'react'; +import { Duration } from 'luxon'; +import { observer } from 'mobx-react-lite'; +import { Icon, Button } from 'UI'; +import { useStore } from 'App/mstore'; +import { INDEXES } from 'App/constants/zindex'; +import TimelinePointer from 'App/components/Session_/OverviewPanel/components/TimelinePointer'; +import EventRow from 'App/components/Session_/OverviewPanel/components/EventRow'; +import { selectEventSteps } from '../../utils'; + +interface IXRay { + xrayProps: { + currentLocation: Record<string, any>[]; + resourceList: Record<string, any>[]; + exceptionsList: Record<string, any>[]; + eventsList: Record<string, any>[]; + endTime: number; + }; + timePointer: number; + stepPickRadius: number; + clearEventSelection: () => void; + setPointer: (time: number) => void; +} + +function XRay({ xrayProps, timePointer, stepPickRadius, clearEventSelection, setPointer }: IXRay) { + const [selectedTime, setTime] = React.useState(0); + const xrayContainer = React.useRef<HTMLDivElement>(); + const { bugReportStore } = useStore(); + + const { resourceList, exceptionsList, eventsList, endTime } = xrayProps; + + const resources = { + NETWORK: resourceList, + ERRORS: exceptionsList, + CLICKRAGE: eventsList.filter((item: any) => item.type === 'CLICKRAGE'), + }; + + const pickEventRadius = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { + e.stopPropagation(); + + const pos = e.clientX - xrayContainer.current?.getBoundingClientRect().left; + const percent = pos / xrayContainer.current?.getBoundingClientRect().width; + const targetTime = percent * endTime; + const selectedSteps = selectEventSteps( + bugReportStore.sessionEventSteps, + targetTime, + stepPickRadius + ); + + setTime(targetTime); + setPointer(e.clientX - xrayContainer.current?.getBoundingClientRect().left); + bugReportStore.setSteps(selectedSteps); + }; + + React.useEffect(() => { + if (timePointer > 0 && selectedTime > 0 && bugReportStore.chosenEventSteps) { + const selectedSteps = selectEventSteps( + bugReportStore.sessionEventSteps, + selectedTime, + stepPickRadius + ); + + bugReportStore.setSteps(selectedSteps); + } + }, [stepPickRadius]); + + const shouldShowPointerReset = timePointer > 0; + + return ( + <> + <div className="flex items-center justify-between my-2"> + <div className=" text-gray-dark py-2"> + X-RAY + {timePointer > 0 ? ( + <span className="text-disabled-text ml-2"> + {Duration.fromMillis(selectedTime).toFormat('hh:mm:ss')} + </span> + ) : null} + </div> + {!shouldShowPointerReset ? ( + <div + className="flex items-center gap-2 rounded bg-active-blue px-2 py-1 whitespace-nowrap overflow-hidden text-clip group" + id="pdf-ignore" + > + <Icon name="info-circle" size={16} /> + <div>Click anywhere in the graph below to drilldown and add steps</div> + </div> + ) : ( + <Button id="pdf-ignore" variant="text-primary" onClick={clearEventSelection}> + Clear Selection + </Button> + )} + </div> + <div + className="relative cursor-pointer group-hover:border-dotted hover:border-dotted group-hover:border-gray-dark hover:border-gray-dark border border-transparent" + onClick={pickEventRadius} + ref={xrayContainer} + > + <div + id="pdf-ignore" + style={{ + pointerEvents: 'none', + background: timePointer > 0 ? 'rgb(57, 78, 255)' : undefined, + opacity: '0.07', + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + }} + /> + {timePointer > 0 ? ( + <div + className="absolute h-full bg-white" + // id="pdf-ignore" + style={{ + zIndex: INDEXES.BUG_REPORT_PICKER, + width: 41, + left: timePointer - 20, + pointerEvents: 'none', + }} + > + <div + style={{ + height: '100%', + width: 0, + borderLeft: '2px dashed rgba(0,0,0, 0.5)', + left: 20, + position: 'absolute', + zIndex: INDEXES.BUG_REPORT + 1, + }} + /> + </div> + ) : null} + {Object.keys(resources).map((feature) => ( + <div key={feature} className="border-b-2 last:border-none relative z-20"> + <EventRow + title={feature} + // @ts-ignore + list={resources[feature]} + zIndex={INDEXES.BUG_REPORT} + noMargin + renderElement={(pointer: any) => ( + <TimelinePointer noClick pointer={pointer} type={feature} /> + )} + endTime={endTime} + /> + </div> + ))} + </div> + </> + ); +} + +export default observer(XRay); diff --git a/frontend/app/components/Session_/BugReport/components/Title.tsx b/frontend/app/components/Session_/BugReport/components/Title.tsx new file mode 100644 index 000000000..b0ea26caf --- /dev/null +++ b/frontend/app/components/Session_/BugReport/components/Title.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import Select from 'Shared/Select'; +import { Icon } from 'UI'; +import ReportTitle from './ReportTitle'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import { SeverityLevels } from 'App/mstore/bugReportStore'; + +const selectOptions = [ + { + label: ( + <div className="flex items-center gap-1 cursor-pointer w-full"> + <Icon name="arrow-up-short" color="red" size="24" /> + HIGH + </div> + ), + value: SeverityLevels.High, + }, + { + label: ( + <div className="flex items-center gap-1 cursor-pointer w-full"> + <Icon name="dash" size="24" color="yellow2" /> + MEDIUM + </div> + ), + value: SeverityLevels.Medium, + }, + { + label: ( + <div className="flex items-center gap-1 cursor-pointer w-full"> + <Icon name="arrow-down-short" color="teal" size="24" /> + LOW + </div> + ), + value: SeverityLevels.Low, + }, +]; + +function Title({ userName }: { userName: string }) { + const { bugReportStore } = useStore(); + + return ( + <div className="flex items-center py-2 px-3 justify-between bg-gray-lightest rounded"> + <div className="flex flex-col gap-2"> + <ReportTitle /> + <div className="text-gray-medium">By {userName}</div> + </div> + <div className="flex items-center gap-2"> + <div className="font-semibold">Severity</div> + <Select + plain + controlStyle={{ minWidth: 115 }} + defaultValue={SeverityLevels.High} + options={selectOptions} + onChange={({ value }) => bugReportStore.setSeverity(value.value)} + /> + </div> + </div> + ); +} + +export default observer(Title); diff --git a/frontend/app/components/Session_/BugReport/overload.module.css b/frontend/app/components/Session_/BugReport/overload.module.css new file mode 100644 index 000000000..4fc49cd3d --- /dev/null +++ b/frontend/app/components/Session_/BugReport/overload.module.css @@ -0,0 +1,3 @@ +body { + line-height: 0.5!important; +} diff --git a/frontend/app/components/Session_/BugReport/types.ts b/frontend/app/components/Session_/BugReport/types.ts new file mode 100644 index 000000000..eb2b2a9d7 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/types.ts @@ -0,0 +1,119 @@ +import { SeverityLevels } from 'App/mstore/bugReportStore'; +import { SubItem } from './components/StepsComponents/SubModalItems'; + +export interface ReportDefaults { + author: string; + env: EnvData; + meta: { + [key: string]: string; + }; + session: { + user: string; + url: string; + id: string; + }; +} + +export interface BugReportPdf extends ReportDefaults { + title: string; + comment?: string; + severity: SeverityLevels; + steps: Step[]; + activity: Activity +} + +export interface Activity { + network: NetworkEvent[]; + console: Exception[]; + clickRage: ClickRage[]; +}; + +interface Event { + time: number; + key: string; +} + +interface NetworkEvent extends Event { + decodedBodySize: number | null; + duration: number | null; + encodedBodySize: number | null; + headerSize: number | null; + index?: number; + method: string; + name: string; + payload: string; + response: string; + responseBodySize: number; + score: number; + status: string; + success: boolean; + timewidth: number; + timings: Record<string, any>; + ttfb: number; + type: string; + url: string; +} + +interface Exception extends Event { + errorId: string; + function: string; + key: string; + message: string; + messageId: number; + name: string; + projectId: number; + sessionId: number; + source: string; + timestamp: number; +} + +interface ClickRage extends Event { + type: 'CLICKRAGE'; + label: string + targetContent: string, + target: { + key: string, + path: string, + label: string | null + }, + count: number +} + + +export interface EnvData { + Browser: string; + OS: string; + Country: string; + Device: string; + Resolution: string; +} + +export interface Step { + key: string; + type: string; + time: number; + details: string; + icon: string; + substeps?: SubItem[]; +} + +export interface Note { + author: string; + message: string; + step: 'note'; +} + +export interface Error { + timestamp: string; + error: string; + step: 'error'; +} + +export interface Request { + url: string; + status: number; + type: 'GET' | 'POST' | 'PUT' | 'DELETE'; + time: number; + name: string; + step: 'request'; +} diff --git a/frontend/app/components/Session_/BugReport/utils.ts b/frontend/app/components/Session_/BugReport/utils.ts new file mode 100644 index 000000000..a97e275d7 --- /dev/null +++ b/frontend/app/components/Session_/BugReport/utils.ts @@ -0,0 +1,69 @@ +import { Step } from './types' + +const TYPES = { CLICKRAGE: 'CLICKRAGE', CLICK: 'CLICK', LOCATION: 'LOCATION' } +export const RADIUS = 3 + +export function mapEvents(events: Record<string,any>[]): Step[] { + const steps: Step[] = [] + events.forEach(event => { + if (event.type === TYPES.LOCATION) { + const step = { + key: event.key, + type: TYPES.LOCATION, + icon: 'event/location', + details: event.url, + time: event.time, + } + steps.push(step) + } + if (event.type === TYPES.CLICK) { + const step = { + key: event.key, + type: TYPES.CLICK, + icon: 'puzzle-piece', + details: event.label, + time: event.time, + } + steps.push(step) + } + if (event.type === TYPES.CLICKRAGE) { + const step = { + key: event.key, + type: TYPES.CLICKRAGE, + icon: 'event/clickrage', + details: event.label, + time: event.time, + } + steps.push(step) + } + }) + + return steps +} + +export function getClosestEventStep(time: number, arr: Step[]) { + let mid; + let low = 0; + let high = arr.length - 1; + while (high - low > 1) { + mid = Math.floor ((low + high) / 2); + if (arr[mid].time < time) { + low = mid; + } else { + high = mid; + } + } + if (time - arr[low].time <= arr[high].time - time) { + return { targetStep: arr[low], index: low } ; + } + return { targetStep: arr[high], index: high } ; +} + +export const selectEventSteps = (steps: Step[], targetTime: number, radius: number) => { + const { targetStep, index } = getClosestEventStep(targetTime, steps) + + const stepsBeforeEvent = steps.slice(index - radius, index) + const stepsAfterEvent = steps.slice(index + 1, index + 1 + radius) + + return [...stepsBeforeEvent, targetStep, ...stepsAfterEvent] +} diff --git a/frontend/app/components/Session_/Console/ConsoleContent.js b/frontend/app/components/Session_/Console/ConsoleContent.js index 54a9745d0..a7482b69e 100644 --- a/frontend/app/components/Session_/Console/ConsoleContent.js +++ b/frontend/app/components/Session_/Console/ConsoleContent.js @@ -7,7 +7,8 @@ import { LEVEL } from 'Types/session/log'; import Autoscroll from '../Autoscroll'; import BottomBlock from '../BottomBlock'; import stl from './console.module.css'; -import { Duration } from 'luxon'; +import ConsoleRow from './ConsoleRow'; +// import { Duration } from 'luxon'; const ALL = 'ALL'; const INFO = 'INFO'; @@ -83,44 +84,34 @@ export default class ConsoleContent extends React.PureComponent { <Tabs tabs={TABS} active={activeTab} onClick={this.onTabClick} border={false} /> </div> <Input - className="input-small" + className="input-small h-8" placeholder="Filter by keyword" icon="search" iconPosition="left" name="filter" + height={28} onChange={this.onFilterChange} /> </BottomBlock.Header> <BottomBlock.Content> - <NoContent title={ - <div className="capitalize flex items-center mt-16"> + <NoContent + title={ + <div className="capitalize flex items-center mt-16"> <Icon name="info-circle" className="mr-2" size="18" /> No Data - </div> - } size="small" show={filtered.length === 0}> + </div> + } + size="small" + show={filtered.length === 0} + > <Autoscroll autoScrollTo={Math.max(lastIndex, 0)}> - {filtered.map((l, index) => ( - <div - className={cn('flex py-2 px-4', { - info: !l.isYellow() && !l.isRed(), - warn: l.isYellow(), - error: l.isRed(), - [stl.activeRow]: lastIndex === index, - // [stl.inactiveRow]: index > lastIndex, - 'cursor-pointer': !isResult, - })} - onClick={() => !isResult && jump(l.time)} - > - <div className={cn(stl.timestamp)}> - <Icon size="14" className={stl.icon} {...getIconProps(l.level)} /> - </div> - <div className={cn(stl.timestamp, {})}> - {Duration.fromMillis(l.time).toFormat('mm:ss.SSS')} - </div> - <div key={l.key} className={cn(stl.line)} data-scroll-item={l.isRed()}> - <div className={stl.message}>{renderWithNL(l.value)}</div> - </div> - </div> + {filtered.map((l) => ( + <ConsoleRow + log={l} + jump={jump} + iconProps={getIconProps(l.level)} + renderWithNL={renderWithNL} + /> ))} </Autoscroll> </NoContent> diff --git a/frontend/app/components/Session_/Console/ConsoleRow/ConsoleRow.tsx b/frontend/app/components/Session_/Console/ConsoleRow/ConsoleRow.tsx new file mode 100644 index 000000000..85457d6b1 --- /dev/null +++ b/frontend/app/components/Session_/Console/ConsoleRow/ConsoleRow.tsx @@ -0,0 +1,51 @@ +import React, { useState } from 'react'; +import cn from 'classnames'; +import stl from '../console.module.css'; +import { Icon } from 'UI'; +import JumpButton from 'Shared/DevTools/JumpButton'; + +interface Props { + log: any; + iconProps: any; + jump?: any; + renderWithNL?: any; + style?: any; +} +function ConsoleRow(props: Props) { + const { log, iconProps, jump, renderWithNL, style } = props; + const [expanded, setExpanded] = useState(false); + const lines = log.value.split('\n').filter((l: any) => !!l); + const canExpand = lines.length > 1; + + return ( + <div + className={cn(stl.line, 'flex py-2 px-4 overflow-hidden group relative select-none', { + info: !log.isYellow() && !log.isRed(), + warn: log.isYellow(), + error: log.isRed(), + 'cursor-pointer': canExpand, + })} + style={style} + onClick={() => setExpanded(!expanded)} + > + <div className={cn(stl.timestamp)}> + <Icon size="14" className={stl.icon} {...iconProps} /> + </div> + {/* <div className={cn(stl.timestamp, {})}> + {Duration.fromMillis(log.time).toFormat('mm:ss.SSS')} + </div> */} + <div key={log.key} className={cn('')} data-scroll-item={log.isRed()}> + <div className={cn(stl.message, 'flex items-center')}> + {canExpand && ( + <Icon name={expanded ? 'caret-down-fill' : 'caret-right-fill'} className="mr-2" /> + )} + <span>{renderWithNL(lines.pop())}</span> + </div> + {canExpand && expanded && lines.map((l: any, i: number) => <div key={l.slice(0,3)+i} className="ml-4 mb-1">{l}</div>)} + </div> + <JumpButton onClick={() => jump(log.time)} /> + </div> + ); +} + +export default ConsoleRow; diff --git a/frontend/app/components/Session_/Console/ConsoleRow/index.ts b/frontend/app/components/Session_/Console/ConsoleRow/index.ts new file mode 100644 index 000000000..c9140d748 --- /dev/null +++ b/frontend/app/components/Session_/Console/ConsoleRow/index.ts @@ -0,0 +1 @@ +export { default } from './ConsoleRow'; diff --git a/frontend/app/components/Session_/Console/console.module.css b/frontend/app/components/Session_/Console/console.module.css index 6f7079d94..2da78f540 100644 --- a/frontend/app/components/Session_/Console/console.module.css +++ b/frontend/app/components/Session_/Console/console.module.css @@ -15,6 +15,9 @@ display: flex; align-items: flex-start; border-bottom: solid thin $gray-light-shade; + &:hover { + background-coor: $active-blue !important; + } } .timestamp { diff --git a/frontend/app/components/Session_/EventsBlock/EventGroupWrapper.js b/frontend/app/components/Session_/EventsBlock/EventGroupWrapper.js index c68dac880..1ec053462 100644 --- a/frontend/app/components/Session_/EventsBlock/EventGroupWrapper.js +++ b/frontend/app/components/Session_/EventsBlock/EventGroupWrapper.js @@ -1,34 +1,47 @@ import React from 'react'; import cn from 'classnames'; - +import { connect } from 'react-redux' import { TextEllipsis } from 'UI'; import withToggle from 'HOCs/withToggle'; import { TYPES } from 'Types/session/event'; import Event from './Event' import stl from './eventGroupWrapper.module.css'; +import NoteEvent from './NoteEvent'; +import { setEditNoteTooltip } from 'Duck/sessions';; // TODO: incapsulate toggler in LocationEvent -@withToggle("showLoadInfo", "toggleLoadInfo") -class EventGroupWrapper extends React.PureComponent { - +@withToggle('showLoadInfo', 'toggleLoadInfo') +@connect( + (state) => ({ + members: state.getIn(['members', 'list']), + currentUserId: state.getIn(['user', 'account', 'id']), + }), + { setEditNoteTooltip } +) +class EventGroupWrapper extends React.Component { toggleLoadInfo = (e) => { e.stopPropagation(); this.props.toggleLoadInfo(); - } + }; componentDidUpdate(prevProps) { - if (prevProps.showLoadInfo !== this.props.showLoadInfo || prevProps.query !== this.props.query) { + if ( + prevProps.showLoadInfo !== this.props.showLoadInfo || + prevProps.query !== this.props.query || + prevProps.event.timestamp !== this.props.event.timestamp || + prevProps.isNote !== this.props.isNote + ) { this.props.mesureHeight(); } } componentDidMount() { - this.props.toggleLoadInfo(this.props.isFirst) + this.props.toggleLoadInfo(this.props.isFirst); this.props.mesureHeight(); } onEventClick = (e) => this.props.onEventClick(e, this.props.event); - onCheckboxClick = e => this.props.onCheckboxClick(e, this.props.event); + onCheckboxClick = (e) => this.props.onCheckboxClick(e, this.props.event); render() { const { @@ -42,58 +55,76 @@ class EventGroupWrapper extends React.PureComponent { showLoadInfo, isFirst, presentInSearch, + isNote, + filterOutNote, } = this.props; const isLocation = event.type === TYPES.LOCATION; - const whiteBg = isLastInGroup && event.type !== TYPES.LOCATION || (!isLastEvent && event.type !== TYPES.LOCATION) + const whiteBg = + (isLastInGroup && event.type !== TYPES.LOCATION) || + (!isLastEvent && event.type !== TYPES.LOCATION); const safeRef = String(event.referrer || ''); + return ( <div - className={ - cn(stl.container, "!py-1", { + className={cn( + stl.container, + '!py-1', + { [stl.last]: isLastInGroup, [stl.first]: event.type === TYPES.LOCATION, [stl.dashAfter]: isLastInGroup && !isLastEvent, - }, isLastInGroup && '!pb-2', event.type === TYPES.LOCATION && "!pt-2 !pb-2") - } + }, + isLastInGroup && '!pb-2', + event.type === TYPES.LOCATION && '!pt-2 !pb-2' + )} > - { isFirst && isLocation && event.referrer && - <div className={ stl.referrer }> + {isFirst && isLocation && event.referrer && ( + <div className={stl.referrer}> <TextEllipsis> Referrer: <span className={stl.url}>{safeRef}</span> </TextEllipsis> </div> - } - { isLocation - ? <Event - extended={isFirst} - key={ event.key } - event={ event } - onClick={ this.onEventClick } - selected={ isSelected } - showLoadInfo={ showLoadInfo } - toggleLoadInfo={ this.toggleLoadInfo } - isCurrent={ isCurrent } - presentInSearch={presentInSearch} - isLastInGroup={isLastInGroup} - whiteBg={whiteBg} - /> - : <Event - key={ event.key } - event={ event } - onClick={ this.onEventClick } - onCheckboxClick={ this.onCheckboxClick } - selected={ isSelected } - isCurrent={ isCurrent } - showSelection={ showSelection } - overlayed={ isEditing } - presentInSearch={presentInSearch} - isLastInGroup={isLastInGroup} - whiteBg={whiteBg} - /> - } + )} + {isNote ? ( + <NoteEvent + userEmail={this.props.members.find((m) => m.id === event.userId)?.email || event.userId} + note={event} + filterOutNote={filterOutNote} + onEdit={this.props.setEditNoteTooltip} + noEdit={this.props.currentUserId !== event.userId} + /> + ) : isLocation ? ( + <Event + extended={isFirst} + key={event.key} + event={event} + onClick={this.onEventClick} + selected={isSelected} + showLoadInfo={showLoadInfo} + toggleLoadInfo={this.toggleLoadInfo} + isCurrent={isCurrent} + presentInSearch={presentInSearch} + isLastInGroup={isLastInGroup} + whiteBg={whiteBg} + /> + ) : ( + <Event + key={event.key} + event={event} + onClick={this.onEventClick} + onCheckboxClick={this.onCheckboxClick} + selected={isSelected} + isCurrent={isCurrent} + showSelection={showSelection} + overlayed={isEditing} + presentInSearch={presentInSearch} + isLastInGroup={isLastInGroup} + whiteBg={whiteBg} + /> + )} </div> - ) + ); } } diff --git a/frontend/app/components/Session_/EventsBlock/EventsBlock.js b/frontend/app/components/Session_/EventsBlock/EventsBlock.js index e690ce3cc..69ba51996 100644 --- a/frontend/app/components/Session_/EventsBlock/EventsBlock.js +++ b/frontend/app/components/Session_/EventsBlock/EventsBlock.js @@ -5,7 +5,7 @@ import { Icon } from 'UI'; import { List, AutoSizer, CellMeasurer, CellMeasurerCache } from "react-virtualized"; import { TYPES } from 'Types/session/event'; import { setSelected } from 'Duck/events'; -import { setEventFilter } from 'Duck/sessions'; +import { setEventFilter, filterOutNote } from 'Duck/sessions'; import { show as showTargetDefiner } from 'Duck/components/targetDefiner'; import EventGroupWrapper from './EventGroupWrapper'; import styles from './eventsBlock.module.css'; @@ -21,9 +21,10 @@ import EventSearch from './EventSearch/EventSearch'; }), { showTargetDefiner, setSelected, - setEventFilter + setEventFilter, + filterOutNote }) -export default class EventsBlock extends React.PureComponent { +export default class EventsBlock extends React.Component { state = { editingEvent: null, mouseOver: false, @@ -52,8 +53,9 @@ export default class EventsBlock extends React.PureComponent { const { filter } = this.state; this.setState({ query: '' }) this.props.setEventFilter({ query: '', filter }) - - this.scroller.current.forceUpdateGrid(); + if (this.scroller.current) { + this.scroller.current.forceUpdateGrid(); + } setTimeout(() => { if (!this.scroller.current) return; @@ -123,21 +125,28 @@ export default class EventsBlock extends React.PureComponent { onMouseOver = () => this.setState({ mouseOver: true }) onMouseLeave = () => this.setState({ mouseOver: false }) + get eventsList() { + const { session: { notesWithEvents }, filteredEvents } = this.props + const usedEvents = filteredEvents || notesWithEvents + + return usedEvents + } + renderGroup = ({ index, key, style, parent }) => { const { - session: { events }, selectedEvents, currentTimeEventIndex, testsAvaliable, playing, eventsIndex, - filteredEvents + filterOutNote, } = this.props; const { query } = this.state; - const _events = filteredEvents || events; + const _events = this.eventsList const isLastEvent = index === _events.size - 1; const isLastInGroup = isLastEvent || _events.get(index + 1).type === TYPES.LOCATION; const event = _events.get(index); + const isNote = !!event.noteId const isSelected = selectedEvents.includes(event); const isCurrent = index === currentTimeEventIndex; const isEditing = this.state.editingEvent === event; @@ -166,9 +175,11 @@ export default class EventsBlock extends React.PureComponent { isCurrent={ isCurrent } isEditing={ isEditing } showSelection={ testsAvaliable && !playing } + isNote={isNote} + filterOutNote={filterOutNote} /> - </div> - )} + </div> + )} </CellMeasurer> ); } @@ -176,15 +187,13 @@ export default class EventsBlock extends React.PureComponent { render() { const { query } = this.state; const { - testsAvaliable, session: { events, }, - filteredEvents, setActiveTab, } = this.props; - const _events = filteredEvents || events; + const _events = this.eventsList const isEmptySearch = query && (_events.size === 0 || !_events) return ( @@ -197,7 +206,7 @@ export default class EventsBlock extends React.PureComponent { setActiveTab={setActiveTab} value={query} header={ - <div className="text-xl">User Actions <span className="color-gray-medium">{ events.size }</span></div> + <div className="text-xl">User Steps <span className="color-gray-medium">{ events.size }</span></div> } /> </div> diff --git a/frontend/app/components/Session_/EventsBlock/NoteEvent.tsx b/frontend/app/components/Session_/EventsBlock/NoteEvent.tsx new file mode 100644 index 000000000..08e5631a9 --- /dev/null +++ b/frontend/app/components/Session_/EventsBlock/NoteEvent.tsx @@ -0,0 +1,131 @@ +import React from 'react'; +import { Icon } from 'UI'; +import { tagProps, iTag, Note } from 'App/services/NotesService'; +import { formatTimeOrDate } from 'App/date'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import { ItemMenu } from 'UI'; +import copy from 'copy-to-clipboard'; +import { toast } from 'react-toastify'; +import { session } from 'App/routes'; +import { confirm } from 'UI'; +import { filterOutNote as filterOutTimelineNote } from 'Player'; +import { TeamBadge } from 'Shared/SessionListContainer/components/Notes'; + +interface Props { + note: Note; + noEdit: boolean; + userEmail: string; + filterOutNote: (id: number) => void; + onEdit: (noteTooltipObj: Record<string, any>) => void; +} + +function NoteEvent(props: Props) { + const { settingsStore, notesStore } = useStore(); + const { timezone } = settingsStore.sessionSettings; + + console.log(props.noEdit); + const onEdit = () => { + props.onEdit({ + isVisible: true, + isEdit: true, + time: props.note.timestamp, + note: { + timestamp: props.note.timestamp, + tag: props.note.tag, + isPublic: props.note.isPublic, + message: props.note.message, + sessionId: props.note.sessionId, + noteId: props.note.noteId, + }, + }); + }; + + const onCopy = () => { + copy( + `${window.location.origin}/${window.location.pathname.split('/')[1]}${session( + props.note.sessionId + )}${props.note.timestamp > 0 ? `?jumpto=${props.note.timestamp}¬e=${props.note.noteId}` : `?note=${props.note.noteId}`}` + ); + toast.success('Note URL copied to clipboard'); + }; + + const onDelete = async () => { + if ( + await confirm({ + header: 'Confirm', + confirmButton: 'Yes, delete', + confirmation: `Are you sure you want to delete this note?`, + }) + ) { + notesStore.deleteNote(props.note.noteId).then((r) => { + props.filterOutNote(props.note.noteId); + filterOutTimelineNote(props.note.noteId); + toast.success('Note deleted'); + }); + } + }; + const menuItems = [ + { icon: 'pencil', text: 'Edit', onClick: onEdit, disabled: props.noEdit }, + { icon: 'link-45deg', text: 'Copy URL', onClick: onCopy }, + { icon: 'trash', text: 'Delete', onClick: onDelete }, + ]; + return ( + <div + className="flex items-start flex-col p-2 border rounded" + style={{ background: '#FFFEF5' }} + > + <div className="flex items-center w-full relative"> + <div className="p-3 bg-gray-light rounded-full"> + <Icon name="quotes" color="main" /> + </div> + <div className="ml-2"> + <div + className="text-base" + style={{ + maxWidth: 150, + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }} + > + {props.userEmail}, {props.userEmail} + </div> + <div className="text-disabled-text text-sm"> + {formatTimeOrDate(props.note.createdAt as unknown as number, timezone)} + </div> + </div> + <div className="cursor-pointer absolute" style={{ right: -5 }}> + <ItemMenu bold items={menuItems} /> + </div> + </div> + <div + className="text-base capitalize-first my-3 overflow-y-scroll overflow-x-hidden" + style={{ maxHeight: 200, maxWidth: 220 }} + > + {props.note.message} + </div> + <div> + <div className="flex items-center gap-2 flex-wrap w-full"> + {props.note.tag ? ( + <div + key={props.note.tag} + style={{ + // @ts-ignore + background: tagProps[props.note.tag], + userSelect: 'none', + padding: '1px 6px', + }} + className="rounded-full text-white text-xs select-none w-fit" + > + {props.note.tag} + </div> + ) : null} + {!props.note.isPublic ? null : <TeamBadge />} + </div> + </div> + </div> + ); +} + +export default observer(NoteEvent); diff --git a/frontend/app/components/Session_/EventsBlock/UserCard/UserCard.js b/frontend/app/components/Session_/EventsBlock/UserCard/UserCard.js index 480cd4e67..2e4e4daa1 100644 --- a/frontend/app/components/Session_/EventsBlock/UserCard/UserCard.js +++ b/frontend/app/components/Session_/EventsBlock/UserCard/UserCard.js @@ -5,11 +5,10 @@ import { countries } from 'App/constants'; import { useStore } from 'App/mstore'; import { browserIcon, osIcon, deviceTypeIcon } from 'App/iconNames'; import { formatTimeOrDate } from 'App/date'; -import { Avatar, TextEllipsis, CountryFlag, Icon } from 'UI'; +import { Avatar, TextEllipsis, CountryFlag, Icon, Tooltip, Popover } from 'UI'; import cn from 'classnames'; import { withRequest } from 'HOCs'; import SessionInfoItem from '../../SessionInfoItem'; -import { Tooltip } from 'react-tippy'; import { useModal } from 'App/components/Modal'; import UserSessionsModal from 'Shared/UserSessionsModal'; @@ -76,14 +75,9 @@ function UserCard({ className, request, session, width, height, similarSessions, {userBrowser}, {userOs}, {userDevice} </span> <span className="mx-1 font-bold text-xl">·</span> - <Tooltip - theme="light" - delay={0} - hideOnClick="persistent" - arrow - interactive - html={ - <div className="text-left"> + <Popover + render={() => ( + <div className="text-left bg-white"> <SessionInfoItem comp={<CountryFlag country={userCountry} />} label={countries[userCountry]} @@ -99,24 +93,13 @@ function UserCard({ className, request, session, width, height, similarSessions, /> {revId && <SessionInfoItem icon="info" label="Rev ID:" value={revId} isLast />} </div> - } - position="bottom center" - hoverable - disabled={false} - on="hover" + )} > - <span className="color-teal cursor-pointer">More</span> - </Tooltip> + <span className="link">More</span> + </Popover> </div> </div> </div> - - {/* <SlideModal - title={ <div>User Sessions</div> } - isDisplayed={ showUserSessions } - content={ showUserSessions && <SessionList similarSessions={ similarSessions } loading={ loading } /> } - onClose={ () => showUserSessions ? setShowUserSessions(false) : null } - /> */} </div> ); } diff --git a/frontend/app/components/Session_/Exceptions/Exceptions.js b/frontend/app/components/Session_/Exceptions/Exceptions.js index b6c65b5ba..334e57688 100644 --- a/frontend/app/components/Session_/Exceptions/Exceptions.js +++ b/frontend/app/components/Session_/Exceptions/Exceptions.js @@ -22,7 +22,7 @@ import BottomBlock from '../BottomBlock'; @connectPlayer((state) => ({ logs: state.logListNow, exceptions: state.exceptionsList, - exceptionsNow: state.exceptionsListNow, + // exceptionsNow: state.exceptionsListNow, })) @connect( (state) => ({ @@ -55,15 +55,15 @@ export default class Exceptions extends React.PureComponent { const filtered = exceptions.filter((e) => filterRE.test(e.name) || filterRE.test(e.message)); - let lastIndex = -1; - filtered.forEach((item, index) => { - if ( - this.props.exceptionsNow.length > 0 && - item.time <= this.props.exceptionsNow[this.props.exceptionsNow.length - 1].time - ) { - lastIndex = index; - } - }); + // let lastIndex = -1; + // filtered.forEach((item, index) => { + // if ( + // this.props.exceptionsNow.length > 0 && + // item.time <= this.props.exceptionsNow[this.props.exceptionsNow.length - 1].time + // ) { + // lastIndex = index; + // } + // }); return ( <> @@ -113,6 +113,7 @@ export default class Exceptions extends React.PureComponent { iconPosition="left" name="filter" onChange={this.onFilterChange} + height={28} /> <QuestionMarkHint className={'mx-4'} @@ -133,13 +134,13 @@ export default class Exceptions extends React.PureComponent { </BottomBlock.Header> <BottomBlock.Content> <NoContent size="small" show={filtered.length === 0} title="No recordings found"> - <Autoscroll autoScrollTo={Math.max(lastIndex, 0)}> + <Autoscroll> {filtered.map((e, index) => ( <ErrorItem onJump={() => jump(e.time)} error={e} key={e.key} - selected={lastIndex === index} + // selected={lastIndex === index} // inactive={index > lastIndex} onErrorClick={(jsEvent) => { jsEvent.stopPropagation(); diff --git a/frontend/app/components/Session_/Fetch/Fetch.js b/frontend/app/components/Session_/Fetch/Fetch.js index fc7d7e76b..8aaadba6d 100644 --- a/frontend/app/components/Session_/Fetch/Fetch.js +++ b/frontend/app/components/Session_/Fetch/Fetch.js @@ -33,7 +33,8 @@ export default class Fetch extends React.PureComponent { hasPreviousError: false, }; - onFilterChange = (e, { value }) => { + onFilterChange = (e) => { + const value = e.target.value; const { list } = this.props; const filterRE = getRE(value, 'i'); const filtered = list.filter( diff --git a/frontend/app/components/Session_/GraphQL/GraphQL.js b/frontend/app/components/Session_/GraphQL/GraphQL.js index a5420584f..8c601dba1 100644 --- a/frontend/app/components/Session_/GraphQL/GraphQL.js +++ b/frontend/app/components/Session_/GraphQL/GraphQL.js @@ -81,12 +81,6 @@ export default class GraphQL extends React.PureComponent { const { list } = nextProps; if (nextProps.time) { const filtered = GraphQL.filterList(list, prevState.filter); - console.log({ - list, - filtered, - time: nextProps.time, - }); - let i = 0; filtered.forEach((item, index) => { if (item.time <= nextProps.time) { diff --git a/frontend/app/components/Session_/Issues/IssueForm.js b/frontend/app/components/Session_/Issues/IssueForm.js index b263739f3..4b6585985 100644 --- a/frontend/app/components/Session_/Issues/IssueForm.js +++ b/frontend/app/components/Session_/Issues/IssueForm.js @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { Form, Input, Button, CircularLoader } from 'UI'; +import { Form, Input, Button, CircularLoader, Loader } from 'UI'; //import { } from 'Duck/issues'; import { addActivity, init, edit, fetchAssignments, fetchMeta } from 'Duck/assignments'; import Select from 'Shared/Select'; @@ -57,8 +57,16 @@ class IssueForm extends React.PureComponent { writeOption = ({ name, value }) => this.props.edit({ [name]: value.value }); render() { - const { creating, projects, users, issueTypes, instance, closeHandler, metaLoading } = - this.props; + const { + creating, + projects, + users, + issueTypes, + instance, + closeHandler, + metaLoading, + projectsLoading, + } = this.props; const projectOptions = projects.map(({ name, id }) => ({ label: name, value: id })).toArray(); const userOptions = users.map(({ name, id }) => ({ label: name, value: id })).toArray(); @@ -69,92 +77,94 @@ class IssueForm extends React.PureComponent { const selectedIssueType = issueTypes.filter((issue) => issue.id == instance.issueType)[0]; return ( - <Form onSubmit={this.onSubmit} className="text-left"> - <Form.Field className="mb-15-imp"> - <label htmlFor="issueType"> - <span className="mr-2">Project</span> - <CircularLoader loading={metaLoading} /> - </label> - <Select - name="projectId" - options={projectOptions} - // value={ instance.projectId } - fluid - onChange={this.writeOption} - placeholder="Project" - /> - </Form.Field> - <Form.Field className="mb-15-imp"> - <label htmlFor="issueType">Issue Type</label> - <Select - selection - name="issueType" - labeled - options={issueTypeOptions} - // value={ instance.issueType } - fluid - onChange={this.writeOption} - placeholder="Select issue type" - text={ - selectedIssueType ? ( - <SelectedValue icon={selectedIssueType.iconUrl} text={selectedIssueType.name} /> - ) : ( - '' - ) - } - /> - </Form.Field> + <Loader loading={projectsLoading} size={40}> + <Form onSubmit={this.onSubmit} className="text-left"> + <Form.Field className="mb-15-imp"> + <label htmlFor="issueType" className="flex items-center"> + <span className="mr-2">Project</span> + <CircularLoader loading={metaLoading} /> + </label> + <Select + name="projectId" + options={projectOptions} + // value={instance.projectId} + fluid + onChange={this.writeOption} + placeholder="Project" + /> + </Form.Field> + <Form.Field className="mb-15-imp"> + <label htmlFor="issueType">Issue Type</label> + <Select + selection + name="issueType" + labeled + options={issueTypeOptions} + value={instance.issueType} + fluid + onChange={this.writeOption} + placeholder="Select issue type" + text={ + selectedIssueType ? ( + <SelectedValue icon={selectedIssueType.iconUrl} text={selectedIssueType.name} /> + ) : ( + '' + ) + } + /> + </Form.Field> - <Form.Field className="mb-15-imp"> - <label htmlFor="assignee">Assignee</label> - <Select - selection - name="assignee" - options={userOptions} - // value={ instance.assignee } - fluid - onChange={this.writeOption} - placeholder="Select a user" - /> - </Form.Field> + <Form.Field className="mb-15-imp"> + <label htmlFor="assignee">Assignee</label> + <Select + selection + name="assignee" + options={userOptions} + // value={ instance.assignee } + fluid + onChange={this.writeOption} + placeholder="Select a user" + /> + </Form.Field> - <Form.Field className="mb-15-imp"> - <label htmlFor="title">Summary</label> - <Input - name="title" - value={instance.title} - placeholder="Issue Title / Summary" - onChange={this.write} - /> - </Form.Field> + <Form.Field className="mb-15-imp"> + <label htmlFor="title">Summary</label> + <Input + name="title" + value={instance.title} + placeholder="Issue Title / Summary" + onChange={this.write} + /> + </Form.Field> - <Form.Field className="mb-15-imp"> - <label htmlFor="description"> - Description - {/* <span className="text-sm text-gray-500">(Optional)</span> */} - </label> - <textarea - name="description" - rows="2" - value={instance.description} - placeholder="E.g. Found this issue at 3:29secs" - onChange={this.write} - /> - </Form.Field> + <Form.Field className="mb-15-imp"> + <label htmlFor="description"> + Description + {/* <span className="text-sm text-gray-500">(Optional)</span> */} + </label> + <textarea + name="description" + rows="2" + value={instance.description} + placeholder="E.g. Found this issue at 3:29secs" + onChange={this.write} + /> + </Form.Field> - <Button - loading={creating} - variant="primary" - disabled={!instance.validate()} - className="float-left mr-2" - type="submit" - > - {'Create'} - </Button> - <Button type="button" onClick={closeHandler}> - {'Cancel'} - </Button> - </Form> + <Button + loading={creating} + variant="primary" + disabled={!instance.validate()} + className="float-left mr-2" + type="submit" + > + {'Create'} + </Button> + <Button type="button" onClick={closeHandler}> + {'Cancel'} + </Button> + </Form> + </Loader> ); } } @@ -163,6 +173,7 @@ export default connect( (state) => ({ creating: state.getIn(['assignments', 'addActivity', 'loading']), projects: state.getIn(['assignments', 'projects']), + projectsLoading: state.getIn(['assignments', 'fetchProjects', 'loading']), users: state.getIn(['assignments', 'users']), instance: state.getIn(['assignments', 'instance']), metaLoading: state.getIn(['assignments', 'fetchMeta', 'loading']), diff --git a/frontend/app/components/Session_/Issues/IssueListItem.js b/frontend/app/components/Session_/Issues/IssueListItem.js index 1ccdbcfe2..c0e561a33 100644 --- a/frontend/app/components/Session_/Issues/IssueListItem.js +++ b/frontend/app/components/Session_/Issues/IssueListItem.js @@ -1,29 +1,32 @@ import React from 'react'; import cn from 'classnames'; -import { Popup } from 'UI'; +import { Tooltip } from 'UI'; import stl from './issueListItem.module.css'; const IssueListItem = ({ issue, onClick, icon, user, active }) => { return ( <div - onClick={ () => onClick(issue) } - className={ cn(stl.wrapper, active ? 'active-bg' : '', 'flex flex-col justify-between cursor-pointer text-base text-gray-800')} + onClick={() => onClick(issue)} + className={cn( + stl.wrapper, + active ? 'active-bg' : '', + 'flex flex-col justify-between cursor-pointer text-base text-gray-800' + )} > <div className="flex items-center justify-between"> <div className="flex items-center"> - { icon } - {/* <img src={ icon } width="16" height="16" className="mr-3" /> */} - <span>{ issue.id }</span> + {icon} + <span>{issue.id}</span> </div> <div className="flex items-center"> - { user && - <Popup content={ 'Assignee ' + user.name } > - <img src={ user.avatarUrls['24x24'] } width="24" height="24" /> - </Popup> - } + {user && ( + <Tooltip title={'Assignee ' + user.name}> + <img src={user.avatarUrls['24x24']} width="24" height="24" /> + </Tooltip> + )} </div> </div> - <div className={ stl.title }>{ issue.title }</div> + <div className={stl.title}>{issue.title}</div> </div> ); }; diff --git a/frontend/app/components/Session_/Issues/Issues.js b/frontend/app/components/Session_/Issues/Issues.js index 200b5b278..3c037a019 100644 --- a/frontend/app/components/Session_/Issues/Issues.js +++ b/frontend/app/components/Session_/Issues/Issues.js @@ -1,28 +1,29 @@ import React from 'react'; import { connect } from 'react-redux'; -import { Popup, Button, Icon } from 'UI'; -import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; +import { Icon, Popover } from 'UI'; import IssuesModal from './IssuesModal'; import { fetchProjects, fetchMeta } from 'Duck/assignments'; import stl from './issues.module.css'; -import { Tooltip } from 'react-tippy' -@connect(state => ({ - issues: state.getIn(['assignments', 'list']), - metaLoading: state.getIn(['assignments', 'fetchMeta', 'loading']), - projects: state.getIn(['assignments', 'projects']), - projectsFetched: state.getIn(['assignments', 'projectsFetched']), - activeIssue: state.getIn(['assignments', 'activeIssue']), - fetchIssueLoading: state.getIn(['assignments', 'fetchAssignment', 'loading']), - fetchIssuesLoading: state.getIn(['assignments', 'fetchAssignments', 'loading']), - projectsLoading: state.getIn(['assignments', 'fetchProjects', 'loading']), - issuesIntegration: state.getIn([ 'issues', 'list']).first() || {}, +@connect( + (state) => ({ + issues: state.getIn(['assignments', 'list']), + metaLoading: state.getIn(['assignments', 'fetchMeta', 'loading']), + projects: state.getIn(['assignments', 'projects']), + projectsFetched: state.getIn(['assignments', 'projectsFetched']), + activeIssue: state.getIn(['assignments', 'activeIssue']), + fetchIssueLoading: state.getIn(['assignments', 'fetchAssignment', 'loading']), + fetchIssuesLoading: state.getIn(['assignments', 'fetchAssignments', 'loading']), + projectsLoading: state.getIn(['assignments', 'fetchProjects', 'loading']), + issuesIntegration: state.getIn(['issues', 'list']).first() || {}, - jiraConfig: state.getIn([ 'issues', 'list' ]).first(), - issuesFetched: state.getIn([ 'issues', 'issuesFetched' ]), -}), { fetchMeta, fetchProjects }) + jiraConfig: state.getIn(['issues', 'list']).first(), + issuesFetched: state.getIn(['issues', 'issuesFetched']), + }), + { fetchMeta, fetchProjects } +) class Issues extends React.Component { - state = {showModal: false }; + state = { showModal: false }; constructor(props) { super(props); @@ -31,64 +32,67 @@ class Issues extends React.Component { closeModal = () => { this.setState({ showModal: false }); - } + }; showIssuesList = (e) => { e.preventDefault(); e.stopPropagation(); this.setState({ showModal: true }); - } + }; handleOpen = () => { this.setState({ showModal: true }); - if (!this.props.projectsFetched) { // cache projects fetch - this.props.fetchProjects().then(function() { - const { projects } = this.props; - if (projects && projects.first()) { - this.props.fetchMeta(projects.first().id) - } - }.bind(this)) + if (!this.props.projectsFetched) { + // cache projects fetch + this.props.fetchProjects().then( + function () { + const { projects } = this.props; + if (projects && projects.first()) { + this.props.fetchMeta(projects.first().id); + } + }.bind(this) + ); } - } + }; render() { const { - sessionId, isModalDisplayed, projectsLoading, metaLoading, fetchIssuesLoading, issuesIntegration + sessionId, + isModalDisplayed, + projectsLoading, + metaLoading, + fetchIssuesLoading, + issuesIntegration, } = this.props; - const provider = issuesIntegration.provider + const provider = issuesIntegration.provider; return ( - <div className="relative"> - <div className={ stl.buttonWrapper} onClick={this.handleOpen}> - <Tooltip - open={this.state.showModal} - position="bottom" - interactive - // animation="shift" - trigger="click" - unmountHTMLWhenHide - // @ts-ignore - theme='light' - arrow - html={ - <OutsideClickDetectingDiv onClickOutside={this.closeModal}> - <IssuesModal - provider={provider} - sessionId={ sessionId } - closeHandler={ this.closeModal } - /> - </OutsideClickDetectingDiv> - } + <div className="relative h-full w-full p-3"> + <div className={stl.buttonWrapper}> + <Popover + onOpen={this.handleOpen} + render={({ close }) => ( + <div> + <IssuesModal + provider={provider} + sessionId={sessionId} + closeHandler={close} + /> + </div> + )} + > + <div + className="flex items-center" + disabled={!isModalDisplayed && (metaLoading || fetchIssuesLoading || projectsLoading)} > - <div className="flex items-center" onClick={this.handleOpen} disabled={!isModalDisplayed && (metaLoading || fetchIssuesLoading || projectsLoading)}> - <Icon name={ `integrations/${ provider === 'jira' ? 'jira' : 'github'}` } size="16" /> - <span className="ml-2">Create Issue</span> - </div> - </Tooltip> - </div> + <Icon name={`integrations/${provider === 'jira' ? 'jira' : 'github'}`} size="16" /> + <span className="ml-2">Create Issue</span> + </div> + </Popover> </div> + </div> ); } -}; +} export default Issues; diff --git a/frontend/app/components/Session_/Network/Network.js b/frontend/app/components/Session_/Network/Network.js index 08779abd6..f824cba09 100644 --- a/frontend/app/components/Session_/Network/Network.js +++ b/frontend/app/components/Session_/Network/Network.js @@ -1,7 +1,7 @@ import React from 'react'; import cn from 'classnames'; import { connectPlayer, jump, pause } from 'Player'; -import { Popup, Button, TextEllipsis } from 'UI'; +import { Tooltip, Button, TextEllipsis } from 'UI'; import { getRE } from 'App/utils'; import { TYPES } from 'Types/session/resource'; import stl from './network.module.css'; @@ -29,12 +29,12 @@ const TAB_TO_TYPE_MAP = { export function renderName(r) { return ( <div className="flex justify-between items-center grow-0 w-full"> - <Popup + <Tooltip style={{ maxWidth: '75%' }} - content={<div className={stl.popupNameContent}>{r.url}</div>} + title={<div className={stl.popupNameContent}>{r.url}</div>} > <TextEllipsis>{r.name}</TextEllipsis> - </Popup> + </Tooltip> </div> ); } @@ -56,9 +56,9 @@ export function renderDuration(r) { } return ( - <Popup content={tooltipText}> + <Tooltip title={tooltipText}> <div className={cn(className, stl.duration)}> {text} </div> - </Popup> + </Tooltip> ); } diff --git a/frontend/app/components/Session_/Network/NetworkContent.js b/frontend/app/components/Session_/Network/NetworkContent.js index 082c87aa0..5f335dbf3 100644 --- a/frontend/app/components/Session_/Network/NetworkContent.js +++ b/frontend/app/components/Session_/Network/NetworkContent.js @@ -1,7 +1,7 @@ import React from 'react'; import cn from 'classnames'; // import { connectPlayer } from 'Player'; -import { QuestionMarkHint, Popup, Tabs, Input, NoContent, Icon, Button } from 'UI'; +import { QuestionMarkHint, Tooltip, Tabs, Input, NoContent, Icon, Toggler, Button } from 'UI'; import { getRE } from 'App/utils'; import { TYPES } from 'Types/session/resource'; import { formatBytes } from 'App/utils'; @@ -40,30 +40,25 @@ const LOAD_TIME_COLOR = 'red'; export function renderType(r) { return ( - <Popup style={{ width: '100%' }} content={<div className={stl.popupNameContent}>{r.type}</div>}> + <Tooltip style={{ width: '100%' }} title={<div className={stl.popupNameContent}>{r.type}</div>}> <div className={stl.popupNameTrigger}>{r.type}</div> - </Popup> + </Tooltip> ); } export function renderName(r) { return ( - <Popup - style={{ width: '100%' }} - content={<div className={stl.popupNameContent}>{r.url}</div>} - > - <div className={stl.popupNameTrigger}>{r.name}</div> - </Popup> + <Tooltip style={{ width: '100%' }} title={<div className={stl.popupNameContent}>{r.url}</div>}> + <div className={stl.popupNameTrigger}>{r.name}</div> + </Tooltip> ); } export function renderStart(r) { return ( <div className="flex justify-between items-center grow-0 w-full"> - <span> - {Duration.fromMillis(r.time).toFormat('mm:ss.SSS')} - </span> - <Button + <span>{Duration.fromMillis(r.time).toFormat('mm:ss.SSS')}</span> + {/* <Button variant="text" className="right-0 text-xs uppercase p-2 color-gray-500 hover:color-teal" onClick={(e) => { @@ -72,16 +67,15 @@ export function renderStart(r) { }} > Jump - </Button> - </div> - ) + </Button> */} + </div> + ); } const renderXHRText = () => ( <span className="flex items-center"> {XHR} <QuestionMarkHint - onHover={true} content={ <> Use our{' '} @@ -134,9 +128,9 @@ function renderSize(r) { } return ( - <Popup style={{ width: '100%' }} content={content}> + <Tooltip style={{ width: '100%' }} content={content}> <div>{triggerText}</div> - </Popup> + </Tooltip> ); } @@ -157,9 +151,9 @@ export function renderDuration(r) { } return ( - <Popup style={{ width: '100%' }} content={tooltipText}> + <Tooltip style={{ width: '100%' }} content={tooltipText}> <div className={cn(className, stl.duration)}> {text} </div> - </Popup> + </Tooltip> ); } @@ -243,39 +237,45 @@ export default class NetworkContent extends React.PureComponent { iconPosition="left" name="filter" onChange={this.onFilterChange} + height={28} /> </BottomBlock.Header> <BottomBlock.Content> - <InfoLine> - <InfoLine.Point label={filtered.length} value=" requests" /> - <InfoLine.Point - label={formatBytes(transferredSize)} - value="transferred" - display={transferredSize > 0} - /> - <InfoLine.Point - label={formatBytes(resourcesSize)} - value="resources" - display={resourcesSize > 0} - /> - <InfoLine.Point - label={formatMs(domBuildingTime)} - value="DOM Building Time" - display={domBuildingTime != null} - /> - <InfoLine.Point - label={domContentLoadedTime && formatMs(domContentLoadedTime.value)} - value="DOMContentLoaded" - display={domContentLoadedTime != null} - dotColor={DOM_LOADED_TIME_COLOR} - /> - <InfoLine.Point - label={loadTime && formatMs(loadTime.value)} - value="Load" - display={loadTime != null} - dotColor={LOAD_TIME_COLOR} - /> - </InfoLine> + <div className="flex items-center justify-between px-4"> + <div> + <Toggler checked={true} name="test" onChange={() => {}} label="4xx-5xx Only" /> + </div> + <InfoLine> + <InfoLine.Point label={filtered.length} value=" requests" /> + <InfoLine.Point + label={formatBytes(transferredSize)} + value="transferred" + display={transferredSize > 0} + /> + <InfoLine.Point + label={formatBytes(resourcesSize)} + value="resources" + display={resourcesSize > 0} + /> + <InfoLine.Point + label={formatMs(domBuildingTime)} + value="DOM Building Time" + display={domBuildingTime != null} + /> + <InfoLine.Point + label={domContentLoadedTime && formatMs(domContentLoadedTime.value)} + value="DOMContentLoaded" + display={domContentLoadedTime != null} + dotColor={DOM_LOADED_TIME_COLOR} + /> + <InfoLine.Point + label={loadTime && formatMs(loadTime.value)} + value="Load" + display={loadTime != null} + dotColor={LOAD_TIME_COLOR} + /> + </InfoLine> + </div> <NoContent title={ <div className="capitalize flex items-center mt-16"> @@ -296,11 +296,11 @@ export default class NetworkContent extends React.PureComponent { activeIndex={lastIndex} > {[ - { - label: 'Start', - width: 120, - render: renderStart, - }, + // { + // label: 'Start', + // width: 120, + // render: renderStart, + // }, { label: 'Status', dataKey: 'status', diff --git a/frontend/app/components/Session_/OverviewPanel/OverviewPanel.tsx b/frontend/app/components/Session_/OverviewPanel/OverviewPanel.tsx index 2f1f75f2c..de3cbdf5f 100644 --- a/frontend/app/components/Session_/OverviewPanel/OverviewPanel.tsx +++ b/frontend/app/components/Session_/OverviewPanel/OverviewPanel.tsx @@ -1,4 +1,4 @@ -import { connectPlayer } from 'App/player'; +import { connectPlayer } from 'Player'; import { toggleBottomBlock } from 'Duck/components/player'; import React, { useEffect } from 'react'; import BottomBlock from '../BottomBlock'; @@ -23,8 +23,10 @@ interface Props { issuesList: any[]; performanceChartData: any; endTime: number; + fetchPresented?: boolean; } function OverviewPanel(props: Props) { + const { fetchPresented = false } = props; const [dataLoaded, setDataLoaded] = React.useState(false); const [selectedFeatures, setSelectedFeatures] = React.useState([ 'PERFORMANCE', @@ -86,7 +88,10 @@ function OverviewPanel(props: Props) { <BottomBlock.Content> <OverviewPanelContainer endTime={props.endTime}> <TimelineScale endTime={props.endTime} /> - <div style={{ width: '100%', height: '187px' }} className="transition relative"> + <div + style={{ width: 'calc(100vw - 1rem)', margin: '0 auto', height: '187px' }} + className="transition relative" + > <NoContent show={selectedFeatures.length === 0} title={ @@ -107,7 +112,11 @@ function OverviewPanel(props: Props) { title={feature} list={resources[feature]} renderElement={(pointer: any) => ( - <TimelinePointer pointer={pointer} type={feature} /> + <TimelinePointer + pointer={pointer} + type={feature} + fetchPresented={fetchPresented} + /> )} endTime={props.endTime} message={HELP_MESSAGE[feature]} @@ -132,6 +141,7 @@ export default connect( } )( connectPlayer((state: any) => ({ + fetchPresented: state.fetchList.length > 0, resourceList: state.resourceList .filter((r: any) => r.isRed() || r.isYellow()) .concat(state.fetchList.filter((i: any) => parseInt(i.status) >= 400)) diff --git a/frontend/app/components/Session_/OverviewPanel/components/EventRow/EventRow.tsx b/frontend/app/components/Session_/OverviewPanel/components/EventRow/EventRow.tsx index 8b5ac8571..cbbdbbddc 100644 --- a/frontend/app/components/Session_/OverviewPanel/components/EventRow/EventRow.tsx +++ b/frontend/app/components/Session_/OverviewPanel/components/EventRow/EventRow.tsx @@ -1,63 +1,87 @@ import React from 'react'; import cn from 'classnames'; import { getTimelinePosition } from 'App/utils'; -import { Icon, Popup } from 'UI'; +import { Icon, Tooltip } from 'UI'; import PerformanceGraph from '../PerformanceGraph'; interface Props { - list?: any[]; - title: string; - message?: string; - className?: string; - endTime?: number; - renderElement?: (item: any) => React.ReactNode; - isGraph?: boolean; + list?: any[]; + title: string; + message?: string; + className?: string; + endTime?: number; + renderElement?: (item: any) => React.ReactNode; + isGraph?: boolean; + zIndex?: number; + noMargin?: boolean; } const EventRow = React.memo((props: Props) => { - const { title, className, list = [], endTime = 0, isGraph = false, message = '' } = props; - const scale = 100 / endTime; - const _list = - !isGraph && - React.useMemo(() => { - return list.map((item: any, _index: number) => { - const spread = item.toJS ? { ...item.toJS() } : { ...item } - return { - ...spread, - left: getTimelinePosition(item.time, scale), - }; - }); - }, [list]); + const { title, className, list = [], endTime = 0, isGraph = false, message = '' } = props; + const scale = 100 / endTime; + const _list = + !isGraph && + React.useMemo(() => { + return list.map((item: any, _index: number) => { + const spread = item.toJS ? { ...item.toJS() } : { ...item }; + return { + ...spread, + left: getTimelinePosition(item.time, scale), + }; + }); + }, [list]); - return ( - <div className={cn('w-full flex flex-col py-2', className)} style={{ height: '60px' }}> - <div className="uppercase color-gray-medium ml-4 text-sm flex items-center py-1"> - <div className="mr-2 leading-none">{title}</div> - <RowInfo message={message} /> - </div> - <div className="relative w-full"> - {isGraph ? ( - <PerformanceGraph list={list} /> - ) : ( - _list.length > 0 ? _list.map((item: any, index: number) => { - return ( - <div key={index} className="absolute" style={{ left: item.left + '%' }}> - {props.renderElement ? props.renderElement(item) : null} - </div> - ); - }) : ( - <div className="ml-4 color-gray-medium text-sm pt-2">None captured.</div> - ) - )} - </div> + return ( + <div + className={cn('w-full flex flex-col py-2', className)} + style={{ height: isGraph ? 60 : 50 }} + > + <div + className={cn( + 'uppercase color-gray-medium text-sm flex items-center py-1', + props.noMargin ? '' : 'ml-2' + )} + > + <div + style={{ zIndex: props.zIndex ? props.zIndex : undefined }} + className="mr-2 leading-none" + > + {title} </div> - ); + {message ? <RowInfo message={message} /> : null} + </div> + <div className="relative w-full" style={{ zIndex: props.zIndex ? props.zIndex : undefined }}> + {isGraph ? ( + <PerformanceGraph list={list} /> + ) : _list.length > 0 ? ( + _list.map((item: any, index: number) => { + return ( + <div + key={index} + className="absolute" + style={{ + left: `clamp(0%, calc(${item.left}% - 7px), calc(100% - 14px))`, + zIndex: props.zIndex ? props.zIndex : undefined, + }} + > + {props.renderElement ? props.renderElement(item) : null} + </div> + ); + }) + ) : ( + <div className={cn('color-gray-medium text-sm pt-2', props.noMargin ? '' : 'ml-4')}> + None captured. + </div> + )} + </div> + </div> + ); }); export default EventRow; -function RowInfo({ message} : any) { - return ( - <Popup content={message} delay={0}> - <Icon name="info-circle" color="gray-medium"/> - </Popup> - ) +function RowInfo({ message }: any) { + return ( + <Tooltip title={message} delay={0}> + <Icon name="info-circle" color="gray-medium" /> + </Tooltip> + ); } diff --git a/frontend/app/components/Session_/OverviewPanel/components/FeatureSelection/FeatureSelection.tsx b/frontend/app/components/Session_/OverviewPanel/components/FeatureSelection/FeatureSelection.tsx index 1f1c35912..bf4599e10 100644 --- a/frontend/app/components/Session_/OverviewPanel/components/FeatureSelection/FeatureSelection.tsx +++ b/frontend/app/components/Session_/OverviewPanel/components/FeatureSelection/FeatureSelection.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Checkbox, Popup } from 'UI'; +import { Checkbox, Tooltip } from 'UI'; const NETWORK = 'NETWORK'; const ERRORS = 'ERRORS'; @@ -8,48 +8,48 @@ const CLICKRAGE = 'CLICKRAGE'; const PERFORMANCE = 'PERFORMANCE'; export const HELP_MESSAGE: any = { - NETWORK: 'Network requests made in this session', - EVENTS: 'Visualizes the events that takes place in the DOM', - ERRORS: 'Visualizes native JS errors like Type, URI, Syntax etc.', - CLICKRAGE: 'Indicates user frustration when repeated clicks are recorded', - PERFORMANCE: 'Summary of this session’s memory, and CPU consumption on the timeline', -} + NETWORK: 'Network requests made in this session', + EVENTS: 'Visualizes the events that takes place in the DOM', + ERRORS: 'Visualizes native JS errors like Type, URI, Syntax etc.', + CLICKRAGE: 'Indicates user frustration when repeated clicks are recorded', + PERFORMANCE: 'Summary of this session’s memory, and CPU consumption on the timeline', +}; interface Props { - list: any[]; - updateList: any; + list: any[]; + updateList: any; } function FeatureSelection(props: Props) { - const { list } = props; - const features = [NETWORK, ERRORS, EVENTS, CLICKRAGE, PERFORMANCE]; - const disabled = list.length >= 3; + const { list } = props; + const features = [NETWORK, ERRORS, EVENTS, CLICKRAGE, PERFORMANCE]; + const disabled = list.length >= 3; - return ( - <React.Fragment> - {features.map((feature, index) => { - const checked = list.includes(feature); - const _disabled = disabled && !checked; - return ( - <Popup content="X-RAY supports up to 3 views" disabled={!_disabled} delay={0}> - <Checkbox - key={index} - label={feature} - checked={checked} - className="mx-4" - disabled={_disabled} - onClick={() => { - if (checked) { - props.updateList(list.filter((item: any) => item !== feature)); - } else { - props.updateList([...list, feature]); - } - }} - /> - </Popup> - ); - })} - </React.Fragment> - ); + return ( + <React.Fragment> + {features.map((feature, index) => { + const checked = list.includes(feature); + const _disabled = disabled && !checked; + return ( + <Tooltip key={index} title="X-RAY supports up to 3 views" disabled={!_disabled} delay={0}> + <Checkbox + key={index} + label={feature} + checked={checked} + className="mx-4" + disabled={_disabled} + onClick={() => { + if (checked) { + props.updateList(list.filter((item: any) => item !== feature)); + } else { + props.updateList([...list, feature]); + } + }} + /> + </Tooltip> + ); + })} + </React.Fragment> + ); } export default FeatureSelection; diff --git a/frontend/app/components/Session_/OverviewPanel/components/OverviewPanelContainer/OverviewPanelContainer.tsx b/frontend/app/components/Session_/OverviewPanel/components/OverviewPanelContainer/OverviewPanelContainer.tsx index 5a898c67e..e017fe1db 100644 --- a/frontend/app/components/Session_/OverviewPanel/components/OverviewPanelContainer/OverviewPanelContainer.tsx +++ b/frontend/app/components/Session_/OverviewPanel/components/OverviewPanelContainer/OverviewPanelContainer.tsx @@ -1,6 +1,6 @@ import React from 'react'; import VerticalLine from '../VerticalLine'; -import { connectPlayer, Controls } from 'App/player'; +import { connectPlayer, Controls } from 'Player'; interface Props { children: React.ReactNode; diff --git a/frontend/app/components/Session_/OverviewPanel/components/PerformanceGraph/PerformanceGraph.tsx b/frontend/app/components/Session_/OverviewPanel/components/PerformanceGraph/PerformanceGraph.tsx index 28193cd10..8da42f303 100644 --- a/frontend/app/components/Session_/OverviewPanel/components/PerformanceGraph/PerformanceGraph.tsx +++ b/frontend/app/components/Session_/OverviewPanel/components/PerformanceGraph/PerformanceGraph.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { connectPlayer } from 'App/player'; +import { connectPlayer } from 'Player'; import { AreaChart, Area, Tooltip, ResponsiveContainer } from 'recharts'; interface Props { diff --git a/frontend/app/components/Session_/OverviewPanel/components/TimelinePointer/TimelinePointer.tsx b/frontend/app/components/Session_/OverviewPanel/components/TimelinePointer/TimelinePointer.tsx index 3e7c4c6f9..5b6434794 100644 --- a/frontend/app/components/Session_/OverviewPanel/components/TimelinePointer/TimelinePointer.tsx +++ b/frontend/app/components/Session_/OverviewPanel/components/TimelinePointer/TimelinePointer.tsx @@ -1,10 +1,8 @@ import React from 'react'; -import { connectPlayer, Controls } from 'App/player'; -import { toggleBottomBlock, NETWORK, EXCEPTIONS, PERFORMANCE } from 'Duck/components/player'; +import { Controls } from 'Player'; +import { NETWORK, EXCEPTIONS } from 'Duck/components/player'; import { useModal } from 'App/components/Modal'; -import { Icon, ErrorDetails, Popup } from 'UI'; -import { Tooltip } from 'react-tippy'; -import { TYPES as EVENT_TYPES } from 'Types/session/event'; +import { Icon, Tooltip } from 'UI'; import StackEventModal from '../StackEventModal'; import ErrorDetailsModal from 'App/components/Dashboard/components/Errors/ErrorDetailsModal'; import FetchDetails from 'Shared/FetchDetailsModal'; @@ -13,10 +11,13 @@ import GraphQLDetailsModal from 'Shared/GraphQLDetailsModal'; interface Props { pointer: any; type: any; + noClick?: boolean; + fetchPresented?: boolean; } const TimelinePointer = React.memo((props: Props) => { - const { showModal, hideModal } = useModal(); + const { showModal } = useModal(); const createEventClickHandler = (pointer: any, type: any) => (e: any) => { + if (props.noClick) return; e.stopPropagation(); Controls.jump(pointer.time); if (!type) { @@ -35,7 +36,7 @@ const TimelinePointer = React.memo((props: Props) => { if (pointer.tp === 'graph_ql') { showModal(<GraphQLDetailsModal resource={pointer} />, { right: true }); } else { - showModal(<FetchDetails resource={pointer} />, { right: true }); + showModal(<FetchDetails resource={pointer} fetchPresented={props.fetchPresented} />, { right: true }); } } // props.toggleBottomBlock(type); @@ -44,52 +45,58 @@ const TimelinePointer = React.memo((props: Props) => { const renderNetworkElement = (item: any) => { const name = item.name || ''; return ( - <Popup - content={ + <Tooltip + title={ <div className=""> - <b>{item.success ? 'Slow resource: ' : 'Missing resource:'}</b> + <b>{item.success ? 'Slow resource: ' : '4xx/5xx Error:'}</b> <br /> - {name.length > 200 ? name.slice(0, 100) + ' ... ' + name.slice(-50) : name.length > 200 ? (item.name.slice(0, 100) + ' ... ' + item.name.slice(-50)) : item.name} + {name.length > 200 + ? name.slice(0, 100) + ' ... ' + name.slice(-50) + : name.length > 200 + ? item.name.slice(0, 100) + ' ... ' + item.name.slice(-50) + : item.name} </div> } delay={0} - position="top" + placement="top" > <div onClick={createEventClickHandler(item, NETWORK)} className="cursor-pointer"> - <div className="h-3 w-3 rounded-full bg-red" /> + <div className="h-4 w-4 rounded-full bg-red text-white font-bold flex items-center justify-center text-sm"> + <span>!</span> + </div> </div> - </Popup> + </Tooltip> ); }; const renderClickRageElement = (item: any) => { return ( - <Popup - content={ + <Tooltip + title={ <div className=""> <b>{'Click Rage'}</b> </div> } delay={0} - position="top" + placement="top" > <div onClick={createEventClickHandler(item, null)} className="cursor-pointer"> <Icon className="bg-white" name="funnel/emoji-angry" color="red" size="16" /> </div> - </Popup> + </Tooltip> ); }; const renderStackEventElement = (item: any) => { return ( - <Popup - content={ + <Tooltip + title={ <div className=""> <b>{'Stack Event'}</b> </div> } delay={0} - position="top" + placement="top" > <div onClick={createEventClickHandler(item, 'EVENT')} @@ -97,20 +104,20 @@ const TimelinePointer = React.memo((props: Props) => { > {/* <Icon className="rounded-full bg-white" name="funnel/exclamation-circle-fill" color="red" size="16" /> */} </div> - </Popup> + </Tooltip> ); }; const renderPerformanceElement = (item: any) => { return ( - <Popup - content={ + <Tooltip + title={ <div className=""> <b>{item.type}</b> </div> } delay={0} - position="top" + placement="top" > <div onClick={createEventClickHandler(item, EXCEPTIONS)} @@ -118,14 +125,14 @@ const TimelinePointer = React.memo((props: Props) => { > {/* <Icon className="rounded-full bg-white" name="funnel/exclamation-circle-fill" color="red" size="16" /> */} </div> - </Popup> + </Tooltip> ); }; const renderExceptionElement = (item: any) => { return ( - <Popup - content={ + <Tooltip + title={ <div className=""> <b>{'Exception'}</b> <br /> @@ -133,17 +140,14 @@ const TimelinePointer = React.memo((props: Props) => { </div> } delay={0} - position="top" + placement="top" > <div onClick={createEventClickHandler(item, 'ERRORS')} className="cursor-pointer"> - <Icon - className="rounded-full bg-white" - name="funnel/exclamation-circle-fill" - color="red" - size="16" - /> + <div className="h-4 w-4 rounded-full bg-red text-white font-bold flex items-center justify-center text-sm"> + <span>!</span> + </div> </div> - </Popup> + </Tooltip> ); }; diff --git a/frontend/app/components/Session_/OverviewPanel/components/TimelineScale/TimelineScale.tsx b/frontend/app/components/Session_/OverviewPanel/components/TimelineScale/TimelineScale.tsx index 3b7fc453e..3905f4538 100644 --- a/frontend/app/components/Session_/OverviewPanel/components/TimelineScale/TimelineScale.tsx +++ b/frontend/app/components/Session_/OverviewPanel/components/TimelineScale/TimelineScale.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { connectPlayer } from 'App/player'; +import { connectPlayer } from 'Player'; import { millisToMinutesAndSeconds } from 'App/utils'; interface Props { diff --git a/frontend/app/components/Session_/OverviewPanel/components/VerticalPointerLine/VerticalPointerLine.tsx b/frontend/app/components/Session_/OverviewPanel/components/VerticalPointerLine/VerticalPointerLine.tsx index 8db015447..688e8364c 100644 --- a/frontend/app/components/Session_/OverviewPanel/components/VerticalPointerLine/VerticalPointerLine.tsx +++ b/frontend/app/components/Session_/OverviewPanel/components/VerticalPointerLine/VerticalPointerLine.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { connectPlayer } from 'App/player'; +import { connectPlayer } from 'Player'; import VerticalLine from '../VerticalLine'; interface Props { - time: number; - scale: number; + time?: number; + scale?: number; } function VerticalPointerLine(props: Props) { const { time, scale } = props; diff --git a/frontend/app/components/Session_/PageInsightsPanel/components/SelectorCard/SelectorCard.tsx b/frontend/app/components/Session_/PageInsightsPanel/components/SelectorCard/SelectorCard.tsx index 9a3ecc210..999dae866 100644 --- a/frontend/app/components/Session_/PageInsightsPanel/components/SelectorCard/SelectorCard.tsx +++ b/frontend/app/components/Session_/PageInsightsPanel/components/SelectorCard/SelectorCard.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import stl from './SelectorCard.module.css'; import cn from 'classnames'; -import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen'; +import type { MarkedTarget } from 'Player'; import { activeTarget } from 'Player'; import { Tooltip } from 'react-tippy'; diff --git a/frontend/app/components/Session_/PageInsightsPanel/components/SelectorsList/SelectorsList.tsx b/frontend/app/components/Session_/PageInsightsPanel/components/SelectorsList/SelectorsList.tsx index 86274baba..14080e718 100644 --- a/frontend/app/components/Session_/PageInsightsPanel/components/SelectorsList/SelectorsList.tsx +++ b/frontend/app/components/Session_/PageInsightsPanel/components/SelectorsList/SelectorsList.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { NoContent } from 'UI'; -import { connectPlayer } from 'Player/store'; +import { connectPlayer } from 'Player'; import SelectorCard from '../SelectorCard/SelectorCard'; -import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen'; +import type { MarkedTarget } from 'Player'; import stl from './selectorList.module.css'; interface Props { diff --git a/frontend/app/components/Session_/Performance/Performance.tsx b/frontend/app/components/Session_/Performance/Performance.tsx index 13c135f7b..994401141 100644 --- a/frontend/app/components/Session_/Performance/Performance.tsx +++ b/frontend/app/components/Session_/Performance/Performance.tsx @@ -2,13 +2,13 @@ import React from 'react'; import { connect } from 'react-redux'; import { Controls as PlayerControls, connectPlayer } from 'Player'; import { - AreaChart, + AreaChart, Area, ComposedChart, Line, - XAxis, + XAxis, YAxis, - Tooltip, + Tooltip, ResponsiveContainer, ReferenceLine, CartesianGrid, @@ -23,40 +23,35 @@ import stl from './performance.module.css'; import BottomBlock from '../BottomBlock'; import InfoLine from '../BottomBlock/InfoLine'; - const CPU_VISUAL_OFFSET = 10; - const FPS_COLOR = '#C5E5E7'; -const FPS_STROKE_COLOR = "#92C7CA"; -const FPS_LOW_COLOR = "pink"; -const FPS_VERY_LOW_COLOR = "red"; -const CPU_COLOR = "#A8D1DE"; -const CPU_STROKE_COLOR = "#69A5B8"; +const FPS_STROKE_COLOR = '#92C7CA'; +const FPS_LOW_COLOR = 'pink'; +const FPS_VERY_LOW_COLOR = 'red'; +const CPU_COLOR = '#A8D1DE'; +const CPU_STROKE_COLOR = '#69A5B8'; const USED_HEAP_COLOR = '#A9ABDC'; -const USED_HEAP_STROKE_COLOR = "#8588CF"; +const USED_HEAP_STROKE_COLOR = '#8588CF'; const TOTAL_HEAP_STROKE_COLOR = '#4A4EB7'; -const NODES_COUNT_COLOR = "#C6A9DC"; -const NODES_COUNT_STROKE_COLOR = "#7360AC"; -const HIDDEN_SCREEN_COLOR = "#CCC"; +const NODES_COUNT_COLOR = '#C6A9DC'; +const NODES_COUNT_STROKE_COLOR = '#7360AC'; +const HIDDEN_SCREEN_COLOR = '#CCC'; - -const CURSOR_COLOR = "#394EFF"; +const CURSOR_COLOR = '#394EFF'; const Gradient = ({ color, id }) => ( - <linearGradient id={ id } x1="-1" y1="0" x2="0" y2="1"> - <stop offset="5%" stopColor={ color } stopOpacity={ 0.7 } /> - <stop offset="95%" stopColor={ color } stopOpacity={ 0.2 } /> + <linearGradient id={id} x1="-1" y1="0" x2="0" y2="1"> + <stop offset="5%" stopColor={color} stopOpacity={0.7} /> + <stop offset="95%" stopColor={color} stopOpacity={0.2} /> </linearGradient> ); - -const TOTAL_HEAP = "Allocated Heap"; -const USED_HEAP = "JS Heap"; -const FPS = "Framerate"; -const CPU = "CPU Load"; -const NODES_COUNT = "Nodes Сount"; - +const TOTAL_HEAP = 'Allocated Heap'; +const USED_HEAP = 'JS Heap'; +const FPS = 'Framerate'; +const CPU = 'CPU Load'; +const NODES_COUNT = 'Nodes Сount'; const FPSTooltip = ({ active, payload }) => { if (!active || !payload || payload.length < 3) { @@ -64,8 +59,8 @@ const FPSTooltip = ({ active, payload }) => { } if (payload[0].value === null) { return ( - <div className={ stl.tooltipWrapper } style={{ color: HIDDEN_SCREEN_COLOR }}> - {"Page is not active. User switched the tab or hid the window."} + <div className={stl.tooltipWrapper} style={{ color: HIDDEN_SCREEN_COLOR }}> + {'Page is not active. User switched the tab or hid the window.'} </div> ); } @@ -79,9 +74,9 @@ const FPSTooltip = ({ active, payload }) => { } return ( - <div className={ stl.tooltipWrapper } style={ style }> - <span className="font-medium">{`${ FPS }: `}</span> - { Math.trunc(payload[0].value) } + <div className={stl.tooltipWrapper} style={style}> + <span className="font-medium">{`${FPS}: `}</span> + {Math.trunc(payload[0].value)} </div> ); }; @@ -91,47 +86,47 @@ const CPUTooltip = ({ active, payload }) => { return null; } return ( - <div className={ stl.tooltipWrapper } > - <span className="font-medium">{`${ CPU }: `}</span> - { payload[0].value - CPU_VISUAL_OFFSET } - {"%"} + <div className={stl.tooltipWrapper}> + <span className="font-medium">{`${CPU}: `}</span> + {payload[0].value - CPU_VISUAL_OFFSET} + {'%'} </div> ); }; -const HeapTooltip = ({ active, payload}) => { +const HeapTooltip = ({ active, payload }) => { if (!active || payload.length < 2) return null; return ( - <div className={ stl.tooltipWrapper } > + <div className={stl.tooltipWrapper}> <p> - <span className="font-medium">{`${ TOTAL_HEAP }: `}</span> - { formatBytes(payload[0].value)} + <span className="font-medium">{`${TOTAL_HEAP}: `}</span> + {formatBytes(payload[0].value)} </p> <p> - <span className="font-medium">{`${ USED_HEAP }: `}</span> - { formatBytes(payload[1].value)} + <span className="font-medium">{`${USED_HEAP}: `}</span> + {formatBytes(payload[1].value)} </p> </div> ); -} +}; -const NodesCountTooltip = ({ active, payload} ) => { +const NodesCountTooltip = ({ active, payload }) => { if (!active || !payload || payload.length === 0) return null; return ( - <div className={ stl.tooltipWrapper } > + <div className={stl.tooltipWrapper}> <p> - <span className="font-medium">{`${ NODES_COUNT }: `}</span> - { payload[0].value } + <span className="font-medium">{`${NODES_COUNT}: `}</span> + {payload[0].value} </p> </div> ); -} +}; const TICKS_COUNT = 10; function generateTicks(data: Array<Timed>): Array<number> { if (data.length === 0) return []; const minTime = data[0].time; - const maxTime = data[data.length-1].time; + const maxTime = data[data.length - 1].time; const ticks = []; const tickGap = (maxTime - minTime) / (TICKS_COUNT + 1); @@ -159,8 +154,9 @@ function addFpsMetadata(data) { } else if (point.fps < LOW_FPS) { fpsLowMarker = LOW_FPS_MARKER_VALUE; } - } - if (point.fps == null || + } + if ( + point.fps == null || (i > 0 && data[i - 1].fps == null) //|| //(i < data.length-1 && data[i + 1].fps == null) ) { @@ -174,17 +170,17 @@ function addFpsMetadata(data) { fpsLowMarker, fpsVeryLowMarker, hiddenScreenMarker, - } + }; }); } -@connect(state => ({ - userDeviceHeapSize: state.getIn([ "sessions", "current", "userDeviceHeapSize" ]), - userDeviceMemorySize: state.getIn([ "sessions", "current", "userDeviceMemorySize" ]), +@connect((state) => ({ + userDeviceHeapSize: state.getIn(['sessions', 'current', 'userDeviceHeapSize']), + userDeviceMemorySize: state.getIn(['sessions', 'current', 'userDeviceMemorySize']), })) export default class Performance extends React.PureComponent { - _timeTicks = generateTicks(this.props.performanceChartData) - _data = addFpsMetadata(this.props.performanceChartData) + _timeTicks = generateTicks(this.props.performanceChartData); + _data = addFpsMetadata(this.props.performanceChartData); // state = { // totalHeap: false, // usedHeap: true, @@ -197,7 +193,7 @@ export default class Performance extends React.PureComponent { if (!!point) { PlayerControls.jump(point.time); } - } + }; onChartClick = (e) => { if (e === null) return; @@ -206,10 +202,10 @@ export default class Performance extends React.PureComponent { if (!!point) { PlayerControls.jump(point.time); } - } + }; render() { - const { + const { userDeviceHeapSize, userDeviceMemorySize, connType, @@ -218,19 +214,19 @@ export default class Performance extends React.PureComponent { avaliability = {}, } = this.props; const { fps, cpu, heap, nodes } = avaliability; - const avaliableCount = [ fps, cpu, heap, nodes ].reduce((c, av) => av ? c + 1 : c, 0); - const height = avaliableCount === 0 ? "0" : `${100 / avaliableCount}%`; + const avaliableCount = [fps, cpu, heap, nodes].reduce((c, av) => (av ? c + 1 : c), 0); + const height = avaliableCount === 0 ? '0' : `${100 / avaliableCount}%`; return ( <BottomBlock> <BottomBlock.Header> - <div className="flex items-center"> - <span className="font-semibold color-gray-medium mr-4">Performance</span> + <div className="flex items-center w-full"> + <div className="font-semibold color-gray-medium mr-auto">Performance</div> <InfoLine> <InfoLine.Point label="Device Heap Size" - value={ formatBytes(userDeviceHeapSize) } - display={ userDeviceHeapSize != null } + value={formatBytes(userDeviceHeapSize)} + display={true} /> {/* <InfoLine.Point */} {/* label="Device Memory Size" */} @@ -238,55 +234,52 @@ export default class Performance extends React.PureComponent { {/* /> */} <InfoLine.Point label="Connection Type" - value={ connType } - display={ connType != null && connType !== "unknown" } + value={connType} + display={connType != null && connType !== 'unknown'} /> <InfoLine.Point label="Connection Speed" - value={ connBandwidth >= 1000 - ? `${ connBandwidth / 1000 } Mbps` - : `${ connBandwidth } Kbps` + value={ + connBandwidth >= 1000 ? `${connBandwidth / 1000} Mbps` : `${connBandwidth} Kbps` } - display={ connBandwidth != null } + display={connBandwidth != null} /> </InfoLine> </div> </BottomBlock.Header> <BottomBlock.Content> - { fps && - <ResponsiveContainer height={ height }> + {fps && ( + <ResponsiveContainer height={height}> <AreaChart - onClick={ this.onChartClick } + onClick={this.onChartClick} data={this._data} syncId="s" margin={{ - top: 0, right: 0, left: 0, bottom: 0, + top: 0, + right: 0, + left: 0, + bottom: 0, }} > <defs> - <Gradient id="fpsGradient" color={ FPS_COLOR } /> + <Gradient id="fpsGradient" color={FPS_COLOR} /> </defs> {/* <CartesianGrid strokeDasharray="1 1" stroke="#ddd" horizontal={ false } /> */} {/* <CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" /> */} - <XAxis + <XAxis dataKey="time" type="number" mirror orientation="top" - tickLine={ false } - tickFormatter={ durationFromMsFormatted } - tick={{ fontSize: "12px" }} + tickLine={false} + tickFormatter={durationFromMsFormatted} + tick={{ fontSize: '12px', fill: '#333' }} domain={[0, 'dataMax']} ticks={this._timeTicks} > - <Label value="FPS" position="insideTopRight" className="fill-gray-medium" /> + <Label value="FPS" position="insideTopRight" className="fill-gray-darkest" /> </XAxis> - <YAxis - axisLine={ false } - tick={ false } - mirror - domain={[0, 85]} - /> + <YAxis axisLine={false} tick={false} mirror domain={[0, 85]} /> {/* <YAxis */} {/* yAxisId="r" */} {/* axisLine={ false } */} @@ -295,41 +288,41 @@ export default class Performance extends React.PureComponent { {/* domain={[0, 120]} */} {/* orientation="right" */} {/* /> */} - <Area - dataKey="fps" - type="stepBefore" + <Area + dataKey="fps" + type="stepBefore" stroke={FPS_STROKE_COLOR} fill="url(#fpsGradient)" dot={false} - activeDot={{ + activeDot={{ onClick: this.onDotClick, - style: { cursor: "pointer" }, - }} - isAnimationActive={ false } - /> + style: { cursor: 'pointer' }, + }} + isAnimationActive={false} + /> <Area - dataKey="fpsLowMarker" + dataKey="fpsLowMarker" type="stepBefore" stroke="none" - fill={ FPS_LOW_COLOR } + fill={FPS_LOW_COLOR} activeDot={false} - isAnimationActive={ false } + isAnimationActive={false} /> - <Area + <Area dataKey="fpsVeryLowMarker" type="stepBefore" stroke="none" - fill={ FPS_VERY_LOW_COLOR } + fill={FPS_VERY_LOW_COLOR} activeDot={false} - isAnimationActive={ false } + isAnimationActive={false} /> <Area dataKey="hiddenScreenMarker" type="stepBefore" stroke="none" - fill={ HIDDEN_SCREEN_COLOR } + fill={HIDDEN_SCREEN_COLOR} activeDot={false} - isAnimationActive={ false } + isAnimationActive={false} /> {/* <Area */} {/* yAxisId="r" */} @@ -346,101 +339,95 @@ export default class Performance extends React.PureComponent { {/* isAnimationActive={ false } */} {/* /> */} <ReferenceLine x={performanceChartTime} stroke={CURSOR_COLOR} /> - <Tooltip - content={FPSTooltip} - filterNull={ false } - /> + <Tooltip content={FPSTooltip} filterNull={false} /> </AreaChart> </ResponsiveContainer> - } - { cpu && - <ResponsiveContainer height={ height }> + )} + {cpu && ( + <ResponsiveContainer height={height}> <AreaChart - onClick={ this.onChartClick } + onClick={this.onChartClick} data={this._data} syncId="s" margin={{ - top: 0, right: 0, left: 0, bottom: 0, + top: 0, + right: 0, + left: 0, + bottom: 0, }} > <defs> - <Gradient id="cpuGradient" color={ CPU_COLOR } /> + <Gradient id="cpuGradient" color={CPU_COLOR} /> </defs> {/* <CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" /> */} - <XAxis - dataKey="time" - type="number" - mirror - orientation="top" - tickLine={false} - tickFormatter={()=> ""} - domain={[0, 'dataMax']} - ticks={this._timeTicks} - > - <Label value="CPU" position="insideTopRight" className="fill-gray-medium" /> - </XAxis> - <YAxis - axisLine={ false } - tick={ false } - mirror - domain={[ 0, 120]} - orientation="right" - /> - <Area - dataKey="cpu" - type="monotone" - stroke={CPU_STROKE_COLOR} - // fill="none" - fill="url(#cpuGradient)" - dot={false} - activeDot={{ - onClick: this.onDotClick, - style: { cursor: "pointer" }, - }} - isAnimationActive={ false } - /> - <Area - dataKey="hiddenScreenMarker" - type="stepBefore" - stroke="none" - fill={ HIDDEN_SCREEN_COLOR } - activeDot={false} - isAnimationActive={ false } - /> - <ReferenceLine x={performanceChartTime} stroke={CURSOR_COLOR} /> - <Tooltip - content={CPUTooltip} - filterNull={ false } - /> - </AreaChart> - </ResponsiveContainer> - } - - { heap && - <ResponsiveContainer height={ height }> - <ComposedChart - onClick={ this.onChartClick } - data={this._data} - margin={{ - top: 0, right: 0, left: 0, bottom: 0, - }} - syncId="s" - > - <defs> - <Gradient id="usedHeapGradient" color={ USED_HEAP_COLOR } /> - </defs> - {/* <CartesianGrid strokeDasharray="1 1" stroke="#ddd" horizontal={ false } /> */} - <XAxis + <XAxis dataKey="time" type="number" mirror orientation="top" tickLine={false} - tickFormatter={()=> ""} // tick={false} + this._timeTicks to cartesian array + tickFormatter={() => ''} domain={[0, 'dataMax']} ticks={this._timeTicks} > - <Label value="HEAP" position="insideTopRight" className="fill-gray-medium" /> + <Label value="CPU" position="insideTopRight" className="fill-gray-darkest" /> + </XAxis> + <YAxis axisLine={false} tick={false} mirror domain={[0, 120]} orientation="right" /> + <Area + dataKey="cpu" + type="monotone" + stroke={CPU_STROKE_COLOR} + // fill="none" + fill="url(#cpuGradient)" + dot={false} + activeDot={{ + onClick: this.onDotClick, + style: { cursor: 'pointer' }, + }} + isAnimationActive={false} + /> + <Area + dataKey="hiddenScreenMarker" + type="stepBefore" + stroke="none" + fill={HIDDEN_SCREEN_COLOR} + activeDot={false} + isAnimationActive={false} + /> + <ReferenceLine x={performanceChartTime} stroke={CURSOR_COLOR} /> + <Tooltip content={CPUTooltip} filterNull={false} /> + </AreaChart> + </ResponsiveContainer> + )} + + {heap && ( + <ResponsiveContainer height={height}> + <ComposedChart + onClick={this.onChartClick} + data={this._data} + margin={{ + top: 0, + right: 0, + left: 0, + bottom: 0, + }} + syncId="s" + > + <defs> + <Gradient id="usedHeapGradient" color={USED_HEAP_COLOR} /> + </defs> + {/* <CartesianGrid strokeDasharray="1 1" stroke="#ddd" horizontal={ false } /> */} + <XAxis + dataKey="time" + type="number" + mirror + orientation="top" + tickLine={false} + tickFormatter={() => ''} // tick={false} + this._timeTicks to cartesian array + domain={[0, 'dataMax']} + ticks={this._timeTicks} + > + <Label value="HEAP" position="insideTopRight" className="fill-gray-darkest" /> </XAxis> <YAxis axisLine={false} @@ -448,19 +435,19 @@ export default class Performance extends React.PureComponent { mirror // Hack to keep only end tick minTickGap={Number.MAX_SAFE_INTEGER} - domain={[0, max => max*1.2]} + domain={[0, (max) => max * 1.2]} /> - <Line + <Line type="monotone" dataKey="totalHeap" // fill="url(#totalHeapGradient)" stroke={TOTAL_HEAP_STROKE_COLOR} dot={false} - activeDot={{ + activeDot={{ onClick: this.onDotClick, - style: { cursor: "pointer" }, + style: { cursor: 'pointer' }, }} - isAnimationActive={ false } + isAnimationActive={false} /> <Area dataKey="usedHeap" @@ -468,81 +455,78 @@ export default class Performance extends React.PureComponent { fill="url(#usedHeapGradient)" stroke={USED_HEAP_STROKE_COLOR} dot={false} - activeDot={{ + activeDot={{ onClick: this.onDotClick, - style: { cursor: "pointer" }, - }} - isAnimationActive={ false } + style: { cursor: 'pointer' }, + }} + isAnimationActive={false} /> <ReferenceLine x={performanceChartTime} stroke={CURSOR_COLOR} /> - <Tooltip - content={HeapTooltip} - filterNull={ false } - /> + <Tooltip content={HeapTooltip} filterNull={false} /> </ComposedChart> </ResponsiveContainer> - } - { nodes && - <ResponsiveContainer height={ height }> + )} + {nodes && ( + <ResponsiveContainer height={height}> <AreaChart - onClick={ this.onChartClick } + onClick={this.onChartClick} data={this._data} syncId="s" margin={{ - top: 0, right: 0, left: 0, bottom: 0, + top: 0, + right: 0, + left: 0, + bottom: 0, }} > <defs> - <Gradient id="nodesGradient" color={ NODES_COUNT_COLOR } /> + <Gradient id="nodesGradient" color={NODES_COUNT_COLOR} /> </defs> {/* <CartesianGrid strokeDasharray="1 1" stroke="#ddd" horizontal={ false } /> */} - <XAxis - dataKey="time" - type="number" - mirror - orientation="top" - tickLine={false} - tickFormatter={()=> ""} - domain={[0, 'dataMax']} - ticks={this._timeTicks} - > - <Label value="NODES" position="insideTopRight" className="fill-gray-medium" /> + <XAxis + dataKey="time" + type="number" + mirror + orientation="top" + tickLine={false} + tickFormatter={() => ''} + domain={[0, 'dataMax']} + ticks={this._timeTicks} + > + <Label value="NODES" position="insideTopRight" className="fill-gray-darkest" /> </XAxis> <YAxis - axisLine={ false } - tick={ false } + axisLine={false} + tick={false} mirror orientation="right" - domain={[0, max => max*1.2]} + domain={[0, (max) => max * 1.2]} /> - <Area - dataKey="nodesCount" - type="monotone" + <Area + dataKey="nodesCount" + type="monotone" stroke={NODES_COUNT_STROKE_COLOR} // fill="none" fill="url(#nodesGradient)" dot={false} - activeDot={{ + activeDot={{ onClick: this.onDotClick, - style: { cursor: "pointer" }, - }} - isAnimationActive={ false } - /> - <ReferenceLine x={performanceChartTime} stroke={CURSOR_COLOR} /> - <Tooltip - content={NodesCountTooltip} - filterNull={ false } + style: { cursor: 'pointer' }, + }} + isAnimationActive={false} /> + <ReferenceLine x={performanceChartTime} stroke={CURSOR_COLOR} /> + <Tooltip content={NodesCountTooltip} filterNull={false} /> </AreaChart> </ResponsiveContainer> - } + )} </BottomBlock.Content> </BottomBlock> ); } } -export const ConnectedPerformance = connectPlayer(state => ({ +export const ConnectedPerformance = connectPlayer((state) => ({ performanceChartTime: state.performanceChartTime, performanceChartData: state.performanceChartData, connType: state.connType, diff --git a/frontend/app/components/Session_/Performance/performance.module.css b/frontend/app/components/Session_/Performance/performance.module.css index 4bd075eec..5c2b85578 100644 --- a/frontend/app/components/Session_/Performance/performance.module.css +++ b/frontend/app/components/Session_/Performance/performance.module.css @@ -3,4 +3,5 @@ padding: 2px 5px; border-radius: 3px; border: 1px solid #ccc; + color: $gray-dark !important; } \ No newline at end of file diff --git a/frontend/app/components/Session_/Player/Controls/ControlButton.js b/frontend/app/components/Session_/Player/Controls/ControlButton.js index 31672c301..3c42895b6 100644 --- a/frontend/app/components/Session_/Player/Controls/ControlButton.js +++ b/frontend/app/components/Session_/Player/Controls/ControlButton.js @@ -8,7 +8,7 @@ const ControlButton = ({ icon = '', disabled = false, onClick, - count = 0, + // count = 0, hasErrors = false, active = false, size = 20, @@ -31,7 +31,7 @@ const ControlButton = ({ > <div className={stl.labels}> {hasErrors && <div className={stl.errorSymbol} />} - {count > 0 && <div className={stl.countLabel}>{count}</div>} + {/* {count > 0 && <div className={stl.countLabel}>{count}</div>} */} </div> {!noIcon && <Icon name={icon} size={size} color="gray-dark" />} {!noLabel && ( diff --git a/frontend/app/components/Session_/Player/Controls/Controls.js b/frontend/app/components/Session_/Player/Controls/Controls.js index 5109bf96b..005403731 100644 --- a/frontend/app/components/Session_/Player/Controls/Controls.js +++ b/frontend/app/components/Session_/Player/Controls/Controls.js @@ -6,11 +6,11 @@ import { STORAGE_TYPES, selectStorageType, selectStorageListNow, -} from 'Player/store'; +} from 'Player'; import LiveTag from 'Shared/LiveTag'; -import { toggleTimetravel, jumpToLive } from 'Player'; +import { jumpToLive } from 'Player'; -import { Icon } from 'UI'; +import { Icon, Tooltip } from 'UI'; import { toggleInspectorMode } from 'Player'; import { fullscreenOn, @@ -25,8 +25,6 @@ import { PROFILER, PERFORMANCE, GRAPHQL, - FETCH, - EXCEPTIONS, INSPECTOR, } from 'Duck/components/player'; import { AssistDuration } from './Time'; @@ -35,26 +33,8 @@ import ControlButton from './ControlButton'; import PlayerControls from './components/PlayerControls'; import styles from './controls.module.css'; -import { Tooltip } from 'react-tippy'; import XRayButton from 'Shared/XRayButton'; -function getStorageIconName(type) { - switch (type) { - case STORAGE_TYPES.REDUX: - return 'vendors/redux'; - case STORAGE_TYPES.MOBX: - return 'vendors/mobx'; - case STORAGE_TYPES.VUEX: - return 'vendors/vuex'; - case STORAGE_TYPES.NGRX: - return 'vendors/ngrx'; - case STORAGE_TYPES.ZUSTAND: - return 'vendors/zustand'; - case STORAGE_TYPES.NONE: - return 'store'; - } -} - const SKIP_INTERVALS = { 2: 2e3, 5: 5e3, @@ -95,25 +75,23 @@ function getStorageName(type) { disabled: state.cssLoading || state.messagesLoading || state.inspectorMode || state.markedTargets, inspectorMode: state.inspectorMode, fullscreenDisabled: state.messagesLoading, - logCount: state.logListNow.length, - logRedCount: state.logRedCountNow, - resourceRedCount: state.resourceRedCountNow, - fetchRedCount: state.fetchRedCountNow, + // logCount: state.logList.length, + logRedCount: state.logMarkedCount, + showExceptions: state.exceptionsList.length > 0, + resourceRedCount: state.resourceMarkedCount, + fetchRedCount: state.fetchMarkedCount, showStack: state.stackList.length > 0, - stackCount: state.stackListNow.length, - stackRedCount: state.stackRedCountNow, - profilesCount: state.profilesListNow.length, + stackCount: state.stackList.length, + stackRedCount: state.stackMarkedCount, + profilesCount: state.profilesList.length, storageCount: selectStorageListNow(state).length, storageType: selectStorageType(state), showStorage: selectStorageType(state) !== STORAGE_TYPES.NONE, showProfiler: state.profilesList.length > 0, showGraphql: state.graphqlList.length > 0, showFetch: state.fetchCount > 0, - fetchCount: state.fetchCountNow, - graphqlCount: state.graphqlListNow.length, - exceptionsCount: state.exceptionsListNow.length, - showExceptions: state.exceptionsList.length > 0, - showLongtasks: state.longtasksList.length > 0, + fetchCount: state.fetchCount, + graphqlCount: state.graphqlList.length, liveTimeTravel: state.liveTimeTravel, })) @connect( @@ -163,8 +141,9 @@ export default class Controls extends React.Component { nextProps.disabled !== this.props.disabled || nextProps.fullscreenDisabled !== this.props.fullscreenDisabled || // nextProps.inspectorMode !== this.props.inspectorMode || - nextProps.logCount !== this.props.logCount || + // nextProps.logCount !== this.props.logCount || nextProps.logRedCount !== this.props.logRedCount || + nextProps.showExceptions !== this.props.showExceptions || nextProps.resourceRedCount !== this.props.resourceRedCount || nextProps.fetchRedCount !== this.props.fetchRedCount || nextProps.showStack !== this.props.showStack || @@ -179,9 +158,6 @@ export default class Controls extends React.Component { nextProps.showFetch !== this.props.showFetch || nextProps.fetchCount !== this.props.fetchCount || nextProps.graphqlCount !== this.props.graphqlCount || - nextProps.showExceptions !== this.props.showExceptions || - nextProps.exceptionsCount !== this.props.exceptionsCount || - nextProps.showLongtasks !== this.props.showLongtasks || nextProps.liveTimeTravel !== this.props.liveTimeTravel || nextProps.skipInterval !== this.props.skipInterval ) @@ -227,7 +203,7 @@ export default class Controls extends React.Component { backTenSeconds = () => { //shouldComponentUpdate const { time, jump, skipInterval } = this.props; - jump(Math.max(0, time - SKIP_INTERVALS[skipInterval])); + jump(Math.max(1, time - SKIP_INTERVALS[skipInterval])); }; goLive = () => this.props.jump(this.props.endTime); @@ -250,11 +226,7 @@ export default class Controls extends React.Component { return ( <Tooltip - delay={0} - position="top" title={label} - interactive - hideOnClick="persistent" className="mr-4" > <div @@ -270,7 +242,7 @@ export default class Controls extends React.Component { controlIcon = (icon, size, action, isBackwards, additionalClasses) => ( <div onClick={action} - className={cn('py-1 px-2 hover-main cursor-pointer bg-gray-lightest', additionalClasses)} + className={cn('py-2 px-2 hover-main cursor-pointer bg-gray-lightest', additionalClasses)} style={{ transform: isBackwards ? 'rotate(180deg)' : '' }} > <Icon name={icon} size={size} color="inherit" /> @@ -286,24 +258,16 @@ export default class Controls extends React.Component { skip, speed, disabled, - logCount, logRedCount, + showExceptions, resourceRedCount, fetchRedCount, showStack, - stackCount, stackRedCount, - profilesCount, - storageCount, showStorage, storageType, showProfiler, showGraphql, - showFetch, - fetchCount, - graphqlCount, - exceptionsCount, - showExceptions, fullscreen, inspectorMode, closedLive, @@ -380,8 +344,7 @@ export default class Controls extends React.Component { label="CONSOLE" noIcon labelClassName="!text-base font-semibold" - count={logCount} - hasErrors={logRedCount > 0} + hasErrors={logRedCount > 0 || showExceptions} containerClassName="mx-2" /> {!live && ( @@ -390,7 +353,7 @@ export default class Controls extends React.Component { onClick={() => toggleBottomTools(NETWORK)} active={bottomBlock === NETWORK && !inspectorMode} label="NETWORK" - hasErrors={resourceRedCount > 0} + hasErrors={resourceRedCount > 0 || fetchRedCount > 0} noIcon labelClassName="!text-base font-semibold" containerClassName="mx-2" @@ -407,25 +370,11 @@ export default class Controls extends React.Component { containerClassName="mx-2" /> )} - {showFetch && ( - <ControlButton - disabled={disabled && !inspectorMode} - onClick={() => toggleBottomTools(FETCH)} - active={bottomBlock === FETCH && !inspectorMode} - hasErrors={fetchRedCount > 0} - count={fetchCount} - label="FETCH" - noIcon - labelClassName="!text-base font-semibold" - containerClassName="mx-2" - /> - )} {!live && showGraphql && ( <ControlButton disabled={disabled && !inspectorMode} onClick={() => toggleBottomTools(GRAPHQL)} active={bottomBlock === GRAPHQL && !inspectorMode} - count={graphqlCount} label="GRAPHQL" noIcon labelClassName="!text-base font-semibold" @@ -437,27 +386,13 @@ export default class Controls extends React.Component { disabled={disabled && !inspectorMode} onClick={() => toggleBottomTools(STORAGE)} active={bottomBlock === STORAGE && !inspectorMode} - count={storageCount} label={getStorageName(storageType)} noIcon labelClassName="!text-base font-semibold" containerClassName="mx-2" /> )} - {showExceptions && ( - <ControlButton - disabled={disabled && !inspectorMode} - onClick={() => toggleBottomTools(EXCEPTIONS)} - active={bottomBlock === EXCEPTIONS && !inspectorMode} - label="EXCEPTIONS" - noIcon - labelClassName="!text-base font-semibold" - containerClassName="mx-2" - count={exceptionsCount} - hasErrors={exceptionsCount > 0} - /> - )} - {!live && showStack && ( + {!live && ( <ControlButton disabled={disabled && !inspectorMode} onClick={() => toggleBottomTools(STACKEVENTS)} @@ -466,7 +401,6 @@ export default class Controls extends React.Component { noIcon labelClassName="!text-base font-semibold" containerClassName="mx-2" - count={stackCount} hasErrors={stackRedCount > 0} /> )} @@ -475,7 +409,6 @@ export default class Controls extends React.Component { disabled={disabled && !inspectorMode} onClick={() => toggleBottomTools(PROFILER)} active={bottomBlock === PROFILER && !inspectorMode} - count={profilesCount} label="PROFILER" noIcon labelClassName="!text-base font-semibold" diff --git a/frontend/app/components/Session_/Player/Controls/Time.js b/frontend/app/components/Session_/Player/Controls/Time.js index ca3c6ce4c..e8221b5b8 100644 --- a/frontend/app/components/Session_/Player/Controls/Time.js +++ b/frontend/app/components/Session_/Player/Controls/Time.js @@ -2,7 +2,6 @@ import React from 'react'; import { Duration } from 'luxon'; import { connectPlayer } from 'Player'; import styles from './time.module.css'; -import { Tooltip } from 'react-tippy'; const Time = ({ time, isCustom, format = 'm:ss', }) => ( <div className={ !isCustom ? styles.time : undefined }> diff --git a/frontend/app/components/Session_/Player/Controls/TimeTooltip.tsx b/frontend/app/components/Session_/Player/Controls/TimeTooltip.tsx deleted file mode 100644 index fe22c4ea9..000000000 --- a/frontend/app/components/Session_/Player/Controls/TimeTooltip.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; -// @ts-ignore -import { Duration } from 'luxon'; -import { connect } from 'react-redux'; -// @ts-ignore -import stl from './timeline.module.css'; - -function TimeTooltip({ time, offset, isVisible, liveTimeTravel }: { time: number; offset: number; isVisible: boolean, liveTimeTravel: boolean }) { - const duration = Duration.fromMillis(time).toFormat(`${liveTimeTravel ? '-' : ''}mm:ss`); - return ( - <div - className={stl.timeTooltip} - style={{ - top: -30, - left: offset - 20, - display: isVisible ? 'block' : 'none' } - } - > - {!time ? 'Loading' : duration} - </div> - ); -} - -export default connect((state) => { - const { time = 0, offset = 0, isVisible } = state.getIn(['sessions', 'timeLineTooltip']); - return { time, offset, isVisible }; -})(TimeTooltip); diff --git a/frontend/app/components/Session_/Player/Controls/Timeline.js b/frontend/app/components/Session_/Player/Controls/Timeline.js index e53f567f0..3ff810d57 100644 --- a/frontend/app/components/Session_/Player/Controls/Timeline.js +++ b/frontend/app/components/Session_/Player/Controls/Timeline.js @@ -1,5 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; +import { Icon } from 'UI' import { connectPlayer, Controls, toggleTimetravel } from 'Player'; import TimeTracker from './TimeTracker'; import stl from './timeline.module.css'; @@ -25,27 +26,16 @@ let debounceTooltipChange = () => null; skipIntervals: state.skipIntervals, events: state.eventList, skip: state.skip, - // not updating properly rn - // skipToIssue: state.skipToIssue, + skipToIssue: state.skipToIssue, disabled: state.cssLoading || state.messagesLoading || state.markedTargets, endTime: state.endTime, live: state.live, - logList: state.logList, - exceptionsList: state.exceptionsList, - resourceList: state.resourceList, - stackList: state.stackList, - fetchList: state.fetchList, + notes: state.notes, })) @connect( (state) => ({ issues: state.getIn(['sessions', 'current', 'issues']), startedAt: state.getIn(['sessions', 'current', 'startedAt']), - clickRageTime: - state.getIn(['sessions', 'current', 'clickRage']) && - state.getIn(['sessions', 'current', 'clickRageTime']), - returningLocationTime: - state.getIn(['sessions', 'current', 'returningLocation']) && - state.getIn(['sessions', 'current', 'returningLocationTime']), tooltipVisible: state.getIn(['sessions', 'timeLineTooltip', 'isVisible']), }), { setTimelinePointer, setTimelineHoverTime } @@ -94,8 +84,7 @@ export default class Timeline extends React.PureComponent { }; componentDidMount() { - const { issues } = this.props; - const skipToIssue = Controls.updateSkipToIssue(); + const { issues, skipToIssue } = this.props; const firstIssue = issues.get(0); deboucneJump = debounce(this.props.jump, 500); debounceTooltipChange = debounce(this.props.setTimelineHoverTime, 50); @@ -170,7 +159,7 @@ export default class Timeline extends React.PureComponent { }; render() { - const { events, skip, skipIntervals, disabled, endTime, live } = this.props; + const { events, skip, skipIntervals, disabled, endTime, live, notes } = this.props; const scale = 100 / endTime; @@ -228,6 +217,22 @@ export default class Timeline extends React.PureComponent { style={{ left: `${getTimelinePosition(e.time, scale)}%` }} /> ))} + {notes.map((note) => note.timestamp > 0 ? ( + <div + key={note.noteId} + style={{ + position: 'absolute', + background: 'white', + zIndex: 3, + pointerEvents: 'none', + height: 10, + width: 16, + left: `${getTimelinePosition(note.timestamp, scale)}%`, + }} + > + <Icon name="quotes" style={{ width: 16, height: 10 }} color="main" /> + </div> + ) : null)} </div> </div> ); diff --git a/frontend/app/components/Session_/Player/Controls/components/CreateNote.tsx b/frontend/app/components/Session_/Player/Controls/components/CreateNote.tsx new file mode 100644 index 000000000..2fe7075f1 --- /dev/null +++ b/frontend/app/components/Session_/Player/Controls/components/CreateNote.tsx @@ -0,0 +1,253 @@ +import React from 'react'; +import { Icon, Button, Checkbox } from 'UI'; +import { Duration } from 'luxon'; +import { connect } from 'react-redux'; +import { WriteNote, tagProps, TAGS, iTag, Note } from 'App/services/NotesService'; +import { setCreateNoteTooltip, addNote, updateNote } from 'Duck/sessions'; +import stl from './styles.module.css'; +import { useStore } from 'App/mstore'; +import { toast } from 'react-toastify'; +import { injectNotes } from 'Player'; +import { fetchList as fetchSlack } from 'Duck/integrations/slack'; +import Select from 'Shared/Select'; +import { TeamBadge } from 'Shared/SessionListContainer/components/Notes' +import { List } from 'immutable'; + +interface Props { + isVisible: boolean; + time: number; + setCreateNoteTooltip: (state: any) => void; + addNote: (note: Note) => void; + updateNote: (note: Note) => void; + sessionId: string; + isEdit: string; + editNote: WriteNote; + slackChannels: List<Record<string, any>>; + fetchSlack: () => void; +} + +function CreateNote({ + isVisible, + time, + setCreateNoteTooltip, + sessionId, + addNote, + isEdit, + editNote, + updateNote, + slackChannels, + fetchSlack, +}: Props) { + const [text, setText] = React.useState(''); + const [channel, setChannel] = React.useState(''); + const [isPublic, setPublic] = React.useState(false); + const [tag, setTag] = React.useState<iTag>(TAGS[0]); + const [useTimestamp, setUseTs] = React.useState(true); + const inputRef = React.createRef<HTMLTextAreaElement>(); + const { notesStore } = useStore(); + + React.useEffect(() => { + if (isEdit) { + setTag(editNote.tag); + setText(editNote.message); + setPublic(editNote.isPublic); + if (editNote.timestamp > 0) { + setUseTs(true); + } + } + }, [isEdit]); + + React.useEffect(() => { + if (inputRef.current && isVisible) { + fetchSlack(); + inputRef.current.focus(); + } + }, [isVisible]); + + const duration = Duration.fromMillis(time).toFormat('mm:ss'); + + const onSubmit = () => { + if (text === '') return; + + const note: WriteNote = { + message: text, + tag, + timestamp: useTimestamp ? (isEdit ? editNote.timestamp : time) : -1, + isPublic, + }; + const onSuccess = (noteId: string) => { + if (channel) { + notesStore.sendSlackNotification(noteId, channel) + } + } + if (isEdit) { + return notesStore + .updateNote(editNote.noteId, note) + .then((r) => { + toast.success('Note updated'); + notesStore.fetchSessionNotes(sessionId).then((notes) => { + injectNotes(notes); + onSuccess(editNote.noteId) + updateNote(r); + }); + }) + .catch((e) => { + toast.error('Error updating note'); + console.error(e); + }) + .finally(() => { + setCreateNoteTooltip({ isVisible: false, time: 0 }); + setText(''); + setTag(undefined); + }); + } + + return notesStore + .addNote(sessionId, note) + .then((r) => { + onSuccess(r.noteId as unknown as string) + toast.success('Note added'); + notesStore.fetchSessionNotes(sessionId).then((notes) => { + injectNotes(notes); + addNote(r); + }); + }) + .catch((e) => { + toast.error('Error adding note'); + console.error(e); + }) + .finally(() => { + setCreateNoteTooltip({ isVisible: false, time: 0 }); + setText(''); + setTag(undefined); + }); + }; + + const closeTooltip = () => { + setCreateNoteTooltip({ isVisible: false, time: 100 }); + }; + + const tagActive = (noteTag: iTag) => tag === noteTag; + + const addTag = (tag: iTag) => { + setTag(tag); + }; + + const slackChannelsOptions = slackChannels.map(({ webhookId, name }) => ({ + value: webhookId, + label: name, + })).toJS() as unknown as { value: string, label: string }[] + + slackChannelsOptions.unshift({ value: null, label: 'Share to slack?' }) + + const changeChannel = ({ value, name }: { value: Record<string, string>; name: string }) => { + setChannel(value.value); + }; + + return ( + <div + className={stl.noteTooltip} + style={{ + top: slackChannelsOptions.length > 0 ? -310 : 255, + width: 350, + left: 'calc(50% - 175px)', + display: isVisible ? 'flex' : 'none', + flexDirection: 'column', + gap: '1rem', + }} + onClick={(e) => e.stopPropagation()} + > + <div className="flex items-center bg-gray-lightest"> + <Icon name="quotes" size={20} /> + <h3 className="text-xl ml-2 mr-4 font-semibold">Add Note</h3> + <div className="flex items-center cursor-pointer" onClick={() => setUseTs(!useTimestamp)}> + <Checkbox checked={useTimestamp} /> + <span className="ml-1"> {`at ${duration}`} </span> + </div> + + <div className="ml-auto cursor-pointer" onClick={closeTooltip}> + <Icon name="close" size={20} /> + </div> + </div> + + <div className=""> + <textarea + ref={inputRef} + name="message" + id="message" + placeholder="Note..." + rows={3} + value={text} + autoFocus + onChange={(e) => setText(e.target.value)} + style={{ + border: 'solid thin #ddd', + borderRadius: 3, + resize: 'none', + background: '#ffff', + }} + /> + </div> + + <div className="flex items-center gap-2" style={{ lineHeight: '15px' }}> + {TAGS.map((tag) => ( + <div + key={tag} + style={{ + background: tagActive(tag) ? tagProps[tag] : 'rgba(0,0,0, 0.38)', + userSelect: 'none', + minWidth: 50, + fontSize: 11, + }} + className="cursor-pointer rounded-full justify-center px-2 py-1 text-white flex items-center gap-2" + onClick={() => addTag(tag)} + > + {tagActive(tag) ? <Icon name="check-circle-fill" color="white" size={13} /> : null} + <div>{tag}</div> + </div> + ))} + </div> + + {slackChannelsOptions.length > 0 ? ( + <div> + <Select + options={slackChannelsOptions} + // @ts-ignore + defaultValue + // @ts-ignore + onChange={changeChannel} + className="mr-4" + /> + </div> + ) : null} + + <div className="flex"> + <Button variant="primary" className="mr-4" disabled={text === ''} onClick={onSubmit}> + Add Note + </Button> + <div className="flex items-center cursor-pointer" onClick={() => setPublic(!isPublic)}> + <Checkbox checked={isPublic} /> + <TeamBadge /> + </div> + </div> + </div> + ); +} + +export default connect( + (state) => { + const { + isVisible, + time = 0, + isEdit, + note: editNote, + // @ts-ignore + } = state.getIn(['sessions', 'createNoteTooltip']); + // @ts-ignore + const slackChannels = state.getIn(['slack', 'list']); + // @ts-ignore + const sessionId = state.getIn(['sessions', 'current', 'sessionId']); + return { isVisible, time, sessionId, isEdit, editNote, slackChannels }; + }, + { setCreateNoteTooltip, addNote, updateNote, fetchSlack } +)(CreateNote); diff --git a/frontend/app/components/Session_/Player/Controls/components/PlayerControls.tsx b/frontend/app/components/Session_/Player/Controls/components/PlayerControls.tsx index 6ad43c2b5..bd1225ad4 100644 --- a/frontend/app/components/Session_/Player/Controls/components/PlayerControls.tsx +++ b/frontend/app/components/Session_/Player/Controls/components/PlayerControls.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { Tooltip } from 'react-tippy'; -import { Icon } from 'UI'; +import { Icon, Tooltip, Popover } from 'UI'; import cn from 'classnames'; import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; import { ReduxTime } from '../Time'; @@ -49,9 +48,13 @@ function PlayerControls(props: Props) { const speedRef = React.useRef(null); const arrowBackRef = React.useRef(null); const arrowForwardRef = React.useRef(null); + const skipRef = React.useRef<HTMLDivElement>(); React.useEffect(() => { const handleKeyboard = (e: KeyboardEvent) => { + if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) { + return; + } if (e.key === 'ArrowRight') { arrowForwardRef.current.focus(); } @@ -72,9 +75,13 @@ function PlayerControls(props: Props) { const toggleTooltip = () => { setShowTooltip(!showTooltip); }; + const handleClickOutside = () => { + setShowTooltip(false); + }; return ( <div className="flex items-center"> {playButton} + <div className="mx-1" /> {!live && ( <div className="flex items-center font-semibold text-center" style={{ minWidth: 85 }}> {/* @ts-ignore */} @@ -86,12 +93,11 @@ function PlayerControls(props: Props) { )} <div className="rounded ml-4 bg-active-blue border border-active-blue-border flex items-stretch"> - {/* @ts-ignore */} - <Tooltip title="Rewind 10s" delay={0} position="top"> - <button - ref={arrowBackRef} - className="h-full hover:border-active-blue-border focus:border focus:border-blue border-borderColor-transparent" - > + <button + ref={arrowBackRef} + className="h-full hover:border-active-blue-border focus:border focus:border-blue border-borderColor-transparent" + > + <Tooltip title="Rewind 10s"> {controlIcon( 'skip-forward-fill', 18, @@ -99,59 +105,57 @@ function PlayerControls(props: Props) { true, 'hover:bg-active-blue-border color-main h-full flex items-center' )} - </button> - </Tooltip> - <div className="p-1 border-l border-r bg-active-blue-border border-active-blue-border"> - <Tooltip - open={showTooltip} - interactive + </Tooltip> + </button> + + <div className="p-1 border-l border-r bg-active-blue-border border-active-blue-border flex items-center"> + <Popover + // open={showTooltip} + // interactive // @ts-ignore theme="nopadding" animation="none" duration={0} className="cursor-pointer select-none" distance={20} - html={ - <OutsideClickDetectingDiv - onClickOutside={() => (showTooltip ? toggleTooltip() : null)} - > - <div className="flex flex-col bg-white border border-borderColor-gray-light-shade text-figmaColors-text-primary rounded"> - <div className="font-semibold py-2 px-4 w-full text-left"> - Jump <span className="text-disabled-text">(Secs)</span> - </div> - {Object.keys(skipIntervals).map((interval) => ( - <div - onClick={() => { - toggleTooltip(); - setSkipInterval(parseInt(interval, 10)); - }} - className={cn( - 'py-2 px-4 cursor-pointer w-full text-left font-semibold', - 'hover:bg-active-blue border-t border-borderColor-gray-light-shade' - )} - > - {interval} - <span className="text-disabled-text">s</span> - </div> - ))} + render={({ close }: any) => ( + <div className="flex flex-col bg-white border border-borderColor-gray-light-shade text-figmaColors-text-primary rounded"> + <div className="font-semibold py-2 px-4 w-full text-left"> + Jump <span className="text-disabled-text">(Secs)</span> </div> - </OutsideClickDetectingDiv> - } + {Object.keys(skipIntervals).map((interval) => ( + <div + key={interval} + onClick={() => { + close(); + setSkipInterval(parseInt(interval, 10)); + }} + className={cn( + 'py-2 px-4 cursor-pointer w-full text-left font-semibold', + 'hover:bg-active-blue border-t border-borderColor-gray-light-shade' + )} + > + {interval} + <span className="text-disabled-text">s</span> + </div> + ))} + </div> + )} > - <div onClick={toggleTooltip}> + <div onClick={toggleTooltip} ref={skipRef} className="cursor-pointer select-none"> {/* @ts-ignore */} <Tooltip disabled={showTooltip} title="Set default skip duration"> {currentInterval}s </Tooltip> </div> - </Tooltip> + </Popover> </div> - {/* @ts-ignore */} - <Tooltip title="Forward 10s" delay={0} position="top"> - <button - ref={arrowForwardRef} - className="h-full hover:border-active-blue-border focus:border focus:border-blue border-borderColor-transparent" - > + + <button + ref={arrowForwardRef} + className="h-full hover:border-active-blue-border focus:border focus:border-blue border-borderColor-transparent" + > + <Tooltip title="Forward 10s"> {controlIcon( 'skip-forward-fill', 18, @@ -159,15 +163,15 @@ function PlayerControls(props: Props) { false, 'hover:bg-active-blue-border color-main h-full flex items-center' )} - </button> - </Tooltip> + </Tooltip> + </button> </div> {!live && ( <div className="flex items-center"> <div className="mx-2" /> {/* @ts-ignore */} - <Tooltip title="Control play back speed (↑↓)" delay={0} position="top"> + <Tooltip title="Control play back speed (↑↓)" placement="top"> <button ref={speedRef} className={cn(styles.speedButton, 'focus:border focus:border-blue')} @@ -179,10 +183,10 @@ function PlayerControls(props: Props) { </Tooltip> <div className="mx-2" /> <button - className={cn( - styles.skipIntervalButton, - { [styles.withCheckIcon]: skip, [styles.active]: skip }, - )} + className={cn(styles.skipIntervalButton, { + [styles.withCheckIcon]: skip, + [styles.active]: skip, + })} onClick={toggleSkip} data-disabled={disabled} > diff --git a/frontend/app/components/Session_/Player/Controls/components/ReadNote.tsx b/frontend/app/components/Session_/Player/Controls/components/ReadNote.tsx new file mode 100644 index 000000000..edc58aa9f --- /dev/null +++ b/frontend/app/components/Session_/Player/Controls/components/ReadNote.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import { Icon } from 'UI'; +import { tagProps, Note } from 'App/services/NotesService'; +import { formatTimeOrDate } from 'App/date'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import { TeamBadge } from 'Shared/SessionListContainer/components/Notes'; + +interface Props { + userEmail: string; + note: Note; + notFound?: boolean; + onClose: () => void; +} + +function ReadNote(props: Props) { + const { settingsStore } = useStore(); + const { timezone } = settingsStore.sessionSettings; + + if (props.notFound) { + return ( + <div style={{ position: 'absolute', top: '45%', left: 'calc(50% - 200px)' }}> + <div + className="flex items-start flex-col p-4 border gap-2 rounded" + style={{ background: '#FFFEF5', width: 400 }} + > + <div className="flex items-start font-semibold w-full text-xl"> + <div style={{ flex: 9 }}> + You do not have access to this note. <br /> Or it’s deleted. + </div> + <div style={{ flex: 1 }} className="cursor-pointer ml-auto" onClick={props.onClose}> + <Icon name="close" size={18} /> + </div> + </div> + <div + onClick={props.onClose} + className="rounded py-2 px-4 mt-2 flex items-center text-blue gap-2 cursor-pointer hover:bg-active-blue" + > + <Icon size={20} name="play-fill" color="main" /> + <span>Play Session</span> + </div> + </div> + </div> + ); + } + + return ( + <div + style={{ position: 'absolute', top: 0, left: 0, height: '100%', width: '100%' }} + className="flex items-center justify-center" + > + <div + className="flex items-start !text-lg flex-col p-4 border gap-2 rounded" + style={{ background: '#FFFEF5', width: 500 }} + > + <div className="flex items-center w-full"> + <div className="p-2 bg-gray-light rounded-full"> + <Icon name="quotes" color="main" size={16} /> + </div> + <div className="ml-2"> + <div className="text-base">{props.userEmail}</div> + <div className="text-disabled-text text-sm"> + {formatTimeOrDate(props.note.createdAt as unknown as number, timezone)} + </div> + </div> + <div className="ml-auto cursor-pointer self-start" onClick={props.onClose}> + <Icon name="close" size={18} /> + </div> + </div> + <div className="text-xl py-3 overflow-y-scroll capitalize-first" style={{ maxHeight: 400 }}> + {props.note.message} + </div> + <div className="w-full"> + <div className="flex items-center gap-2 flex-wrap w-full"> + {props.note.tag ? ( + <div + // @ts-ignore + style={{ background: tagProps[props.note.tag], userSelect: 'none', fontSize: 11 }} + className="rounded-full text-sm px-2 py-1 text-white flex items-center justify-center" + > + {props.note.tag} + </div> + ) : null} + {!props.note.isPublic ? null : <TeamBadge />} + + <div + onClick={props.onClose} + className="ml-auto rounded py-2 px-4 flex items-center text-blue gap-2 cursor-pointer hover:bg-active-blue" + > + <Icon size={20} name="play-fill" color="main" /> + <span>Play Session</span> + </div> + </div> + </div> + </div> + </div> + ); +} + +export default observer(ReadNote); diff --git a/frontend/app/components/Session_/Player/Controls/components/TimeTooltip.tsx b/frontend/app/components/Session_/Player/Controls/components/TimeTooltip.tsx new file mode 100644 index 000000000..e1be98622 --- /dev/null +++ b/frontend/app/components/Session_/Player/Controls/components/TimeTooltip.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +// @ts-ignore +import { Duration } from 'luxon'; +import { connect } from 'react-redux'; +import stl from './styles.module.css'; + +interface Props { + time: number; + offset: number; + isVisible: boolean; + liveTimeTravel: boolean; +} + +function TimeTooltip({ + time, + offset, + isVisible, + liveTimeTravel, +}: Props) { + const duration = Duration.fromMillis(time).toFormat(`${liveTimeTravel ? '-' : ''}mm:ss`); + return ( + <div + className={stl.timeTooltip} + style={{ + top: -30, + left: offset - 20, + display: isVisible ? 'block' : 'none', + }} + > + {!time ? 'Loading' : duration} + </div> + ); +} + +export default connect((state) => { + const { time = 0, offset = 0, isVisible } = state.getIn(['sessions', 'timeLineTooltip']); + return { time, offset, isVisible }; +})(TimeTooltip); diff --git a/frontend/app/components/Session_/Player/Controls/components/TooltipContainer.tsx b/frontend/app/components/Session_/Player/Controls/components/TooltipContainer.tsx index 19396fbc6..d1b98eca6 100644 --- a/frontend/app/components/Session_/Player/Controls/components/TooltipContainer.tsx +++ b/frontend/app/components/Session_/Player/Controls/components/TooltipContainer.tsx @@ -1,5 +1,6 @@ import React from 'react' -import TimeTooltip from '../TimeTooltip'; +import TimeTooltip from './TimeTooltip'; +import CreateNote from './CreateNote'; import store from 'App/store'; import { Provider } from 'react-redux'; @@ -7,7 +8,10 @@ function TooltipContainer({ live }: { live: boolean }) { return ( <Provider store={store}> - <TimeTooltip liveTimeTravel={live} /> + <> + <TimeTooltip liveTimeTravel={live} /> + <CreateNote /> + </> </Provider> ) } diff --git a/frontend/app/components/Session_/Player/Controls/components/styles.module.css b/frontend/app/components/Session_/Player/Controls/components/styles.module.css new file mode 100644 index 000000000..2a34e1129 --- /dev/null +++ b/frontend/app/components/Session_/Player/Controls/components/styles.module.css @@ -0,0 +1,52 @@ + +.timeTooltip { + position: absolute; + padding: 0.25rem; + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + background: black; + top: -35px; + color: white; + + &:after { + content:''; + position: absolute; + top: 100%; + left: 0; + right: 0; + margin: 0 auto; + width: 0; + height: 0; + border-top: solid 5px black; + border-left: solid 5px transparent; + border-right: solid 5px transparent; + } +} + +.noteTooltip { + position: absolute; + padding: 1rem; + border-radius: 0.25rem; + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + background: #F5F5F5; + top: -35px; + color: black; + cursor: default; + box-shadow: 0 4px 20px 4px rgb(0 20 60 / 10%), 0 4px 80px -8px rgb(0 20 60 / 20%); +} + +.arrow { + position: absolute; + top: 100%; + left: 0; + right: 0; + margin: 0 auto; + width: 0; + height: 0; + border-top: solid 10px #f5f5f5; + border-left: solid 10px transparent; + border-right: solid 10px transparent; +} diff --git a/frontend/app/components/Session_/Player/Overlay.tsx b/frontend/app/components/Session_/Player/Overlay.tsx index 14a2f2a17..7b610ded1 100644 --- a/frontend/app/components/Session_/Player/Overlay.tsx +++ b/frontend/app/components/Session_/Player/Overlay.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { connectPlayer } from 'Player'; -import { getStatusText } from 'Player/MessageDistributor/managers/AssistManager'; -import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen'; -import { CallingState, ConnectionStatus, RemoteControlStatus } from 'Player/MessageDistributor/managers/AssistManager'; +import { getStatusText } from 'Player'; +import type { MarkedTarget } from 'Player'; +import { CallingState, ConnectionStatus, RemoteControlStatus } from 'Player'; import AutoplayTimer from './Overlay/AutoplayTimer'; import PlayIconLayer from './Overlay/PlayIconLayer'; diff --git a/frontend/app/components/Session_/Player/Overlay/ElementsMarker/Marker.tsx b/frontend/app/components/Session_/Player/Overlay/ElementsMarker/Marker.tsx index cc8f3fd1f..cbb772020 100644 --- a/frontend/app/components/Session_/Player/Overlay/ElementsMarker/Marker.tsx +++ b/frontend/app/components/Session_/Player/Overlay/ElementsMarker/Marker.tsx @@ -1,10 +1,9 @@ -//@ts-nocheck import React from 'react'; -import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen'; +import type { MarkedTarget } from 'Player'; import cn from 'classnames'; import stl from './Marker.module.css'; import { activeTarget } from 'Player'; -import { Tooltip } from 'react-tippy'; +import { Tooltip } from 'UI'; interface Props { target: MarkedTarget; @@ -17,23 +16,17 @@ export default function Marker({ target, active }: Props) { left: `${target.boundingRect.left}px`, width: `${target.boundingRect.width}px`, height: `${target.boundingRect.height}px`, - } + }; return ( - <div className={cn(stl.marker, { [stl.active]: active })} style={style} onClick={() => activeTarget(target.index)}> + <div + className={cn(stl.marker, { [stl.active]: active })} + style={style} + onClick={() => activeTarget(target.index)} + > <div className={stl.index}>{target.index + 1}</div> - {/* @ts-expect-error Tooltip doesn't have children property */} - <Tooltip - open={active} - arrow - sticky - distance={15} - html={( - <div>{target.count} Clicks</div> - )} - trigger="mouseenter" - > + <Tooltip open={active} delay={0} title={<div>{target.count} Clicks</div>}> <div className="absolute inset-0"></div> </Tooltip> </div> - ) -} \ No newline at end of file + ); +} diff --git a/frontend/app/components/Session_/Player/Overlay/LiveStatusText.tsx b/frontend/app/components/Session_/Player/Overlay/LiveStatusText.tsx index a416bf529..52238adf0 100644 --- a/frontend/app/components/Session_/Player/Overlay/LiveStatusText.tsx +++ b/frontend/app/components/Session_/Player/Overlay/LiveStatusText.tsx @@ -1,6 +1,6 @@ import React from 'react'; import ovStl from './overlay.module.css'; -import { ConnectionStatus } from 'Player/MessageDistributor/managers/AssistManager'; +import { ConnectionStatus } from 'Player'; import { Loader } from 'UI'; interface Props { diff --git a/frontend/app/components/Session_/Player/Overlay/PlayIconLayer.tsx b/frontend/app/components/Session_/Player/Overlay/PlayIconLayer.tsx index 95549ddce..71ef1a76b 100644 --- a/frontend/app/components/Session_/Player/Overlay/PlayIconLayer.tsx +++ b/frontend/app/components/Session_/Player/Overlay/PlayIconLayer.tsx @@ -1,32 +1,36 @@ import React, { useState, useCallback, useEffect } from 'react'; import cn from 'classnames'; import { Icon } from 'UI'; - +import { connect } from 'react-redux'; import cls from './PlayIconLayer.module.css'; import clsOv from './overlay.module.css'; interface Props { - togglePlay: () => void, - playing: boolean, + togglePlay: () => void; + playing: boolean; + notesEdit: boolean; } -export default function PlayIconLayer({ playing, togglePlay }: Props) { - const [ showPlayOverlayIcon, setShowPlayOverlayIcon ] = useState(false); +function PlayIconLayer({ playing, togglePlay, notesEdit }: Props) { + const [showPlayOverlayIcon, setShowPlayOverlayIcon] = useState(false); useEffect(() => { // TODO Find a better way to do this document.addEventListener('keydown', onKeyDown); - + return () => { document.removeEventListener('keydown', onKeyDown); - } - }, []) + }; + }, [notesEdit]); - const onKeyDown = (e) => { + const getIsEdit = React.useCallback(() => notesEdit, [notesEdit]) + + const onKeyDown = (e: any) => { + if (getIsEdit() || e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return; if (e.key === ' ') { - togglePlayAnimated() + togglePlayAnimated(); } - } + }; const togglePlayAnimated = useCallback(() => { setShowPlayOverlayIcon(true); @@ -35,18 +39,19 @@ export default function PlayIconLayer({ playing, togglePlay }: Props) { }, []); return ( - <div className={ clsOv.overlay } onClick={ togglePlayAnimated }> - <div - className={ cn(cls.iconWrapper, { - [ cls.zoomIcon ]: showPlayOverlayIcon - }) } + <div className={clsOv.overlay} onClick={togglePlayAnimated}> + <div + className={cn(cls.iconWrapper, { + [cls.zoomIcon]: showPlayOverlayIcon, + })} > - <Icon - name={ playing ? "play" : "pause" } - color="gray-medium" - size={30} - /> + <Icon name={playing ? 'play' : 'pause'} color="gray-medium" size={30} /> </div> </div> - ) -} \ No newline at end of file + ); +} + +export default connect((state) => ({ + // @ts-ignore + notesEdit: state.getIn(['sessions', 'createNoteTooltip', 'isVisible']), +}))(PlayIconLayer); diff --git a/frontend/app/components/Session_/Player/Player.js b/frontend/app/components/Session_/Player/Player.js index babe4f2b0..83748dc0d 100644 --- a/frontend/app/components/Session_/Player/Player.js +++ b/frontend/app/components/Session_/Player/Player.js @@ -14,20 +14,18 @@ import { PROFILER, PERFORMANCE, GRAPHQL, - FETCH, EXCEPTIONS, LONGTASKS, INSPECTOR, OVERVIEW, } from 'Duck/components/player'; -import Network from '../Network'; +import NetworkPanel from 'Shared/DevTools/NetworkPanel'; import Console from '../Console/Console'; import StackEvents from '../StackEvents/StackEvents'; import Storage from '../Storage'; import Profiler from '../Profiler'; import { ConnectedPerformance } from '../Performance'; import GraphQL from '../GraphQL'; -import Fetch from '../Fetch'; import Exceptions from '../Exceptions/Exceptions'; import LongTasks from '../LongTasks'; import Inspector from '../Inspector'; @@ -42,29 +40,39 @@ import Overlay from './Overlay'; import stl from './player.module.css'; import { updateLastPlayedSession } from 'Duck/sessions'; import OverviewPanel from '../OverviewPanel'; +import ConsolePanel from 'Shared/DevTools/ConsolePanel'; +import ProfilerPanel from 'Shared/DevTools/ProfilerPanel'; +import StackEventPanel from 'Shared/DevTools/StackEventPanel'; -@connectPlayer(state => ({ +@connectPlayer((state) => ({ live: state.live, })) -@connect(state => { - const isAssist = window.location.pathname.includes('/assist/'); - return { - fullscreen: state.getIn([ 'components', 'player', 'fullscreen' ]), - nextId: state.getIn([ 'sessions', 'nextId' ]), - sessionId: state.getIn([ 'sessions', 'current', 'sessionId' ]), - closedLive: !!state.getIn([ 'sessions', 'errors' ]) || (isAssist && !state.getIn([ 'sessions', 'current', 'live' ])), +@connect( + (state) => { + const isAssist = window.location.pathname.includes('/assist/'); + return { + fullscreen: state.getIn(['components', 'player', 'fullscreen']), + nextId: state.getIn(['sessions', 'nextId']), + sessionId: state.getIn(['sessions', 'current', 'sessionId']), + closedLive: + !!state.getIn(['sessions', 'errors']) || + (isAssist && !state.getIn(['sessions', 'current', 'live'])), + }; + }, + { + hideTargetDefiner, + fullscreenOff, + updateLastPlayedSession, } -}, { - hideTargetDefiner, - fullscreenOff, - updateLastPlayedSession, -}) +) export default class Player extends React.PureComponent { screenWrapper = React.createRef(); componentDidUpdate(prevProps) { - if ([ prevProps.bottomBlock, this.props.bottomBlock ].includes(NONE) || - prevProps.fullscreen !== this.props.fullscreen) { + if ( + [prevProps.bottomBlock, this.props.bottomBlock].includes(NONE) || + prevProps.fullscreen !== this.props.fullscreen + ) { scalePlayerScreen(); } } @@ -73,7 +81,7 @@ export default class Player extends React.PureComponent { this.props.updateLastPlayedSession(this.props.sessionId); if (this.props.closedLive) return; - const parentElement = findDOMNode(this.screenWrapper.current); //TODO: good architecture + const parentElement = findDOMNode(this.screenWrapper.current); //TODO: good architecture attachPlayer(parentElement); } @@ -86,66 +94,41 @@ export default class Player extends React.PureComponent { nextId, closedLive, bottomBlock, - activeTab + activeTab, + fullView = false, } = this.props; - const maxWidth = activeTab ? 'calc(100vw - 270px)' : '100vw' + const maxWidth = activeTab ? 'calc(100vw - 270px)' : '100vw'; return ( <div - className={ cn(className, stl.playerBody, "flex flex-col relative", fullscreen && 'pb-2') } - data-bottom-block={ bottomBlockIsActive } + className={cn(className, stl.playerBody, 'flex flex-col relative', fullscreen && 'pb-2')} + data-bottom-block={bottomBlockIsActive} > - {fullscreen && <EscapeButton onClose={ fullscreenOff } />} + {fullscreen && <EscapeButton onClose={fullscreenOff} />} <div className="relative flex-1 overflow-hidden"> <Overlay nextId={nextId} togglePlay={PlayerControls.togglePlay} closedLive={closedLive} /> - <div - className={ stl.screenWrapper } - ref={ this.screenWrapper } - /> + <div className={stl.screenWrapper} ref={this.screenWrapper} /> </div> - { !fullscreen && !!bottomBlock && + {!fullscreen && !!bottomBlock && ( <div style={{ maxWidth, width: '100%' }}> - { bottomBlock === OVERVIEW && - <OverviewPanel /> - } - { bottomBlock === CONSOLE && - <Console /> - } - { bottomBlock === NETWORK && - <Network /> - } - { bottomBlock === STACKEVENTS && - <StackEvents /> - } - { bottomBlock === STORAGE && - <Storage /> - } - { bottomBlock === PROFILER && - <Profiler /> - } - { bottomBlock === PERFORMANCE && - <ConnectedPerformance /> - } - { bottomBlock === GRAPHQL && - <GraphQL /> - } - { bottomBlock === FETCH && - <Fetch /> - } - { bottomBlock === EXCEPTIONS && - <Exceptions /> - } - { bottomBlock === LONGTASKS && - <LongTasks /> - } - { bottomBlock === INSPECTOR && - <Inspector /> - } + {bottomBlock === OVERVIEW && <OverviewPanel />} + {bottomBlock === CONSOLE && <ConsolePanel />} + {bottomBlock === NETWORK && ( + // <Network /> + <NetworkPanel /> + )} + {/* {bottomBlock === STACKEVENTS && <StackEvents />} */} + {bottomBlock === STACKEVENTS && <StackEventPanel />} + {bottomBlock === STORAGE && <Storage />} + {bottomBlock === PROFILER && <ProfilerPanel />} + {bottomBlock === PERFORMANCE && <ConnectedPerformance />} + {bottomBlock === GRAPHQL && <GraphQL />} + {bottomBlock === EXCEPTIONS && <Exceptions />} + {bottomBlock === LONGTASKS && <LongTasks />} + {bottomBlock === INSPECTOR && <Inspector />} </div> - } - <Controls - { ...PlayerControls } - /> + )} + {!fullView && <Controls {...PlayerControls} /> } </div> ); } diff --git a/frontend/app/components/Session_/PlayerBlock.js b/frontend/app/components/Session_/PlayerBlock.js index 562ea8958..54130adf5 100644 --- a/frontend/app/components/Session_/PlayerBlock.js +++ b/frontend/app/components/Session_/PlayerBlock.js @@ -1,47 +1,36 @@ import React from 'react'; -import cn from "classnames"; +import cn from 'classnames'; import { connect } from 'react-redux'; -import { } from 'Player'; -import { - NONE, OVERVIEW, -} from 'Duck/components/player'; +import { NONE } from 'Duck/components/player'; import Player from './Player'; import SubHeader from './Subheader'; import styles from './playerBlock.module.css'; -@connect(state => ({ - fullscreen: state.getIn([ 'components', 'player', 'fullscreen' ]), - bottomBlock: state.getIn([ 'components', 'player', 'bottomBlock' ]), - sessionId: state.getIn([ 'sessions', 'current', 'sessionId' ]), - disabled: state.getIn([ 'components', 'targetDefiner', 'inspectorMode' ]), - jiraConfig: state.getIn([ 'issues', 'list' ]).first(), +@connect((state) => ({ + fullscreen: state.getIn(['components', 'player', 'fullscreen']), + bottomBlock: state.getIn(['components', 'player', 'bottomBlock']), + sessionId: state.getIn(['sessions', 'current', 'sessionId']), + disabled: state.getIn(['components', 'targetDefiner', 'inspectorMode']), + jiraConfig: state.getIn(['issues', 'list']).first(), })) export default class PlayerBlock extends React.PureComponent { render() { - const { - fullscreen, - bottomBlock, - sessionId, - disabled, - activeTab, - jiraConfig, - } = this.props; + const { fullscreen, bottomBlock, sessionId, disabled, activeTab, jiraConfig, fullView = false } = this.props; return ( - <div className={ cn(styles.playerBlock, "flex flex-col overflow-x-hidden") }> - {!fullscreen && <SubHeader - sessionId={sessionId} - disabled={disabled} - jiraConfig={jiraConfig} - />} + <div className={cn(styles.playerBlock, 'flex flex-col overflow-x-hidden')}> + {!fullscreen && !fullView && ( + <SubHeader sessionId={sessionId} disabled={disabled} jiraConfig={jiraConfig} /> + )} <Player className="flex-1" - bottomBlockIsActive={ !fullscreen && bottomBlock !== NONE } + bottomBlockIsActive={!fullscreen && bottomBlock !== NONE} // bottomBlockIsActive={ true } bottomBlock={bottomBlock} fullscreen={fullscreen} activeTab={activeTab} + fullView={fullView} /> </div> ); diff --git a/frontend/app/components/Session_/Profiler/Profiler.js b/frontend/app/components/Session_/Profiler/Profiler.js index 1d9c8a5a3..398560a3d 100644 --- a/frontend/app/components/Session_/Profiler/Profiler.js +++ b/frontend/app/components/Session_/Profiler/Profiler.js @@ -51,6 +51,7 @@ export default class Profiler extends React.PureComponent { icon="search" name="filter" onChange={ this.onFilterChange } + height={28} /> </BottomBlock.Header> <BottomBlock.Content> diff --git a/frontend/app/components/Session_/SessionInfoItem/SessionInfoItem.tsx b/frontend/app/components/Session_/SessionInfoItem/SessionInfoItem.tsx index e4e481067..b29730215 100644 --- a/frontend/app/components/Session_/SessionInfoItem/SessionInfoItem.tsx +++ b/frontend/app/components/Session_/SessionInfoItem/SessionInfoItem.tsx @@ -12,7 +12,7 @@ interface Props { export default function SessionInfoItem(props: Props) { const { label, icon, value, comp, isLast = false } = props return ( - <div className={cn("flex items-center w-full py-2", {'border-b' : !isLast})}> + <div className={cn("flex items-center w-full py-2 color-gray-dark", {'border-b' : !isLast})}> <div className="px-2 capitalize" style={{ width: '30px' }}> { icon && <Icon name={icon} size="16" /> } { comp && comp } diff --git a/frontend/app/components/Session_/StackEvents/StackEvents.js b/frontend/app/components/Session_/StackEvents/StackEvents.js index 4ce3ce86c..516a9adde 100644 --- a/frontend/app/components/Session_/StackEvents/StackEvents.js +++ b/frontend/app/components/Session_/StackEvents/StackEvents.js @@ -6,6 +6,7 @@ import withEnumToggle from 'HOCs/withEnumToggle'; import { connectPlayer, jump } from 'Player'; import React from 'react'; import { connect } from 'react-redux'; +import StackEventRow from 'Shared/DevTools/StackEventRow'; import { DATADOG, SENTRY, STACKDRIVER, typeList } from 'Types/session/stackEvent'; import { NoContent, SlideModal, Tabs, Link } from 'UI'; import Autoscroll from '../Autoscroll'; @@ -19,7 +20,7 @@ const TABS = [ALL, ...typeList].map((tab) => ({ text: tab, key: tab })); @withEnumToggle('activeTab', 'setActiveTab', ALL) @connectPlayer((state) => ({ stackEvents: state.stackList, - stackEventsNow: state.stackListNow, + // stackEventsNow: state.stackListNow, })) @connect( (state) => ({ @@ -69,20 +70,20 @@ export default class StackEvents extends React.PureComponent { ({ key }) => key === ALL || stackEvents.some(({ source }) => key === source) ); - const filteredStackEvents = stackEvents - // .filter(({ data }) => data.includes(filter)) - .filter(({ source }) => activeTab === ALL || activeTab === source); + const filteredStackEvents = stackEvents.filter( + ({ source }) => activeTab === ALL || activeTab === source + ); - let lastIndex = -1; - // TODO: Need to do filtering in store, or preferably in a selector - filteredStackEvents.forEach((item, index) => { - if ( - this.props.stackEventsNow.length > 0 && - item.time <= this.props.stackEventsNow[this.props.stackEventsNow.length - 1].time - ) { - lastIndex = index; - } - }); + // let lastIndex = -1; + // // TODO: Need to do filtering in store, or preferably in a selector + // filteredStackEvents.forEach((item, index) => { + // if ( + // this.props.stackEventsNow.length > 0 && + // item.time <= this.props.stackEventsNow[this.props.stackEventsNow.length - 1].time + // ) { + // lastIndex = index; + // } + // }); return ( <> @@ -135,7 +136,7 @@ export default class StackEvents extends React.PureComponent { {' and '} <a className="underline color-teal" - href="https://docs.openreplay.com/api#event" + href="https://docs.openreplay.com/installation/custom-events" target="_blank" > Events @@ -154,16 +155,21 @@ export default class StackEvents extends React.PureComponent { size="small" show={filteredStackEvents.length === 0} > - <Autoscroll autoScrollTo={Math.max(lastIndex, 0)}> + <Autoscroll> {filteredStackEvents.map((userEvent, index) => ( - <UserEvent + <StackEventRow key={userEvent.key} - onDetailsClick={this.onDetailsClick.bind(this)} - inactive={index > lastIndex} - selected={lastIndex === index} - userEvent={userEvent} + event={userEvent} onJump={() => jump(userEvent.time)} /> + // <UserEvent + // key={userEvent.key} + // onDetailsClick={this.onDetailsClick.bind(this)} + // // inactive={index > lastIndex} + // // selected={lastIndex === index} + // userEvent={userEvent} + // onJump={() => jump(userEvent.time)} + // /> ))} </Autoscroll> </NoContent> diff --git a/frontend/app/components/Session_/StackEvents/UserEvent/JsonViewer.js b/frontend/app/components/Session_/StackEvents/UserEvent/JsonViewer.js index 1a46046b1..fc94eb673 100644 --- a/frontend/app/components/Session_/StackEvents/UserEvent/JsonViewer.js +++ b/frontend/app/components/Session_/StackEvents/UserEvent/JsonViewer.js @@ -18,7 +18,9 @@ export default class JsonViewer extends React.PureComponent { {isObjectData && <JSONTree src={data} collapsed={false} />} {!isObjectData && Array.isArray(data) && ( <div> - <div className="text-lg">{data[0]}</div> + <div className="code-font mb-2"> + {typeof data[0] === 'string' ? data[0] : JSON.stringify(data[0])} + </div> <JSONTree src={data[1]} collapsed={false} /> </div> )} diff --git a/frontend/app/components/Session_/StackEvents/UserEvent/UserEvent.js b/frontend/app/components/Session_/StackEvents/UserEvent/UserEvent.js index 5890c5e1a..2dfd4d8aa 100644 --- a/frontend/app/components/Session_/StackEvents/UserEvent/UserEvent.js +++ b/frontend/app/components/Session_/StackEvents/UserEvent/UserEvent.js @@ -1,12 +1,13 @@ import React from 'react'; import cn from 'classnames'; import { OPENREPLAY, SENTRY, DATADOG, STACKDRIVER } from 'Types/session/stackEvent'; -import { Icon, IconButton } from 'UI'; +import { Icon } from 'UI'; import withToggle from 'HOCs/withToggle'; import Sentry from './Sentry'; import JsonViewer from './JsonViewer'; import stl from './userEvent.module.css'; import { Duration } from 'luxon'; +import JumpButton from 'Shared/DevTools/JumpButton'; // const modalSources = [ SENTRY, DATADOG ]; @@ -34,34 +35,33 @@ export default class UserEvent extends React.PureComponent { render() { const { userEvent, inactive, selected } = this.props; - //const message = this.getEventMessage(); + let message = userEvent.payload[0] || ''; + message = typeof message === 'string' ? message : JSON.stringify(message); return ( <div data-scroll-item={userEvent.isRed()} - // onClick={ this.props.switchOpen } // - onClick={this.props.onJump} // - className={cn('group flex py-2 px-4 ', stl.userEvent, this.getLevelClassname(), { - // [stl.inactive]: inactive, - [stl.selected]: selected, - })} + onClick={this.onClickDetails} + className={cn( + 'group flex items-center py-2 px-4 border-b cursor-pointer relative', + // stl.userEvent, + // this.getLevelClassname(), + // { + // [stl.selected]: selected, + // }, + 'hover:bg-active-blue' + )} > - <div className={'self-start pr-4'}> + {/* <div className={'self-start pr-4'}> {Duration.fromMillis(userEvent.time).toFormat('mm:ss.SSS')} - </div> - <div className={cn('mr-auto', stl.infoWrapper)}> - <div className={stl.title}> - <Icon {...this.getIconProps()} /> - {userEvent.name} + </div> */} + <div className={cn('mr-auto flex items-start')}> + <Icon {...this.getIconProps()} /> + <div> + <div className="capitalize font-medium mb-1">{userEvent.name}</div> + <div className="code-font text-xs">{message}</div> </div> </div> - <div className="self-center"> - <IconButton - outline={!userEvent.isRed()} - red={userEvent.isRed()} - onClick={this.onClickDetails} - label="DETAILS" - /> - </div> + <JumpButton onClick={this.props.onJump} /> </div> ); } diff --git a/frontend/app/components/Session_/Storage/DiffRow.tsx b/frontend/app/components/Session_/Storage/DiffRow.tsx new file mode 100644 index 000000000..ebc54ad4d --- /dev/null +++ b/frontend/app/components/Session_/Storage/DiffRow.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import cn from 'classnames'; + +interface Props { + shades: Record<string, string>; + pathRoot: string; + path: string; + diff: Record<string, any>; +} + +const getCircularReplacer = () => { + const seen = new WeakSet(); + // @ts-ignore + return (key, value) => { + if (typeof value === 'object' && value !== null) { + if (seen.has(value)) { + return; + } + seen.add(value); + } + return value; + }; +}; + +function DiffRow({ diff, path }: Props) { + const [shorten, setShorten] = React.useState(true); + const [shortenOldVal, setShortenOldVal] = React.useState(true); + const [shortenNewVal, setShortenNewVal] = React.useState(true); + + const oldValue = diff.item + ? JSON.stringify(diff.item.lhs, getCircularReplacer(), 1) + : JSON.stringify(diff.lhs, getCircularReplacer(), 1); + const newValue = diff.item + ? JSON.stringify(diff.item.rhs, getCircularReplacer(), 1) + : JSON.stringify(diff.rhs, getCircularReplacer(), 1); + + const length = path.length; + const diffLengths = [oldValue?.length || 0, newValue?.length || 0]; + + const pathStr = + length > 20 && shorten ? path.slice(0, 5) + '...' + path.slice(length - 10, length) : path; + + const oldValueSafe = + diffLengths[0] > 50 && shortenOldVal + ? `${oldValue.slice(0, 10)} ... ${oldValue.slice(diffLengths[0] - 25, diffLengths[0])}` + : oldValue; + const newValueSafe = + diffLengths[1] > 50 && shortenNewVal + ? `${newValue.slice(0, 10)} ... ${newValue.slice(diffLengths[1] - 25, diffLengths[1])}` + : newValue; + + return ( + <div className="p-1 rounded flex flex-wrap gap-2"> + <span className={length > 20 ? 'cursor-pointer' : ''} onClick={() => setShorten(!shorten)}> + {pathStr} + {': '} + </span> + <div + onClick={() => setShortenOldVal(!shortenOldVal)} + className={cn( + 'text-disabled-text', + diffLengths[0] > 50 ? 'cursor-pointer' : '' + )} + > + <span className="line-through">{oldValueSafe || 'undefined'}</span> + {diffLengths[0] > 50 + ? ( + <div onClick={() => setShortenOldVal(!shortenOldVal)} className="cursor-pointer px-1 text-white bg-gray-light rounded text-sm w-fit"> + {!shortenOldVal ? 'collapse' : 'expand'} + </div> + ) : null} + </div> + {' -> '} + <div + className={cn( + 'whitespace-pre', + newValue ? 'text-red' : 'text-green', + )} + > + {newValueSafe || 'undefined'} + {diffLengths[1] > 50 + ? ( + <div onClick={() => setShortenNewVal(!shortenNewVal)} className="cursor-pointer px-1 text-white bg-gray-light rounded text-sm w-fit"> + {!shortenNewVal ? 'collapse' : 'expand'} + </div> + ) : null} + </div> + </div> + ); +} + +export default DiffRow; diff --git a/frontend/app/components/Session_/Storage/Storage.js b/frontend/app/components/Session_/Storage/Storage.js index 9bd6c0174..e0fbb73f6 100644 --- a/frontend/app/components/Session_/Storage/Storage.js +++ b/frontend/app/components/Session_/Storage/Storage.js @@ -2,249 +2,367 @@ import React from 'react'; import { connect } from 'react-redux'; import { hideHint } from 'Duck/components/player'; import { - connectPlayer, - selectStorageType, - STORAGE_TYPES, - selectStorageListNow, - selectStorageList, -} from 'Player/store'; -import { JSONTree, NoContent } from 'UI'; + connectPlayer, + selectStorageType, + STORAGE_TYPES, + selectStorageListNow, + selectStorageList, +} from 'Player'; +import { JSONTree, NoContent, Tooltip } from 'UI'; import { formatMs } from 'App/date'; - +import { diff } from 'deep-diff'; import { jump } from 'Player'; -import Autoscroll from '../Autoscroll'; import BottomBlock from '../BottomBlock/index'; - +import DiffRow from './DiffRow'; import stl from './storage.module.css'; +import { List, CellMeasurer, CellMeasurerCache, AutoSizer } from 'react-virtualized'; -// const STATE = 'STATE'; -// const DIFF = 'DIFF'; -// const TABS = [ DIFF, STATE ].map(tab => ({ text: tab, key: tab })); +const ROW_HEIGHT = 90; function getActionsName(type) { - switch(type) { - case STORAGE_TYPES.MOBX: - return "MUTATIONS"; - case STORAGE_TYPES.VUEX: - return "MUTATIONS"; - default: - return "ACTIONS"; - } + switch (type) { + case STORAGE_TYPES.MOBX: + case STORAGE_TYPES.VUEX: + return 'MUTATIONS'; + default: + return 'ACTIONS'; + } } -@connectPlayer(state => ({ - type: selectStorageType(state), - list: selectStorageList(state), - listNow: selectStorageListNow(state), +@connectPlayer((state) => ({ + type: selectStorageType(state), + list: selectStorageList(state), + listNow: selectStorageListNow(state), })) -@connect(state => ({ - hintIsHidden: state.getIn(['components', 'player', 'hiddenHints', 'storage']), -}), { - hideHint -}) -//@withEnumToggle('activeTab', 'setActiveTab', DIFF) +@connect( + (state) => ({ + hintIsHidden: state.getIn(['components', 'player', 'hiddenHints', 'storage']), + }), + { + hideHint, + } +) export default class Storage extends React.PureComponent { - lastBtnRef = React.createRef() + constructor(props) { + super(props); - focusNextButton() { - if (this.lastBtnRef.current) { - this.lastBtnRef.current.focus(); - } - } + this.lastBtnRef = React.createRef(); + this._list = React.createRef(); + this.cache = new CellMeasurerCache({ + fixedWidth: true, + keyMapper: (index) => this.props.listNow[index], + }); + this._rowRenderer = this._rowRenderer.bind(this); + } - componentDidMount() { - this.focusNextButton(); - } + focusNextButton() { + if (this.lastBtnRef.current) { + this.lastBtnRef.current.focus(); + } + } - componentDidUpdate(prevProps) { - if (prevProps.listNow.length !== this.props.listNow.length) { - this.focusNextButton(); - } - } + componentDidMount() { + this.focusNextButton(); + } - renderDiff() { - // const { listNow, type } = this.props; - // const lastRAction = listNow[ listNow.length - 1 ]; - // if (lastRAction.state) { - // const greenPaths = Object.keys(lastRAction.state).map(key => [ key ]); - // return <DiffTree data={ lastRAction.state } greenPaths={ greenPaths } />; - // } - // const df = {}; - // const redPaths = []; - // const yellowPaths = []; - // const greenPaths = []; - // lastRAction.diff.forEach(d => { - // try { - // let { path, kind, rhs: value } = d; - // if (kind === 'A') { - // path.slice().push(d.index); - // kind = d.item.kind; - // value = d.item.rhs; - // } - // setIn(df, path, value); - // if (kind === 'N') greenPaths.push(d.path.slice().reverse()); - // if (kind === 'D') redPaths.push(d.path.slice().reverse()); - // if (kind === 'E') yellowPaths.push(d.path.slice().reverse()); - // } catch (e) { - // } - // }); - // return ( - // <DiffTree - // data={ df } - // redPaths={ redPaths } - // yellowPaths={ yellowPaths } - // greenPaths={ greenPaths } - // /> - // ); - } + componentDidUpdate(prevProps, prevState) { + if (prevProps.listNow.length !== this.props.listNow.length) { + this.focusNextButton(); + /** possible performance gain, but does not work with dynamic list insertion for some reason + * getting NaN offsets, maybe I detect changed rows wrongly + */ + // const newRows = this.props.listNow.filter(evt => prevProps.listNow.indexOf(evt._index) < 0); + // if (newRows.length > 0) { + // const newRowsIndexes = newRows.map(r => this.props.listNow.indexOf(r)) + // newRowsIndexes.forEach(ind => this.cache.clear(ind)) + // this._list.recomputeRowHeights(newRowsIndexes) + // } + } + } - ensureString(actionType) { - if (typeof actionType === 'string') return actionType; - return "UNKNOWN"; - } + renderDiff(item, prevItem) { + if (!prevItem) { + // we don't have state before first action + return <div style={{ flex: 3 }} className="p-1" />; + } - goNext = () => { - const { list, listNow } = this.props; - jump(list[ listNow.length ].time, list[ listNow.length ]._index); - } + const stateDiff = diff(prevItem.state, item.state); + if (!stateDiff) { + return ( + <div style={{ flex: 3 }} className="flex flex-col p-2 pr-0 font-mono text-disabled-text"> + No diff + </div> + ); + } - renderTab () { - const { listNow } = this.props; - if (listNow.length === 0) { - return "Not initialized"; //? - } - return <JSONTree src={ listNow[ listNow.length - 1 ].state } />; - } + return ( + <div + style={{ flex: 3, maxHeight: ROW_HEIGHT, overflowY: 'scroll' }} + className="flex flex-col p-1 font-mono" + > + {stateDiff.map((d, i) => this.renderDiffs(d, i))} + </div> + ); + } - renderItem(item, i) { - const { type, listNow, list } = this.props; - let src; - let name; + renderDiffs(diff, i) { + const path = this.createPath(diff); - // ZUSTAND TODO - console.log(item, type) - switch(type) { - case STORAGE_TYPES.REDUX: - case STORAGE_TYPES.NGRX: - src = item.action; - name = src && src.type; - break; - case STORAGE_TYPES.VUEX: - src = item.mutation; - name = src && src.type; - break; - case STORAGE_TYPES.MOBX: - src = item.payload; - name = `@${item.type} ${src && src.type}`; - break; - case STORAGE_TYPES.ZUSTAND: - src = null; - name = item.mutation.join('') - } + return ( + <React.Fragment key={i}> + <DiffRow shades={this.pathShades} path={path} diff={diff} /> + </React.Fragment> + ); + } - return ( - <div className="flex justify-between items-start" key={ `store-${i}` }> - {src === null ? ( - <div className="font-mono"> {name} </div> - ) : ( - <JSONTree - name={ this.ensureString(name) } - src={ src } - collapsed - collapseStringsAfterLength={ 7 } - /> - )} - <div className="flex items-center"> - { i + 1 < listNow.length && - <button - className={ stl.button } - onClick={ () => jump(item.time, item._index) } - > - {"JUMP"} - </button> - } - { i + 1 === listNow.length && i + 1 < list.length && - <button - className={ stl.button } - ref={ this.lastBtnRef } - onClick={ this.goNext } - > - {"NEXT"} - </button> - } - { typeof item.duration === 'number' && - <div className="font-size-12 color-gray-medium"> - { formatMs(item.duration) } - </div> - } - </div> - </div> - ); - } + createPath = (diff) => { + let path = []; - render() { - const { - type, - listNow, - list, - hintIsHidden, - } = this.props; + if (diff.path) { + path = path.concat(diff.path); + } + if (typeof diff.index !== 'undefined') { + path.push(diff.index); + } - const showStore = type !== STORAGE_TYPES.MOBX; - return ( - <BottomBlock> - <BottomBlock.Header> - <span className="font-semibold color-gray-medium mr-4">State</span> - { list.length > 0 && - <div className="flex w-full"> - { showStore && - <h3 style={{ width: "40%" }}> - {"STORE"} - </h3> - } - <h3 style={{ width: "40%" }}> - {getActionsName(type)} - </h3> - </div> - } - </BottomBlock.Header> - <BottomBlock.Content className="flex" > - <NoContent + const pathStr = path.length ? path.join('.') : ''; + return pathStr; + }; + + ensureString(actionType) { + if (typeof actionType === 'string') return actionType; + return 'UNKNOWN'; + } + + goNext = () => { + const { list, listNow } = this.props; + jump(list[listNow.length].time, list[listNow.length]._index); + }; + + renderTab() { + const { listNow } = this.props; + if (listNow.length === 0) { + return 'Not initialized'; //? + } + return <JSONTree collapsed={2} src={listNow[listNow.length - 1].state} />; + } + + renderItem(item, i, prevItem, style) { + const { type } = this.props; + let src; + let name; + + switch (type) { + case STORAGE_TYPES.REDUX: + case STORAGE_TYPES.NGRX: + src = item.action; + name = src && src.type; + break; + case STORAGE_TYPES.VUEX: + src = item.mutation; + name = src && src.type; + break; + case STORAGE_TYPES.MOBX: + src = item.payload; + name = `@${item.type} ${src && src.type}`; + break; + case STORAGE_TYPES.ZUSTAND: + src = null; + name = item.mutation.join(''); + } + + return ( + <div + style={{ ...style, height: ROW_HEIGHT }} + className="flex justify-between items-start border-b" + key={`store-${i}`} + > + {src === null ? ( + <div className="font-mono" style={{ flex: 2, marginLeft: '26.5%' }}> + {name} + </div> + ) : ( + <> + {this.renderDiff(item, prevItem, i)} + <div + style={{ flex: 2, maxHeight: ROW_HEIGHT, overflowY: 'scroll', overflowX: 'scroll' }} + className="flex pl-10 pt-2" + > + <JSONTree + name={this.ensureString(name)} + src={src} + collapsed + collapseStringsAfterLength={7} + onSelect={() => console.log('test')} + /> + </div> + </> + )} + <div + style={{ flex: 1 }} + className="flex-1 flex gap-2 pt-2 items-center justify-end self-start" + > + {typeof item.duration === 'number' && ( + <div className="font-size-12 color-gray-medium">{formatMs(item.duration)}</div> + )} + <div className="w-12"> + {i + 1 < this.props.listNow.length && ( + <button className={stl.button} onClick={() => jump(item.time, item._index)}> + {'JUMP'} + </button> + )} + {i + 1 === this.props.listNow.length && i + 1 < this.props.list.length && ( + <button className={stl.button} ref={this.lastBtnRef} onClick={this.goNext}> + {'NEXT'} + </button> + )} + </div> + </div> + </div> + ); + } + + _rowRenderer({ index, parent, key, style }) { + const { listNow } = this.props; + + if (!listNow[index]) return console.warn(index, listNow); + + return ( + <CellMeasurer cache={this.cache} columnIndex={0} key={key} rowIndex={index} parent={parent}> + {this.renderItem(listNow[index], index, index > 0 ? listNow[index - 1] : undefined, style)} + </CellMeasurer> + ); + } + + render() { + const { type, list, listNow, hintIsHidden } = this.props; + + const showStore = type !== STORAGE_TYPES.MOBX; + return ( + <BottomBlock> + <BottomBlock.Header> + {list.length > 0 && ( + <div className="flex w-full"> + {showStore && ( + <h3 style={{ width: '25%', marginRight: 20 }} className="font-semibold"> + {'STATE'} + </h3> + )} + {type !== STORAGE_TYPES.ZUSTAND ? ( + <h3 style={{ width: '39%' }} className="font-semibold"> + DIFFS + </h3> + ) : null} + <h3 style={{ width: '30%' }} className="font-semibold"> + {getActionsName(type)} + </h3> + <h3 style={{ paddingRight: 30, marginLeft: 'auto' }} className="font-semibold"> + <Tooltip title="Time to execute">TTE</Tooltip> + </h3> + </div> + )} + </BottomBlock.Header> + <BottomBlock.Content className="flex"> + <NoContent title="Nothing to display yet." - subtext={ !hintIsHidden - ? + subtext={ + !hintIsHidden ? ( <> - {'Inspect your application state while you’re replaying your users sessions. OpenReplay supports '} - <a className="underline color-teal" href="https://docs.openreplay.com/plugins/redux" target="_blank">Redux</a>{', '} - <a className="underline color-teal" href="https://docs.openreplay.com/plugins/vuex" target="_blank">VueX</a>{', '} - {/* ZUSTAND TODO */} - <a className="underline color-teal" href="https://docs.openreplay.com/plugins/mobx" target="_blank">MobX</a>{' and '} - <a className="underline color-teal" href="https://docs.openreplay.com/plugins/ngrx" target="_blank">NgRx</a>. - <br/><br/> - <button className="color-teal" onClick={() => this.props.hideHint("storage")}>Got It!</button> + { + 'Inspect your application state while you’re replaying your users sessions. OpenReplay supports ' + } + <a + className="underline color-teal" + href="https://docs.openreplay.com/plugins/redux" + target="_blank" + > + Redux + </a> + {', '} + <a + className="underline color-teal" + href="https://docs.openreplay.com/plugins/vuex" + target="_blank" + > + VueX + </a> + {', '} + <a + className="underline color-teal" + href="https://docs.openreplay.com/plugins/pinia" + target="_blank" + > + Pinia + </a> + {', '} + <a + className="underline color-teal" + href="https://docs.openreplay.com/plugins/zustand" + target="_blank" + > + Zustand + </a> + {', '} + <a + className="underline color-teal" + href="https://docs.openreplay.com/plugins/mobx" + target="_blank" + > + MobX + </a> + {' and '} + <a + className="underline color-teal" + href="https://docs.openreplay.com/plugins/ngrx" + target="_blank" + > + NgRx + </a> + . + <br /> + <br /> + <button className="color-teal" onClick={() => this.props.hideHint('storage')}> + Got It! + </button> </> - : null + ) : null } size="small" - show={ listNow.length === 0 } + show={listNow.length === 0} > - { showStore && - <div className="ph-10 scroll-y" style={{ width: "40%" }} > - { listNow.length === 0 - ? <div className="color-gray-light font-size-16 mt-20 text-center" >{ "Empty state." }</div> - : this.renderTab() - } - </div> - } - <div className="flex" style={{ width: showStore ? "60%" : "100%" }} > - <Autoscroll className="ph-10" > - { listNow.map((item, i) => this.renderItem(item, i)) } - </Autoscroll> - </div> - </NoContent> - </BottomBlock.Content> - </BottomBlock> - ); - } + {showStore && ( + <div className="ph-10 scroll-y" style={{ width: '25%' }}> + {listNow.length === 0 ? ( + <div className="color-gray-light font-size-16 mt-20 text-center"> + {'Empty state.'} + </div> + ) : ( + this.renderTab() + )} + </div> + )} + <div className="flex" style={{ width: showStore ? '75%' : '100%' }}> + <AutoSizer> + {({ height, width }) => ( + <List + ref={(element) => { + this._list = element; + }} + deferredMeasurementCache={this.cache} + overscanRowCount={1} + rowCount={Math.ceil(parseInt(this.props.listNow.length) || 1)} + rowHeight={ROW_HEIGHT} + rowRenderer={this._rowRenderer} + width={width} + height={height} + /> + )} + </AutoSizer> + </div> + </NoContent> + </BottomBlock.Content> + </BottomBlock> + ); + } } diff --git a/frontend/app/components/Session_/Storage/Storge.DEPRECATED.js b/frontend/app/components/Session_/Storage/Storge.DEPRECATED.js new file mode 100644 index 000000000..660d2057e --- /dev/null +++ b/frontend/app/components/Session_/Storage/Storge.DEPRECATED.js @@ -0,0 +1,284 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { hideHint } from 'Duck/components/player'; +import { + connectPlayer, + selectStorageType, + STORAGE_TYPES, + selectStorageListNow, + selectStorageList, +} from 'Player'; +import { JSONTree, NoContent } from 'UI'; +import { formatMs } from 'App/date'; +import { diff } from 'deep-diff'; +import DiffTree from './DiffTree' +import { setIn } from 'immutable'; +import { jump } from 'Player'; +import Autoscroll from '../Autoscroll'; +import BottomBlock from '../BottomBlock/index'; + +import stl from './storage.module.css'; + +// const STATE = 'STATE'; +// const DIFF = 'DIFF'; +// const TABS = [ DIFF, STATE ].map(tab => ({ text: tab, key: tab })); + +function getActionsName(type) { + switch(type) { + case STORAGE_TYPES.MOBX: + return "MUTATIONS"; + case STORAGE_TYPES.VUEX: + return "MUTATIONS"; + default: + return "ACTIONS"; + } +} + +@connectPlayer(state => ({ + type: selectStorageType(state), + list: selectStorageList(state), + listNow: selectStorageListNow(state), +})) +@connect(state => ({ + hintIsHidden: state.getIn(['components', 'player', 'hiddenHints', 'storage']), +}), { + hideHint +}) +//@withEnumToggle('activeTab', 'setActiveTab', DIFF) +export default class Storage extends React.PureComponent { + lastBtnRef = React.createRef() + + focusNextButton() { + if (this.lastBtnRef.current) { + this.lastBtnRef.current.focus(); + } + } + + componentDidMount() { + this.focusNextButton(); + } + + componentDidUpdate(prevProps) { + if (prevProps.listNow.length !== this.props.listNow.length) { + this.focusNextButton(); + } + } + + renderDiff(item, prevItem) { + if (!prevItem) { + return <div style={{ flex: 1}} /> + } + const stateDiff = diff(prevItem.state, item.state) + console.log(item.state, prevItem.state, stateDiff) + const greenPaths = [] + const redPaths = [] + const yellowPaths = [] + if (!stateDiff) { + return <span> No diff </span> + } + // stateDiff.forEach(d => { + // try { + // let { path, kind, rhs: value } = d; + // if (kind === 'A') { + // path.slice().push(d.index); + // kind = d.item.kind; + // value = d.item.rhs; + // } + + // if (kind === 'N') greenPaths.push(d.path.slice().reverse()); + // if (kind === 'D') redPaths.push(d.path.slice().reverse()); + // if (kind === 'E') yellowPaths.push(d.path.slice().reverse()); + // } catch (e) { + // console.error(e) + // } + // }); + function renderDiffs(diff, i) { + const oldValue = diff.item ? JSON.stringify(diff.item.lhs) : JSON.stringify(diff.lhs) + const newValue = diff.item ? JSON.stringify(diff.item.rhs) : JSON.stringify(diff.rhs) + + const createPath = () => { + let path = []; + + if (diff.path) { + path = path.concat(diff.path); + } + if (typeof(diff.index) !== 'undefined') { + path.push(diff.index); + } + return path.length ? path.join('.') : ''; + } + + return ( + <div key={i}> + { createPath() }: <span className="line-through">{ oldValue || 'undefined' }</span>{' -> '}<span className="font-semibold"> { newValue || 'undefined'} </span> + </div> + ) + } + return ( + <div style={{ flex: 1}} className='flex flex-col p-1 border bg-light-blue-bg font-mono'> + {stateDiff.map((d, i) => renderDiffs(d, i))} + </div> + ) + // <DiffTree + // data={ prevItem.state } + // redPaths={ redPaths } + // yellowPaths={ yellowPaths } + // greenPaths={ greenPaths } + // /> + ; + } + + ensureString(actionType) { + if (typeof actionType === 'string') return actionType; + return "UNKNOWN"; + } + + goNext = () => { + const { list, listNow } = this.props; + jump(list[ listNow.length ].time, list[ listNow.length ]._index); + } + + + renderTab () { + const { listNow } = this.props; + if (listNow.length === 0) { + return "Not initialized"; //? + } + return <JSONTree src={ listNow[ listNow.length - 1 ].state } />; + } + + renderItem(item, i, prevItem) { + const { type, listNow, list } = this.props; + let src; + let name; + + switch(type) { + case STORAGE_TYPES.REDUX: + case STORAGE_TYPES.NGRX: + src = item.action; + name = src && src.type; + break; + case STORAGE_TYPES.VUEX: + src = item.mutation; + name = src && src.type; + break; + case STORAGE_TYPES.MOBX: + src = item.payload; + name = `@${item.type} ${src && src.type}`; + break; + case STORAGE_TYPES.ZUSTAND: + src = null; + name = item.mutation.join('') + } + + return ( + <div className="flex justify-between items-start" key={ `store-${i}` }> + {src === null ? ( + <div className="font-mono"> {name} </div> + ) : ( + <> + {this.renderDiff(item, prevItem)} + <div style={{ flex: 2 }} className="flex pl-10"> + <JSONTree + name={ this.ensureString(name) } + src={ src } + collapsed + collapseStringsAfterLength={ 7 } + /> + </div> + </> + )} + <div style={{ flex: 1 }} className="flex-1 flex items-center justify-end"> + { i + 1 < listNow.length && + <button + className={ stl.button } + onClick={ () => jump(item.time, item._index) } + > + {"JUMP"} + </button> + } + { i + 1 === listNow.length && i + 1 < list.length && + <button + className={ stl.button } + ref={ this.lastBtnRef } + onClick={ this.goNext } + > + {"NEXT"} + </button> + } + { typeof item.duration === 'number' && + <div className="font-size-12 color-gray-medium"> + { formatMs(item.duration) } + </div> + } + </div> + </div> + ); + } + + render() { + const { + type, + listNow, + list, + hintIsHidden, + } = this.props; + + const showStore = type !== STORAGE_TYPES.MOBX; + return ( + <BottomBlock> + <BottomBlock.Header> + <span className="font-semibold color-gray-medium mr-4">State</span> + { list.length > 0 && + <div className="flex w-full"> + { showStore && + <h3 style={{ width: "40%" }}> + {"STORE"} + </h3> + } + <h3 style={{ width: "40%" }}> + {getActionsName(type)} + </h3> + </div> + } + </BottomBlock.Header> + <BottomBlock.Content className="flex" > + <NoContent + title="Nothing to display yet." + subtext={ !hintIsHidden + ? + <> + {'Inspect your application state while you’re replaying your users sessions. OpenReplay supports '} + <a className="underline color-teal" href="https://docs.openreplay.com/plugins/redux" target="_blank">Redux</a>{', '} + <a className="underline color-teal" href="https://docs.openreplay.com/plugins/vuex" target="_blank">VueX</a>{', '} + <a className="underline color-teal" href="https://docs.openreplay.com/plugins/pinia" target="_blank">Pinia</a>{', '} + <a className="underline color-teal" href="https://docs.openreplay.com/plugins/zustand" target="_blank">Zustand</a>{', '} + <a className="underline color-teal" href="https://docs.openreplay.com/plugins/mobx" target="_blank">MobX</a>{' and '} + <a className="underline color-teal" href="https://docs.openreplay.com/plugins/ngrx" target="_blank">NgRx</a>. + <br/><br/> + <button className="color-teal" onClick={() => this.props.hideHint("storage")}>Got It!</button> + </> + : null + } + size="small" + show={ listNow.length === 0 } + > + { showStore && + <div className="ph-10 scroll-y" style={{ width: "40%" }} > + { listNow.length === 0 + ? <div className="color-gray-light font-size-16 mt-20 text-center" >{ "Empty state." }</div> + : this.renderTab() + } + </div> + } + <div className="flex" style={{ width: showStore ? "60%" : "100%" }} > + <Autoscroll className="ph-10" > + { listNow.map((item, i) => this.renderItem(item, i, i > 0 ? listNow[i - 1] : undefined)) } + </Autoscroll> + </div> + </NoContent> + </BottomBlock.Content> + </BottomBlock> + ); + } +} diff --git a/frontend/app/components/Session_/Storage/storage.module.css b/frontend/app/components/Session_/Storage/storage.module.css index 55f04d5db..d34ab27b9 100644 --- a/frontend/app/components/Session_/Storage/storage.module.css +++ b/frontend/app/components/Session_/Storage/storage.module.css @@ -1,8 +1,7 @@ .button { - padding: 2px 6px; + padding: 3px 6px; cursor: pointer; - width: 60px; border-radius: 3px; color: $gray-light; &:hover { @@ -14,4 +13,4 @@ font-size: 12px; margin-right: 5px; -} \ No newline at end of file +} diff --git a/frontend/app/components/Session_/Subheader.js b/frontend/app/components/Session_/Subheader.js index c378386ee..a1ee8e48d 100644 --- a/frontend/app/components/Session_/Subheader.js +++ b/frontend/app/components/Session_/Subheader.js @@ -1,80 +1,121 @@ import React from 'react'; -import { Icon } from 'UI'; +import { Icon, Tooltip, Button } from 'UI'; import Autoplay from './Autoplay'; -import Bookmark from 'Shared/Bookmark' +import Bookmark from 'Shared/Bookmark'; import SharePopup from '../shared/SharePopup/SharePopup'; -import { connectPlayer } from 'Player'; import copy from 'copy-to-clipboard'; -import { Tooltip } from 'react-tippy'; import Issues from './Issues/Issues'; +import NotePopup from './components/NotePopup'; +import { connectPlayer, pause } from 'Player'; +import ItemMenu from './components/HeaderMenu'; +import { useModal } from 'App/components/Modal'; +import BugReportModal from './BugReport/BugReportModal'; function SubHeader(props) { - const [isCopied, setCopied] = React.useState(false); + const [isCopied, setCopied] = React.useState(false); + const { showModal, hideModal } = useModal(); + const isAssist = window.location.pathname.includes('/assist/'); - const isAssist = window.location.pathname.includes('/assist/'); + const location = + props.currentLocation && props.currentLocation.length > 60 + ? `${props.currentLocation.slice(0, 60)}...` + : props.currentLocation; - const location = props.currentLocation && props.currentLocation.length > 60 ? `${props.currentLocation.slice(0, 60)}...` : props.currentLocation - return ( - <div className="w-full px-4 py-2 flex items-center border-b"> - {location && ( - <div - className="flex items-center cursor-pointer color-gray-medium text-sm p-1 hover:bg-gray-light-shade rounded-md" - onClick={() => { - copy(props.currentLocation); - setCopied(true) - setTimeout(() => setCopied(false), 5000) - }} - > - <Icon size="20" name="event/link" className="mr-1" /> - <Tooltip - delay={0} - arrow - animation="fade" - hideOnClick={false} - position="bottom center" - title={isCopied ? 'URL Copied to clipboard' : 'Click to copy'} - > - {location} - </Tooltip> - </div> - )} - {!isAssist ? ( - <div className="ml-auto text-sm flex items-center color-gray-medium" style={{ width: 'max-content' }}> - <div className="cursor-pointer mr-4 hover:bg-gray-light-shade rounded-md p-1"> - {props.jiraConfig && props.jiraConfig.token && <Issues sessionId={props.sessionId} />} - </div> - <div className="cursor-pointer"> - <SharePopup - entity="sessions" - id={ props.sessionId } - showCopyLink={true} - trigger={ - <div className="flex items-center hover:bg-gray-light-shade rounded-md p-1"> - <Icon - className="mr-2" - disabled={ props.disabled } - name="share-alt" - size="16" - /> - <span>Share</span> - </div> - } - /> - </div> - <div className="mx-4 hover:bg-gray-light-shade rounded-md p-1"> - <Bookmark noMargin sessionId={props.sessionId} /> - </div> - <div> - <Autoplay /> - </div> - <div> - </div> - </div> - ) : null} + const showReportModal = () => { + pause(); + const xrayProps = { + currentLocation: props.currentLocation, + resourceList: props.resourceList, + exceptionsList: props.exceptionsList, + eventsList: props.eventsList, + endTime: props.endTime, + } + showModal(<BugReportModal width={props.width} height={props.height} xrayProps={xrayProps} hideModal={hideModal} />, { right: true }); + }; + + return ( + <div className="w-full px-4 py-2 flex items-center border-b"> + {location && ( + <div + className="flex items-center cursor-pointer color-gray-medium text-sm p-1 hover:bg-gray-light-shade rounded-md" + onClick={() => { + copy(props.currentLocation); + setCopied(true); + setTimeout(() => setCopied(false), 5000); + }} + > + <Icon size="20" name="event/link" className="mr-1" /> + <Tooltip title={isCopied ? 'URL Copied to clipboard' : 'Click to copy'}> + {location} + </Tooltip> </div> - ) + )} + {!isAssist ? ( + <div + className="ml-auto text-sm flex items-center color-gray-medium gap-2" + style={{ width: 'max-content' }} + > + <Button icon="file-pdf" variant="text" onClick={showReportModal}>Create Bug Report</Button> + <NotePopup /> + <ItemMenu + items={[ + { + key: 2, + component: props.jiraConfig && props.jiraConfig.token && ( + <Issues sessionId={props.sessionId} /> + ), + }, + { + key: 3, + component: ( + <SharePopup + entity="sessions" + id={props.sessionId} + showCopyLink={true} + trigger={ + <div className="flex items-center h-full w-full"> + <Icon + className="mr-2" + disabled={props.disabled} + name="share-alt" + size="16" + /> + <span>Share</span> + </div> + } + /> + ), + }, + { + key: 4, + component: <Bookmark noMargin sessionId={props.sessionId} />, + }, + ]} + /> + + <div> + <Autoplay /> + </div> + </div> + ) : null} + </div> + ); } -const SubH = connectPlayer(state => ({ currentLocation: state.location }))(SubHeader) +const SubH = connectPlayer( + (state) => ({ + width: state.width, + height: state.height, + currentLocation: state.location, + resourceList: state.resourceList + .filter((r) => r.isRed() || r.isYellow()) + .concat(state.fetchList.filter((i) => parseInt(i.status) >= 400)) + .concat(state.graphqlList.filter((i) => parseInt(i.status) >= 400)), + exceptionsList: state.exceptionsList, + eventsList: state.eventList, + endTime: state.endTime, + }) -export default React.memo(SubH) + )(SubHeader); + +export default React.memo(SubH); diff --git a/frontend/app/components/Session_/TimeTable/BarRow.tsx b/frontend/app/components/Session_/TimeTable/BarRow.tsx index 9de1a8279..98aa3e3fb 100644 --- a/frontend/app/components/Session_/TimeTable/BarRow.tsx +++ b/frontend/app/components/Session_/TimeTable/BarRow.tsx @@ -1,25 +1,30 @@ -import { Popup } from 'UI'; +import { Tooltip } from 'UI'; import { percentOf } from 'App/utils'; -import styles from './barRow.module.css' +import styles from './barRow.module.css'; import tableStyles from './timeTable.module.css'; import React from 'react'; -const formatTime = time => time < 1000 ? `${time.toFixed(2)}ms` : `${time / 1000}s`; +const formatTime = (time) => (time < 1000 ? `${time.toFixed(2)}ms` : `${time / 1000}s`); interface Props { resource: { - time: number - ttfb?: number - duration?: number - key: string - } - popup?: boolean - timestart: number - timewidth: number + time: number; + ttfb?: number; + duration?: number; + key: string; + }; + popup?: boolean; + timestart: number; + timewidth: number; } // TODO: If request has no duration, set duration to 0.2s. Enforce existence of duration in the future. -const BarRow = ({ resource: { time, ttfb = 0, duration = 200, key }, popup = false, timestart = 0, timewidth }: Props) => { +const BarRow = ({ + resource: { time, ttfb = 0, duration = 200, key }, + popup = false, + timestart = 0, + timewidth, +}: Props) => { const timeOffset = time - timestart; ttfb = ttfb || 0; const trigger = ( @@ -28,7 +33,7 @@ const BarRow = ({ resource: { time, ttfb = 0, duration = 200, key }, popup = fal style={{ left: `${percentOf(timeOffset, timewidth)}%`, right: `${100 - percentOf(timeOffset + duration, timewidth)}%`, - minWidth: '5px' + minWidth: '5px', }} > <div @@ -41,23 +46,28 @@ const BarRow = ({ resource: { time, ttfb = 0, duration = 200, key }, popup = fal className={styles.downloadBar} style={{ width: `${percentOf(duration - ttfb, duration)}%`, - minWidth: '5px' + minWidth: '5px', }} /> </div> ); - if (!popup) return <div key={key} className={tableStyles.row} > {trigger} </div>; + if (!popup) + return ( + <div key={key} className={tableStyles.row}> + {' '} + {trigger}{' '} + </div> + ); return ( - <div key={key} className={tableStyles.row} > - <Popup - basic - content={ + <div key={key} className={tableStyles.row}> + <Tooltip + title={ <React.Fragment> - {ttfb != null && + {ttfb != null && ( <div className={styles.popupRow}> <div className={styles.title}>{'Waiting (TTFB)'}</div> - <div className={styles.popupBarWrapper} > + <div className={styles.popupBarWrapper}> <div className={styles.ttfbBar} style={{ @@ -66,11 +76,11 @@ const BarRow = ({ resource: { time, ttfb = 0, duration = 200, key }, popup = fal }} /> </div> - <div className={styles.time} >{formatTime(ttfb)}</div> + <div className={styles.time}>{formatTime(ttfb)}</div> </div> - } + )} <div className={styles.popupRow}> - <div className={styles.title} >{'Content Download'}</div> + <div className={styles.title}>{'Content Download'}</div> <div className={styles.popupBarWrapper}> <div className={styles.downloadBar} @@ -86,11 +96,13 @@ const BarRow = ({ resource: { time, ttfb = 0, duration = 200, key }, popup = fal } size="mini" position="top center" - /> + > + {trigger} + </Tooltip> </div> ); -} +}; -BarRow.displayName = "BarRow"; +BarRow.displayName = 'BarRow'; -export default BarRow; \ No newline at end of file +export default BarRow; diff --git a/frontend/app/components/Session_/TimeTable/timeTable.module.css b/frontend/app/components/Session_/TimeTable/timeTable.module.css index 17feaf459..c2412ff8d 100644 --- a/frontend/app/components/Session_/TimeTable/timeTable.module.css +++ b/frontend/app/components/Session_/TimeTable/timeTable.module.css @@ -9,7 +9,7 @@ $offset: 10px; .headers { box-shadow: 0 1px 2px 0 $gray-light; background-color: $gray-lightest; - color: $gray-medium; + color: $gray-darkest; font-size: 12px; overflow-x: hidden; white-space: nowrap; @@ -47,6 +47,10 @@ $offset: 10px; .row { display: flex; padding: 0 $offset; + + &:hover { + background-color: $active-blue; + } /*align-items: center; cursor: pointer; */ diff --git a/frontend/app/components/Session_/components/HeaderMenu.tsx b/frontend/app/components/Session_/components/HeaderMenu.tsx new file mode 100644 index 000000000..08c875f96 --- /dev/null +++ b/frontend/app/components/Session_/components/HeaderMenu.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { Icon } from 'UI'; +import styles from './menu.module.css'; +import cn from 'classnames'; +import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; + +interface MenuItem { + key: number; + component?: React.ReactElement; +} + +interface Props { + items: MenuItem[]; +} + +export default class ItemMenu extends React.PureComponent<Props> { + state = { + displayed: false, + }; + + handleEsc = (e: KeyboardEvent) => e.key === 'Escape' && this.state.displayed && this.toggleMenu(); + + componentDidMount() { + document.addEventListener('keydown', this.handleEsc, false); + } + componentWillUnmount() { + document.removeEventListener('keydown', this.handleEsc, false); + } + + toggleMenu = () => { + this.setState({ displayed: !this.state.displayed }); + }; + + closeMenu = () => { + this.setState({ displayed: false }) + } + + render() { + const { items } = this.props; + const { displayed } = this.state; + + return ( + <div className={styles.wrapper}> + <OutsideClickDetectingDiv onClickOutside={this.closeMenu}> + <div + onClick={this.toggleMenu} + className={cn( + 'flex items-center cursor-pointer select-none', + 'rounded p-2', displayed ? 'bg-gray-light' : 'hover:bg-gray-light-shade' + )} + > + <div + className={cn('rounded-full flex items-center justify-center', { + 'bg-gray-light': displayed, + })} + role="button" + > + <Icon name="ellipsis-v" size="16" /> + </div> + <span className={'mr-1 text-disabled-text'}>More</span> + </div> + <div className={cn(styles.menu, styles.menuDim)} data-displayed={displayed}> + {items.map((item) => + item.component ? ( + <div + key={item.key} + role="menuitem" + className="hover:bg-gray-light-shade cursor-pointer flex items-center w-full" + > + {item.component} + </div> + ) : null + )} + </div> + </OutsideClickDetectingDiv> + </div> + ); + } +} diff --git a/frontend/app/components/Session_/components/NotePopup.tsx b/frontend/app/components/Session_/components/NotePopup.tsx new file mode 100644 index 000000000..83201fc57 --- /dev/null +++ b/frontend/app/components/Session_/components/NotePopup.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { Button } from 'UI'; +import { connectPlayer, pause } from 'Player'; +import { connect } from 'react-redux'; +import { setCreateNoteTooltip } from 'Duck/sessions'; +import GuidePopup, { FEATURE_KEYS } from 'Shared/GuidePopup'; + +function NotePopup({ + setCreateNoteTooltip, + time, + tooltipActive, +}: { + setCreateNoteTooltip: (args: any) => void; + time: number; + tooltipActive: boolean; +}) { + const toggleNotePopup = () => { + if (tooltipActive) return; + pause(); + setCreateNoteTooltip({ time: time, isVisible: true }); + }; + + React.useEffect(() => { + return () => setCreateNoteTooltip({ time: -1, isVisible: false }); + }, []); + + return ( + <GuidePopup + title="Introducing Notes" + description={'Annotate session replays and share your feedback with the rest of your team.'} + > + <Button icon="quotes" variant="text" disabled={tooltipActive} onClick={toggleNotePopup}> + Add Note + </Button> + </GuidePopup> + ); +} + +const NotePopupPl = connectPlayer( + // @ts-ignore + (state) => ({ time: state.time }) +)(React.memo(NotePopup)); + +const NotePopupComp = connect( + (state: any) => ({ tooltipActive: state.getIn(['sessions', 'createNoteTooltip', 'isVisible']) }), + { setCreateNoteTooltip } +)(NotePopupPl); + +export default React.memo(NotePopupComp); diff --git a/frontend/app/components/Session_/components/menu.module.css b/frontend/app/components/Session_/components/menu.module.css new file mode 100644 index 000000000..be06d9133 --- /dev/null +++ b/frontend/app/components/Session_/components/menu.module.css @@ -0,0 +1,102 @@ +@import 'icons.css'; + +.wrapper { + position: relative; + display: inline-block; +} + +.menuBtn { + @mixin icon-before ellipsis-v, $gray-darkest, 18px { + margin: 5px; + } + width: 36px; + height: 36px; + border-radius: 18px; + border: 1px solid transparent; + transition: all 0.2s; + margin: 0 auto; + cursor: pointer; + + &:hover { + border-color: $active-blue-border; + transition: all 0.2s; + background-color: #fff; + } +} + +.menuDim { + border: none!important; + box-shadow: 0 1px 3px 0 $gray-light!important; + + & .menuItem { + color: $gray-dark!important; + } +} + +.menu { + &[data-displayed=false] { + display: none; + } + + white-space: nowrap; + z-index: 20; + position: absolute; + right: 0px; + top: 37px; + min-width: 150px; + background-color: $white; + border-radius: 3px; + border: 1px solid rgba(34,36,38,.15); + box-shadow: 0 2px 3px 0 rgb(34 36 38 / 15%); + + + & .menuItem { + cursor: pointer; + /* padding: 10px; */ + color: black; + display: flex; + align-items: center; + border-bottom: 1px solid $gray-light; + position: relative; + + & .iconWrapper { + width: 13px; + height: 13px ; + margin-right: 8px; + } + + &:hover { + background-color: $active-blue; + } + + &:last-child { + border: none; + } + + & .edit { + @mixin icon pencil, $gray-medium, 15px; + margin-right: 10px; + } + + & .copy { + @mixin icon copy, $gray-medium, 15px; + margin-right: 10px; + } + + & .remove { + @mixin icon trash, $gray-medium, 15px; + margin-right: 10px; + } + + & .enabled { + @mixin icon eye, $gray-medium, 15px; + margin-right: 10px; + } + + & .disabled { + @mixin icon eye-slash, $gray-medium, 15px; + margin-right: 10px; + } + + } +} diff --git a/frontend/app/components/hocs/withCopy.tsx b/frontend/app/components/hocs/withCopy.tsx index 2b3a9d541..374f287ec 100644 --- a/frontend/app/components/hocs/withCopy.tsx +++ b/frontend/app/components/hocs/withCopy.tsx @@ -1,27 +1,27 @@ import React from 'react'; import copy from 'copy-to-clipboard'; -import { Tooltip } from 'react-tippy'; +import { Tooltip } from 'UI'; const withCopy = (WrappedComponent: React.ComponentType) => { - const ComponentWithCopy = (props: any) => { - const [copied, setCopied] = React.useState(false); - const { value, tooltip } = props; - const copyToClipboard = (text: string) => { - copy(text); - setCopied(true); - setTimeout(() => { - setCopied(false); - }, 1000); - }; - return ( - <div onClick={() => copyToClipboard(value)} className="w-fit"> - <Tooltip delay={0} arrow animation="fade" hideOnClick={false} title={copied ? tooltip : 'Click to copy'}> - <WrappedComponent {...props} copyToClipboard={copyToClipboard} /> - </Tooltip> - </div> - ); + const ComponentWithCopy = (props: any) => { + const [copied, setCopied] = React.useState(false); + const { value, tooltip } = props; + const copyToClipboard = (text: string) => { + copy(text); + setCopied(true); + setTimeout(() => { + setCopied(false); + }, 1000); }; - return ComponentWithCopy; + return ( + <div onClick={() => copyToClipboard(value)} className="w-fit cursor-pointer"> + <Tooltip title={copied ? tooltip : 'Click to copy'} delay={0}> + <WrappedComponent {...props} copyToClipboard={copyToClipboard} /> + </Tooltip> + </div> + ); + }; + return ComponentWithCopy; }; export default withCopy; diff --git a/frontend/app/components/hocs/withReport.tsx b/frontend/app/components/hocs/withReport.tsx index 115a65dfd..aebd72998 100644 --- a/frontend/app/components/hocs/withReport.tsx +++ b/frontend/app/components/hocs/withReport.tsx @@ -6,154 +6,181 @@ import { observer, useObserver } from 'mobx-react-lite'; import { connect } from 'react-redux'; import { fileNameFormat } from 'App/utils'; import { toast } from 'react-toastify'; +import { forceVisible } from 'react-lazyload'; + +const TEXT_GENERATING = 'Generating report...'; +const TEXT_SUCCESS = 'Report successfully generated'; interface Props { - site: any; + site: any; } export default function withReport<P extends Props>(WrappedComponent: React.ComponentType<P>) { - const ComponentWithReport = (props: P) => { - const [rendering, setRendering] = React.useState(false); - const { site } = props; - const { dashboardStore } = useStore(); - const dashboard: any = useObserver(() => dashboardStore.selectedDashboard); - const widgets: any = useObserver(() => dashboard?.widgets); - const period = useObserver(() => dashboardStore.period); + const ComponentWithReport = (props: P) => { + const [rendering, setRendering] = React.useState(false); + const { site } = props; + const { dashboardStore } = useStore(); + const dashboard: any = useObserver(() => dashboardStore.selectedDashboard); + const period = useObserver(() => dashboardStore.period); + const pendingRequests = useObserver(() => dashboardStore.pendingRequests); - const addFooters = (doc: any) => { - const pageCount = doc.internal.getNumberOfPages(); - for (var i = 1; i <= pageCount; i++) { - doc.setPage(i); - doc.setFontSize(8); - doc.setTextColor(136, 136, 136); - doc.text('Page ' + String(i) + ' of ' + String(pageCount), 200, 290, null, null, 'right'); - doc.addImage('/assets/img/logo-open-replay-grey.png', 'png', 10, 288, 20, 0); - } - }; + useEffect(() => { + if (rendering && pendingRequests <= 0) { + processReport(); + } + }, [pendingRequests]); - const renderPromise = async (): Promise<any> => { - const promise = new Promise((resolve, reject) => { - renderReport(resolve); - }); - toast.promise(promise, { - pending: 'Generating report...', - success: 'Report successfully generated', - }); - }; - - const renderReport = async (cb: any) => { - document.body.scrollIntoView(); - const doc = new jsPDF('p', 'mm', 'a4'); - const now = new Date().toISOString(); - - doc.addMetadata('Author', 'OpenReplay'); - doc.addMetadata('Title', 'OpenReplay Report'); - doc.addMetadata('Subject', 'OpenReplay Report'); - doc.addMetadata('Keywords', 'OpenReplay Report'); - doc.addMetadata('Creator', 'OpenReplay'); - doc.addMetadata('Producer', 'OpenReplay'); - doc.addMetadata('CreationDate', now); - - const parentElement = document.getElementById('report') as HTMLElement; - const pageHeight = 1200; - const pagesCount = parentElement.offsetHeight / pageHeight; - const pages: Array<any> = []; - for (let i = 0; i < pagesCount; i++) { - const page = document.createElement('div'); - page.classList.add('page'); - page.style.height = `${pageHeight}px`; - page.style.whiteSpace = 'no-wrap !important'; - - const childrens = Array.from(parentElement.children).filter((child) => { - const rect = child.getBoundingClientRect(); - const parentRect = parentElement.getBoundingClientRect(); - const top = rect.top - parentRect.top; - return top >= i * pageHeight && top < (i + 1) * pageHeight; - }); - if (childrens.length > 0) { - pages.push(childrens); - } - } - - const rportLayer = document.getElementById('report-layer'); - - pages.forEach(async (page, index) => { - const pageDiv = document.createElement('div'); - pageDiv.classList.add('grid', 'gap-4', 'grid-cols-4', 'items-start', 'pb-10', 'auto-rows-min', 'printable-report'); - pageDiv.id = `page-${index}`; - pageDiv.style.backgroundColor = '#f6f6f6'; - pageDiv.style.gridAutoRows = 'min-content'; - pageDiv.style.padding = '50px'; - pageDiv.style.height = '490mm'; - - if (index > 0) { - pageDiv.style.paddingTop = '100px'; - } - - if (index === 0) { - const header = document.getElementById('report-header')?.cloneNode(true) as HTMLElement; - header.classList.add('col-span-4'); - header.style.display = 'block'; - pageDiv.appendChild(header); - } - page.forEach((child: any) => { - pageDiv.appendChild(child.cloneNode(true)); - }); - rportLayer?.appendChild(pageDiv); - }); - - setTimeout(async () => { - for (let i = 0; i < pages.length; i++) { - const pageDiv = document.getElementById(`page-${i}`) as HTMLElement; - const pageImage = await convertElementToImage(pageDiv); - doc.addImage(pageImage, 'PNG', 0, 0, 210, 0); - if (i === pages.length - 1) { - addFooters(doc); - doc.save(fileNameFormat(dashboard.name + '_Report_' + Date.now(), '.pdf')); - rportLayer!.innerHTML = ''; - cb(); - } else { - doc.addPage(); - } - } - }, 100); - }; - - return ( - <> - <div className="mb-2" id="report-header" style={{ display: 'none' }}> - <div className="flex items-end justify-between" style={{ margin: '-50px', padding: '25px 50px', backgroundColor: 'white' }}> - <div className="flex items-center"> - <img src="/assets/logo.svg" style={{ height: '30px' }} /> - <div className="text-lg color-gray-medium ml-2 mt-1">REPORT</div> - </div> - <div style={{ whiteSpace: 'nowrap' }}> - <span className="font-semibold">Project:</span> {site && site.name} - </div> - </div> - <div className="flex items-end mt-20 justify-between"> - <div className="text-2xl font-semibold">{dashboard && dashboard.name}</div> - <div className="font-semibold"> - {period && period.range.start.format('MMM Do YY') + ' - ' + period.range.end.format('MMM Do YY')} - </div> - </div> - {dashboard && dashboard.description && <div className="color-gray-medum whitespace-pre-wrap my-2">{dashboard.description}</div>} - </div> - - <div - id="report-layer" - style={{ - position: 'fixed', - top: '0', - left: '0', - zIndex: '-1', - opacity: '0', - }} - ></div> - <WrappedComponent {...props} renderReport={renderPromise} rendering={rendering} /> - </> - ); + const addFooters = (doc: any) => { + const pageCount = doc.internal.getNumberOfPages(); + for (var i = 1; i <= pageCount; i++) { + doc.setPage(i); + doc.setFontSize(8); + doc.setTextColor(136, 136, 136); + doc.text('Page ' + String(i) + ' of ' + String(pageCount), 200, 290, null, null, 'right'); + doc.addImage('/assets/img/logo-open-replay-grey.png', 'png', 10, 288, 20, 0); + } }; - return connect((state: any) => ({ - site: state.getIn(['site', 'instance']), - }))(ComponentWithReport); + const renderPromise = async (): Promise<any> => { + forceVisible(); + setRendering(true); + toast.info(TEXT_GENERATING, { + autoClose: false, + isLoading: true, + }); + }; + + const processReport = () => { + document.body.scrollIntoView(); + const doc = new jsPDF('p', 'mm', 'a4'); + const now = new Date().toISOString(); + + doc.addMetadata('Author', 'OpenReplay'); + doc.addMetadata('Title', 'OpenReplay Report'); + doc.addMetadata('Subject', 'OpenReplay Report'); + doc.addMetadata('Keywords', 'OpenReplay Report'); + doc.addMetadata('Creator', 'OpenReplay'); + doc.addMetadata('Producer', 'OpenReplay'); + doc.addMetadata('CreationDate', now); + + const parentElement = document.getElementById('report') as HTMLElement; + const pageHeight = 1200; + const pagesCount = parentElement.offsetHeight / pageHeight; + const pages: Array<any> = []; + for (let i = 0; i < pagesCount; i++) { + const page = document.createElement('div'); + page.classList.add('page'); + page.style.height = `${pageHeight}px`; + page.style.whiteSpace = 'no-wrap !important'; + + const childrens = Array.from(parentElement.children).filter((child) => { + const rect = child.getBoundingClientRect(); + const parentRect = parentElement.getBoundingClientRect(); + const top = rect.top - parentRect.top; + return top >= i * pageHeight && top < (i + 1) * pageHeight; + }); + if (childrens.length > 0) { + pages.push(childrens); + } + } + + const rportLayer = document.getElementById('report-layer'); + + pages.forEach(async (page, index) => { + const pageDiv = document.createElement('div'); + pageDiv.classList.add( + 'grid', + 'gap-4', + 'grid-cols-4', + 'items-start', + 'pb-10', + 'auto-rows-min', + 'printable-report' + ); + pageDiv.id = `page-${index}`; + pageDiv.style.backgroundColor = '#f6f6f6'; + pageDiv.style.gridAutoRows = 'min-content'; + pageDiv.style.padding = '50px'; + pageDiv.style.height = '490mm'; + + if (index > 0) { + pageDiv.style.paddingTop = '100px'; + } + + if (index === 0) { + const header = document.getElementById('report-header')?.cloneNode(true) as HTMLElement; + header.classList.add('col-span-4'); + header.style.display = 'block'; + pageDiv.appendChild(header); + } + page.forEach((child: any) => { + pageDiv.appendChild(child.cloneNode(true)); + }); + rportLayer?.appendChild(pageDiv); + }); + + setTimeout(async () => { + for (let i = 0; i < pages.length; i++) { + const pageDiv = document.getElementById(`page-${i}`) as HTMLElement; + const pageImage = await convertElementToImage(pageDiv); + doc.addImage(pageImage, 'PNG', 0, 0, 210, 0); + if (i === pages.length - 1) { + addFooters(doc); + doc.save(fileNameFormat(dashboard.name + '_Report_' + Date.now(), '.pdf')); + rportLayer!.innerHTML = ''; + setRendering(false); + toast.dismiss(); + toast.success(TEXT_SUCCESS); + } else { + doc.addPage(); + } + } + }, 100); + }; + + return ( + <> + <div className="mb-2" id="report-header" style={{ display: 'none' }}> + <div + className="flex items-end justify-between" + style={{ margin: '-50px', padding: '25px 50px', backgroundColor: 'white' }} + > + <div className="flex items-center"> + <img src="/assets/logo.svg" style={{ height: '30px' }} /> + <div className="text-lg color-gray-medium ml-2 mt-1">REPORT</div> + </div> + <div style={{ whiteSpace: 'nowrap' }}> + <span className="font-semibold">Project:</span> {site && site.name} + </div> + </div> + <div className="flex items-end mt-20 justify-between"> + <div className="text-2xl font-semibold">{dashboard && dashboard.name}</div> + <div className="font-semibold"> + {period && + period.range.start.format('MMM Do YY') + + ' - ' + + period.range.end.format('MMM Do YY')} + </div> + </div> + {dashboard && dashboard.description && ( + <div className="color-gray-medum whitespace-pre-wrap my-2">{dashboard.description}</div> + )} + </div> + + <div + id="report-layer" + style={{ + position: 'fixed', + top: '0', + left: '0', + zIndex: '-1', + opacity: '0', + }} + ></div> + <WrappedComponent {...props} renderReport={renderPromise} rendering={rendering} /> + </> + ); + }; + + return connect((state: any) => ({ + site: state.getIn(['site', 'instance']), + }))(ComponentWithReport); } diff --git a/frontend/app/components/shared/Bookmark/Bookmark.tsx b/frontend/app/components/shared/Bookmark/Bookmark.tsx index ff615540a..04c88e589 100644 --- a/frontend/app/components/shared/Bookmark/Bookmark.tsx +++ b/frontend/app/components/shared/Bookmark/Bookmark.tsx @@ -1,23 +1,23 @@ -import React, { useEffect, useState } from 'react' -import { Popup, Button, Icon } from 'UI' -import { toggleFavorite } from 'Duck/sessions' -import { connect } from 'react-redux' +import React, { useEffect, useState } from 'react'; +import { Tooltip, Button, Icon } from 'UI'; +import { toggleFavorite } from 'Duck/sessions'; +import { connect } from 'react-redux'; import { toast } from 'react-toastify'; -import { Tooltip } from 'react-tippy'; -import cn from 'classnames'; interface Props { toggleFavorite: (sessionId: string) => Promise<void>; - favorite: Boolean; + favorite: boolean; sessionId: any; - isEnterprise: Boolean; + isEnterprise: boolean; noMargin?: boolean; } -function Bookmark(props : Props ) { +function Bookmark(props: Props) { const { sessionId, favorite, isEnterprise, noMargin } = props; const [isFavorite, setIsFavorite] = useState(favorite); const ADDED_MESSAGE = isEnterprise ? 'Session added to vault' : 'Session added to your bookmarks'; - const REMOVED_MESSAGE = isEnterprise ? 'Session removed from vault' : 'Session removed from your bookmarks'; + const REMOVED_MESSAGE = isEnterprise + ? 'Session removed from vault' + : 'Session removed from your bookmarks'; const TOOLTIP_TEXT_ADD = isEnterprise ? 'Add to vault' : 'Add to bookmarks'; const TOOLTIP_TEXT_REMOVE = isEnterprise ? 'Remove from vault' : 'Remove from bookmarks'; @@ -33,34 +33,39 @@ function Bookmark(props : Props ) { toast.success(isFavorite ? REMOVED_MESSAGE : ADDED_MESSAGE); setIsFavorite(!isFavorite); }); - } + }; return ( - <Popup - delay={500} - content={isFavorite ? TOOLTIP_TEXT_REMOVE : TOOLTIP_TEXT_ADD} - hideOnClick={true} - distance={20} - > - {noMargin ? ( - <div onClick={ toggleFavorite } className="flex items-center cursor-pointer"> - <Icon name={ isFavorite ? ACTIVE_ICON : INACTIVE_ICON } color={isFavorite ? "teal" : undefined} size="16" /> - <span className="ml-2">{isEnterprise ? 'Vault' : 'Bookmark'}</span> - </div> - ) : ( - <Button - onClick={ toggleFavorite } - data-favourite={ isFavorite } - > - <Icon name={ isFavorite ? ACTIVE_ICON : INACTIVE_ICON } color={isFavorite ? "teal" : undefined} size="16" /> - <span className="ml-2">{isEnterprise ? 'Vault' : 'Bookmark'}</span> - </Button> - )} - </Popup> - ) + <div onClick={toggleFavorite} className="w-full"> + <Tooltip title={isFavorite ? TOOLTIP_TEXT_REMOVE : TOOLTIP_TEXT_ADD}> + {noMargin ? ( + <div className="flex items-center cursor-pointer h-full w-full p-3"> + <Icon + name={isFavorite ? ACTIVE_ICON : INACTIVE_ICON} + color={isFavorite ? 'teal' : undefined} + size="16" + /> + <span className="ml-2">{isEnterprise ? 'Vault' : 'Bookmark'}</span> + </div> + ) : ( + <Button data-favourite={isFavorite}> + <Icon + name={isFavorite ? ACTIVE_ICON : INACTIVE_ICON} + color={isFavorite ? 'teal' : undefined} + size="16" + /> + <span className="ml-2">{isEnterprise ? 'Vault' : 'Bookmark'}</span> + </Button> + )} + </Tooltip> + </div> + ); } -export default connect(state => ({ - isEnterprise: state.getIn([ 'user', 'account', 'edition' ]) === 'ee', - favorite: state.getIn([ 'sessions', 'current', 'favorite']), -}), { toggleFavorite })(Bookmark) +export default connect( + (state: any) => ({ + isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee', + favorite: state.getIn(['sessions', 'current', 'favorite']), + }), + { toggleFavorite } +)(Bookmark); diff --git a/frontend/app/components/shared/CopyText/CopyText.tsx b/frontend/app/components/shared/CopyText/CopyText.tsx new file mode 100644 index 000000000..635865d0d --- /dev/null +++ b/frontend/app/components/shared/CopyText/CopyText.tsx @@ -0,0 +1,26 @@ +import React, { useState } from 'react'; +import { Tooltip } from 'UI'; +import copy from 'copy-to-clipboard'; + +interface Props { + label?: string; + afterLabel?: string; + children: any; + content: string; +} +function CopyText(props: Props) { + const { children, label = 'Click to copy', afterLabel = 'Copied', content = '' } = props; + const [isCopied, setIsCopied] = useState(false); + const onClick = () => { + copy(content); + setIsCopied(true); + setTimeout(() => setIsCopied(false), 5000); + }; + return ( + <Tooltip delay={0} title={isCopied ? afterLabel : label}> + <span onClick={onClick}>{children}</span> + </Tooltip> + ); +} + +export default CopyText; diff --git a/frontend/app/components/shared/CopyText/index.ts b/frontend/app/components/shared/CopyText/index.ts new file mode 100644 index 000000000..3444d5f22 --- /dev/null +++ b/frontend/app/components/shared/CopyText/index.ts @@ -0,0 +1 @@ +export { default } from './CopyText'; diff --git a/frontend/app/components/shared/DevTools/BottomBlock/BottomBlock.js b/frontend/app/components/shared/DevTools/BottomBlock/BottomBlock.js new file mode 100644 index 000000000..8b7826755 --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/BottomBlock.js @@ -0,0 +1,30 @@ +import React, { useEffect } from 'react'; +import cn from 'classnames'; +import stl from './bottomBlock.module.css'; + +let timer = null; +const BottomBlock = ({ + children = null, + className = '', + additionalHeight = 0, + onMouseEnter = () => {}, + onMouseLeave = () => {}, + ...props +}) => { + useEffect(() => {}, []); + + return ( + <div + className={cn(stl.wrapper, 'flex flex-col mb-2')} + {...props} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} + > + {children} + </div> + ); +}; + +BottomBlock.displayName = 'BottomBlock'; + +export default BottomBlock; diff --git a/frontend/app/components/shared/DevTools/BottomBlock/Content.js b/frontend/app/components/shared/DevTools/BottomBlock/Content.js new file mode 100644 index 000000000..3df383911 --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/Content.js @@ -0,0 +1,17 @@ +import React from 'react'; +import cn from 'classnames'; +import stl from './content.module.css'; + +const Content = ({ + children, + className, + ...props +}) => ( + <div className={ cn(className, stl.content) } { ...props } > + { children } + </div> +); + +Content.displayName = 'Content'; + +export default Content; diff --git a/frontend/app/components/shared/DevTools/BottomBlock/Header.js b/frontend/app/components/shared/DevTools/BottomBlock/Header.js new file mode 100644 index 000000000..15dd7a0c9 --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/Header.js @@ -0,0 +1,26 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import cn from 'classnames'; +import { closeBottomBlock } from 'Duck/components/player'; +import { Input, CloseButton } from 'UI'; +import stl from './header.module.css'; + +const Header = ({ + children, + className, + closeBottomBlock, + onFilterChange, + showClose = true, + ...props +}) => ( + <div className={ cn("relative border-r border-l py-1", stl.header) } > + <div className={ cn("w-full h-full flex justify-between items-center", className) } > + <div className="w-full flex items-center justify-between">{ children }</div> + { showClose && <CloseButton onClick={ closeBottomBlock } size="18" className="ml-2" /> } + </div> + </div> +); + +Header.displayName = 'Header'; + +export default connect(null, { closeBottomBlock })(Header); diff --git a/frontend/app/components/shared/DevTools/BottomBlock/InfoLine.js b/frontend/app/components/shared/DevTools/BottomBlock/InfoLine.js new file mode 100644 index 000000000..3059c70d3 --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/InfoLine.js @@ -0,0 +1,20 @@ +import React from 'react'; +import cn from 'classnames'; +import cls from './infoLine.module.css'; + +const InfoLine = ({ children }) => ( + <div className={ cls.info }> + { children } + </div> +) + +const Point = ({ label = '', value = '', display=true, color, dotColor }) => display + ? <div className={ cls.infoPoint } style={{ color }}> + { dotColor != null && <div className={ cn(cls.dot, `bg-${dotColor}`) } /> } + <span className={cls.label}>{ `${label}` }</span> { value } + </div> + : null; + +InfoLine.Point = Point; + +export default InfoLine; diff --git a/frontend/app/components/shared/DevTools/BottomBlock/bottomBlock.module.css b/frontend/app/components/shared/DevTools/BottomBlock/bottomBlock.module.css new file mode 100644 index 000000000..99bdd42b4 --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/bottomBlock.module.css @@ -0,0 +1,9 @@ + +.wrapper { + background: $white; + /* padding-right: 10px; */ + /* border: solid thin $gray-light; */ + height: 300px; + + border-top: thin dashed #cccccc; +} diff --git a/frontend/app/components/shared/DevTools/BottomBlock/content.module.css b/frontend/app/components/shared/DevTools/BottomBlock/content.module.css new file mode 100644 index 000000000..fe8303013 --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/content.module.css @@ -0,0 +1,3 @@ +.content { + height: 86%; +} \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/BottomBlock/header.module.css b/frontend/app/components/shared/DevTools/BottomBlock/header.module.css new file mode 100644 index 000000000..99faa61c7 --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/header.module.css @@ -0,0 +1,6 @@ + +.header { + padding: 0 10px; + height: 40px; + border-bottom: 1px solid $gray-light; +} \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/BottomBlock/index.js b/frontend/app/components/shared/DevTools/BottomBlock/index.js new file mode 100644 index 000000000..846d7ec6f --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/index.js @@ -0,0 +1,8 @@ +import BottomBlock from './BottomBlock'; +import Header from './Header'; +import Content from './Content'; + +BottomBlock.Header = Header; +BottomBlock.Content = Content; + +export default BottomBlock; \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/BottomBlock/infoLine.module.css b/frontend/app/components/shared/DevTools/BottomBlock/infoLine.module.css new file mode 100644 index 000000000..37e47f013 --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/infoLine.module.css @@ -0,0 +1,31 @@ + + +.info { + padding-left: 10px; + height: 36px; + display: flex; + align-items: center; + & >.infoPoint { + font-size: 14px; + display: flex; + align-items: center; + &:not(:last-child):after { + content: ''; + margin: 0 12px; + height: 30px; + border-right: 1px solid $gray-light-shade; + } + & .label { + font-weight: 500; + margin-right: 6px; + } + } +} + +.dot { + width: 10px; + height: 10px; + border-radius: 5px; + margin-right: 5px; +} + diff --git a/frontend/app/components/shared/DevTools/BottomBlock/tabs.js b/frontend/app/components/shared/DevTools/BottomBlock/tabs.js new file mode 100644 index 000000000..6addd161e --- /dev/null +++ b/frontend/app/components/shared/DevTools/BottomBlock/tabs.js @@ -0,0 +1,9 @@ +// import { NONE, CONSOLE, NETWORK, STACKEVENTS, REDUX_STATE, PROFILER, PERFORMANCE, GRAPHQL } from 'Duck/components/player'; +// +// +// export default { +// [NONE]: { +// Component: null, +// +// } +// } \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx b/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx new file mode 100644 index 000000000..38714b92d --- /dev/null +++ b/frontend/app/components/shared/DevTools/ConsolePanel/ConsolePanel.tsx @@ -0,0 +1,264 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { connectPlayer, jump } from 'Player'; +import Log from 'Types/session/log'; +import BottomBlock from '../BottomBlock'; +import { LEVEL } from 'Types/session/log'; +import { Tabs, Input, Icon, NoContent } from 'UI'; +import cn from 'classnames'; +import ConsoleRow from '../ConsoleRow'; +import { getRE } from 'App/utils'; +import { List, CellMeasurer, CellMeasurerCache, AutoSizer } from 'react-virtualized'; +import { useObserver } from 'mobx-react-lite'; +import { useStore } from 'App/mstore'; +import ErrorDetailsModal from 'App/components/Dashboard/components/Errors/ErrorDetailsModal'; +import { useModal } from 'App/components/Modal'; + +const ALL = 'ALL'; +const INFO = 'INFO'; +const WARNINGS = 'WARNINGS'; +const ERRORS = 'ERRORS'; + +const LEVEL_TAB = { + [LEVEL.INFO]: INFO, + [LEVEL.LOG]: INFO, + [LEVEL.WARNING]: WARNINGS, + [LEVEL.ERROR]: ERRORS, + [LEVEL.EXCEPTION]: ERRORS, +}; + +const TABS = [ALL, ERRORS, WARNINGS, INFO].map((tab) => ({ text: tab, key: tab })); + +function renderWithNL(s = '') { + if (typeof s !== 'string') return ''; + return s.split('\n').map((line, i) => <div className={cn({ 'ml-20': i !== 0 })}>{line}</div>); +} + +const getIconProps = (level: any) => { + switch (level) { + case LEVEL.INFO: + case LEVEL.LOG: + return { + name: 'console/info', + color: 'blue2', + }; + case LEVEL.WARN: + case LEVEL.WARNING: + return { + name: 'console/warning', + color: 'red2', + }; + case LEVEL.ERROR: + return { + name: 'console/error', + color: 'red', + }; + } + return null; +}; + +const INDEX_KEY = 'console'; +let timeOut: any = null; +const TIMEOUT_DURATION = 5000; +interface Props { + logs: any; + exceptions: any; + time: any; +} +function ConsolePanel(props: Props) { + const { logs, time } = props; + const additionalHeight = 0; + // const [activeTab, setActiveTab] = useState(ALL); + // const [filter, setFilter] = useState(''); + const { + sessionStore: { devTools }, + } = useStore(); + const [isDetailsModalActive, setIsDetailsModalActive] = useState(false); + const [filteredList, setFilteredList] = useState([]); + const filter = useObserver(() => devTools[INDEX_KEY].filter); + const activeTab = useObserver(() => devTools[INDEX_KEY].activeTab); + const activeIndex = useObserver(() => devTools[INDEX_KEY].index); + const [pauseSync, setPauseSync] = useState(activeIndex > 0); + const synRef: any = useRef({}); + const { showModal } = useModal(); + + const onTabClick = (activeTab: any) => devTools.update(INDEX_KEY, { activeTab }); + const onFilterChange = ({ target: { value } }: any) => { + devTools.update(INDEX_KEY, { filter: value }); + }; + + synRef.current = { + pauseSync, + activeIndex, + }; + + const removePause = () => { + setIsDetailsModalActive(false); + clearTimeout(timeOut); + timeOut = setTimeout(() => { + devTools.update(INDEX_KEY, { index: getCurrentIndex() }); + setPauseSync(false); + }, TIMEOUT_DURATION); + }; + + const onMouseLeave = () => { + if (isDetailsModalActive) return; + removePause(); + }; + + useEffect(() => { + if (pauseSync) { + removePause(); + } + + return () => { + clearTimeout(timeOut); + if (!synRef.current.pauseSync) { + devTools.update(INDEX_KEY, { index: 0 }); + } + }; + }, []); + + const getCurrentIndex = () => { + return filteredList.filter((item: any) => item.time <= time).length - 1; + }; + + useEffect(() => { + const currentIndex = getCurrentIndex(); + if (currentIndex !== activeIndex && !pauseSync) { + devTools.update(INDEX_KEY, { index: currentIndex }); + } + }, [time]); + + const cache = new CellMeasurerCache({ + fixedWidth: true, + keyMapper: (index: number) => filteredList[index], + }); + const _list = React.useRef(); + + const showDetails = (log: any) => { + setIsDetailsModalActive(true); + showModal(<ErrorDetailsModal errorId={log.errorId} />, { right: true, onClose: removePause }); + devTools.update(INDEX_KEY, { index: filteredList.indexOf(log) }); + setPauseSync(true); + }; + + const _rowRenderer = ({ index, key, parent, style }: any) => { + const item = filteredList[index]; + + return ( + // @ts-ignore + <CellMeasurer cache={cache} columnIndex={0} key={key} rowIndex={index} parent={parent}> + {({ measure }: any) => ( + <ConsoleRow + style={style} + log={item} + jump={jump} + iconProps={getIconProps(item.level)} + renderWithNL={renderWithNL} + onClick={() => showDetails(item)} + recalcHeight={() => { + measure(); + (_list as any).current.recomputeRowHeights(index); + }} + /> + )} + </CellMeasurer> + ); + }; + + React.useMemo(() => { + const filterRE = getRE(filter, 'i'); + let list = logs; + + list = list.filter( + ({ value, level }: any) => + (!!filter ? filterRE.test(value) : true) && + (activeTab === ALL || activeTab === LEVEL_TAB[level]) + ); + setFilteredList(list); + }, [logs, filter, activeTab]); + + useEffect(() => { + if (_list.current) { + // @ts-ignore + _list.current.scrollToRow(activeIndex); + } + }, [activeIndex]); + + return ( + <BottomBlock + style={{ height: 300 + additionalHeight + 'px' }} + onMouseEnter={() => setPauseSync(true)} + onMouseLeave={onMouseLeave} + > + {/* @ts-ignore */} + <BottomBlock.Header> + <div className="flex items-center"> + <span className="font-semibold color-gray-medium mr-4">Console</span> + <Tabs tabs={TABS} active={activeTab} onClick={onTabClick} border={false} /> + </div> + <Input + className="input-small h-8" + placeholder="Filter by keyword" + icon="search" + iconPosition="left" + name="filter" + height={28} + onChange={onFilterChange} + value={filter} + /> + {/* @ts-ignore */} + </BottomBlock.Header> + {/* @ts-ignore */} + <BottomBlock.Content className="overflow-y-auto"> + <NoContent + title={ + <div className="capitalize flex items-center mt-16"> + <Icon name="info-circle" className="mr-2" size="18" /> + No Data + </div> + } + size="small" + show={filteredList.length === 0} + > + {/* @ts-ignore */} + <AutoSizer> + {({ height, width }: any) => ( + // @ts-ignore + <List + ref={_list} + deferredMeasurementCache={cache} + overscanRowCount={5} + rowCount={Math.ceil(filteredList.length || 1)} + rowHeight={cache.rowHeight} + rowRenderer={_rowRenderer} + width={width} + height={height} + // scrollToIndex={activeIndex} + scrollToAlignment="center" + /> + )} + </AutoSizer> + </NoContent> + {/* @ts-ignore */} + </BottomBlock.Content> + </BottomBlock> + ); +} + +export default connectPlayer((state: any) => { + const logs = state.logList; + const exceptions = state.exceptionsList; // TODO merge + const logExceptions = exceptions.map(({ time, errorId, name, projectId }: any) => + Log({ + level: LEVEL.ERROR, + value: name, + time, + errorId, + }) + ); + return { + time: state.time, + logs: logs.concat(logExceptions), + }; +})(ConsolePanel); diff --git a/frontend/app/components/shared/DevTools/ConsolePanel/index.ts b/frontend/app/components/shared/DevTools/ConsolePanel/index.ts new file mode 100644 index 000000000..cbbf61684 --- /dev/null +++ b/frontend/app/components/shared/DevTools/ConsolePanel/index.ts @@ -0,0 +1 @@ +export { default } from './ConsolePanel'; diff --git a/frontend/app/components/shared/DevTools/ConsoleRow/ConsoleRow.tsx b/frontend/app/components/shared/DevTools/ConsoleRow/ConsoleRow.tsx new file mode 100644 index 000000000..83929cbed --- /dev/null +++ b/frontend/app/components/shared/DevTools/ConsoleRow/ConsoleRow.tsx @@ -0,0 +1,65 @@ +import React, { useState } from 'react'; +import cn from 'classnames'; +import { Icon } from 'UI'; +import JumpButton from 'Shared/DevTools/JumpButton'; + +interface Props { + log: any; + iconProps: any; + jump?: any; + renderWithNL?: any; + style?: any; + recalcHeight?: () => void; + onClick: () => void; +} +function ConsoleRow(props: Props) { + const { log, iconProps, jump, renderWithNL, style, recalcHeight } = props; + const [expanded, setExpanded] = useState(false); + const lines = log.value.split('\n').filter((l: any) => !!l); + const canExpand = lines.length > 1; + + const clickable = canExpand || !!log.errorId; + + const toggleExpand = () => { + setExpanded(!expanded); + setTimeout(() => recalcHeight(), 0); + }; + return ( + <div + style={style} + className={cn( + 'border-b flex items-center py-2 px-4 overflow-hidden group relative select-none', + { + info: !log.isYellow() && !log.isRed(), + warn: log.isYellow(), + error: log.isRed(), + 'cursor-pointer': clickable, + 'cursor-pointer underline decoration-dotted decoration-gray-200': !!log.errorId, + } + )} + onClick={clickable ? () => (!!log.errorId ? props.onClick() : toggleExpand()) : () => {}} + > + <div className="mr-2"> + <Icon size="14" {...iconProps} /> + </div> + <div key={log.key} data-scroll-item={log.isRed()}> + <div className={cn('flex items-center')}> + {canExpand && ( + <Icon name={expanded ? 'caret-down-fill' : 'caret-right-fill'} className="mr-2" /> + )} + <span>{renderWithNL(lines.pop())}</span> + </div> + {canExpand && + expanded && + lines.map((l: string, i: number) => ( + <div key={l.slice(0, 4) + i} className="ml-4 mb-1"> + {l} + </div> + ))} + </div> + <JumpButton onClick={() => jump(log.time)} /> + </div> + ); +} + +export default ConsoleRow; diff --git a/frontend/app/components/shared/DevTools/ConsoleRow/index.ts b/frontend/app/components/shared/DevTools/ConsoleRow/index.ts new file mode 100644 index 000000000..c9140d748 --- /dev/null +++ b/frontend/app/components/shared/DevTools/ConsoleRow/index.ts @@ -0,0 +1 @@ +export { default } from './ConsoleRow'; diff --git a/frontend/app/components/shared/DevTools/JumpButton/JumpButton.tsx b/frontend/app/components/shared/DevTools/JumpButton/JumpButton.tsx new file mode 100644 index 000000000..31307fd9b --- /dev/null +++ b/frontend/app/components/shared/DevTools/JumpButton/JumpButton.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Icon, Tooltip } from 'UI'; + +interface Props { + onClick: any; + tooltip?: string; +} +function JumpButton(props: Props) { + const { tooltip } = props; + return ( + <div className="absolute right-0 top-0 bottom-0 my-auto flex items-center"> + <Tooltip title={tooltip} disabled={!tooltip}> + <div + className="mr-2 border cursor-pointer invisible group-hover:visible rounded-lg bg-active-blue text-xs flex items-center px-2 py-1 color-teal hover:shadow h-6" + onClick={(e: any) => { + e.stopPropagation(); + props.onClick(); + }} + > + <Icon name="caret-right-fill" size="12" color="teal" /> + <span>JUMP</span> + </div> + </Tooltip> + </div> + ); +} + +export default JumpButton; diff --git a/frontend/app/components/shared/DevTools/JumpButton/index.ts b/frontend/app/components/shared/DevTools/JumpButton/index.ts new file mode 100644 index 000000000..82ff65fc1 --- /dev/null +++ b/frontend/app/components/shared/DevTools/JumpButton/index.ts @@ -0,0 +1 @@ +export { default } from './JumpButton'; diff --git a/frontend/app/components/shared/DevTools/NetworkPanel/NetworkPanel.tsx b/frontend/app/components/shared/DevTools/NetworkPanel/NetworkPanel.tsx new file mode 100644 index 000000000..634aa9bae --- /dev/null +++ b/frontend/app/components/shared/DevTools/NetworkPanel/NetworkPanel.tsx @@ -0,0 +1,431 @@ +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { Tooltip, Tabs, Input, NoContent, Icon, Toggler } from 'UI'; +import { getRE } from 'App/utils'; +import Resource, { TYPES } from 'Types/session/resource'; +import { formatBytes } from 'App/utils'; +import { formatMs } from 'App/date'; + +import TimeTable from '../TimeTable'; +import BottomBlock from '../BottomBlock'; +import InfoLine from '../BottomBlock/InfoLine'; +import { Duration } from 'luxon'; +import { connectPlayer, jump } from 'Player'; +import { useModal } from 'App/components/Modal'; +import FetchDetailsModal from 'Shared/FetchDetailsModal'; +import { useStore } from 'App/mstore'; +import { useObserver } from 'mobx-react-lite'; + +const INDEX_KEY = 'network'; + +const ALL = 'ALL'; +const XHR = 'xhr'; +const JS = 'js'; +const CSS = 'css'; +const IMG = 'img'; +const MEDIA = 'media'; +const OTHER = 'other'; + +const TAB_TO_TYPE_MAP: any = { + [XHR]: TYPES.XHR, + [JS]: TYPES.JS, + [CSS]: TYPES.CSS, + [IMG]: TYPES.IMG, + [MEDIA]: TYPES.MEDIA, + [OTHER]: TYPES.OTHER, +}; +const TABS: any = [ALL, XHR, JS, CSS, IMG, MEDIA, OTHER].map((tab) => ({ + text: tab === 'xhr' ? 'Fetch/XHR' : tab, + key: tab, +})); + +const DOM_LOADED_TIME_COLOR = 'teal'; +const LOAD_TIME_COLOR = 'red'; + +function compare(a: any, b: any, key: string) { + if (a[key] > b[key]) return 1; + if (a[key] < b[key]) return -1; + return 0; +} + +export function renderType(r: any) { + return ( + <Tooltip style={{ width: '100%' }} title={<div>{r.type}</div>}> + <div>{r.type}</div> + </Tooltip> + ); +} + +export function renderName(r: any) { + return ( + <Tooltip style={{ width: '100%' }} title={<div>{r.url}</div>}> + <div>{r.name}</div> + </Tooltip> + ); +} + +export function renderStart(r: any) { + return ( + <div className="flex justify-between items-center grow-0 w-full"> + <span>{Duration.fromMillis(r.time).toFormat('mm:ss.SSS')}</span> + </div> + ); +} + +function renderSize(r: any) { + if (r.responseBodySize) return formatBytes(r.responseBodySize); + let triggerText; + let content; + if (r.decodedBodySize == null || r.decodedBodySize === 0) { + triggerText = 'x'; + content = 'Not captured'; + } else { + const headerSize = r.headerSize || 0; + const encodedSize = r.encodedBodySize || 0; + const transferred = headerSize + encodedSize; + const showTransferred = r.headerSize != null; + + triggerText = formatBytes(r.decodedBodySize); + content = ( + <ul> + {showTransferred && ( + <li>{`${formatBytes(r.encodedBodySize + headerSize)} transfered over network`}</li> + )} + <li>{`Resource size: ${formatBytes(r.decodedBodySize)} `}</li> + </ul> + ); + } + + return ( + <Tooltip style={{ width: '100%' }} title={content}> + <div>{triggerText}</div> + </Tooltip> + ); +} + +export function renderDuration(r: any) { + if (!r.success) return 'x'; + + const text = `${Math.floor(r.duration)}ms`; + if (!r.isRed() && !r.isYellow()) return text; + + let tooltipText; + let className = 'w-full h-full flex items-center '; + if (r.isYellow()) { + tooltipText = 'Slower than average'; + className += 'warn color-orange'; + } else { + tooltipText = 'Much slower than average'; + className += 'error color-red'; + } + + return ( + <Tooltip style={{ width: '100%' }} title={tooltipText}> + <div> {text} </div> + </Tooltip> + ); +} + +let timeOut: any = null; +const TIMEOUT_DURATION = 5000; + +interface Props { + location: any; + resources: any; + fetchList: any; + domContentLoadedTime: any; + loadTime: any; + playing: boolean; + domBuildingTime: any; + time: any; +} +function NetworkPanel(props: Props) { + const { resources, time, domContentLoadedTime, loadTime, domBuildingTime, fetchList } = props; + const { showModal } = useModal(); + + const [filteredList, setFilteredList] = useState([]); + const [showOnlyErrors, setShowOnlyErrors] = useState(false); + const [isDetailsModalActive, setIsDetailsModalActive] = useState(false); + const additionalHeight = 0; + const fetchPresented = fetchList.length > 0; + const { + sessionStore: { devTools }, + } = useStore(); + // const [filter, setFilter] = useState(devTools[INDEX_KEY].filter); + // const [activeTab, setActiveTab] = useState(ALL); + const filter = useObserver(() => devTools[INDEX_KEY].filter); + const activeTab = useObserver(() => devTools[INDEX_KEY].activeTab); + const activeIndex = useObserver(() => devTools[INDEX_KEY].index); + const [pauseSync, setPauseSync] = useState(activeIndex > 0); + const synRef: any = useRef({}); + + const onTabClick = (activeTab: any) => devTools.update(INDEX_KEY, { activeTab }); + const onFilterChange = ({ target: { value } }: any) => { + devTools.update(INDEX_KEY, { filter: value }); + }; + + synRef.current = { + pauseSync, + activeIndex, + }; + + const removePause = () => { + setIsDetailsModalActive(false); + clearTimeout(timeOut); + timeOut = setTimeout(() => { + devTools.update(INDEX_KEY, { index: getCurrentIndex() }); + setPauseSync(false); + }, TIMEOUT_DURATION); + }; + + const onMouseLeave = () => { + if (isDetailsModalActive) return; + removePause(); + }; + + useEffect(() => { + if (pauseSync) { + removePause(); + } + + return () => { + clearTimeout(timeOut); + if (!synRef.current.pauseSync) { + devTools.update(INDEX_KEY, { index: 0 }); + } + }; + }, []); + + const getCurrentIndex = () => { + return filteredList.filter((item: any) => item.time <= time).length - 1; + }; + + useEffect(() => { + const currentIndex = getCurrentIndex(); + if (currentIndex !== activeIndex && !pauseSync) { + devTools.update(INDEX_KEY, { index: currentIndex }); + } + }, [time]); + + const { resourcesSize, transferredSize } = useMemo(() => { + const resourcesSize = resources.reduce( + (sum: any, { decodedBodySize }: any) => sum + (decodedBodySize || 0), + 0 + ); + + const transferredSize = resources.reduce( + (sum: any, { headerSize, encodedBodySize }: any) => + sum + (headerSize || 0) + (encodedBodySize || 0), + 0 + ); + return { + resourcesSize, + transferredSize, + }; + }, [resources]); + + useEffect(() => { + const filterRE = getRE(filter, 'i'); + let list = resources; + fetchList.forEach( + (fetchCall: any) => + (list = list.filter((networkCall: any) => networkCall.url !== fetchCall.url)) + ); + list = list.concat(fetchList); + + list = list.filter( + ({ type, name, status, success }: any) => + (!!filter ? filterRE.test(status) || filterRE.test(name) || filterRE.test(type) : true) && + (activeTab === ALL || type === TAB_TO_TYPE_MAP[activeTab]) && + (showOnlyErrors ? parseInt(status) >= 400 || !success : true) + ); + setFilteredList(list); + }, [resources, filter, showOnlyErrors, activeTab]); + + const referenceLines = useMemo(() => { + const arr = []; + + if (domContentLoadedTime != null) { + arr.push({ + time: domContentLoadedTime.time, + color: DOM_LOADED_TIME_COLOR, + }); + } + if (loadTime != null) { + arr.push({ + time: loadTime.time, + color: LOAD_TIME_COLOR, + }); + } + + return arr; + }, []); + + const showDetailsModal = (row: any) => { + setIsDetailsModalActive(true); + showModal( + <FetchDetailsModal resource={row} rows={filteredList} fetchPresented={fetchPresented} />, + { + right: true, + onClose: removePause, + } + ); + devTools.update(INDEX_KEY, { index: filteredList.indexOf(row) }); + setPauseSync(true); + }; + + useEffect(() => { + devTools.update(INDEX_KEY, { filter, activeTab }); + }, [filter, activeTab]); + + return ( + <React.Fragment> + <BottomBlock + style={{ height: 300 + additionalHeight + 'px' }} + className="border" + onMouseEnter={() => setPauseSync(true)} + onMouseLeave={onMouseLeave} + > + <BottomBlock.Header> + <div className="flex items-center"> + <span className="font-semibold color-gray-medium mr-4">Network</span> + <Tabs + className="uppercase" + tabs={TABS} + active={activeTab} + onClick={onTabClick} + border={false} + /> + </div> + <Input + className="input-small" + placeholder="Filter by name, type or value" + icon="search" + iconPosition="left" + name="filter" + onChange={onFilterChange} + height={28} + width={230} + value={filter} + /> + </BottomBlock.Header> + <BottomBlock.Content> + <div className="flex items-center justify-between px-4"> + <div> + <Toggler + checked={showOnlyErrors} + name="test" + onChange={() => setShowOnlyErrors(!showOnlyErrors)} + label="4xx-5xx Only" + /> + </div> + <InfoLine> + <InfoLine.Point label={filteredList.length + ''} value=" requests" /> + <InfoLine.Point + label={formatBytes(transferredSize)} + value="transferred" + display={transferredSize > 0} + /> + <InfoLine.Point + label={formatBytes(resourcesSize)} + value="resources" + display={resourcesSize > 0} + /> + <InfoLine.Point + label={formatMs(domBuildingTime)} + value="DOM Building Time" + display={domBuildingTime != null} + /> + <InfoLine.Point + label={domContentLoadedTime && formatMs(domContentLoadedTime.value)} + value="DOMContentLoaded" + display={domContentLoadedTime != null} + dotColor={DOM_LOADED_TIME_COLOR} + /> + <InfoLine.Point + label={loadTime && formatMs(loadTime.value)} + value="Load" + display={loadTime != null} + dotColor={LOAD_TIME_COLOR} + /> + </InfoLine> + </div> + <NoContent + title={ + <div className="capitalize flex items-center mt-16"> + <Icon name="info-circle" className="mr-2" size="18" /> + No Data + </div> + } + size="small" + show={filteredList.length === 0} + > + <TimeTable + rows={filteredList} + referenceLines={referenceLines} + renderPopup + onRowClick={showDetailsModal} + additionalHeight={additionalHeight} + onJump={(row: any) => { + setPauseSync(true); + devTools.update(INDEX_KEY, { index: filteredList.indexOf(row) }); + jump(row.time); + }} + activeIndex={activeIndex} + > + {[ + // { + // label: 'Start', + // width: 120, + // render: renderStart, + // }, + { + label: 'Status', + dataKey: 'status', + width: 70, + }, + { + label: 'Type', + dataKey: 'type', + width: 90, + render: renderType, + }, + { + label: 'Name', + width: 240, + dataKey: 'name', + render: renderName, + }, + { + label: 'Size', + width: 80, + dataKey: 'decodedBodySize', + render: renderSize, + hidden: activeTab === XHR, + }, + { + label: 'Time', + width: 80, + dataKey: 'duration', + render: renderDuration, + }, + ]} + </TimeTable> + </NoContent> + </BottomBlock.Content> + </BottomBlock> + </React.Fragment> + ); +} + +export default connectPlayer((state: any) => ({ + location: state.location, + resources: state.resourceList, + fetchList: state.fetchList.map((i: any) => + Resource({ ...i.toJS(), type: TYPES.XHR, time: i.time < 0 ? 0 : i.time }) + ), + domContentLoadedTime: state.domContentLoadedTime, + loadTime: state.loadTime, + time: state.time, + playing: state.playing, + domBuildingTime: state.domBuildingTime, +}))(NetworkPanel); diff --git a/frontend/app/components/shared/DevTools/NetworkPanel/index.ts b/frontend/app/components/shared/DevTools/NetworkPanel/index.ts new file mode 100644 index 000000000..3014d5b0b --- /dev/null +++ b/frontend/app/components/shared/DevTools/NetworkPanel/index.ts @@ -0,0 +1 @@ +export { default } from './NetworkPanel' \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/ProfilerModal/ProfilerModal.tsx b/frontend/app/components/shared/DevTools/ProfilerModal/ProfilerModal.tsx new file mode 100644 index 000000000..a5909ada7 --- /dev/null +++ b/frontend/app/components/shared/DevTools/ProfilerModal/ProfilerModal.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +interface Props { + profile: any; +} +function ProfilerModal(props: Props) { + const { + profile: { name, args, result }, + } = props; + + return ( + <div className="bg-white overflow-y-auto h-screen p-5" style={{ width: '500px' }}> + <h5 className="mb-2 text-2xl">{name}</h5> + <h5 className="py-3">{'Arguments'}</h5> + <ul className="color-gray-medium"> + {args.split(',').map((arg: any) => ( + <li> {`${arg}`} </li> + ))} + </ul> + <h5 className="py-3">{'Result'}</h5> + <div className="color-gray-medium">{`${result}`}</div> + </div> + ); +} + +export default ProfilerModal; diff --git a/frontend/app/components/shared/DevTools/ProfilerModal/index.ts b/frontend/app/components/shared/DevTools/ProfilerModal/index.ts new file mode 100644 index 000000000..dbb2c0fa8 --- /dev/null +++ b/frontend/app/components/shared/DevTools/ProfilerModal/index.ts @@ -0,0 +1 @@ +export { default } from './ProfilerModal'; diff --git a/frontend/app/components/shared/DevTools/ProfilerPanel/ProfilerPanel.tsx b/frontend/app/components/shared/DevTools/ProfilerPanel/ProfilerPanel.tsx new file mode 100644 index 000000000..f1fa16219 --- /dev/null +++ b/frontend/app/components/shared/DevTools/ProfilerPanel/ProfilerPanel.tsx @@ -0,0 +1,75 @@ +import React, { useState } from 'react'; +import { connectPlayer } from 'Player'; +import { TextEllipsis, Input } from 'UI'; +import { getRE } from 'App/utils'; + +// import ProfileInfo from './ProfileInfo'; +import TimeTable from '../TimeTable'; +import BottomBlock from '../BottomBlock'; +import { useModal } from 'App/components/Modal'; +import ProfilerModal from '../ProfilerModal'; + +const renderDuration = (p: any) => `${p.duration}ms`; +const renderName = (p: any) => <TextEllipsis text={p.name} />; + +interface Props { + profiles: any; +} +function ProfilerPanel(props: Props) { + const { profiles } = props; + const { showModal } = useModal(); + const [filter, setFilter] = useState(''); + const filtered: any = React.useMemo(() => { + const filterRE = getRE(filter, 'i'); + let list = profiles; + + list = list.filter(({ name }: any) => (!!filter ? filterRE.test(name) : true)); + return list; + }, [filter]); + + const onFilterChange = ({ target: { value } }: any) => setFilter(value); + const onRowClick = (profile: any) => { + showModal(<ProfilerModal profile={profile} />, { right: true }); + }; + return ( + <BottomBlock> + <BottomBlock.Header> + <div className="flex items-center"> + <span className="font-semibold color-gray-medium mr-4">Profiler</span> + </div> + <Input + // className="input-small" + placeholder="Filter by name" + icon="search" + name="filter" + onChange={onFilterChange} + height={28} + /> + </BottomBlock.Header> + <BottomBlock.Content> + <TimeTable rows={filtered} onRowClick={onRowClick} hoverable> + {[ + { + label: 'Name', + dataKey: 'name', + width: 200, + render: renderName, + }, + { + label: 'Time', + key: 'duration', + width: 80, + render: renderDuration, + }, + ]} + </TimeTable> + </BottomBlock.Content> + </BottomBlock> + ); +} + +export default connectPlayer((state: any) => { + return { + profiles: state.profilesList, + }; +})(ProfilerPanel); diff --git a/frontend/app/components/shared/DevTools/ProfilerPanel/index.ts b/frontend/app/components/shared/DevTools/ProfilerPanel/index.ts new file mode 100644 index 000000000..53bccddef --- /dev/null +++ b/frontend/app/components/shared/DevTools/ProfilerPanel/index.ts @@ -0,0 +1 @@ +export { default } from './ProfilerPanel'; diff --git a/frontend/app/components/shared/DevTools/StackEventModal/StackEventModal.tsx b/frontend/app/components/shared/DevTools/StackEventModal/StackEventModal.tsx new file mode 100644 index 000000000..c68c0ca80 --- /dev/null +++ b/frontend/app/components/shared/DevTools/StackEventModal/StackEventModal.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { DATADOG, SENTRY, STACKDRIVER, typeList } from 'Types/session/stackEvent'; +import JsonViewer from 'Components/Session_/StackEvents/UserEvent/JsonViewer'; +import Sentry from 'Components/Session_/StackEvents/UserEvent/Sentry'; + +interface Props { + event: any; +} +function StackEventModal(props: Props) { + const { event } = props; + const renderPopupContent = () => { + const { source, payload, name } = event; + switch (source) { + case SENTRY: + return <Sentry event={payload} />; + case DATADOG: + return <JsonViewer title={name} data={payload} icon="integrations/datadog" />; + case STACKDRIVER: + return <JsonViewer title={name} data={payload} icon="integrations/stackdriver" />; + default: + return <JsonViewer title={name} data={payload} icon={`integrations/${source}`} />; + } + }; + return ( + <div className="bg-white overflow-y-auto h-screen p-5" style={{ width: '500px' }}> + <h5 className="mb-2 text-2xl">Stack Event</h5> + {renderPopupContent()} + </div> + ); +} + +export default StackEventModal; diff --git a/frontend/app/components/shared/DevTools/StackEventModal/index.ts b/frontend/app/components/shared/DevTools/StackEventModal/index.ts new file mode 100644 index 000000000..93a084d28 --- /dev/null +++ b/frontend/app/components/shared/DevTools/StackEventModal/index.ts @@ -0,0 +1 @@ +export { default } from './StackEventModal'; diff --git a/frontend/app/components/shared/DevTools/StackEventPanel/StackEventPanel.tsx b/frontend/app/components/shared/DevTools/StackEventPanel/StackEventPanel.tsx new file mode 100644 index 000000000..557c72172 --- /dev/null +++ b/frontend/app/components/shared/DevTools/StackEventPanel/StackEventPanel.tsx @@ -0,0 +1,203 @@ +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { hideHint } from 'Duck/components/player'; +import { Tooltip, Tabs, Input, NoContent, Icon, Toggler } from 'UI'; +import { getRE } from 'App/utils'; +import { List, CellMeasurer, CellMeasurerCache, AutoSizer } from 'react-virtualized'; + +import BottomBlock from '../BottomBlock'; +import { connectPlayer, jump } from 'Player'; +import { useModal } from 'App/components/Modal'; +import { useStore } from 'App/mstore'; +import { useObserver } from 'mobx-react-lite'; +import { DATADOG, SENTRY, STACKDRIVER, typeList } from 'Types/session/stackEvent'; +import { connect } from 'react-redux'; +import StackEventRow from 'Shared/DevTools/StackEventRow'; +import StackEventModal from '../StackEventModal'; + +let timeOut: any = null; +const TIMEOUT_DURATION = 5000; +const INDEX_KEY = 'stackEvent'; +const ALL = 'ALL'; +const TABS = [ALL, ...typeList].map((tab) => ({ text: tab, key: tab })); + +interface Props { + list: any; + hideHint: any; + time: any; +} +function StackEventPanel(props: Props) { + const { list, time } = props; + const additionalHeight = 0; + const { + sessionStore: { devTools }, + } = useStore(); + const { showModal } = useModal(); + const [isDetailsModalActive, setIsDetailsModalActive] = useState(false); + const [filteredList, setFilteredList] = useState([]); + const filter = useObserver(() => devTools[INDEX_KEY].filter); + const activeTab = useObserver(() => devTools[INDEX_KEY].activeTab); + const activeIndex = useObserver(() => devTools[INDEX_KEY].index); + const [pauseSync, setPauseSync] = useState(activeIndex > 0); + const synRef: any = useRef({}); + synRef.current = { + pauseSync, + activeIndex, + }; + const _list = React.useRef(); + + const onTabClick = (activeTab: any) => devTools.update(INDEX_KEY, { activeTab }); + const onFilterChange = ({ target: { value } }: any) => { + devTools.update(INDEX_KEY, { filter: value }); + }; + + const getCurrentIndex = () => { + return filteredList.filter((item: any) => item.time <= time).length - 1; + }; + + const removePause = () => { + clearTimeout(timeOut); + setIsDetailsModalActive(false); + timeOut = setTimeout(() => { + devTools.update(INDEX_KEY, { index: getCurrentIndex() }); + setPauseSync(false); + }, TIMEOUT_DURATION); + }; + + useEffect(() => { + const currentIndex = getCurrentIndex(); + if (currentIndex !== activeIndex && !pauseSync) { + devTools.update(INDEX_KEY, { index: currentIndex }); + } + }, [time]); + + const onMouseLeave = () => { + if (isDetailsModalActive) return; + removePause(); + }; + + React.useMemo(() => { + const filterRE = getRE(filter, 'i'); + let list = props.list; + + list = list.filter( + ({ name, source }: any) => + (!!filter ? filterRE.test(name) : true) && (activeTab === ALL || activeTab === source) + ); + + setFilteredList(list); + }, [filter, activeTab]); + + const tabs = useMemo(() => { + return TABS.filter(({ key }) => key === ALL || list.some(({ source }: any) => key === source)); + }, []); + + const cache = new CellMeasurerCache({ + fixedWidth: true, + keyMapper: (index: number) => filteredList[index], + }); + + const showDetails = (item: any) => { + setIsDetailsModalActive(true); + showModal(<StackEventModal event={item} />, { right: true, onClose: removePause }); + devTools.update(INDEX_KEY, { index: filteredList.indexOf(item) }); + setPauseSync(true); + }; + + const _rowRenderer = ({ index, key, parent, style }: any) => { + const item = filteredList[index]; + + return ( + // @ts-ignore + <CellMeasurer cache={cache} columnIndex={0} key={key} rowIndex={index} parent={parent}> + {() => ( + <StackEventRow + isActive={activeIndex === index} + style={style} + key={item.key} + event={item} + onJump={() => { + setPauseSync(true); + devTools.update(INDEX_KEY, { index: filteredList.indexOf(item) }); + jump(item.time); + }} + onClick={() => showDetails(item)} + /> + )} + </CellMeasurer> + ); + }; + + useEffect(() => { + if (_list.current) { + // @ts-ignore + _list.current.scrollToRow(activeIndex); + } + }, [activeIndex]); + + return ( + <BottomBlock + style={{ height: 300 + additionalHeight + 'px' }} + onMouseEnter={() => setPauseSync(true)} + onMouseLeave={onMouseLeave} + > + <BottomBlock.Header> + <div className="flex items-center"> + <span className="font-semibold color-gray-medium mr-4">Stack Events</span> + <Tabs tabs={tabs} active={activeTab} onClick={onTabClick} border={false} /> + </div> + <Input + className="input-small h-8" + placeholder="Filter by keyword" + icon="search" + iconPosition="left" + name="filter" + height={28} + onChange={onFilterChange} + value={filter} + /> + </BottomBlock.Header> + <BottomBlock.Content className="overflow-y-auto"> + <NoContent + title={ + <div className="capitalize flex items-center mt-16"> + <Icon name="info-circle" className="mr-2" size="18" /> + No Data + </div> + } + size="small" + show={filteredList.length === 0} + > + <AutoSizer> + {({ height, width }: any) => ( + <List + ref={_list} + deferredMeasurementCache={cache} + overscanRowCount={5} + rowCount={Math.ceil(filteredList.length || 1)} + rowHeight={cache.rowHeight} + rowRenderer={_rowRenderer} + width={width} + height={height} + scrollToAlignment="center" + /> + )} + </AutoSizer> + </NoContent> + </BottomBlock.Content> + </BottomBlock> + ); +} + +export default connect( + (state: any) => ({ + hintIsHidden: + state.getIn(['components', 'player', 'hiddenHints', 'stack']) || + !state.getIn(['site', 'list']).some((s: any) => s.stackIntegrations), + }), + { hideHint } +)( + connectPlayer((state: any) => ({ + list: state.stackList, + time: state.time, + }))(StackEventPanel) +); diff --git a/frontend/app/components/shared/DevTools/StackEventPanel/index.ts b/frontend/app/components/shared/DevTools/StackEventPanel/index.ts new file mode 100644 index 000000000..bb0ca8cb6 --- /dev/null +++ b/frontend/app/components/shared/DevTools/StackEventPanel/index.ts @@ -0,0 +1 @@ +export { default } from './StackEventPanel'; diff --git a/frontend/app/components/shared/DevTools/StackEventRow/StackEventRow.tsx b/frontend/app/components/shared/DevTools/StackEventRow/StackEventRow.tsx new file mode 100644 index 000000000..0d2eeb554 --- /dev/null +++ b/frontend/app/components/shared/DevTools/StackEventRow/StackEventRow.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import JumpButton from '../JumpButton'; +import { Icon } from 'UI'; +import cn from 'classnames'; +import { OPENREPLAY, SENTRY, DATADOG, STACKDRIVER } from 'Types/session/stackEvent'; + +interface Props { + event: any; + onJump: any; + style?: any; + isActive?: boolean; + onClick?: any; +} +function StackEventRow(props: Props) { + const { event, onJump, style, isActive } = props; + let message = event.payload[0] || ''; + message = typeof message === 'string' ? message : JSON.stringify(message); + + const iconProps: any = React.useMemo(() => { + const { source } = event; + return { + name: `integrations/${source}`, + size: 18, + marginRight: source === OPENREPLAY ? 11 : 10, + }; + }, [event]); + + return ( + <div + style={style} + data-scroll-item={event.isRed()} + onClick={props.onClick} + className={cn( + 'group flex items-center py-2 px-4 border-b cursor-pointer relative', + 'hover:bg-active-blue', + { 'bg-teal-light': isActive } + )} + > + <div className={cn('mr-auto flex items-start')}> + <Icon {...iconProps} /> + <div> + <div className="capitalize font-medium mb-1">{event.name}</div> + <div className="code-font text-xs">{message}</div> + </div> + </div> + <JumpButton onClick={onJump} /> + </div> + ); +} + +export default StackEventRow; diff --git a/frontend/app/components/shared/DevTools/StackEventRow/index.ts b/frontend/app/components/shared/DevTools/StackEventRow/index.ts new file mode 100644 index 000000000..321f9231b --- /dev/null +++ b/frontend/app/components/shared/DevTools/StackEventRow/index.ts @@ -0,0 +1 @@ +export { default } from './StackEventRow'; diff --git a/frontend/app/components/shared/DevTools/TimeTable/BarRow.tsx b/frontend/app/components/shared/DevTools/TimeTable/BarRow.tsx new file mode 100644 index 000000000..f283eb7ac --- /dev/null +++ b/frontend/app/components/shared/DevTools/TimeTable/BarRow.tsx @@ -0,0 +1,105 @@ +import { Tooltip } from 'UI'; +import { percentOf } from 'App/utils'; +import styles from './barRow.module.css'; +import tableStyles from './timeTable.module.css'; +import React from 'react'; + +const formatTime = (time) => (time < 1000 ? `${time.toFixed(2)}ms` : `${time / 1000}s`); + +interface Props { + resource: { + time: number; + ttfb?: number; + duration?: number; + key: string; + }; + popup?: boolean; + timestart: number; + timewidth: number; +} + +// TODO: If request has no duration, set duration to 0.2s. Enforce existence of duration in the future. +const BarRow = ({ + resource: { time, ttfb = 0, duration = 200, key }, + popup = false, + timestart = 0, + timewidth, +}: Props) => { + const timeOffset = time - timestart; + ttfb = ttfb || 0; + // TODO fix the tooltip + + const content = ( + <React.Fragment> + {ttfb != null && ( + <div className={styles.popupRow}> + <div className={styles.title}>{'Waiting (TTFB)'}</div> + <div className={styles.popupBarWrapper}> + <div + className={styles.ttfbBar} + style={{ + left: 0, + width: `${percentOf(ttfb, duration)}%`, + }} + /> + </div> + <div className={styles.time}>{formatTime(ttfb)}</div> + </div> + )} + <div className={styles.popupRow}> + <div className={styles.title}>{'Content Download'}</div> + <div className={styles.popupBarWrapper}> + <div + className={styles.downloadBar} + style={{ + left: `${percentOf(ttfb, duration)}%`, + width: `${percentOf(duration - ttfb, duration)}%`, + }} + /> + </div> + <div className={styles.time}>{formatTime(duration - ttfb)}</div> + </div> + </React.Fragment> + ); + const trigger = ( + <div + className={styles.barWrapper} + style={{ + left: `${percentOf(timeOffset, timewidth)}%`, + right: `${100 - percentOf(timeOffset + duration, timewidth)}%`, + minWidth: '5px', + }} + > + <div + className={styles.ttfbBar} + style={{ + width: `${percentOf(ttfb, duration)}%`, + }} + /> + <div + className={styles.downloadBar} + style={{ + width: `${percentOf(duration - ttfb, duration)}%`, + minWidth: '5px', + }} + /> + </div> + ); + if (!popup) + return ( + <div key={key} className={tableStyles.row}> + {' '} + {trigger}{' '} + </div> + ); + + return ( + <div key={key} className={tableStyles.row} style={{ height: '15px' }}> + {trigger} + </div> + ); +}; + +BarRow.displayName = 'BarRow'; + +export default BarRow; diff --git a/frontend/app/components/shared/DevTools/TimeTable/TimeTable.tsx b/frontend/app/components/shared/DevTools/TimeTable/TimeTable.tsx new file mode 100644 index 000000000..8271a6561 --- /dev/null +++ b/frontend/app/components/shared/DevTools/TimeTable/TimeTable.tsx @@ -0,0 +1,389 @@ +import React from 'react'; +import { List, AutoSizer } from 'react-virtualized'; +import cn from 'classnames'; +import { Duration } from 'luxon'; +import { NoContent, Icon, Button } from 'UI'; +import { percentOf } from 'App/utils'; + +import BarRow from './BarRow'; +import stl from './timeTable.module.css'; + +import autoscrollStl from '../autoscroll.module.css'; //aaa +import JumpButton from '../JumpButton'; + +type Timed = { + time: number; +}; + +type Durationed = { + duration: number; +}; + +type CanBeRed = { + //+isRed: boolean, + isRed: () => boolean; +}; + +interface Row extends Timed, Durationed, CanBeRed { + [key: string]: any; + key: string; +} + +type Line = { + color: string; // Maybe use typescript? + hint?: string; + onClick?: any; +} & Timed; + +type Column = { + label: string; + width: number; + dataKey?: string; + render?: (row: any) => void; + referenceLines?: Array<Line>; + style?: React.CSSProperties; + onClick?: void; +} & RenderOrKey; + +// type RenderOrKey = { // Disjoint? +// render: Row => React.Node +// } | { +// dataKey: string, +// } +type RenderOrKey = + | { + render?: (row: Row) => React.ReactNode; + key?: string; + } + | { + dataKey: string; + }; + +type Props = { + className?: string; + rows: Array<Row>; + children: Array<Column>; + tableHeight?: number; + activeIndex?: number; + renderPopup?: boolean; + navigation?: boolean; + referenceLines?: any[]; + additionalHeight?: number; + hoverable?: boolean; + onRowClick?: (row: any, index: number) => void; + onJump?: (time: any) => void; +}; + +type TimeLineInfo = { + timestart: number; + timewidth: number; +}; + +type State = TimeLineInfo & typeof initialState; + +//const TABLE_HEIGHT = 195; +let _additionalHeight = 0; +const ROW_HEIGHT = 32; +//const VISIBLE_COUNT = Math.ceil(TABLE_HEIGHT/ROW_HEIGHT); + +const TIME_SECTIONS_COUNT = 8; +const ZERO_TIMEWIDTH = 1000; +function formatTime(ms: number) { + if (ms < 0) return ''; + if (ms < 1000) return Duration.fromMillis(ms).toFormat('0.SSS'); + return Duration.fromMillis(ms).toFormat('mm:ss'); +} + +function computeTimeLine( + rows: Array<Row>, + firstVisibleRowIndex: number, + visibleCount: number +): TimeLineInfo { + const visibleRows = rows.slice( + firstVisibleRowIndex, + firstVisibleRowIndex + visibleCount + _additionalHeight + ); + let timestart = visibleRows.length > 0 ? Math.min(...visibleRows.map((r) => r.time)) : 0; + // TODO: GraphQL requests do not have a duration, so their timeline is borked. Assume a duration of 0.2s for every GraphQL request + const timeend = + visibleRows.length > 0 ? Math.max(...visibleRows.map((r) => r.time + (r.duration ?? 200))) : 0; + let timewidth = timeend - timestart; + const offset = timewidth / 70; + if (timestart >= offset) { + timestart -= offset; + } + timewidth *= 1.5; // += offset; + if (timewidth === 0) { + timewidth = ZERO_TIMEWIDTH; + } + return { + timestart, + timewidth, + }; +} + +const initialState = { + firstVisibleRowIndex: 0, +}; + +export default class TimeTable extends React.PureComponent<Props, State> { + state = { + ...computeTimeLine(this.props.rows, initialState.firstVisibleRowIndex, this.visibleCount), + ...initialState, + }; + + get tableHeight() { + return this.props.tableHeight || 195; + } + + get visibleCount() { + return Math.ceil(this.tableHeight / ROW_HEIGHT); + } + + scroller = React.createRef<List>(); + autoScroll = true; + + // componentDidMount() { + // if (this.scroller.current) { + // this.scroller.current.scrollToRow(this.props.activeIndex); + // } + // } + + adjustScroll(prevActiveIndex: number) { + if ( + this.props.activeIndex && + this.props.activeIndex >= 0 && + prevActiveIndex !== this.props.activeIndex && + this.scroller.current + ) { + this.scroller.current.scrollToRow(this.props.activeIndex); + } + } + + componentDidUpdate(prevProps: any, prevState: any) { + if ( + prevState.firstVisibleRowIndex !== this.state.firstVisibleRowIndex || + (this.props.rows.length <= this.visibleCount + _additionalHeight && + prevProps.rows.length !== this.props.rows.length) + ) { + this.setState({ + ...computeTimeLine(this.props.rows, this.state.firstVisibleRowIndex, this.visibleCount), + }); + } + + // this.adjustScroll(prevProps.activeIndex); + } + + onScroll = ({ + scrollTop, + scrollHeight, + clientHeight, + }: { + scrollTop: number; + scrollHeight: number; + clientHeight: number; + }): void => { + const firstVisibleRowIndex = Math.floor(scrollTop / ROW_HEIGHT + 0.33); + + if (this.state.firstVisibleRowIndex !== firstVisibleRowIndex) { + this.autoScroll = scrollHeight - clientHeight - scrollTop < ROW_HEIGHT / 2; + this.setState({ firstVisibleRowIndex }); + } + }; + + onJump = (index: any) => { + if (this.props.onJump) { + this.props.onJump(this.props.rows[index]); + } + }; + + renderRow = ({ index, key, style: rowStyle }: any) => { + const { activeIndex } = this.props; + const { children: columns, rows, renderPopup, hoverable, onRowClick } = this.props; + const { timestart, timewidth } = this.state; + const row = rows[index]; + return ( + <div + style={rowStyle} + key={key} + className={cn( + 'dev-row border-b border-color-gray-light-shade group items-center', + stl.row, + { + [stl.hoverable]: hoverable, + 'error color-red': !!row.isRed && row.isRed(), + 'cursor-pointer': typeof onRowClick === 'function', + [stl.activeRow]: activeIndex === index, + // [stl.inactiveRow]: !activeIndex || index > activeIndex, + } + )} + onClick={typeof onRowClick === 'function' ? () => onRowClick(row, index) : undefined} + id="table-row" + > + {columns + .filter((i: any) => !i.hidden) + .map(({ dataKey, render, width }) => ( + <div className={stl.cell} style={{ width: `${width}px` }}> + {render + ? render(row) + : row[dataKey || ''] || <i className="color-gray-light">{'empty'}</i>} + </div> + ))} + <div className={cn('relative flex-1 flex', stl.timeBarWrapper)}> + <BarRow resource={row} timestart={timestart} timewidth={timewidth} popup={renderPopup} /> + </div> + <JumpButton onClick={() => this.onJump(index)} /> + </div> + ); + }; + + onPrevClick = () => { + let prevRedIndex = -1; + for (let i = this.state.firstVisibleRowIndex - 1; i >= 0; i--) { + if (this.props.rows[i].isRed()) { + prevRedIndex = i; + break; + } + } + if (this.scroller.current != null) { + this.scroller.current.scrollToRow(prevRedIndex); + } + }; + + onNextClick = () => { + let prevRedIndex = -1; + for (let i = this.state.firstVisibleRowIndex + 1; i < this.props.rows.length; i++) { + if (this.props.rows[i].isRed()) { + prevRedIndex = i; + break; + } + } + if (this.scroller.current != null) { + this.scroller.current.scrollToRow(prevRedIndex); + } + }; + + onColumnClick = (dataKey: string, onClick: any) => { + if (typeof onClick === 'function') { + // this.scroller.current.scrollToRow(0); + onClick(dataKey); + this.scroller.current.forceUpdateGrid(); + } + }; + + render() { + const { + className, + rows, + navigation = false, + referenceLines = [], + additionalHeight = 0, + activeIndex, + } = this.props; + const columns = this.props.children.filter((i: any) => !i.hidden); + const { timewidth, timestart } = this.state; + + _additionalHeight = additionalHeight; + + const sectionDuration = Math.round(timewidth / TIME_SECTIONS_COUNT); + const timeColumns: number[] = []; + if (timewidth > 0) { + for (let i = 0; i < TIME_SECTIONS_COUNT; i++) { + timeColumns.push(timestart + i * sectionDuration); + } + } + + const visibleRefLines = referenceLines.filter( + ({ time }) => time > timestart && time < timestart + timewidth + ); + + const columnsSumWidth = columns.reduce((sum, { width }) => sum + width, 0); + + return ( + <div className={cn(className, 'relative')}> + {navigation && ( + <div className={cn(autoscrollStl.navButtons, 'flex items-center')}> + <Button + variant="text-primary" + icon="chevron-up" + tooltip={{ + title: 'Previous Error', + delay: 0, + }} + onClick={this.onPrevClick} + /> + <Button + variant="text-primary" + icon="chevron-down" + tooltip={{ + title: 'Next Error', + delay: 0, + }} + onClick={this.onNextClick} + /> + </div> + )} + <div className={stl.headers}> + <div className={stl.infoHeaders}> + {columns.map(({ label, width, dataKey, onClick = null }) => ( + <div + className={cn(stl.headerCell, 'flex items-center select-none', { + 'cursor-pointer': typeof onClick === 'function', + })} + style={{ width: `${width}px` }} + // onClick={() => this.onColumnClick(dataKey, onClick)} + > + <span>{label}</span> + </div> + ))} + </div> + <div className={stl.waterfallHeaders}> + {timeColumns.map((time, i) => ( + <div className={stl.timeCell} key={`tc-${i}`}> + {formatTime(time)} + </div> + ))} + </div> + </div> + + <NoContent size="small" show={rows.length === 0}> + <div className="relative"> + <div className={stl.timePart} style={{ left: `${columnsSumWidth}px` }}> + {timeColumns.map((_, index) => ( + <div key={`tc-${index}`} className={stl.timeCell} /> + ))} + {visibleRefLines.map(({ time, color, onClick }) => ( + <div + className={cn(stl.refLine, `bg-${color}`)} + style={{ + left: `${percentOf(time - timestart, timewidth)}%`, + cursor: typeof onClick === 'function' ? 'click' : 'auto', + }} + onClick={onClick} + /> + ))} + </div> + <AutoSizer disableHeight> + {({ width }: { width: number }) => ( + <List + scrollToIndex={this.props.activeIndex || 0} + ref={this.scroller} + className={stl.list} + height={this.tableHeight + additionalHeight} + width={width} + overscanRowCount={20} + rowCount={rows.length} + rowHeight={ROW_HEIGHT} + rowRenderer={this.renderRow} + onScroll={this.onScroll} + scrollToAlignment="center" + forceUpdateProp={timestart | timewidth | (activeIndex || 0)} + /> + )} + </AutoSizer> + </div> + </NoContent> + </div> + ); + } +} diff --git a/frontend/app/components/shared/DevTools/TimeTable/barRow.module.css b/frontend/app/components/shared/DevTools/TimeTable/barRow.module.css new file mode 100644 index 000000000..e45d1f7b2 --- /dev/null +++ b/frontend/app/components/shared/DevTools/TimeTable/barRow.module.css @@ -0,0 +1,45 @@ + + + +.barWrapper { + display: flex; + position: absolute; + top: 35%; + bottom: 35%; + border-radius: 3px; + overflow: hidden; +} + +.downloadBar, .ttfbBar { + /* box-shadow: inset 0px 0px 0px 1px $teal; */ + height: 100%; + box-sizing: border-box; + position: relative; +} +.ttfbBar { + background-color: rgba(175, 226, 221, 0.8); +} +.downloadBar { + background-color: rgba(133, 200, 192, 0.8); +} + +.popupRow { + color: $gray-medium; + display: flex; + align-items: center; + padding: 2px 0; + font-size: 12px; +} +.title { + width: 105px; +} +.time { + width: 60px; + padding-left: 10px; +} +.popupBarWrapper { + width: 220px; + height: 15px; + border-radius: 3px; + overflow: hidden; +} \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/TimeTable/index.js b/frontend/app/components/shared/DevTools/TimeTable/index.js new file mode 100644 index 000000000..c3c329b0a --- /dev/null +++ b/frontend/app/components/shared/DevTools/TimeTable/index.js @@ -0,0 +1 @@ +export { default } from './TimeTable'; \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/TimeTable/timeTable.module.css b/frontend/app/components/shared/DevTools/TimeTable/timeTable.module.css new file mode 100644 index 000000000..46c54bc03 --- /dev/null +++ b/frontend/app/components/shared/DevTools/TimeTable/timeTable.module.css @@ -0,0 +1,120 @@ + + +$offset: 10px; + +.timeCell { + border-left: solid thin rgba(0, 0, 0, 0.05); +} + +.headers { + box-shadow: 0 1px 2px 0 $gray-light; + background-color: $gray-lightest; + color: $gray-darkest; + font-size: 12px; + overflow-x: hidden; + white-space: nowrap; + width: 100%; + display: flex; + padding: 0 $offset; +} +.infoHeaders { + text-transform: uppercase; + display: flex; + & .headerCell { + padding: 4px 2px; + } +} +.waterfallHeaders { + display: flex; + flex: 1; + & .timeCell { + flex: 1; + overflow: hidden; + padding: 4px 0; + } +} + +.list { + /* TODO hide the scrollbar track */ + &::-webkit-scrollbar { + width: 1px; + } + scrollbar-width: thin; + font-size: 12px; + font-family: 'Menlo', 'monaco', 'consolas', monospace; +} + +.row { + display: flex; + padding: 0 $offset; + + &:hover { + background-color: $active-blue; + } + /*align-items: center; + cursor: pointer; + */ + /* &:nth-child(even) { + background-color: $gray-lightest; + } */ + /* & > div:first-child { + padding-left: 5px; + }*/ +} +.cell { + height: 100%; + display: flex; + align-items: center; + overflow: hidden; + padding: 0 6px; + white-space: nowrap; + + & > div > div { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + } +} +.hoverable { + transition: all 0.3s; + cursor: pointer; + &:hover { + background-color: $active-blue; + transition: all 0.2s; + color: $gray-dark; + } +} +.timeBarWrapper{ + overflow: hidden; +} + +.timePart { + position: absolute; + top: 0; + bottom: 0; + /*left:0;*/ + right: 0; + display: flex; + margin: 0 $offset; + & .timeCell { + height: 100%; + flex: 1; + z-index: 1; + pointer-events: none; + } + & .refLine { + position: absolute; + height: 100%; + width: 1px; + z-index: 1; + } +} + +.activeRow { + background-color: $teal-light; +} + +.inactiveRow { + opacity: 0.5; +} \ No newline at end of file diff --git a/frontend/app/components/shared/DevTools/autoscroll.module.css b/frontend/app/components/shared/DevTools/autoscroll.module.css new file mode 100644 index 000000000..209badfb2 --- /dev/null +++ b/frontend/app/components/shared/DevTools/autoscroll.module.css @@ -0,0 +1,12 @@ +.navButtons { + position: absolute; + + background: rgba(255, 255, 255, 0.5); + padding: 4px; + + right: 24px; + top: 8px; + z-index: 1; +} + + diff --git a/frontend/app/components/shared/EmailVerificationMessage/EmailVerificationMessage.js b/frontend/app/components/shared/EmailVerificationMessage/EmailVerificationMessage.js index 4d548e7bc..2f29ce2c5 100644 --- a/frontend/app/components/shared/EmailVerificationMessage/EmailVerificationMessage.js +++ b/frontend/app/components/shared/EmailVerificationMessage/EmailVerificationMessage.js @@ -1,30 +1,40 @@ -import React from 'react' +import React, { useState } from 'react'; import { connect } from 'react-redux'; -import { Popup } from 'UI' -import { resendEmailVerification } from 'Duck/user' +import { Tooltip } from 'UI'; +import { resendEmailVerification } from 'Duck/user'; import { toast } from 'react-toastify'; function EmailVerificationMessage(props) { + const [sent, setSent] = useState(false); const { email } = props; const send = () => { - props.resendEmailVerification(email).then(function() { + props.resendEmailVerification(email).then(function () { toast.success(`Verification email sent to ${email}`); - }) - } - return ( - <Popup - content={ - `We've sent a verification email to "${email}" please follow the instructions in it to use OpenReplay uninterruptedly.` - } + setSent(true); + }); + }; + return !sent ? ( + <Tooltip + title={`We've sent a verification email to "${email}" please follow the instructions in it to use OpenReplay uninterruptedly.`} > <div - className="mt-3 px-3 rounded-2xl font-medium" - style={{ paddingTop: '3px', height: '28px', backgroundColor: 'rgba(255, 239, 239, 1)', border: 'solid thin rgba(221, 181, 181, 1)' }} + className="mt-3 px-3 rounded-2xl font-medium" + style={{ + paddingTop: '3px', + height: '28px', + backgroundColor: 'rgba(255, 239, 239, 1)', + border: 'solid thin rgba(221, 181, 181, 1)', + }} > - <span>Please, verify your email.</span> <a href="#" className="link" onClick={send}>Resend</a> + <span>Please, verify your email.</span>{' '} + <a href="#" className="link" onClick={send}> + Resend + </a> </div> - </Popup> - ) + </Tooltip> + ) : ( + <></> + ); } -export default connect(null, { resendEmailVerification })(EmailVerificationMessage) +export default connect(null, { resendEmailVerification })(EmailVerificationMessage); diff --git a/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.js b/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.js deleted file mode 100644 index 6f3ad549e..000000000 --- a/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.js +++ /dev/null @@ -1,182 +0,0 @@ -import React from 'react'; -import { JSONTree, NoContent, Button, Tabs } from 'UI'; -import cn from 'classnames'; -import stl from './fetchDetails.module.css'; -import Headers from './components/Headers'; -import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; - -const HEADERS = 'HEADERS'; -const REQUEST = 'REQUEST'; -const RESPONSE = 'RESPONSE'; - -const TABS = [HEADERS, REQUEST, RESPONSE].map((tab) => ({ text: tab, key: tab })); - -export default class FetchDetailsModal extends React.PureComponent { - state = { activeTab: REQUEST, tabs: [] }; - - onTabClick = (activeTab) => this.setState({ activeTab }); - - componentDidMount() { - this.checkTabs(); - } - - renderActiveTab = (tab) => { - const { - resource: { payload, response = this.props.resource.body }, - } = this.props; - let jsonPayload, - jsonResponse, - requestHeaders, - responseHeaders = undefined; - - try { - jsonPayload = typeof payload === 'string' ? JSON.parse(payload) : payload; - requestHeaders = jsonPayload.headers; - jsonPayload.body = - typeof jsonPayload.body === 'string' ? JSON.parse(jsonPayload.body) : jsonPayload.body; - delete jsonPayload.headers; - } catch (e) {} - - try { - jsonResponse = typeof response === 'string' ? JSON.parse(response) : response; - responseHeaders = jsonResponse.headers; - jsonResponse.body = - typeof jsonResponse.body === 'string' ? JSON.parse(jsonResponse.body) : jsonResponse.body; - delete jsonResponse.headers; - } catch (e) {} - - switch (tab) { - case REQUEST: - return ( - <NoContent - title={ - <div className="flex flex-col items-center justify-center"> - <AnimatedSVG name={ICONS.NO_RESULTS} size="170" /> - <div className="mt-6 text-2xl">Body is Empty.</div> - </div> - } - size="small" - show={!payload} - // animatedIcon="no-results" - > - <div> - <div className="mt-6"> - {jsonPayload === undefined ? ( - <div className="ml-3 break-words my-3"> {payload} </div> - ) : ( - <JSONTree src={jsonPayload} collapsed={false} enableClipboard /> - )} - </div> - <div className="divider" /> - </div> - </NoContent> - ); - case RESPONSE: - return ( - <NoContent - title={ - <div className="flex flex-col items-center justify-center"> - <AnimatedSVG name={ICONS.NO_RESULTS} size="170" /> - <div className="mt-6 text-2xl">Body is Empty.</div> - </div> - } - size="small" - show={!response} - // animatedIcon="no-results" - > - <div> - <div className="mt-6"> - {jsonResponse === undefined ? ( - <div className="ml-3 break-words my-3"> {response} </div> - ) : ( - <JSONTree src={jsonResponse} collapsed={false} enableClipboard /> - )} - </div> - <div className="divider" /> - </div> - </NoContent> - ); - case HEADERS: - return <Headers requestHeaders={requestHeaders} responseHeaders={responseHeaders} />; - } - }; - - componentDidUpdate(prevProps) { - if (prevProps.resource.index === this.props.resource.index) return; - - this.checkTabs(); - } - - checkTabs() { - const { - resource: { payload, response, body }, - isResult, - } = this.props; - const _tabs = TABS; - // const _tabs = TABS.filter(t => { - // if (t.key == REQUEST && !!payload) { - // return true - // } - - // if (t.key == RESPONSE && !!response) { - // return true; - // } - - // return false; - // }) - this.setState({ tabs: _tabs, activeTab: _tabs.length > 0 ? _tabs[0].key : null }); - } - - render() { - const { - resource: { method, url, duration }, - nextClick, - prevClick, - first = false, - last = false, - } = this.props; - const { activeTab, tabs } = this.state; - - const _duration = parseInt(duration) - console.log('_duration', _duration); - - return ( - <div className="bg-white p-5 h-screen overflow-y-auto" style={{ width: '500px' }}> - <h5 className="mb-2">{'URL'}</h5> - <div className={cn(stl.url, 'color-gray-darkest')}>{url}</div> - <div className="flex items-start mt-4"> - {method && ( - <div className="w-4/12"> - <div className="font-medium mb-2">Method</div> - <div>{method}</div> - </div> - )} - {!!_duration && ( - <div className="w-4/12"> - <div className="font-medium mb-2">Duration</div> - <div>{_duration } ms</div> - </div> - )} - </div> - - <div className="mt-6"> - <div> - <Tabs tabs={tabs} active={activeTab} onClick={this.onTabClick} border={true} /> - <div style={{ height: 'calc(100vh - 314px)', overflowY: 'auto' }}> - {this.renderActiveTab(activeTab)} - </div> - </div> - - {/* <div className="flex justify-between absolute bottom-0 left-0 right-0 p-3 border-t bg-white"> - <Button variant="outline" onClick={prevClick} disabled={first}> - Prev - </Button> - <Button variant="outline" onClick={nextClick} disabled={last}> - Next - </Button> - </div> */} - </div> - </div> - ); - } -} diff --git a/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.tsx b/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.tsx new file mode 100644 index 000000000..bcee5f5b9 --- /dev/null +++ b/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.tsx @@ -0,0 +1,69 @@ +import React, { useEffect, useState } from 'react'; +import FetchBasicDetails from './components/FetchBasicDetails'; +import { Button } from 'UI'; +import FetchPluginMessage from './components/FetchPluginMessage'; +import { TYPES } from 'Types/session/resource'; +import FetchTabs from './components/FetchTabs/FetchTabs'; +import { useStore } from 'App/mstore'; + +interface Props { + resource: any; + rows?: any; + fetchPresented?: boolean; +} +function FetchDetailsModal(props: Props) { + const { rows = [], fetchPresented = false } = props; + const [resource, setResource] = useState(props.resource); + const [first, setFirst] = useState(false); + const [last, setLast] = useState(false); + const isXHR = resource.type === TYPES.XHR || resource.type === TYPES.FETCH; + const { + sessionStore: { devTools }, + } = useStore(); + + useEffect(() => { + const index = rows.indexOf(resource); + const length = rows.length - 1; + setFirst(index === 0); + setLast(index === length); + }, [resource]); + + const prevClick = () => { + const index = rows.indexOf(resource); + if (index > 0) { + setResource(rows[index - 1]); + devTools.update('network', { index: index - 1 }) + } + }; + + const nextClick = () => { + const index = rows.indexOf(resource); + if (index < rows.length - 1) { + setResource(rows[index + 1]); + devTools.update('network', { index: index + 1 }) + } + }; + + return ( + <div className="bg-white p-5 h-screen overflow-y-auto" style={{ width: '500px' }}> + <h5 className="mb-2 text-2xl">Network Request</h5> + <FetchBasicDetails resource={resource} /> + + {isXHR && !fetchPresented && <FetchPluginMessage />} + {isXHR && <FetchTabs resource={resource} />} + + {rows && rows.length > 0 && ( + <div className="flex justify-between absolute bottom-0 left-0 right-0 p-3 border-t bg-white"> + <Button variant="outline" onClick={prevClick} disabled={first}> + Prev + </Button> + <Button variant="outline" onClick={nextClick} disabled={last}> + Next + </Button> + </div> + )} + </div> + ); +} + +export default FetchDetailsModal; diff --git a/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/FetchBasicDetails.tsx b/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/FetchBasicDetails.tsx new file mode 100644 index 000000000..49e16c00f --- /dev/null +++ b/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/FetchBasicDetails.tsx @@ -0,0 +1,82 @@ +import React, { useMemo } from 'react'; +import { formatBytes } from 'App/utils'; +import CopyText from 'Shared/CopyText'; +import cn from 'classnames'; + +interface Props { + resource: any; +} +function FetchBasicDetails({ resource }: Props) { + const _duration = parseInt(resource.duration); + const text = useMemo(() => { + if (resource.url.length > 50) { + const endText = resource.url.split('/').pop(); + return resource.url.substring(0, 50 - endText.length) + '.../' + endText; + } + return resource.url; + }, [resource]); + + return ( + <div> + <div className="flex items-center py-1"> + <div className="font-medium">Name</div> + <div className="rounded-lg bg-active-blue px-2 py-1 ml-2 whitespace-nowrap overflow-hidden text-clip cursor-pointer"> + <CopyText content={resource.url}>{text}</CopyText> + </div> + </div> + + <div className="flex items-center py-1"> + <div className="font-medium">Type</div> + <div className="rounded bg-active-blue px-2 py-1 ml-2 whitespace-nowrap overflow-hidden text-clip"> + {resource.type} + </div> + </div> + + {!!resource.decodedBodySize && ( + <div className="flex items-center py-1"> + <div className="font-medium">Size</div> + <div className="rounded bg-active-blue px-2 py-1 ml-2 whitespace-nowrap overflow-hidden text-clip"> + {formatBytes(resource.decodedBodySize)} + </div> + </div> + )} + + {resource.method && ( + <div className="flex items-center py-1"> + <div className="font-medium">Request Method</div> + <div className="rounded bg-active-blue px-2 py-1 ml-2 whitespace-nowrap overflow-hidden text-clip"> + {resource.method} + </div> + </div> + )} + + {resource.status && ( + <div className="flex items-center py-1"> + <div className="font-medium">Status</div> + <div + className={cn( + 'rounded bg-active-blue px-2 py-1 ml-2 whitespace-nowrap overflow-hidden text-clip flex items-center', + { 'error color-red': !resource.success } + )} + > + {resource.status === '200' && ( + <div className="w-4 h-4 bg-green rounded-full mr-2"></div> + )} + {resource.status} + </div> + </div> + )} + + {!!_duration && ( + <div className="flex items-center py-1"> + <div className="font-medium">Time</div> + <div className="rounded bg-active-blue px-2 py-1 ml-2 whitespace-nowrap overflow-hidden text-clip"> + {_duration} ms + </div> + </div> + )} + </div> + ); +} + +export default FetchBasicDetails; diff --git a/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/index.ts b/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/index.ts new file mode 100644 index 000000000..86f95ff45 --- /dev/null +++ b/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/index.ts @@ -0,0 +1 @@ +export { default } from './FetchBasicDetails'; diff --git a/frontend/app/components/shared/FetchDetailsModal/components/FetchPluginMessage/FetchPluginMessage.tsx b/frontend/app/components/shared/FetchDetailsModal/components/FetchPluginMessage/FetchPluginMessage.tsx new file mode 100644 index 000000000..8699b8cb6 --- /dev/null +++ b/frontend/app/components/shared/FetchDetailsModal/components/FetchPluginMessage/FetchPluginMessage.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { Icon } from 'UI'; + +function FetchPluginMessage() { + return ( + <div className="bg-active-blue rounded p-3 mt-4"> + <div className="mb-2 flex items-center"> + <Icon name="lightbulb" size="18" /> + <span className="ml-2 font-medium">Get more out of network requests</span> + </div> + <ul className="list-disc ml-5"> + <li> + Integrate{' '} + <a href="https://docs.openreplay.com/plugins/fetch" className="link" target="_blank"> + Fetch plugin + </a>{' '} + to capture fetch payloads. + </li> + <li> + Find a detailed{' '} + <a href="https://www.youtube.com/watch?v=YFCKstPZzZg" className="link" target="_blank"> + video tutorial + </a>{' '} + to understand practical example of how to use fetch plugin. + </li> + </ul> + </div> + ); +} + +export default FetchPluginMessage; diff --git a/frontend/app/components/shared/FetchDetailsModal/components/FetchPluginMessage/index.ts b/frontend/app/components/shared/FetchDetailsModal/components/FetchPluginMessage/index.ts new file mode 100644 index 000000000..df224dbbf --- /dev/null +++ b/frontend/app/components/shared/FetchDetailsModal/components/FetchPluginMessage/index.ts @@ -0,0 +1 @@ +export { default } from './FetchPluginMessage'; diff --git a/frontend/app/components/shared/FetchDetailsModal/components/FetchTabs/FetchTabs.tsx b/frontend/app/components/shared/FetchDetailsModal/components/FetchTabs/FetchTabs.tsx new file mode 100644 index 000000000..837a61ec6 --- /dev/null +++ b/frontend/app/components/shared/FetchDetailsModal/components/FetchTabs/FetchTabs.tsx @@ -0,0 +1,112 @@ +import React, { useEffect, useState } from 'react'; +import Headers from '../Headers'; +import { JSONTree, Tabs, NoContent } from 'UI'; +import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; + +const HEADERS = 'HEADERS'; +const REQUEST = 'REQUEST'; +const RESPONSE = 'RESPONSE'; +const TABS = [HEADERS, REQUEST, RESPONSE].map((tab) => ({ text: tab, key: tab })); + +interface Props { + resource: any; +} +function FetchTabs(props: Props) { + const { resource } = props; + const [activeTab, setActiveTab] = useState(HEADERS); + const onTabClick = (tab: string) => setActiveTab(tab); + const [jsonPayload, setJsonPayload] = useState(null); + const [jsonResponse, setJsonResponse] = useState(null); + const [requestHeaders, setRequestHeaders] = useState(null); + const [responseHeaders, setResponseHeaders] = useState(null); + + useEffect(() => { + const { payload, response } = resource; + + try { + let jsonPayload = typeof payload === 'string' ? JSON.parse(payload) : payload; + let requestHeaders = jsonPayload.headers; + jsonPayload.body = + typeof jsonPayload.body === 'string' ? JSON.parse(jsonPayload.body) : jsonPayload.body; + delete jsonPayload.headers; + setJsonPayload(jsonPayload); + setRequestHeaders(requestHeaders); + } catch (e) {} + + try { + let jsonResponse = typeof response === 'string' ? JSON.parse(response) : response; + let responseHeaders = jsonResponse.headers; + jsonResponse.body = + typeof jsonResponse.body === 'string' ? JSON.parse(jsonResponse.body) : jsonResponse.body; + delete jsonResponse.headers; + setJsonResponse(jsonResponse); + setResponseHeaders(responseHeaders); + } catch (e) {} + }, [resource, activeTab]); + + const renderActiveTab = () => { + const { payload, response } = resource; + switch (activeTab) { + case REQUEST: + return ( + <NoContent + title={ + <div className="flex flex-col items-center justify-center"> + <AnimatedSVG name={ICONS.NO_RESULTS} size="170" /> + <div className="mt-6 text-2xl">Body is Empty.</div> + </div> + } + size="small" + show={!payload} + // animatedIcon="no-results" + > + <div> + <div className="mt-6"> + {jsonPayload === undefined ? ( + <div className="ml-3 break-words my-3"> {payload} </div> + ) : ( + <JSONTree src={jsonPayload} collapsed={false} enableClipboard /> + )} + </div> + <div className="divider" /> + </div> + </NoContent> + ); + case RESPONSE: + return ( + <NoContent + title={ + <div className="flex flex-col items-center justify-center"> + <AnimatedSVG name={ICONS.NO_RESULTS} size="170" /> + <div className="mt-6 text-2xl">Body is Empty.</div> + </div> + } + size="small" + show={!response} + // animatedIcon="no-results" + > + <div> + <div className="mt-6"> + {jsonResponse === undefined ? ( + <div className="ml-3 break-words my-3"> {response} </div> + ) : ( + <JSONTree src={jsonResponse} collapsed={false} enableClipboard /> + )} + </div> + <div className="divider" /> + </div> + </NoContent> + ); + case HEADERS: + return <Headers requestHeaders={requestHeaders} responseHeaders={responseHeaders} />; + } + }; + return ( + <div> + <Tabs tabs={TABS} active={activeTab} onClick={onTabClick} border={true} /> + <div style={{ height: 'calc(100vh - 314px)', overflowY: 'auto' }}>{renderActiveTab()}</div> + </div> + ); +} + +export default FetchTabs; diff --git a/frontend/app/components/shared/FetchDetailsModal/components/Headers/Headers.tsx b/frontend/app/components/shared/FetchDetailsModal/components/Headers/Headers.tsx index c2ec31a07..78c4a5e64 100644 --- a/frontend/app/components/shared/FetchDetailsModal/components/Headers/Headers.tsx +++ b/frontend/app/components/shared/FetchDetailsModal/components/Headers/Headers.tsx @@ -1,9 +1,13 @@ -import React from 'react' -import { NoContent, TextEllipsis } from 'UI' -import stl from './headers.module.css' +import React from 'react'; +import { NoContent, TextEllipsis } from 'UI'; +import stl from './headers.module.css'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; -function Headers(props) { +interface Props { + requestHeaders: any; + responseHeaders: any; +} +function Headers(props: Props) { return ( <div> <NoContent @@ -14,37 +18,33 @@ function Headers(props) { </div> } size="small" - show={ !props.requestHeaders && !props.responseHeaders } + show={!props.requestHeaders && !props.responseHeaders} // animatedIcon="no-results" > - { props.requestHeaders && ( + {props.requestHeaders && ( <> <div className="mb-4 mt-4"> <div className="my-2 font-medium">Request Headers</div> - { - Object.keys(props.requestHeaders).map(h => ( - <div className={stl.row}> - <span className="mr-2 font-medium">{h}:</span> - <span>{props.requestHeaders[h]}</span> - </div> - )) - } + {Object.keys(props.requestHeaders).map((h) => ( + <div className={stl.row}> + <span className="mr-2 font-medium">{h}:</span> + <span>{props.requestHeaders[h]}</span> + </div> + ))} </div> <hr /> </> )} - - { props.responseHeaders && ( + + {props.responseHeaders && ( <div className="mt-4"> <div className="my-2 font-medium">Response Headers</div> - { - Object.keys(props.responseHeaders).map(h => ( - <div className={stl.row}> - <span className="mr-2 font-medium">{h}:</span> - <span>{props.responseHeaders[h]}</span> - </div> - )) - } + {Object.keys(props.responseHeaders).map((h) => ( + <div className={stl.row}> + <span className="mr-2 font-medium">{h}:</span> + <span>{props.responseHeaders[h]}</span> + </div> + ))} </div> )} </NoContent> @@ -52,4 +52,4 @@ function Headers(props) { ); } -export default Headers; \ No newline at end of file +export default Headers; diff --git a/frontend/app/components/shared/Filters/FilterList/FilterList.tsx b/frontend/app/components/shared/Filters/FilterList/FilterList.tsx index 1116c044f..ab53a4214 100644 --- a/frontend/app/components/shared/Filters/FilterList/FilterList.tsx +++ b/frontend/app/components/shared/Filters/FilterList/FilterList.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import FilterItem from '../FilterItem'; -import { SegmentSelection, Popup } from 'UI'; +import { SegmentSelection, Tooltip } from 'UI'; import { List } from 'immutable'; import { useObserver } from 'mobx-react-lite'; @@ -24,31 +24,34 @@ function FilterList(props: Props) { const onRemoveFilter = (filterIndex: any) => { props.onRemoveFilter(filterIndex); - } + }; return useObserver(() => ( <div className="flex flex-col"> - { hasEvents && ( + {hasEvents && ( <> <div className="flex items-center mb-2"> <div className="text-sm color-gray-medium mr-auto">EVENTS</div> - { !hideEventsOrder && ( + {!hideEventsOrder && ( <div className="flex items-center"> - <div className="mr-2 color-gray-medium text-sm" style={{ textDecoration: 'underline dotted'}}> - <Popup - content={ `Select the operator to be applied between events in your search.` } + <div + className="mr-2 color-gray-medium text-sm" + style={{ textDecoration: 'underline dotted' }} + > + <Tooltip + title={`Select the operator to be applied between events in your search.`} > <div>Events Order</div> - </Popup> + </Tooltip> </div> - + <SegmentSelection primary name="eventsOrder" extraSmall={true} onSelect={props.onChangeEventsOrder} value={{ value: filter.eventsOrder }} - list={ [ + list={[ { name: 'THEN', value: 'then' }, { name: 'AND', value: 'and' }, { name: 'OR', value: 'or' }, @@ -57,38 +60,42 @@ function FilterList(props: Props) { </div> )} </div> - {filters.map((filter: any, filterIndex: any) => filter.isEvent ? ( - <FilterItem - key={`${filter.key}-${filterIndex}`} - filterIndex={rowIndex++} - filter={filter} - onUpdate={(filter) => props.onUpdateFilter(filterIndex, filter)} - onRemoveFilter={() => onRemoveFilter(filterIndex) } - saveRequestPayloads={saveRequestPayloads} - /> - ): null)} - <div className='mb-2' /> + {filters.map((filter: any, filterIndex: any) => + filter.isEvent ? ( + <FilterItem + key={`${filter.key}-${filterIndex}`} + filterIndex={rowIndex++} + filter={filter} + onUpdate={(filter) => props.onUpdateFilter(filterIndex, filter)} + onRemoveFilter={() => onRemoveFilter(filterIndex)} + saveRequestPayloads={saveRequestPayloads} + /> + ) : null + )} + <div className="mb-2" /> </> )} {hasFilters && ( <> - {hasEvents && <div className='border-t -mx-5 mb-4' />} + {hasEvents && <div className="border-t -mx-5 mb-4" />} <div className="mb-2 text-sm color-gray-medium mr-auto">FILTERS</div> - {filters.map((filter: any, filterIndex: any) => !filter.isEvent ? ( - <FilterItem - key={filterIndex} - isFilter={true} - filterIndex={filterIndex} - filter={filter} - onUpdate={(filter) => props.onUpdateFilter(filterIndex, filter)} - onRemoveFilter={() => onRemoveFilter(filterIndex) } - /> - ): null)} + {filters.map((filter: any, filterIndex: any) => + !filter.isEvent ? ( + <FilterItem + key={filterIndex} + isFilter={true} + filterIndex={filterIndex} + filter={filter} + onUpdate={(filter) => props.onUpdateFilter(filterIndex, filter)} + onRemoveFilter={() => onRemoveFilter(filterIndex)} + /> + ) : null + )} </> )} </div> )); } -export default FilterList; \ No newline at end of file +export default FilterList; diff --git a/frontend/app/components/shared/Filters/FilterModal/FilterModal.module.css b/frontend/app/components/shared/Filters/FilterModal/FilterModal.module.css index 463a7a2a9..37cf966c6 100644 --- a/frontend/app/components/shared/Filters/FilterModal/FilterModal.module.css +++ b/frontend/app/components/shared/Filters/FilterModal/FilterModal.module.css @@ -10,6 +10,7 @@ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; + max-width: 200px; &:hover { background-color: $active-blue; color: $teal !important; @@ -34,4 +35,4 @@ overflow: hidden; text-overflow: ellipsis; } -} \ No newline at end of file +} diff --git a/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx b/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx index c833583f7..421a12837 100644 --- a/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx +++ b/frontend/app/components/shared/Filters/FilterModal/FilterModal.tsx @@ -8,19 +8,19 @@ import { filtersMap } from 'Types/filter/newFilter'; export const getMatchingEntries = (searchQuery: string, filters: Record<string, any>) => { const matchingCategories: string[] = []; const matchingFilters: Record<string, any> = {}; - - if (searchQuery.length === 0) return { + const lowerCaseQuery = searchQuery.toLowerCase(); + if (lowerCaseQuery.length === 0) return { matchingCategories: Object.keys(filters), matchingFilters: filters, }; Object.keys(filters).forEach(name => { - if (name.toLocaleLowerCase().includes(searchQuery)) { + if (name.toLocaleLowerCase().includes(lowerCaseQuery)) { matchingCategories.push(name); matchingFilters[name] = filters[name]; } else { const filtersQuery = filters[name] - .filter(filterOption => filterOption.label.toLocaleLowerCase().includes(searchQuery)) + .filter((filterOption: any) => filterOption.label.toLocaleLowerCase().includes(lowerCaseQuery)) if (filtersQuery.length > 0) matchingFilters[name] = filtersQuery filtersQuery.length > 0 && matchingCategories.push(name); @@ -64,10 +64,10 @@ function FilterModal(props: Props) { // console.log(matchingFilters) return ( <div className={stl.wrapper} style={{ width: '480px', maxHeight: '380px', overflowY: 'auto'}}> - <div className={searchQuery && !isResultEmpty ? 'mb-6' : ''} style={{ columns: "auto 200px" }}> + <div className={searchQuery && !isResultEmpty ? 'mb-6' : ''} style={{ columns: matchingCategories.length > 1 ? 'auto 200px' : 1 }}> {matchingCategories.map((key) => { return ( - <div className="mb-6" key={key}> + <div className="mb-6 flex flex-col gap-2" key={key}> <div className="uppercase font-medium mb-1 color-gray-medium tracking-widest text-sm">{key}</div> <div> {matchingFilters[key] && matchingFilters[key].map((filter: any) => ( diff --git a/frontend/app/components/shared/Filters/FilterSource/FilterSource.tsx b/frontend/app/components/shared/Filters/FilterSource/FilterSource.tsx index 0975f7335..eed1e6e1d 100644 --- a/frontend/app/components/shared/Filters/FilterSource/FilterSource.tsx +++ b/frontend/app/components/shared/Filters/FilterSource/FilterSource.tsx @@ -28,7 +28,7 @@ function FilterSource(props: Props) { case FilterType.NUMBER: return ( <div className="relative"> - <input name="source" className={cn(stl.inputField, "rounded-l px-1 block")} value={value} onBlur={write} onChange={write} type="number" /> + <input name="source" placeholder={filter.sourcePlaceholder} className={cn(stl.inputField, "rounded-l px-1 block")} value={value} onBlur={write} onChange={write} type="number" /> <div className="absolute right-0 top-0 bottom-0 bg-gray-lightest rounded-r px-1 border-l border-color-gray-light flex items-center" style={{ margin: '1px', minWidth: '24px'}}>{filter.sourceUnit}</div> </div> ); diff --git a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx index 5638f9a1d..7daab8acb 100644 --- a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx +++ b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx @@ -93,7 +93,8 @@ function FilterValue(props: Props) { <FilterValueDropdown // search={true} value={value} - filter={filter} + placeholder={filter.placeholder} + // filter={filter} options={filter.options} onChange={({ value }) => onChange(null, { value }, valueIndex)} /> @@ -106,6 +107,7 @@ function FilterValue(props: Props) { // multiple={true} value={value} // filter={filter} + placeholder={filter.placeholder} options={filter.options} onChange={({ value }) => onChange(null, value, valueIndex)} onAddValue={onAddValue} @@ -164,7 +166,7 @@ function FilterValue(props: Props) { endpoint="/events/search" params={getParms(filter.key)} headerText={''} - // placeholder={''} + placeholder={filter.placeholder} onSelect={(e, item) => onChange(e, item, valueIndex)} icon={filter.icon} /> @@ -173,8 +175,7 @@ function FilterValue(props: Props) { }; return ( - // - <div className={cn("grid gap-3 w-full", { 'grid-cols-2': filter.hasSource, 'grid-cols-3' : !filter.hasSource })}> + <div className={cn("grid gap-3", { 'grid-cols-2': filter.hasSource, 'grid-cols-3' : !filter.hasSource })}> {filter.type === FilterType.DURATION ? renderValueFiled(filter.value, 0) : filter.value && diff --git a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx index 13c40cbd8..28e1d23a1 100644 --- a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx +++ b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx @@ -71,6 +71,7 @@ const dropdownStyles = { interface Props { // filter: any; // event/filter // options: any[]; + placeholder?: string value: string; onChange: (value: any) => void; className?: string; @@ -84,7 +85,7 @@ interface Props { isMultilple?: boolean; } function FilterValueDropdown(props: Props) { - const { isMultilple = true, search = false, options, onChange, value, className = '', showCloseButton = true, showOrButton = true } = props; + const { placeholder = 'Select', isMultilple = true, search = false, options, onChange, value, className = '', showCloseButton = true, showOrButton = true } = props; // const options = [] return ( @@ -97,7 +98,7 @@ function FilterValueDropdown(props: Props) { name="issue_type" defaultValue={ value } onChange={ (value: any) => onChange(value.value) } - placeholder="Select" + placeholder={placeholder} styles={dropdownStyles} /> <div diff --git a/frontend/app/components/shared/GraphQLDetailsModal/GraphQLDetailsModal.tsx b/frontend/app/components/shared/GraphQLDetailsModal/GraphQLDetailsModal.tsx index a742d4ddf..d64a91b5d 100644 --- a/frontend/app/components/shared/GraphQLDetailsModal/GraphQLDetailsModal.tsx +++ b/frontend/app/components/shared/GraphQLDetailsModal/GraphQLDetailsModal.tsx @@ -26,16 +26,16 @@ function GraphQLDetailsModal(props: Props) { return ( <div className="p-5 bg-white h-screen overflow-y-auto" style={{ width: '500px' }}> - <h5 className="mb-2">{'Operation Name'}</h5> + <h5 className="mb-2 font-medium">{'Operation Name'}</h5> <div className={dataClass}>{operationName}</div> <div className="flex items-center gap-4 mt-4"> <div className="w-6/12"> - <div className="mb-2">Operation Kind</div> + <div className="mb-2 font-medium">Operation Kind</div> <div className={dataClass}>{operationKind}</div> </div> <div className="w-6/12"> - <div className="mb-2">Duration</div> + <div className="mb-2 font-medium">Duration</div> <div className={dataClass}>{duration ? parseInt(duration) : '???'} ms</div> </div> </div> @@ -43,7 +43,7 @@ function GraphQLDetailsModal(props: Props) { <div style={{ height: 'calc(100vh - 314px)', overflowY: 'auto' }}> <div> <div className="flex justify-between items-start mt-6 mb-2"> - <h5 className="mt-1 mr-1">{'Variables'}</h5> + <h5 className="mt-1 mr-1 font-medium">{'Variables'}</h5> </div> <div className={dataClass}> {jsonVars === undefined ? variables : <JSONTree src={jsonVars} />} @@ -53,7 +53,7 @@ function GraphQLDetailsModal(props: Props) { <div> <div className="flex justify-between items-start mt-6 mb-2"> - <h5 className="mt-1 mr-1">{'Response'}</h5> + <h5 className="mt-1 mr-1 font-medium">{'Response'}</h5> </div> <div className={dataClass}> {jsonResponse === undefined ? response : <JSONTree src={jsonResponse} />} diff --git a/frontend/app/components/shared/GuidePopup/GuidePopup.tsx b/frontend/app/components/shared/GuidePopup/GuidePopup.tsx index 4f6e4907c..52739144d 100644 --- a/frontend/app/components/shared/GuidePopup/GuidePopup.tsx +++ b/frontend/app/components/shared/GuidePopup/GuidePopup.tsx @@ -1,37 +1,74 @@ -import React from 'react'; -import { Tooltip } from 'react-tippy'; +import React, { useEffect, useState } from 'react'; +import { Controls as Player } from 'Player'; +import { Tooltip } from 'UI'; +import { INDEXES } from 'App/constants/zindex'; export const FEATURE_KEYS = { - XRAY: 'featureViewed' -} + XRAY: 'featureViewed', + NOTES: 'notesFeatureViewed', +}; interface IProps { - children: React.ReactNode - title: React.ReactNode - description: React.ReactNode - key?: keyof typeof FEATURE_KEYS + children?: React.ReactNode; + title: React.ReactNode; + description: React.ReactNode; + key?: keyof typeof FEATURE_KEYS; } export default function GuidePopup({ children, title, description }: IProps) { - return ( - // @ts-ignore - <Tooltip - html={ - <div> - <div className="font-bold"> - {title} + const [showGuide, setShowGuide] = useState(!localStorage.getItem(FEATURE_KEYS.NOTES)); + useEffect(() => { + if (!showGuide) { + return; + } + Player.pause(); + }, []); + + const onClick = () => { + setShowGuide(false); + localStorage.setItem(FEATURE_KEYS.NOTES, 'true'); + Player.togglePlay() + }; + + return showGuide ? ( + <div> + <div + onClick={onClick} + className="bg-gray-darkest fixed inset-0 z-10 w-full h-screen cursor-pointer" + style={{ zIndex: INDEXES.POPUP_GUIDE_BG, opacity: '0.7' }} + ></div> + <Tooltip + offset={20} + className="!bg-white rounded text-center shadow !p-6" + title={ + <div className="relative"> + <div className="font-bold text-figmaColors-text-primary">{title}</div> + <div className="color-gray-dark w-80">{description}</div> + <div className="w-4 h-4 bg-white rotate-45 absolute right-0 left-0 m-auto" style={{ top: '-28px'}} /> </div> - <div className="color-gray-medium"> - {description} + } + open={true} + > + <div className="relative pointer-events-none"> + <div className="" style={{ zIndex: INDEXES.POPUP_GUIDE_BTN, position: 'inherit' }}> + {children} </div> + <div + className="absolute bg-white top-0 left-0" + style={{ + zIndex: INDEXES.POPUP_GUIDE_BG, + width: '120px', + height: '40px', + borderRadius: '30px', + margin: '-2px -10px', + }} + ></div> </div> - } - distance={30} - theme={'light'} - open={true} - arrow={true} - > + </Tooltip> + </div> + ) : ( + <> {children} - </Tooltip> + </> ); } diff --git a/frontend/app/components/shared/LiveSearchBar/LiveSearchBar.tsx b/frontend/app/components/shared/LiveSearchBar/LiveSearchBar.tsx index 186524020..269c932bf 100644 --- a/frontend/app/components/shared/LiveSearchBar/LiveSearchBar.tsx +++ b/frontend/app/components/shared/LiveSearchBar/LiveSearchBar.tsx @@ -1,36 +1,39 @@ import React from 'react'; import LiveSessionSearchField from 'Shared/LiveSessionSearchField'; -import { Button, Popup } from 'UI'; +import { Button, Tooltip } from 'UI'; import { clearSearch } from 'Duck/liveSearch'; import { connect } from 'react-redux'; interface Props { - clearSearch: () => void; - appliedFilter: any; + clearSearch: () => void; + appliedFilter: any; } const LiveSearchBar = (props: Props) => { const { appliedFilter } = props; const hasFilters = appliedFilter && appliedFilter.filters && appliedFilter.filters.size > 0; return ( <div className="flex items-center"> - <div style={{ width: "60%", marginRight: "10px"}}> - <LiveSessionSearchField /> - </div> - <div className="flex items-center" style={{ width: "40%"}}> - <Popup content={'Clear Steps'} > - <Button - variant="text-primary" - disabled={!hasFilters} - className="ml-auto font-medium" - onClick={() => props.clearSearch()} - > - Clear - </Button> - </Popup> - </div> + <div style={{ width: '60%', marginRight: '10px' }}> + <LiveSessionSearchField /> + </div> + <div className="flex items-center" style={{ width: '40%' }}> + <Tooltip title={'Clear Steps'}> + <Button + variant="text-primary" + disabled={!hasFilters} + className="ml-auto font-medium" + onClick={() => props.clearSearch()} + > + Clear + </Button> + </Tooltip> + </div> </div> - ) -} -export default connect(state => ({ + ); +}; +export default connect( + (state) => ({ appliedFilter: state.getIn(['liveSearch', 'instance']), -}), { clearSearch })(LiveSearchBar); \ No newline at end of file + }), + { clearSearch } +)(LiveSearchBar); diff --git a/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx b/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx index 97ffb4000..c4d0d7f78 100644 --- a/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx +++ b/frontend/app/components/shared/LiveSessionList/LiveSessionList.tsx @@ -20,175 +20,188 @@ const AUTOREFRESH_INTERVAL = 0.5 * 60 * 1000; const PER_PAGE = 10; interface Props { - loading: boolean; - metaListLoading: boolean; - list: List<any>; - // fetchLiveList: () => Promise<void>, - applyFilter: (filter: any) => void; - filter: any; - // addAttribute: (obj: any) => void, - addFilterByKeyAndValue: (key: FilterKey, value: string) => void; - updateCurrentPage: (page: number) => void; - currentPage: number; - totla: number; - metaList: any; - sort: any; - total: number; + loading: boolean; + metaListLoading: boolean; + list: List<any>; + // fetchLiveList: () => Promise<void>, + applyFilter: (filter: any) => void; + filter: any; + // addAttribute: (obj: any) => void, + addFilterByKeyAndValue: (key: FilterKey, value: string) => void; + updateCurrentPage: (page: number) => void; + currentPage: number; + totla: number; + metaList: any; + sort: any; + total: number; } function LiveSessionList(props: Props) { - const { loading, metaListLoading, filter, list, currentPage, total, metaList = [], sort } = props; - var timeoutId: any; - const { filters } = filter; - const hasUserFilter = filters.map((i: any) => i.key).includes(KEYS.USERID); - const sortOptions = [{ label: 'Newest', value: 'timestamp' }].concat( - metaList - .map((i: any) => ({ - label: capitalize(i), - value: i, - })) - .toJS() - ); + const { loading, metaListLoading, filter, list, currentPage, total, metaList = [], sort } = props; + var timeoutId: any; + const { filters } = filter; + const hasUserFilter = filters.map((i: any) => i.key).includes(KEYS.USERID); + const sortOptions = [{ label: 'Newest', value: 'timestamp' }].concat( + metaList + .map((i: any) => ({ + label: capitalize(i), + value: i, + })) + .toJS() + ); - useEffect(() => { - if (metaListLoading) return; - const _filter = { ...filter }; - if (sortOptions[1] && !filter.sort) { - _filter.sort = sortOptions[1].value; - } - props.applyFilter(_filter); - timeout(); - return () => { - clearTimeout(timeoutId); - }; - }, [metaListLoading]); - - const onUserClick = (userId: string, userAnonymousId: string) => { - if (userId) { - props.addFilterByKeyAndValue(FilterKey.USERID, userId); - } else { - props.addFilterByKeyAndValue(FilterKey.USERANONYMOUSID, userAnonymousId); - } + useEffect(() => { + if (metaListLoading) return; + const _filter = { ...filter }; + if (sortOptions[1] && !filter.sort) { + _filter.sort = sortOptions[1].value; + } + props.applyFilter(_filter); + timeout(); + return () => { + clearTimeout(timeoutId); }; + }, [metaListLoading]); - const onSortChange = ({ value }: any) => { - props.applyFilter({ sort: value.value }); - }; + const onUserClick = (userId: string, userAnonymousId: string) => { + if (userId) { + props.addFilterByKeyAndValue(FilterKey.USERID, userId); + } else { + props.addFilterByKeyAndValue(FilterKey.USERANONYMOUSID, userAnonymousId); + } + }; - const timeout = () => { - timeoutId = setTimeout(() => { - props.applyFilter({ ...filter }); - timeout(); - }, AUTOREFRESH_INTERVAL); - }; + const onSortChange = ({ value }: any) => { + props.applyFilter({ sort: value.value }); + }; - return ( - <div> - <div className="bg-white p-3 rounded border"> - <div className="flex mb-6 justify-between items-center"> - <div className="flex items-baseline"> - <h3 className="text-2xl capitalize mr-4"> - <span>Live Sessions</span> - {/* <span className="ml-2 font-normal color-gray-medium">{numberWithCommas(total)}</span> */} - </h3> + const timeout = () => { + timeoutId = setTimeout(() => { + props.applyFilter({ ...filter }); + timeout(); + }, AUTOREFRESH_INTERVAL); + }; - <LiveSessionReloadButton onClick={() => props.applyFilter({ ...filter })} /> - </div> - <div className="flex items-center"> - <div className="flex items-center ml-6"> - <span className="mr-2 color-gray-medium">Sort By</span> - <div className={cn('flex items-center', { disabled: sortOptions.length === 0 })}> - <Select - plain - right - options={sortOptions} - onChange={onSortChange} - value={sortOptions.find((i: any) => i.value === filter.sort) || sortOptions[0]} - /> - <div className="mx-2" /> - <SortOrderButton onChange={(state: any) => props.applyFilter({ order: state })} sortOrder={filter.order} /> - </div> - </div> - </div> - </div> - <Loader loading={loading}> - <NoContent - title={ - <div className="flex items-center justify-center flex-col"> - <AnimatedSVG name={ICONS.NO_LIVE_SESSIONS} size={170} /> - <div className="mt-2" /> - <div className="text-center text-gray-600">No live sessions found.</div> - </div> - } - subtext={ - <div className="text-center flex justify-center items-center flex-col"> - <span> - Assist allows you to support your users through live screen viewing and audio/video calls.{' '} - <a target="_blank" className="link" href="https://docs.openreplay.com/plugins/assist"> - {'Learn More'} - </a> - </span> + return ( + <div> + <div className="bg-white p-3 rounded border"> + <div className="flex mb-6 justify-between items-center"> + <div className="flex items-center"> + <h3 className="text-2xl capitalize mr-4"> + <span>Live Sessions</span> + {/* <span className="ml-2 font-normal color-gray-medium">{numberWithCommas(total)}</span> */} + </h3> - <Button variant="text-primary" className="mt-4" icon="sync-alt" onClick={() => props.applyFilter({ ...filter })}> - Refresh - </Button> - </div> - } - // image={<img src="/assets/img/live-sessions.png" style={{ width: '70%', marginBottom: '30px' }} />} - show={!loading && list.size === 0} - > - <div> - {list.map((session) => ( - <> - <SessionItem - key={session.sessionId} - session={session} - live - hasUserFilter={hasUserFilter} - onUserClick={onUserClick} - metaList={metaList} - /> - <div className="border-b" /> - </> - ))} - </div> - <div className={cn("flex items-center justify-between p-5", { disabled: loading })}> - <div> - Showing <span className="font-medium">{(currentPage - 1) * PER_PAGE + 1}</span> to{' '} - <span className="font-medium">{(currentPage - 1) * PER_PAGE + list.size}</span> of{' '} - <span className="font-medium">{numberWithCommas(total)}</span> sessions. - </div> - <Pagination - page={currentPage} - totalPages={Math.ceil(total / PER_PAGE)} - onPageChange={(page: any) => props.updateCurrentPage(page)} - limit={PER_PAGE} - debounceRequest={500} - /> - </div> - </NoContent> - </Loader> + <LiveSessionReloadButton onClick={() => props.applyFilter({ ...filter })} /> + </div> + <div className="flex items-center"> + <div className="flex items-center ml-6"> + <span className="mr-2 color-gray-medium">Sort By</span> + <div className={cn('flex items-center', { disabled: sortOptions.length === 0 })}> + <Select + plain + right + options={sortOptions} + onChange={onSortChange} + value={sortOptions.find((i: any) => i.value === filter.sort) || sortOptions[0]} + /> + <div className="mx-2" /> + <SortOrderButton + onChange={(state: any) => props.applyFilter({ order: state })} + sortOrder={filter.order} + /> + </div> </div> + </div> </div> - ); + <Loader loading={loading}> + <NoContent + title={ + <div className="flex items-center justify-center flex-col"> + <AnimatedSVG name={ICONS.NO_LIVE_SESSIONS} size={170} /> + <div className="mt-2" /> + <div className="text-center text-gray-600">No live sessions found.</div> + </div> + } + subtext={ + <div className="text-center flex justify-center items-center flex-col"> + <span> + Assist allows you to support your users through live screen viewing and + audio/video calls.{' '} + <a + target="_blank" + className="link" + href="https://docs.openreplay.com/plugins/assist" + > + {'Learn More'} + </a> + </span> + + <Button + variant="text-primary" + className="mt-4" + icon="arrow-repeat" + iconSize={20} + onClick={() => props.applyFilter({ ...filter })} + > + Refresh + </Button> + </div> + } + // image={<img src="/assets/img/live-sessions.png" style={{ width: '70%', marginBottom: '30px' }} />} + show={!loading && list.size === 0} + > + <div> + {list.map((session) => ( + <React.Fragment key={session.sessionId}> + <SessionItem + session={session} + live + hasUserFilter={hasUserFilter} + onUserClick={onUserClick} + metaList={metaList} + /> + <div className="border-b" /> + </React.Fragment> + ))} + </div> + <div className={cn('flex items-center justify-between p-5', { disabled: loading })}> + <div> + Showing <span className="font-medium">{(currentPage - 1) * PER_PAGE + 1}</span> to{' '} + <span className="font-medium">{(currentPage - 1) * PER_PAGE + list.size}</span> of{' '} + <span className="font-medium">{numberWithCommas(total)}</span> sessions. + </div> + <Pagination + page={currentPage} + totalPages={Math.ceil(total / PER_PAGE)} + onPageChange={(page: any) => props.updateCurrentPage(page)} + limit={PER_PAGE} + debounceRequest={500} + /> + </div> + </NoContent> + </Loader> + </div> + </div> + ); } export default withPermissions(['ASSIST_LIVE'])( - connect( - (state: any) => ({ - list: state.getIn(['liveSearch', 'list']), - loading: state.getIn(['liveSearch', 'fetchList', 'loading']), - metaListLoading: state.getIn(['customFields', 'fetchRequest', 'loading']), - filter: state.getIn(['liveSearch', 'instance']), - total: state.getIn(['liveSearch', 'total']), - currentPage: state.getIn(['liveSearch', 'currentPage']), - metaList: state.getIn(['customFields', 'list']).map((i: any) => i.key), - sort: state.getIn(['liveSearch', 'sort']), - }), - { - applyFilter, - addFilterByKeyAndValue, - updateCurrentPage, - } - )(LiveSessionList) + connect( + (state: any) => ({ + list: state.getIn(['liveSearch', 'list']), + loading: state.getIn(['liveSearch', 'fetchList', 'loading']), + metaListLoading: state.getIn(['customFields', 'fetchRequest', 'loading']), + filter: state.getIn(['liveSearch', 'instance']), + total: state.getIn(['liveSearch', 'total']), + currentPage: state.getIn(['liveSearch', 'currentPage']), + metaList: state.getIn(['customFields', 'list']).map((i: any) => i.key), + sort: state.getIn(['liveSearch', 'sort']), + }), + { + applyFilter, + addFilterByKeyAndValue, + updateCurrentPage, + } + )(LiveSessionList) ); diff --git a/frontend/app/components/shared/ReloadButton/ReloadButton.tsx b/frontend/app/components/shared/ReloadButton/ReloadButton.tsx index 3e7cf90a6..1eba6c115 100644 --- a/frontend/app/components/shared/ReloadButton/ReloadButton.tsx +++ b/frontend/app/components/shared/ReloadButton/ReloadButton.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { CircularLoader, Icon, Popup } from 'UI'; +import { CircularLoader, Icon, Tooltip } from 'UI'; import cn from 'classnames'; interface Props { @@ -10,15 +10,13 @@ interface Props { className?: string; } export default function ReloadButton(props: Props) { - const { loading, onClick, iconSize = '14', iconName = 'sync-alt', className = '' } = props; + const { loading, onClick, iconSize = '20', iconName = 'arrow-repeat', className = '' } = props; return ( - <Popup content="Refresh"> - <div - className={cn('h-5 w-6 flex items-center justify-center', className)} - onClick={onClick} - > + <Tooltip title="Refresh"> + <div className={cn('h-5 w-6 flex items-center justify-center', className)} onClick={onClick}> + {/* @ts-ignore */} {loading ? <CircularLoader className="ml-1" /> : <Icon name={iconName} size={iconSize} />} </div> - </Popup> + </Tooltip> ); } diff --git a/frontend/app/components/shared/SavedSearch/components/SavedSearchModal/SavedSearchModal.tsx b/frontend/app/components/shared/SavedSearch/components/SavedSearchModal/SavedSearchModal.tsx index ac67f4158..02fdd236e 100644 --- a/frontend/app/components/shared/SavedSearch/components/SavedSearchModal/SavedSearchModal.tsx +++ b/frontend/app/components/shared/SavedSearch/components/SavedSearchModal/SavedSearchModal.tsx @@ -2,7 +2,7 @@ import React, { MouseEvent, useState } from 'react'; import cn from 'classnames'; import { Icon, Input } from 'UI'; import { List } from 'immutable'; -import { confirm, Popup } from 'UI'; +import { confirm, Tooltip } from 'UI'; import { applySavedSearch, remove, editSavedSearch } from 'Duck/search'; import { connect } from 'react-redux'; import { useModal } from 'App/components/Modal'; @@ -18,9 +18,10 @@ interface ITooltipIcon { function TooltipIcon(props: ITooltipIcon) { return ( <div onClick={(e) => props.onClick(e)}> - <Popup content={props.title} hideOnClick={true}> + <Tooltip title={props.title}> + {/* @ts-ignore */} <Icon size="16" name={props.name} color="main" /> - </Popup> + </Tooltip> </div> ); } diff --git a/frontend/app/components/shared/Select/Select.tsx b/frontend/app/components/shared/Select/Select.tsx index 3ef9383ca..3a6928e7c 100644 --- a/frontend/app/components/shared/Select/Select.tsx +++ b/frontend/app/components/shared/Select/Select.tsx @@ -6,23 +6,24 @@ const { ValueContainer } = components; type ValueObject = { value: string | number, - label: string, + label: React.ReactNode, } interface Props<Value extends ValueObject> { options: Value[]; isSearchable?: boolean; - defaultValue?: string; + defaultValue?: string | number; plain?: boolean; components?: any; - styles?: any; + styles?: Record<string, any>; + controlStyle?: Record<string, any>; onChange: (newValue: { name: string, value: Value }) => void; name?: string; placeholder?: string; [x:string]: any; } -export default function<Value extends ValueObject>({ placeholder='Select', name = '', onChange, right = false, plain = false, options, isSearchable = false, components = {}, styles = {}, defaultValue = '', ...rest }: Props<Value>) { +export default function<Value extends ValueObject>({ placeholder='Select', name = '', onChange, right = false, plain = false, options, isSearchable = false, components = {}, styles = {}, defaultValue = '', controlStyle = {}, ...rest }: Props<Value>) { const defaultSelected = defaultValue ? (options.find(o => o.value === defaultValue) || options[0]): null; const customStyles = { option: (provided: any, state: any) => ({ @@ -71,7 +72,8 @@ export default function<Value extends ValueObject>({ placeholder='Select', name ['&:hover']: { backgroundColor: colors['gray-lightest'], transition: 'all 0.2s ease-in-out' - } + }, + ...controlStyle, } if (plain) { obj['backgroundColor'] = 'transparent'; @@ -103,7 +105,7 @@ export default function<Value extends ValueObject>({ placeholder='Select', name singleValue: (provided: any, state: { isDisabled: any; }) => { const opacity = state.isDisabled ? 0.5 : 1; const transition = 'opacity 300ms'; - + return { ...provided, opacity, transition, fontWeight: '500' }; }, input: (provided: any) => ({ @@ -160,13 +162,13 @@ const DropdownIndicator = ( const CustomValueContainer = ({ children, ...rest }: any) => { const selectedCount = rest.getValue().length const conditional = (selectedCount < 3) - + let firstChild: any = [] - + if (!conditional) { firstChild = [children[0].shift(), children[1]] } - + return ( <ValueContainer {...rest}> {conditional ? children : firstChild} diff --git a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx index 7eaabc252..e7d8c8831 100644 --- a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx +++ b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx @@ -40,6 +40,7 @@ function SelectDateRange(props: Props) { const isCustomRange = period.rangeName === CUSTOM_RANGE; const customRange = isCustomRange ? period.rangeFormatted() : ''; + return ( <div className="relative"> <Select @@ -63,7 +64,7 @@ function SelectDateRange(props: Props) { {isCustom && ( <OutsideClickDetectingDiv onClickOutside={(e: any) => { - if (e.target.parentElement.parentElement.classList.contains('rc-time-picker-panel-select')) { + if (e.target.parentElement.parentElement.classList.contains('rc-time-picker-panel-select') || e.target.parentElement.parentElement.classList[0].includes('-menu')) { return false; } setIsCustom(false); diff --git a/frontend/app/components/shared/SessionItem/MetaMoreButton/MetaMoreButton.tsx b/frontend/app/components/shared/SessionItem/MetaMoreButton/MetaMoreButton.tsx index 0b6450f86..9253b2de9 100644 --- a/frontend/app/components/shared/SessionItem/MetaMoreButton/MetaMoreButton.tsx +++ b/frontend/app/components/shared/SessionItem/MetaMoreButton/MetaMoreButton.tsx @@ -1,32 +1,30 @@ -import React from 'react' -import { Popup } from 'UI' -import MetaItem from '../MetaItem' +import React from 'react'; +import { Popover, Button } from 'UI'; +import MetaItem from '../MetaItem'; interface Props { - list: any[], - maxLength: number, + list: any[]; + maxLength: number; } export default function MetaMoreButton(props: Props) { - const { list, maxLength } = props - return ( - <Popup - className="p-0" - theme="light" - content={ - <div className="text-sm grid grid-col p-4 gap-3" style={{ maxHeight: '200px', overflowY: 'auto'}}> - {list.slice(maxLength).map(({ label, value }, index) => ( - <MetaItem key={index} label={label} value={value} /> - ))} - </div> - } - on="click" - position="center center" + const { list, maxLength } = props; + return ( + <Popover + render={() => ( + <div + className="text-sm grid grid-col p-4 gap-3 bg-white" + style={{ maxHeight: '200px', overflowY: 'auto' }} > - <div className=" flex items-center"> - <span className="rounded bg-active-blue color-teal p-2 color-gray-dark cursor-pointer whitespace-nowrap"> - +{list.length - maxLength} More - </span> - </div> - </Popup> - ) + {list.slice(maxLength).map(({ label, value }, index) => ( + <MetaItem key={index} label={label} value={value} /> + ))} + </div> + )} + placement="bottom" + > + <div className="flex items-center"> + <Button variant="text-primary">+{list.length - maxLength} More</Button> + </div> + </Popover> + ); } diff --git a/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx b/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx index a063641ec..805240dd8 100644 --- a/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx +++ b/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx @@ -15,7 +15,8 @@ interface Props { viewed: boolean; sessionId: string; onClick?: () => void; - queryParams: any; + queryParams?: any; + newTab?: boolean; } export default function PlayLink(props: Props) { const { isAssist, viewed, sessionId, onClick = null, queryParams } = props; @@ -35,6 +36,7 @@ export default function PlayLink(props: Props) { to={isAssist ? liveSessionRoute(sessionId, queryParams) : sessionRoute(sessionId)} onMouseEnter={() => toggleHover(true)} onMouseLeave={() => toggleHover(false)} + target={props.newTab ? "_blank" : undefined} rel={props.newTab ? "noopener noreferrer" : undefined} > <Icon name={iconName} size={38} color={isAssist ? 'tealx' : 'teal'} /> </Link> diff --git a/frontend/app/components/shared/SessionItem/SessionItem.tsx b/frontend/app/components/shared/SessionItem/SessionItem.tsx index 7b66a6bd9..0288461fa 100644 --- a/frontend/app/components/shared/SessionItem/SessionItem.tsx +++ b/frontend/app/components/shared/SessionItem/SessionItem.tsx @@ -1,6 +1,6 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import cn from 'classnames'; -import { CountryFlag, Avatar, TextEllipsis, Label, Icon } from 'UI'; +import { CountryFlag, Avatar, TextEllipsis, Label, Icon, Tooltip } from 'UI'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; import { durationFormatted, formatTimeOrDate } from 'App/date'; @@ -12,7 +12,6 @@ import PlayLink from './PlayLink'; import ErrorBars from './ErrorBars'; import { assist as assistRoute, liveSession, sessions as sessionsRoute, isRoute } from 'App/routes'; import { capitalize } from 'App/utils'; -import { Tooltip } from 'react-tippy'; const ASSIST_ROUTE = assistRoute(); const ASSIST_LIVE_SESSION = liveSession(); @@ -132,8 +131,8 @@ function SessionItem(props: RouteComponentProps & Props) { )} <div style={{ width: compact ? '40%' : '20%' }} className="px-2 flex flex-col justify-between"> <div> - {/* @ts-ignore */} <Tooltip + delay={0} title={`${formatTimeOrDate(startedAt, timezone, true)} ${timezone.label}`} className="w-fit !block" > diff --git a/frontend/app/components/shared/SessionItem/SessionMetaList/SessionMetaList.tsx b/frontend/app/components/shared/SessionItem/SessionMetaList/SessionMetaList.tsx index 599eac3e2..236dde8ea 100644 --- a/frontend/app/components/shared/SessionItem/SessionMetaList/SessionMetaList.tsx +++ b/frontend/app/components/shared/SessionItem/SessionMetaList/SessionMetaList.tsx @@ -1,27 +1,25 @@ -import React from 'react' -import { Popup } from 'UI' -import cn from 'classnames' +import React from 'react'; +import { Popup } from 'UI'; +import cn from 'classnames'; import MetaItem from '../MetaItem'; import MetaMoreButton from '../MetaMoreButton'; interface Props { - className?: string, - metaList: any[], - maxLength?: number, + className?: string; + metaList: any[]; + maxLength?: number; } export default function SessionMetaList(props: Props) { - const { className = '', metaList, maxLength = 4 } = props + const { className = '', metaList, maxLength = 4 } = props; return ( - <div className={cn("text-sm flex items-center", className)}> + <div className={cn('text-sm flex items-center', className)}> {metaList.slice(0, maxLength).map(({ label, value }, index) => ( - <MetaItem key={index} label={label} value={''+value} className="mr-3" /> + <MetaItem key={index} label={label} value={'' + value} className="mr-3" /> ))} - {metaList.length > maxLength && ( - <MetaMoreButton list={metaList} maxLength={maxLength} /> - )} + {metaList.length > maxLength && <MetaMoreButton list={metaList} maxLength={maxLength} />} </div> - ) + ); } diff --git a/frontend/app/components/shared/SessionListContainer/SessionListContainer.tsx b/frontend/app/components/shared/SessionListContainer/SessionListContainer.tsx index 0b8bc35c6..6a863e69b 100644 --- a/frontend/app/components/shared/SessionListContainer/SessionListContainer.tsx +++ b/frontend/app/components/shared/SessionListContainer/SessionListContainer.tsx @@ -1,15 +1,39 @@ import React from 'react'; import SessionList from './components/SessionList'; import SessionHeader from './components/SessionHeader'; +import NotesList from './components/Notes/NoteList'; +import { connect } from 'react-redux'; +import { fetchList as fetchMembers } from 'Duck/member'; +import LatestSessionsMessage from './components/LatestSessionsMessage'; -function SessionListContainer() { - return ( - <div className="widget-wrapper"> - <SessionHeader /> - <div className="border-b" /> - <SessionList /> - </div> - ); +function SessionListContainer({ + activeTab, + fetchMembers, + members, +}: { + activeTab: string; + fetchMembers: () => void; + members: object[]; +}) { + React.useEffect(() => { + fetchMembers(); + }, []); + return ( + <div className="widget-wrapper"> + <SessionHeader /> + <div className="border-b" /> + <LatestSessionsMessage /> + {activeTab !== 'notes' ? <SessionList /> : <NotesList members={members} />} + </div> + ); } -export default SessionListContainer; +export default connect( + (state) => ({ + // @ts-ignore + activeTab: state.getIn(['search', 'activeTab', 'type']), + // @ts-ignore + members: state.getIn(['members', 'list']), + }), + { fetchMembers } +)(SessionListContainer); diff --git a/frontend/app/components/shared/SessionListContainer/components/LatestSessionsMessage/LatestSessionsMessage.tsx b/frontend/app/components/shared/SessionListContainer/components/LatestSessionsMessage/LatestSessionsMessage.tsx new file mode 100644 index 000000000..39ed264bf --- /dev/null +++ b/frontend/app/components/shared/SessionListContainer/components/LatestSessionsMessage/LatestSessionsMessage.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { updateCurrentPage } from 'Duck/search'; +import { numberWithCommas } from 'App/utils' + +interface Props { + latestSessions: any; + updateCurrentPage: (page: number) => void; +} +function LatestSessionsMessage(props: Props) { + const { latestSessions = [] } = props; + const count = latestSessions.length; + return count > 0 ? ( + <div + className="bg-amber-50 p-1 flex w-full border-b text-center justify-center link" + style={{ backgroundColor: 'rgb(255 251 235)' }} + onClick={() => props.updateCurrentPage(1)} + > + Show {numberWithCommas(count)} New {count > 1 ? 'Sessions' : 'Session'} + </div> + ) : ( + <></> + ); +} + +export default connect( + (state: any) => ({ + latestSessions: state.getIn(['search', 'latestList']), + }), + { updateCurrentPage } +)(LatestSessionsMessage); diff --git a/frontend/app/components/shared/SessionListContainer/components/LatestSessionsMessage/index.ts b/frontend/app/components/shared/SessionListContainer/components/LatestSessionsMessage/index.ts new file mode 100644 index 000000000..8142abba2 --- /dev/null +++ b/frontend/app/components/shared/SessionListContainer/components/LatestSessionsMessage/index.ts @@ -0,0 +1 @@ +export { default } from './LatestSessionsMessage'; diff --git a/frontend/app/components/shared/SessionListContainer/components/Notes/NoteItem.tsx b/frontend/app/components/shared/SessionListContainer/components/Notes/NoteItem.tsx new file mode 100644 index 000000000..d445e926c --- /dev/null +++ b/frontend/app/components/shared/SessionListContainer/components/Notes/NoteItem.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import { Icon, Link } from 'UI'; +import PlayLink from 'Shared/SessionItem/PlayLink'; +import { tagProps, Note } from 'App/services/NotesService'; +import { formatTimeOrDate } from 'App/date'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; +import { ItemMenu } from 'UI'; +import copy from 'copy-to-clipboard'; +import { toast } from 'react-toastify'; +import { session } from 'App/routes'; +import TeamBadge from './TeamBadge'; + +interface Props { + note: Note; + userEmail: string; +} + +function NoteItem(props: Props) { + const { settingsStore, notesStore } = useStore(); + const { timezone } = settingsStore.sessionSettings; + + const onCopy = () => { + copy( + `${window.location.origin}/${window.location.pathname.split('/')[1]}${session( + props.note.sessionId + )}${props.note.timestamp > 0 ? `?jumpto=${props.note.timestamp}¬e=${props.note.noteId}` : `?note=${props.note.noteId}`}` + ); + toast.success('Note URL copied to clipboard'); + }; + const onDelete = () => { + notesStore.deleteNote(props.note.noteId).then((r) => { + notesStore.fetchNotes(); + toast.success('Note deleted'); + }); + }; + const menuItems = [ + { icon: 'link-45deg', text: 'Copy Note URL', onClick: onCopy }, + { icon: 'trash', text: 'Delete', onClick: onDelete }, + ]; + + const safeStrMessage = + props.note.message.length > 150 ? props.note.message.slice(0, 150) + '...' : props.note.message; + return ( + <div className="flex items-center p-2 border-b"> + <Link + style={{ width: '90%' }} + to={ + session(props.note.sessionId) + + (props.note.timestamp > 0 + ? `?jumpto=${props.note.timestamp}¬e=${props.note.noteId}` + : `?note=${props.note.noteId}`) + } + > + <div className="flex flex-col gap-1 p-2 rounded cursor-pointer note-hover"> + <div className="py-1 capitalize-first text-lg">{safeStrMessage}</div> + <div className="flex items-center gap-2"> + {props.note.tag ? ( + <div + style={{ + // @ts-ignore + background: tagProps[props.note.tag], + padding: '1px 6px', + }} + className="rounded-full text-white text-xs select-none w-fit" + > + {props.note.tag} + </div> + ) : null} + <div className="text-disabled-text flex items-center text-sm"> + <span className="color-gray-darkest mr-1">By </span> + {props.userEmail},{' '} + {formatTimeOrDate(props.note.createdAt as unknown as number, timezone)} + <div className="mx-2" /> + {!props.note.isPublic ? null : <TeamBadge />} + </div> + </div> + </div> + </Link> + <div className="ml-auto"> + <PlayLink isAssist={false} viewed={false} sessionId={props.note.sessionId} /> + </div> + <div className="ml-2 cursor-pointer"> + <ItemMenu bold items={menuItems} /> + </div> + </div> + ); +} + +export default observer(NoteItem); diff --git a/frontend/app/components/shared/SessionListContainer/components/Notes/NoteList.tsx b/frontend/app/components/shared/SessionListContainer/components/Notes/NoteList.tsx new file mode 100644 index 000000000..8b9c056ed --- /dev/null +++ b/frontend/app/components/shared/SessionListContainer/components/Notes/NoteList.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { NoContent, Pagination, Loader, Icon } from 'UI'; +import { sliceListPerPage } from 'App/utils'; +import NoteItem from './NoteItem'; +import { observer } from 'mobx-react-lite'; +import { useStore } from 'App/mstore'; + +function NotesList({ members }: { members: Array<Record<string, any>> }) { + const { notesStore } = useStore(); + + React.useEffect(() => { + notesStore.fetchNotes(); + }, []); + + const list = notesStore.notes; + + return ( + <Loader loading={notesStore.loading}> + <NoContent + show={list.length === 0} + title={ + <div className="flex flex-col items-center justify-center"> + <Icon name="no-dashboard" size={80} color="figmaColors-accent-secondary" /> + <div className="text-center text-gray-600 my-4">No notes yet</div> + </div> + } + > + <div className="border-b rounded bg-white"> + {sliceListPerPage(list, notesStore.page - 1, notesStore.pageSize).map((note) => ( + <React.Fragment key={note.noteId}> + <NoteItem + note={note} + userEmail={members.find((m) => m.id === note.userId)?.email || note.userId} + /> + </React.Fragment> + ))} + </div> + + <div className="w-full flex items-center justify-between py-4 px-6"> + <div className="text-disabled-text"> + Showing{' '} + <span className="font-semibold">{Math.min(list.length, notesStore.pageSize)}</span> out + of <span className="font-semibold">{list.length}</span> notes + </div> + <Pagination + page={notesStore.page} + totalPages={Math.ceil(list.length / notesStore.pageSize)} + onPageChange={(page) => notesStore.changePage(page)} + limit={notesStore.pageSize} + debounceRequest={100} + /> + </div> + </NoContent> + </Loader> + ); +} + +export default observer(NotesList); diff --git a/frontend/app/components/shared/SessionListContainer/components/Notes/NoteTags.tsx b/frontend/app/components/shared/SessionListContainer/components/Notes/NoteTags.tsx new file mode 100644 index 000000000..26e57cc58 --- /dev/null +++ b/frontend/app/components/shared/SessionListContainer/components/Notes/NoteTags.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import Select from 'Shared/Select'; +import { TAGS, iTag } from 'App/services/NotesService'; +import { TagItem } from '../SessionTags'; +import { useStore } from 'App/mstore'; +import { observer } from 'mobx-react-lite'; + +const sortOptionsMap = { + 'createdAt-DESC': 'Newest', + 'createdAt-ASC': 'Oldest', +}; +const sortOptions = Object.entries(sortOptionsMap).map(([value, label]) => ({ value, label })); +const notesOwner = [{ value: '0', label: 'All Notes'},{ value: '1', label: 'My Notes'}] +function NoteTags() { + const { notesStore } = useStore() + + + return ( + <div className="flex items-center"> + <div> + <TagItem + onClick={() => notesStore.toggleTag()} + label="ALL" + isActive={notesStore.activeTags.length === 0} + /> + </div> + {TAGS.map((tag: iTag) => ( + <div key={tag}> + <TagItem + onClick={() => notesStore.toggleTag(tag)} + label={tag} + isActive={notesStore.activeTags.includes(tag)} + /> + </div> + ))} + <div className="ml-2" /> + <Select name="notesOwner" plain right options={notesOwner} onChange={({ value }) => notesStore.toggleShared(value.value === '1')} defaultValue={notesOwner[0].value} /> + <div className="ml-2" /> + <Select name="sortNotes" plain right options={sortOptions} onChange={({ value }) => notesStore.toggleSort(value.value)} defaultValue={sortOptions[0].value} /> + </div> + ); +} + +export default observer(NoteTags); diff --git a/frontend/app/components/shared/SessionListContainer/components/Notes/TeamBadge.tsx b/frontend/app/components/shared/SessionListContainer/components/Notes/TeamBadge.tsx new file mode 100644 index 000000000..3ddab831e --- /dev/null +++ b/frontend/app/components/shared/SessionListContainer/components/Notes/TeamBadge.tsx @@ -0,0 +1,11 @@ +import React from 'react' +import { Icon } from 'UI' + +export default function TeamBadge() { + return ( + <div className="flex items-center ml-2"> + <Icon name="user-friends" className="mr-1" color="gray-darkest" /> + <span className="text-disabled-text text-sm">Team</span> + </div> + ) +} diff --git a/frontend/app/components/shared/SessionListContainer/components/Notes/index.ts b/frontend/app/components/shared/SessionListContainer/components/Notes/index.ts new file mode 100644 index 000000000..0d46fcee2 --- /dev/null +++ b/frontend/app/components/shared/SessionListContainer/components/Notes/index.ts @@ -0,0 +1,2 @@ +export { default } from './NoteList' +export { default as TeamBadge } from './TeamBadge' diff --git a/frontend/app/components/shared/SessionListContainer/components/SessionHeader/SessionHeader.tsx b/frontend/app/components/shared/SessionListContainer/components/SessionHeader/SessionHeader.tsx index e991c8c31..ebf0ad48b 100644 --- a/frontend/app/components/shared/SessionListContainer/components/SessionHeader/SessionHeader.tsx +++ b/frontend/app/components/shared/SessionListContainer/components/SessionHeader/SessionHeader.tsx @@ -4,75 +4,96 @@ import { applyFilter } from 'Duck/search'; import Period from 'Types/app/period'; import SelectDateRange from 'Shared/SelectDateRange'; import SessionTags from '../SessionTags'; +import NoteTags from '../Notes/NoteTags'; import { connect } from 'react-redux'; import SessionSort from '../SessionSort'; import cn from 'classnames'; import { setActiveTab } from 'Duck/search'; import SessionSettingButton from '../SessionSettingButton'; +// @ts-ignore +const Tab = ({ addBorder, onClick, children }) => ( + <div + className={cn('py-3 cursor-pointer border-b', { + 'border-b color-teal border-teal': addBorder, + 'border-transparent': !addBorder, + })} + onClick={onClick} + > + {children} + </div> +); + interface Props { - listCount: number; - filter: any; - isBookmark: any; - isEnterprise: boolean; - applyFilter: (filter: any) => void; - setActiveTab: (tab: any) => void; + listCount: number; + filter: any; + activeTab: string; + isEnterprise: boolean; + applyFilter: (filter: any) => void; + setActiveTab: (tab: any) => void; } function SessionHeader(props: Props) { - const { - filter: { startDate, endDate, rangeValue }, - isBookmark, - isEnterprise, - } = props; + const { + filter: { startDate, endDate, rangeValue }, + activeTab, + isEnterprise, + } = props; - const period = Period({ start: startDate, end: endDate, rangeName: rangeValue }); + const period = Period({ start: startDate, end: endDate, rangeName: rangeValue }); - const onDateChange = (e: any) => { - const dateValues = e.toJSON(); - props.applyFilter(dateValues); - }; + const onDateChange = (e: any) => { + const dateValues = e.toJSON(); + props.applyFilter(dateValues); + }; - return ( - <div className="flex items-center px-4 justify-between"> - <div className="flex items-center justify-between"> - <div className="mr-3 text-lg flex items-center"> - <div - className={cn('py-3 cursor-pointer mr-4', { - 'border-b color-teal border-teal': !isBookmark, - })} - onClick={() => props.setActiveTab({ type: 'all' })} - > - <span className="font-bold">SESSIONS</span> - </div> - <div - className={cn('py-3 cursor-pointer', { - 'border-b color-teal border-teal': isBookmark, - })} - onClick={() => props.setActiveTab({ type: 'bookmark' })} - > - <span className="font-bold">{`${isEnterprise ? 'VAULT' : 'BOOKMARKS'}`}</span> - </div> - </div> - </div> - - {!isBookmark && <div className="flex items-center"> - <SessionTags /> - <div className="mx-4" /> - <SelectDateRange period={period} onChange={onDateChange} right={true} /> - <div className="mx-2" /> - <SessionSort /> - <SessionSettingButton /> - </div>} + return ( + <div className="flex items-center px-4 justify-between"> + <div className="flex items-center justify-between"> + <div className="mr-3 text-base flex items-center gap-4"> + <Tab onClick={() => props.setActiveTab({ type: 'all' })} addBorder={activeTab === 'all'}> + <span className="font-bold">SESSIONS</span> + </Tab> + <Tab + onClick={() => props.setActiveTab({ type: 'bookmark' })} + addBorder={activeTab === 'bookmark'} + > + <span className="font-bold">{`${isEnterprise ? 'VAULT' : 'BOOKMARKS'}`}</span> + </Tab> + <Tab + addBorder={activeTab === 'notes'} + onClick={() => props.setActiveTab({ type: 'notes' })} + > + <span className="font-bold">NOTES</span> + </Tab> </div> - ); + </div> + + {activeTab !== 'notes' && activeTab !== 'bookmark' ? ( + <div className="flex items-center"> + <SessionTags /> + <div className="mx-4" /> + <SelectDateRange period={period} onChange={onDateChange} right={true} /> + <div className="mx-2" /> + <SessionSort /> + <SessionSettingButton /> + </div> + ) : null} + + {activeTab === 'notes' && ( + <div className="flex items-center"> + <NoteTags /> + </div> + )} + </div> + ); } export default connect( - (state: any) => ({ - filter: state.getIn(['search', 'instance']), - listCount: numberWithCommas(state.getIn(['sessions', 'total'])), - isBookmark: state.getIn(['search', 'activeTab', 'type']) === 'bookmark', - isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee', - }), - { applyFilter, setActiveTab } + (state: any) => ({ + filter: state.getIn(['search', 'instance']), + listCount: numberWithCommas(state.getIn(['sessions', 'total'])), + activeTab: state.getIn(['search', 'activeTab', 'type']), + isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee', + }), + { applyFilter, setActiveTab } )(SessionHeader); diff --git a/frontend/app/components/shared/SessionListContainer/components/SessionList/SessionList.tsx b/frontend/app/components/shared/SessionListContainer/components/SessionList/SessionList.tsx index ec4c0cec9..97c02d4ca 100644 --- a/frontend/app/components/shared/SessionListContainer/components/SessionList/SessionList.tsx +++ b/frontend/app/components/shared/SessionListContainer/components/SessionList/SessionList.tsx @@ -1,152 +1,227 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; import { FilterKey } from 'Types/filter/filterType'; import SessionItem from 'Shared/SessionItem'; -import { NoContent, Loader, Pagination, Button } from 'UI'; +import { NoContent, Loader, Pagination, Button, Icon } from 'UI'; import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; -import { fetchSessions, addFilterByKeyAndValue, updateCurrentPage, setScrollPosition } from 'Duck/search'; +import { + fetchSessions, + addFilterByKeyAndValue, + updateCurrentPage, + setScrollPosition, + checkForLatestSessions, +} from 'Duck/search'; import useTimeout from 'App/hooks/useTimeout'; import { numberWithCommas } from 'App/utils'; +import { fetchListActive as fetchMetadata } from 'Duck/customField'; + +enum NoContentType { + Bookmarked, + Vaulted, + ToDate, +} const AUTOREFRESH_INTERVAL = 5 * 60 * 1000; -const PER_PAGE = 10; +let sessionTimeOut: any = null; interface Props { - loading: boolean; - list: any; - currentPage: number; - total: number; - filters: any; - lastPlayedSessionId: string; - metaList: any; - scrollY: number; - addFilterByKeyAndValue: (key: string, value: any, operator?: string) => void; - updateCurrentPage: (page: number) => void; - setScrollPosition: (scrollPosition: number) => void; - fetchSessions: (filters: any, force: boolean) => void; - activeTab: any; - isEnterprise?: boolean; + loading: boolean; + list: any; + currentPage: number; + pageSize: number; + total: number; + filters: any; + lastPlayedSessionId: string; + metaList: any; + scrollY: number; + addFilterByKeyAndValue: (key: string, value: any, operator?: string) => void; + updateCurrentPage: (page: number) => void; + setScrollPosition: (scrollPosition: number) => void; + fetchSessions: (filters: any, force: boolean) => void; + fetchMetadata: () => void; + activeTab: any; + isEnterprise?: boolean; + checkForLatestSessions: () => void; } function SessionList(props: Props) { - const { loading, list, currentPage, total, filters, lastPlayedSessionId, metaList, activeTab, isEnterprise = false } = props; - const _filterKeys = filters.map((i: any) => i.key); - const hasUserFilter = _filterKeys.includes(FilterKey.USERID) || _filterKeys.includes(FilterKey.USERANONYMOUSID); - const isBookmark = activeTab.type === 'bookmark'; - const isVault = isBookmark && isEnterprise; - const NO_CONTENT = React.useMemo(() => { - if (isBookmark && !isEnterprise) { - return { - icon: ICONS.NO_BOOKMARKS, - message: 'No sessions bookmarked.', - }; - } else if (isVault) { - return { - icon: ICONS.NO_SESSIONS_IN_VAULT, - message: 'No sessions found in vault.', - }; - } - return { - icon: ICONS.NO_SESSIONS, - message: 'No relevant sessions found for the selected time period.', - }; - }, [isBookmark, isVault, activeTab]); - - useTimeout(() => { - props.fetchSessions(null, true); - }, AUTOREFRESH_INTERVAL); - - - useEffect(() => { - // handle scroll position - const { scrollY } = props; - window.scrollTo(0, scrollY); - if (total === 0) { - props.fetchSessions(null, true); - } - - return () => { - props.setScrollPosition(window.scrollY); - }; - }, []); - - const onUserClick = (userId: any) => { - if (userId) { - props.addFilterByKeyAndValue(FilterKey.USERID, userId); - } else { - props.addFilterByKeyAndValue(FilterKey.USERID, '', 'isUndefined'); - } + const [noContentType, setNoContentType] = React.useState<NoContentType>(NoContentType.ToDate); + const { + loading, + list, + currentPage, + pageSize, + total, + filters, + lastPlayedSessionId, + metaList, + activeTab, + isEnterprise = false, + } = props; + const _filterKeys = filters.map((i: any) => i.key); + const hasUserFilter = + _filterKeys.includes(FilterKey.USERID) || _filterKeys.includes(FilterKey.USERANONYMOUSID); + const isBookmark = activeTab.type === 'bookmark'; + const isVault = isBookmark && isEnterprise; + const NO_CONTENT = React.useMemo(() => { + if (isBookmark && !isEnterprise) { + setNoContentType(NoContentType.Bookmarked); + return { + icon: ICONS.NO_BOOKMARKS, + message: 'No sessions bookmarked.', + }; + } else if (isVault) { + setNoContentType(NoContentType.Vaulted); + return { + icon: ICONS.NO_SESSIONS_IN_VAULT, + message: 'No sessions found in vault.', + }; + } + setNoContentType(NoContentType.ToDate); + return { + icon: ICONS.NO_SESSIONS, + message: 'No relevant sessions found for the selected time period.', }; + }, [isBookmark, isVault, activeTab]); - return ( - <Loader loading={loading}> - <NoContent - title={ - <div className="flex items-center justify-center flex-col"> - <AnimatedSVG name={NO_CONTENT.icon} size={170} /> - <div className="mt-2" /> - <div className="text-center text-gray-600">{NO_CONTENT.message}</div> - </div> - } - subtext={ - <div className="flex flex-col items-center"> - {(isVault || isBookmark) && ( - <div> - {isVault - ? 'Add a session to your vault from player screen to retain it for ever.' - : 'Bookmark important sessions in player screen and quickly find them here.'} - </div> - )} - <Button variant="text-primary" className="mt-4" icon="sync-alt" onClick={() => props.fetchSessions(null, true)}> - Refresh - </Button> - </div> - } - show={!loading && list.size === 0} - > - {list.map((session: any) => ( - <div key={session.sessionId} className="border-b"> - <SessionItem - session={session} - hasUserFilter={hasUserFilter} - onUserClick={onUserClick} - metaList={metaList} - lastPlayedSessionId={lastPlayedSessionId} - /> - </div> - ))} - </NoContent> + useTimeout(() => { + if (!document.hidden) { + props.checkForLatestSessions(); + } + }, AUTOREFRESH_INTERVAL); - {total > 0 && ( - <div className="flex items-center justify-between p-5"> - <div> - Showing <span className="font-medium">{(currentPage - 1) * PER_PAGE + 1}</span> to{' '} - <span className="font-medium">{(currentPage - 1) * PER_PAGE + list.size}</span> of{' '} - <span className="font-medium">{numberWithCommas(total)}</span> sessions. - </div> - <Pagination - page={currentPage} - totalPages={Math.ceil(total / PER_PAGE)} - onPageChange={(page) => props.updateCurrentPage(page)} - limit={PER_PAGE} - debounceRequest={1000} - /> + useEffect(() => { + // handle scroll position + const { scrollY } = props; + window.scrollTo(0, scrollY); + if (total === 0) { + props.fetchSessions(null, true); + } + props.fetchMetadata(); + + return () => { + props.setScrollPosition(window.scrollY); + }; + }, []); + + const refreshOnActive = () => { + if (document.hidden && !!sessionTimeOut) { + clearTimeout(sessionTimeOut); + return; + } + + sessionTimeOut = setTimeout(function () { + if (!document.hidden) { + props.checkForLatestSessions(); + } + }, 5000); + }; + + useEffect(() => { + document.addEventListener('visibilitychange', refreshOnActive); + return () => { + document.removeEventListener('visibilitychange', refreshOnActive); + }; + }, []); + + const onUserClick = (userId: any) => { + if (userId) { + props.addFilterByKeyAndValue(FilterKey.USERID, userId); + } else { + props.addFilterByKeyAndValue(FilterKey.USERID, '', 'isUndefined'); + } + }; + + return ( + <Loader loading={loading}> + <NoContent + title={ + <div className="flex items-center justify-center flex-col"> + <AnimatedSVG name={NO_CONTENT.icon} size={170} /> + <div className="mt-2" /> + <div className="text-center text-gray-600 relative"> + {NO_CONTENT.message} + {noContentType === NoContentType.ToDate ? ( + <div style={{ position: 'absolute', right: -170, top: -110 }}> + <Icon name="list-arrow" size={130} width={150} /> </div> + ) : null} + </div> + </div> + } + subtext={ + <div className="flex flex-col items-center"> + {(isVault || isBookmark) && ( + <div> + {isVault + ? 'Add a session to your vault from player screen to retain it for ever.' + : 'Bookmark important sessions in player screen and quickly find them here.'} + </div> )} - </Loader> - ); + <Button + variant="text-primary" + className="mt-4" + icon="arrow-repeat" + iconSize={20} + onClick={() => props.fetchSessions(null, true)} + > + Refresh + </Button> + </div> + } + show={!loading && list.size === 0} + > + {list.map((session: any) => ( + <div key={session.sessionId} className="border-b"> + <SessionItem + session={session} + hasUserFilter={hasUserFilter} + onUserClick={onUserClick} + metaList={metaList} + lastPlayedSessionId={lastPlayedSessionId} + /> + </div> + ))} + </NoContent> + + {total > 0 && ( + <div className="flex items-center justify-between p-5"> + <div> + Showing <span className="font-medium">{(currentPage - 1) * pageSize + 1}</span> to{' '} + <span className="font-medium">{(currentPage - 1) * pageSize + list.size}</span> of{' '} + <span className="font-medium">{numberWithCommas(total)}</span> sessions. + </div> + <Pagination + page={currentPage} + totalPages={Math.ceil(total / pageSize)} + onPageChange={(page) => props.updateCurrentPage(page)} + limit={pageSize} + debounceRequest={1000} + /> + </div> + )} + </Loader> + ); } export default connect( - (state: any) => ({ - list: state.getIn(['sessions', 'list']), - filters: state.getIn(['search', 'instance', 'filters']), - lastPlayedSessionId: state.getIn(['sessions', 'lastPlayedSessionId']), - metaList: state.getIn(['customFields', 'list']).map((i: any) => i.key), - loading: state.getIn(['sessions', 'loading']), - currentPage: state.getIn(['search', 'currentPage']) || 1, - total: state.getIn(['sessions', 'total']) || 0, - scrollY: state.getIn(['search', 'scrollY']), - activeTab: state.getIn(['search', 'activeTab']), - isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee', - }), - { updateCurrentPage, addFilterByKeyAndValue, setScrollPosition, fetchSessions } + (state: any) => ({ + list: state.getIn(['sessions', 'list']), + filters: state.getIn(['search', 'instance', 'filters']), + lastPlayedSessionId: state.getIn(['sessions', 'lastPlayedSessionId']), + metaList: state.getIn(['customFields', 'list']).map((i: any) => i.key), + loading: state.getIn(['sessions', 'loading']), + currentPage: state.getIn(['search', 'currentPage']) || 1, + total: state.getIn(['sessions', 'total']) || 0, + scrollY: state.getIn(['search', 'scrollY']), + activeTab: state.getIn(['search', 'activeTab']), + pageSize: state.getIn(['search', 'pageSize']), + isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee', + }), + { + updateCurrentPage, + addFilterByKeyAndValue, + setScrollPosition, + fetchSessions, + fetchMetadata, + checkForLatestSessions, + } )(SessionList); diff --git a/frontend/app/components/shared/SessionListContainer/components/SessionSettingButton/SessionSettingButton.tsx b/frontend/app/components/shared/SessionListContainer/components/SessionSettingButton/SessionSettingButton.tsx index 5d76f8979..428b8f153 100644 --- a/frontend/app/components/shared/SessionListContainer/components/SessionSettingButton/SessionSettingButton.tsx +++ b/frontend/app/components/shared/SessionListContainer/components/SessionSettingButton/SessionSettingButton.tsx @@ -1,8 +1,7 @@ import { useModal } from 'App/components/Modal'; import React from 'react'; import SessionSettings from 'Shared/SessionSettings'; -import { Button } from 'UI'; -import { Tooltip } from 'react-tippy'; +import { Button, Tooltip } from 'UI'; function SessionSettingButton(props: any) { const { showModal } = useModal(); @@ -13,7 +12,6 @@ function SessionSettingButton(props: any) { return ( <div className="cursor-pointer ml-4" onClick={handleClick}> - {/* @ts-ignore */} <Tooltip title="Session Settings"> <Button icon="sliders" variant="text" /> </Tooltip> diff --git a/frontend/app/components/shared/SessionListContainer/components/SessionTags/SessionTags.tsx b/frontend/app/components/shared/SessionListContainer/components/SessionTags/SessionTags.tsx index 22824e6e5..b8eb23d1e 100644 --- a/frontend/app/components/shared/SessionListContainer/components/SessionTags/SessionTags.tsx +++ b/frontend/app/components/shared/SessionListContainer/components/SessionTags/SessionTags.tsx @@ -47,7 +47,7 @@ export default connect( } )(SessionTags); -function TagItem({ isActive, onClick, label, icon = '', disabled = false }: any) { +export function TagItem({ isActive, onClick, label, icon = '', disabled = false }: any) { return ( <div> <button diff --git a/frontend/app/components/shared/SessionListContainer/components/SessionTags/index.ts b/frontend/app/components/shared/SessionListContainer/components/SessionTags/index.ts index 4f5e62f6c..e549909dc 100644 --- a/frontend/app/components/shared/SessionListContainer/components/SessionTags/index.ts +++ b/frontend/app/components/shared/SessionListContainer/components/SessionTags/index.ts @@ -1 +1 @@ -export { default } from './SessionTags'; \ No newline at end of file +export { default, TagItem } from './SessionTags'; diff --git a/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx b/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx index 647ee68bd..f2624b460 100644 --- a/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx +++ b/frontend/app/components/shared/SessionSearchQueryParamHandler/SessionSearchQueryParamHandler.tsx @@ -49,10 +49,12 @@ const SessionSearchQueryParamHandler = React.memo((props: Props) => { } else { const _filters: any = { ...filtersMap }; const _filter = _filters[key]; - _filter.value = valueArr; - _filter.operator = operator; - _filter.source = sourceArr; - props.addFilter(_filter); + if (!!_filter) { + _filter.value = valueArr; + _filter.operator = operator; + _filter.source = sourceArr; + props.addFilter(_filter); + } } } }; diff --git a/frontend/app/components/shared/SessionSettings/components/CaptureRate.tsx b/frontend/app/components/shared/SessionSettings/components/CaptureRate.tsx index b4b847950..563fe65ca 100644 --- a/frontend/app/components/shared/SessionSettings/components/CaptureRate.tsx +++ b/frontend/app/components/shared/SessionSettings/components/CaptureRate.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { Icon, Toggler, Button, Input, Loader, Popup } from 'UI'; +import { Icon, Toggler, Button, Input, Loader, Tooltip } from 'UI'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; import { connect } from 'react-redux'; @@ -43,17 +43,17 @@ function CaptureRate({ isAdmin = false }) { <Loader loading={loading}> <h3 className="text-lg">Capture Rate</h3> <div className="my-1">The percentage of session you want to capture</div> - <Popup content="You don't have permission to change." disabled={isAdmin} delay={0}> + <Tooltip title="You don't have permission to change." disabled={isAdmin} delay={0}> <div className={cn('mt-2 mb-4 mr-1 flex items-center', { disabled: !isAdmin })}> <Toggler checked={captureAll} name="test" onChange={toggleRate} /> <span className="ml-2" style={{ color: captureAll ? '#000000' : '#999' }}> 100% </span> </div> - </Popup> + </Tooltip> {!captureAll && ( <div className="flex items-center"> - <Popup content="You don't have permission to change." disabled={isAdmin} delay={0}> + <Tooltip title="You don't have permission to change." disabled={isAdmin} delay={0}> <div className={cn("relative", { 'disabled' : !isAdmin })}> <Input type="number" @@ -66,7 +66,7 @@ function CaptureRate({ isAdmin = false }) { /> <Icon className="absolute right-0 mr-6 top-0 bottom-0 m-auto" name="percent" color="gray-medium" size="18" /> </div> - </Popup> + </Tooltip> <span className="mx-3">of the sessions</span> <Button disabled={!changed} diff --git a/frontend/app/components/shared/SessionSettings/components/ListingVisibility.tsx b/frontend/app/components/shared/SessionSettings/components/ListingVisibility.tsx index 1151c0eed..c18629490 100644 --- a/frontend/app/components/shared/SessionSettings/components/ListingVisibility.tsx +++ b/frontend/app/components/shared/SessionSettings/components/ListingVisibility.tsx @@ -38,7 +38,7 @@ function ListingVisibility() { <div className="col-span-4"> <Select options={numberOptions} - defaultValue={numberOptions[0].value} + defaultValue={durationSettings.operator || numberOptions[0].value} onChange={({ value }) => { changeSettings({ operator: value.value }) }} diff --git a/frontend/app/components/shared/SharePopup/SessionCopyLink/SessionCopyLink.tsx b/frontend/app/components/shared/SharePopup/SessionCopyLink/SessionCopyLink.tsx index bc8c09830..fccbb6b81 100644 --- a/frontend/app/components/shared/SharePopup/SessionCopyLink/SessionCopyLink.tsx +++ b/frontend/app/components/shared/SharePopup/SessionCopyLink/SessionCopyLink.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { IconButton } from 'UI'; +import { Button, Icon } from 'UI'; import copy from 'copy-to-clipboard'; import { connectPlayer } from 'Player'; @@ -7,12 +7,13 @@ interface Props { content: string; time: any; } + function SessionCopyLink({ content = '', time }: Props) { - const [copied, setCopied] = React.useState(false) + const [copied, setCopied] = React.useState(false); const copyHandler = () => { setCopied(true); - copy(window.location.origin + window.location.pathname + '?jumpto=' + Math.round(time)); + copy(window.location.origin + window.location.pathname + '?jumpto=' + Math.round(time)); setTimeout(() => { setCopied(false); }, 1000); @@ -20,10 +21,25 @@ function SessionCopyLink({ content = '', time }: Props) { return ( <div className="flex justify-between items-center w-full mt-2"> - <IconButton label="Copy URL at current time" primaryText icon="link-45deg" onClick={copyHandler} /> - { copied && <div className="color-gray-medium">Copied</div> } + {/* <IconButton + label="Copy URL at current time" + primaryText + icon="link-45deg" + onClick={copyHandler} + /> */} + <Button variant="text-primary" onClick={copyHandler}> + <> + <Icon name="link-45deg" className="mr-2" color="teal" size="18" /> + <span>Copy URL at current time</span> + </> + </Button> + {copied && <div className="color-gray-medium">Copied</div>} </div> - ) + ); } -export default SessionCopyLink +const SessionCopyLinkCompo = connectPlayer((state: any) => ({ + time: state.time, +}))(SessionCopyLink); + +export default React.memo(SessionCopyLinkCompo); diff --git a/frontend/app/components/shared/SharePopup/SharePopup.js b/frontend/app/components/shared/SharePopup/SharePopup.js index d4c5ecd98..9fef76843 100644 --- a/frontend/app/components/shared/SharePopup/SharePopup.js +++ b/frontend/app/components/shared/SharePopup/SharePopup.js @@ -1,21 +1,15 @@ import React from 'react'; import { connect } from 'react-redux'; import { toast } from 'react-toastify'; -import { connectPlayer } from 'Player'; import withRequest from 'HOCs/withRequest'; -import { Icon, Button } from 'UI'; +import { Icon, Button, Popover } from 'UI'; import styles from './sharePopup.module.css'; import IntegrateSlackButton from '../IntegrateSlackButton/IntegrateSlackButton'; import SessionCopyLink from './SessionCopyLink'; import Select from 'Shared/Select'; -import { Tooltip } from 'react-tippy'; import cn from 'classnames'; -import { fetchList, init } from 'Duck/integrations/slack'; -import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; +import { fetchList } from 'Duck/integrations/slack'; -@connectPlayer((state) => ({ - time: state.time, -})) @connect( (state) => ({ channels: state.getIn(['slack', 'list']), @@ -58,100 +52,84 @@ export default class SharePopup extends React.PureComponent { }; handleSuccess = () => { - this.setState({ isOpen: false, comment: '' }) + this.setState({ isOpen: false, comment: '' }); toast.success('Sent to Slack.'); }; - changeChannel = ({ value }) => this.setState({ channelId: value }); + changeChannel = ({ value }) => this.setState({ channelId: value.value }); onClickHandler = () => { this.setState({ isOpen: true }); }; render() { - const { trigger, loading, channels, showCopyLink = false, time } = this.props; + const { trigger, loading, channels, showCopyLink = false } = this.props; const { comment, channelId, isOpen } = this.state; const options = channels .map(({ webhookId, name }) => ({ value: webhookId, label: name })) .toJS(); - return ( - <Tooltip - open={isOpen} - theme="light" - interactive - position="bottom" - unmountHTMLWhenHide - useContext - arrow - trigger="click" - shown={this.handleOpen} - // beforeHidden={this.handleClose} - html={ - <OutsideClickDetectingDiv - className={cn('relative flex items-center')} - onClickOutside={() => { - this.setState({ isOpen: false }) - }} - > - <div className={styles.wrapper}> - <div className={styles.header}> - <div className={cn(styles.title, 'text-lg')}>Share this session link to Slack</div> - </div> - {options.length === 0 ? ( - <> - <div className={styles.body}> - <IntegrateSlackButton /> - </div> - {showCopyLink && ( - <div className={styles.footer}> - <SessionCopyLink time={time} /> - </div> - )} - </> - ) : ( - <div> - <div className={styles.body}> - <textarea - name="message" - id="message" - cols="30" - rows="4" - resize="none" - onChange={this.editMessage} - value={comment} - placeholder="Add Message (Optional)" - className="p-4" - /> - <div className="flex items-center justify-between"> - <Select - options={options} - defaultValue={channelId} - onChange={this.changeChannel} - className="mr-4" - /> - <div> - <Button onClick={this.share} primary> - <div className="flex items-center"> - <Icon name="integrations/slack-bw" size="18" marginRight="10" /> - {loading ? 'Sending...' : 'Send'} - </div> - </Button> - </div> - </div> - </div> + return ( + <Popover + render={() => ( + <div className={styles.wrapper}> + <div className={styles.header}> + <div className={cn(styles.title, 'text-lg')}>Share this session link to Slack</div> + </div> + {options.length === 0 ? ( + <> + <div className={styles.body}> + <IntegrateSlackButton /> + </div> + {showCopyLink && ( <div className={styles.footer}> - <SessionCopyLink time={time} /> + <SessionCopyLink /> + </div> + )} + </> + ) : ( + <div> + <div className={styles.body}> + <textarea + name="message" + id="message" + cols="30" + rows="4" + resize="none" + onChange={this.editMessage} + value={comment} + placeholder="Add Message (Optional)" + className="p-4" + /> + + <div className="flex items-center justify-between"> + <Select + options={options} + defaultValue={channelId} + onChange={this.changeChannel} + className="mr-4" + /> + <div> + <Button onClick={this.share} variant="primary"> + <div className="flex items-center"> + <Icon name="integrations/slack-bw" size="18" marginRight="10" /> + {loading ? 'Sending...' : 'Send'} + </div> + </Button> + </div> </div> </div> - )} - </div> - </OutsideClickDetectingDiv> - } + <div className={styles.footer}> + <SessionCopyLink /> + </div> + </div> + )} + </div> + )} > - <span onClick={this.onClickHandler}>{trigger}</span> - </Tooltip> + <div className="p-3 w-full">{trigger}</div> + </Popover> ); } } diff --git a/frontend/app/components/shared/SortOrderButton/SortOrderButton.tsx b/frontend/app/components/shared/SortOrderButton/SortOrderButton.tsx index e693864fe..11c897dd9 100644 --- a/frontend/app/components/shared/SortOrderButton/SortOrderButton.tsx +++ b/frontend/app/components/shared/SortOrderButton/SortOrderButton.tsx @@ -1,34 +1,40 @@ -import React from 'react' -import { Icon, Popup } from 'UI' -import cn from 'classnames' +import React from 'react'; +import { Icon, Tooltip } from 'UI'; +import cn from 'classnames'; interface Props { - sortOrder: string, - onChange?: (sortOrder: string) => void, + sortOrder: string; + onChange?: (sortOrder: string) => void; } export default React.memo(function SortOrderButton(props: Props) { - const { sortOrder, onChange = () => null } = props - const isAscending = sortOrder === 'asc' + const { sortOrder, onChange = () => null } = props; + const isAscending = sortOrder === 'asc'; - return ( - <div className="flex items-center border"> - <Popup content={'Ascending'} > - <div - className={cn("p-2 hover:bg-active-blue", { 'cursor-pointer bg-white' : !isAscending, 'bg-active-blue pointer-events-none' : isAscending })} - onClick={() => onChange('asc')} - > - <Icon name="arrow-up" size="14" color={isAscending ? 'teal' : 'gray-medium'} /> - </div> - </Popup> - - <Popup content={'Descending'} > - <div - className={cn("p-2 hover:bg-active-blue border-l", { 'cursor-pointer bg-white' : isAscending, 'bg-active-blue pointer-events-none' : !isAscending })} - onClick={() => onChange('desc')} - > - <Icon name="arrow-down" size="14" color={!isAscending ? 'teal' : 'gray-medium'} /> - </div> - </Popup> + return ( + <div className="flex items-center border"> + <Tooltip title={'Ascending'}> + <div + className={cn('p-2 hover:bg-active-blue', { + 'cursor-pointer bg-white': !isAscending, + 'bg-active-blue pointer-events-none': isAscending, + })} + onClick={() => onChange('asc')} + > + <Icon name="arrow-up" size="14" color={isAscending ? 'teal' : 'gray-medium'} /> </div> - ) -}) + </Tooltip> + + <Tooltip title={'Descending'}> + <div + className={cn('p-2 hover:bg-active-blue border-l', { + 'cursor-pointer bg-white': isAscending, + 'bg-active-blue pointer-events-none': !isAscending, + })} + onClick={() => onChange('desc')} + > + <Icon name="arrow-down" size="14" color={!isAscending ? 'teal' : 'gray-medium'} /> + </div> + </Tooltip> + </div> + ); +}); diff --git a/frontend/app/components/shared/SupportCallout/SupportCallout.tsx b/frontend/app/components/shared/SupportCallout/SupportCallout.tsx index dbcdd5f95..784c10202 100644 --- a/frontend/app/components/shared/SupportCallout/SupportCallout.tsx +++ b/frontend/app/components/shared/SupportCallout/SupportCallout.tsx @@ -1,6 +1,5 @@ import React from 'react'; -// import SlackIcon from '../../../svg/slack-help.svg'; -import { Popup, Icon } from 'UI'; +import { Icon } from 'UI'; import SupportList from './components/SupportList'; function SupportCallout() { @@ -10,11 +9,9 @@ function SupportCallout() { <SupportList /> </div> <div className="fixed z-50 left-0 bottom-0 m-4"> - {/* <Popup content="OpenReplay community" delay={0}> */} <div className="w-12 h-12 cursor-pointer bg-white border rounded-full flex items-center justify-center group-hover:shadow-lg group-hover:!bg-active-blue"> <Icon name="question-lg" size={30} color="teal" /> </div> - {/* </Popup> */} </div> </div> ); diff --git a/frontend/app/components/shared/UserSessionsModal/UserSessionsModal.tsx b/frontend/app/components/shared/UserSessionsModal/UserSessionsModal.tsx index 5a2b6f618..cb5baf47f 100644 --- a/frontend/app/components/shared/UserSessionsModal/UserSessionsModal.tsx +++ b/frontend/app/components/shared/UserSessionsModal/UserSessionsModal.tsx @@ -72,7 +72,7 @@ function UserSessionsModal(props: Props) { <div className="border rounded m-5"> <Loader loading={loading}> {data.sessions.map((session: any) => ( - <div className="border-b last:border-none"> + <div className="border-b last:border-none" key={session.sessionId}> <SessionItem key={session.sessionId} session={session} compact={true} onClick={hideModal} /> </div> ))} diff --git a/frontend/app/components/shared/XRayButton/XRayButton.tsx b/frontend/app/components/shared/XRayButton/XRayButton.tsx index 87aee92e0..58daaa070 100644 --- a/frontend/app/components/shared/XRayButton/XRayButton.tsx +++ b/frontend/app/components/shared/XRayButton/XRayButton.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import stl from './xrayButton.module.css'; import cn from 'classnames'; -import { Popup } from 'UI'; +import { Tooltip } from 'UI'; import GuidePopup, { FEATURE_KEYS } from 'Shared/GuidePopup'; import { Controls as Player } from 'Player'; import { INDEXES } from 'App/constants/zindex'; @@ -12,7 +12,10 @@ interface Props { } function XRayButton(props: Props) { const { isActive } = props; - const [showGuide, setShowGuide] = useState(!localStorage.getItem(FEATURE_KEYS.XRAY)); + // const [showGuide, setShowGuide] = useState(!localStorage.getItem(FEATURE_KEYS.XRAY)); + const showGuide = false; + const setShowGuide = (anyt: any) => anyt; + useEffect(() => { if (!showGuide) { return; @@ -39,10 +42,10 @@ function XRayButton(props: Props) { )} <div className="relative"> {showGuide ? ( - <GuidePopup - title={<>Introducing <span className={stl.text}>X-Ray</span></>} - description={"Get a quick overview on the issues in this session."} - > + // <GuidePopup + // title={<div className="color-gray-dark">Introducing <span className={stl.text}>X-Ray</span></div>} + // description={"Get a quick overview on the issues in this session."} + // > <button className={cn(stl.wrapper, { [stl.default]: !isActive, [stl.active]: isActive })} onClick={onClick} @@ -51,26 +54,26 @@ function XRayButton(props: Props) { <span className="z-1">X-RAY</span> </button> - <div - className="absolute bg-white top-0 left-0 z-0" - style={{ - zIndex: INDEXES.POPUP_GUIDE_BG, - width: '100px', - height: '50px', - borderRadius: '30px', - margin: '-10px -16px', - }} - ></div> - </GuidePopup> + // <div + // className="absolute bg-white top-0 left-0 z-0" + // style={{ + // zIndex: INDEXES.POPUP_GUIDE_BG, + // width: '100px', + // height: '50px', + // borderRadius: '30px', + // margin: '-10px -16px', + // }} + // ></div> + // </GuidePopup> ) : ( - <Popup content="Get a quick overview on the issues in this session." disabled={isActive}> + <Tooltip title="Get a quick overview on the issues in this session." disabled={isActive}> <button className={cn(stl.wrapper, { [stl.default]: !isActive, [stl.active]: isActive })} onClick={onClick} > <span className="z-1">X-RAY</span> </button> - </Popup> + </Tooltip> )} </div> </> diff --git a/frontend/app/components/shared/XRayButton/xrayButton.module.css b/frontend/app/components/shared/XRayButton/xrayButton.module.css index c94b9c2f1..d1c7ae6d9 100644 --- a/frontend/app/components/shared/XRayButton/xrayButton.module.css +++ b/frontend/app/components/shared/XRayButton/xrayButton.module.css @@ -2,7 +2,7 @@ text-align: center; padding: 4px 14px; border: none; - border-radius: 6px; + border-radius: 3px; font-weight: 500; &.default { diff --git a/frontend/app/components/ui/Avatar/Avatar.js b/frontend/app/components/ui/Avatar/Avatar.js index 71327fafa..52f4e910e 100644 --- a/frontend/app/components/ui/Avatar/Avatar.js +++ b/frontend/app/components/ui/Avatar/Avatar.js @@ -2,23 +2,39 @@ import React from 'react'; import cn from 'classnames'; import { avatarIconName } from 'App/iconNames'; import stl from './avatar.module.css'; -import { Icon, Popup } from 'UI'; +import { Icon, Tooltip } from 'UI'; -const Avatar = ({ isActive = false, isAssist = false, width = '38px', height = '38px', iconSize = 26, seed }) => { - var iconName = avatarIconName(seed); - return ( - <Popup content={isActive ? 'Active user' : 'User might be inactive'} disabled={!isAssist}> - <div className={cn(stl.wrapper, 'p-2 border flex items-center justify-center rounded-full relative')} style={{ width, height }}> - <Icon name={iconName} size={iconSize} color="tealx" /> - {isAssist && ( - <div - className={cn('w-2 h-2 rounded-full absolute right-0 bottom-0', { 'bg-green': isActive, 'bg-orange': !isActive })} - style={{ marginRight: '3px', marginBottom: '3px' }} - /> - )} - </div> - </Popup> - ); +const Avatar = ({ + isActive = false, + isAssist = false, + width = '38px', + height = '38px', + iconSize = 26, + seed, +}) => { + var iconName = avatarIconName(seed); + return ( + <Tooltip title={isActive ? 'Active user' : 'User might be inactive'} disabled={!isAssist}> + <div + className={cn( + stl.wrapper, + 'p-2 border flex items-center justify-center rounded-full relative' + )} + style={{ width, height }} + > + <Icon name={iconName} size={iconSize} color="tealx" /> + {isAssist && ( + <div + className={cn('w-2 h-2 rounded-full absolute right-0 bottom-0', { + 'bg-green': isActive, + 'bg-orange': !isActive, + })} + style={{ marginRight: '3px', marginBottom: '3px' }} + /> + )} + </div> + </Tooltip> + ); }; export default Avatar; diff --git a/frontend/app/components/ui/BackLink/BackLink.js b/frontend/app/components/ui/BackLink/BackLink.js index b44737233..a150865bb 100644 --- a/frontend/app/components/ui/BackLink/BackLink.js +++ b/frontend/app/components/ui/BackLink/BackLink.js @@ -12,7 +12,7 @@ export default function BackLink ({ { label && <div className="ml-1">{ label }</div> } </div> ); - const verticalClassName = cn(className, cls.backLink, "flex justify-center items-center pr-4 color-gray-dark", { "flex-col": vertical }); + const verticalClassName = cn(className, cls.backLink, "flex justify-center items-center pr-2 color-gray-dark", { "flex-col": vertical }); return to ? <Link className={ verticalClassName } diff --git a/frontend/app/components/ui/Button/Button.tsx b/frontend/app/components/ui/Button/Button.tsx index e7aa306dc..dc73f9e60 100644 --- a/frontend/app/components/ui/Button/Button.tsx +++ b/frontend/app/components/ui/Button/Button.tsx @@ -1,93 +1,104 @@ import React from 'react'; import cn from 'classnames'; -import { CircularLoader, Icon, Popup } from 'UI'; +import { CircularLoader, Icon, Tooltip } from 'UI'; interface Props { - className?: string; - children?: React.ReactNode; - onClick?: () => void; - disabled?: boolean; - type?: 'button' | 'submit' | 'reset'; - variant?: 'default' | 'primary' | 'text' | 'text-primary' | 'text-red' | 'outline' | 'green' - loading?: boolean; - icon?: string; - rounded?: boolean; - tooltip?: any; - [x: string]: any; + className?: string; + children?: React.ReactNode; + onClick?: () => void; + disabled?: boolean; + type?: 'button' | 'submit' | 'reset'; + variant?: 'default' | 'primary' | 'text' | 'text-primary' | 'text-red' | 'outline' | 'green'; + loading?: boolean; + icon?: string; + iconSize?: number; + rounded?: boolean; + tooltip?: any; + [x: string]: any; } export default (props: Props) => { - const { - icon = '', - className = '', - variant = 'default', // 'default|primary|text|text-primary|text-red|outline', - type = 'button', - size = '', - disabled = false, - children, - loading = false, - rounded = false, - tooltip = null, - ...rest - } = props; + const { + icon = '', + iconSize = 18, + className = '', + variant = 'default', // 'default|primary|text|text-primary|text-red|outline', + type = 'button', + size = '', + disabled = false, + children, + loading = false, + rounded = false, + tooltip = null, + ...rest + } = props; - let classes = ['relative flex items-center h-10 px-3 rounded tracking-wide whitespace-nowrap']; - let iconColor = variant === 'text' || variant === 'default' ? 'gray-dark' : 'teal'; + let classes = ['relative flex items-center h-10 px-3 rounded tracking-wide whitespace-nowrap']; + let iconColor = variant === 'text' || variant === 'default' ? 'gray-dark' : 'teal'; - if (variant === 'default') { - classes.push('bg-white hover:bg-gray-light border border-gray-light'); - } + if (variant === 'default') { + classes.push('bg-white hover:bg-gray-light border border-gray-light'); + } - if (variant === 'primary') { - classes.push('bg-teal color-white hover:bg-teal-dark'); - } + if (variant === 'primary') { + classes.push('bg-teal color-white hover:bg-teal-dark'); + } - if (variant === 'green') { - classes.push('bg-green color-white hover:bg-green-dark'); - iconColor = 'white'; - } + if (variant === 'green') { + classes.push('bg-green color-white hover:bg-green-dark'); + iconColor = 'white'; + } - if (variant === 'text') { - classes.push('bg-transparent color-gray-dark hover:bg-gray-light hover:color-gray-dark'); - } + if (variant === 'text') { + classes.push('bg-transparent color-gray-dark hover:bg-gray-light-shade'); + } - if (variant === 'text-primary') { - classes.push('bg-transparent color-teal hover:bg-teal-light hover:color-teal-dark'); - } + if (variant === 'text-primary') { + classes.push('bg-transparent color-teal hover:bg-teal-light hover:color-teal-dark'); + } - if (variant === 'text-red') { - classes.push('bg-transparent color-red hover:bg-teal-light'); - } + if (variant === 'text-red') { + classes.push('bg-transparent color-red hover:bg-teal-light'); + } - if (variant === 'outline') { - classes.push('bg-white color-teal border border-teal hover:bg-teal-light'); - } + if (variant === 'outline') { + classes.push('bg-white color-teal border border-teal hover:bg-teal-light'); + } - if (disabled) { - classes.push('opacity-40 pointer-events-none'); - } + if (disabled) { + classes.push('opacity-40 pointer-events-none'); + } - if (variant === 'primary') { - iconColor = 'white'; - } - if (variant === 'text-red') { - iconColor = 'red'; - } + if (variant === 'primary') { + iconColor = 'white'; + } + if (variant === 'text-red') { + iconColor = 'red'; + } - if (rounded) { - classes = classes.map((c) => c.replace('rounded', 'rounded-full h-10 w-10 justify-center')); - } + if (rounded) { + classes = classes.map((c) => c.replace('rounded', 'rounded-full h-10 w-10 justify-center')); + } - const render = () => ( - <button {...rest} type={type} className={cn(classes, className)}> - {icon && <Icon className={cn({ 'mr-2': children })} name={icon} color={iconColor} size="16" />} - {loading && ( - <div className="absolute flex items-center justify-center inset-0 z-1 rounded"> - <CircularLoader /> - </div> - )} - <div className={cn({ 'opacity-0': loading }, 'flex items-center')}>{children}</div> - </button> - ); + const render = () => ( + <button {...rest} type={type} className={cn(classes, className)}> + {icon && ( + // @ts-ignore + <Icon className={cn({ 'mr-2': children })} name={icon} color={iconColor} size={iconSize} /> + )} + {loading && ( + <div className="absolute flex items-center justify-center inset-0 z-1 rounded"> + <CircularLoader /> + </div> + )} + <div className={cn({ 'opacity-0': loading }, 'flex items-center')}>{children}</div> + </button> + ); - return tooltip ? <Popup content={tooltip.title} {...tooltip}>{render()}</Popup> : render(); + return tooltip ? ( + <Tooltip title={tooltip.title} {...tooltip}> + {render()} + </Tooltip> + ) : ( + render() + ); }; diff --git a/frontend/app/components/ui/Checkbox/Checkbox.tsx b/frontend/app/components/ui/Checkbox/Checkbox.tsx index 2b68ccc97..666982b38 100644 --- a/frontend/app/components/ui/Checkbox/Checkbox.tsx +++ b/frontend/app/components/ui/Checkbox/Checkbox.tsx @@ -2,7 +2,7 @@ import React from 'react'; import cn from 'classnames'; interface Props { - classNam?: string; + className?: string; label?: string; [x: string]: any; } @@ -10,7 +10,7 @@ export default (props: Props) => { const { className = '', label = '', ...rest } = props; return ( <label className={cn('flex items-center cursor-pointer', className)}> - <input type="checkbox" {...rest} /> + <input type="checkbox" onChange={() => null} {...rest} /> {label && <span className="ml-2 select-none mb-0">{label}</span>} </label> ); diff --git a/frontend/app/components/ui/ErrorItem/ErrorItem.js b/frontend/app/components/ui/ErrorItem/ErrorItem.tsx similarity index 54% rename from frontend/app/components/ui/ErrorItem/ErrorItem.js rename to frontend/app/components/ui/ErrorItem/ErrorItem.tsx index db6a7e6e8..74ad634d9 100644 --- a/frontend/app/components/ui/ErrorItem/ErrorItem.js +++ b/frontend/app/components/ui/ErrorItem/ErrorItem.tsx @@ -5,34 +5,43 @@ import stl from './errorItem.module.css'; import { Duration } from 'luxon'; import { useModal } from 'App/components/Modal'; import ErrorDetailsModal from 'App/components/Dashboard/components/Errors/ErrorDetailsModal'; +import JumpButton from 'Shared/DevTools/JumpButton'; -function ErrorItem({ error = {}, onJump, inactive, selected }) { +interface Props { + error: any; + onJump: any; + inactive?: Boolean; + selected?: Boolean; +} +function ErrorItem({ error = {}, onJump, inactive, selected }: Props) { const { showModal } = useModal(); const onErrorClick = () => { showModal(<ErrorDetailsModal errorId={error.errorId} />, { right: true }); - } + }; return ( <div - className={cn(stl.wrapper, 'py-2 px-4 flex cursor-pointer', { - [stl.inactive]: inactive, - [stl.selected]: selected, + className={cn(stl.wrapper, 'py-2 px-4 flex cursor-pointer hover:bg-active-blue relative group', { + // [stl.inactive]: inactive, + // [stl.selected]: selected, })} - onClick={onJump} + onClick={onErrorClick} + // onClick={onJump} > - <div className={'self-start pr-4 color-red'}> + {/* <div className={'self-start pr-4 color-red'}> {Duration.fromMillis(error.time).toFormat('mm:ss.SSS')} - </div> - <div className="mr-auto overflow-hidden"> + </div> */} + <div className="overflow-hidden"> <div className="color-red mb-1 cursor-pointer code-font"> {error.name} <span className="color-gray-darkest ml-2">{error.stack0InfoString}</span> </div> - <div className="text-sm color-gray-medium">{error.message}</div> + <div className="text-xs code-font">{error.message}</div> </div> - <div className="self-center"> + {/* <div className="self-center"> <IconButton red onClick={onErrorClick} label="DETAILS" /> - </div> + </div> */} + <JumpButton onClick={onJump} /> </div> ); } diff --git a/frontend/app/components/ui/ErrorItem/index.js b/frontend/app/components/ui/ErrorItem/index.ts similarity index 100% rename from frontend/app/components/ui/ErrorItem/index.js rename to frontend/app/components/ui/ErrorItem/index.ts diff --git a/frontend/app/components/ui/HelpText/HelpText.tsx b/frontend/app/components/ui/HelpText/HelpText.tsx index c8e1862f8..0bfdfdc5e 100644 --- a/frontend/app/components/ui/HelpText/HelpText.tsx +++ b/frontend/app/components/ui/HelpText/HelpText.tsx @@ -1,19 +1,20 @@ - -import React from 'react' -import { Icon, Popup } from 'UI' +import React from 'react'; +import { Icon, Tooltip } from 'UI'; interface Props { - text: string, - className?: string, - position?: string, + text: string; + className?: string; + position?: string; } export default function HelpText(props: Props) { - const { text, className = '', position = 'top center' } = props - return ( - <div> - <Popup content={text} > - <div className={className}><Icon name="question-circle" size={16} /></div> - </Popup> + const { text, className = '', position = 'top center' } = props; + return ( + <div> + <Tooltip title={text}> + <div className={className}> + <Icon name="question-circle" size={16} /> </div> - ) + </Tooltip> + </div> + ); } diff --git a/frontend/app/components/ui/IconButton/IconButton.js b/frontend/app/components/ui/IconButton/IconButton.js index 1b80bf98d..2d24bd1f5 100644 --- a/frontend/app/components/ui/IconButton/IconButton.js +++ b/frontend/app/components/ui/IconButton/IconButton.js @@ -1,79 +1,81 @@ import React from 'react'; import cn from 'classnames'; -import { CircularLoader, Icon, Popup } from 'UI'; +import { CircularLoader, Icon, Tooltip } from 'UI'; import stl from './iconButton.module.css'; -const IconButton = React.forwardRef(({ - icon, - label = false, - active, - onClick, - plain = false, - shadow = false, - red = false, - primary = false, - primaryText = false, - redText = false, - outline = false, - loading = false, - roundedOutline = false, - hideLoader = false, - circle = false, - size = 'default', - marginRight, - buttonSmall, - className = '', - style, - name, - disabled = false, - tooltip = false, - tooltipPosition = 'top center', - compact = false, - ...rest -}, ref) => ( - <Popup - content={tooltip} - position={tooltipPosition} - > - <button - ref={ ref } - name={ name } - className={ cn(stl.button, className, { - [ stl.plain ]: plain, - [ stl.active ]: active, - [ stl.shadow ]: shadow, - [ stl.primary ]: primary, - [ stl.red ]: red, - [ stl.primaryText ]: primaryText, - [ stl.redText ]: redText, - [ stl.outline ]: outline, - [ stl.circle ]: circle, - [ stl.roundedOutline ]: roundedOutline, - [ stl.buttonSmall ]: buttonSmall, - [ stl.small ]: size === 'small', - [ stl.tiny ]: size === 'tiny', - [ stl.marginRight ]: marginRight, - [ stl.compact ]: compact, - [ stl.hasLabel]: !!label - }) } - onClick={ onClick } - disabled={ disabled || loading } +const IconButton = React.forwardRef( + ( + { + icon, + label = false, + active, + onClick, + plain = false, + shadow = false, + red = false, + primary = false, + primaryText = false, + redText = false, + outline = false, + loading = false, + roundedOutline = false, + hideLoader = false, + circle = false, + size = 'default', + marginRight, + buttonSmall, + className = '', + style, + name, + disabled = false, + tooltip = false, + tooltipPosition = 'top center', + compact = false, + ...rest + }, + ref + ) => ( + <Tooltip title={tooltip} position={tooltipPosition}> + <button + ref={ref} + name={name} + className={cn(stl.button, className, { + [stl.plain]: plain, + [stl.active]: active, + [stl.shadow]: shadow, + [stl.primary]: primary, + [stl.red]: red, + [stl.primaryText]: primaryText, + [stl.redText]: redText, + [stl.outline]: outline, + [stl.circle]: circle, + [stl.roundedOutline]: roundedOutline, + [stl.buttonSmall]: buttonSmall, + [stl.small]: size === 'small', + [stl.tiny]: size === 'tiny', + [stl.marginRight]: marginRight, + [stl.compact]: compact, + [stl.hasLabel]: !!label, + })} + onClick={onClick} + disabled={disabled || loading} style={style} - { ...rest } + {...rest} > - { !hideLoader && <CircularLoader loading={ loading } /> } - { icon && + {!hideLoader && <CircularLoader loading={loading} />} + {icon && ( <Icon color="teal" - name={ icon } - data-hidden={ loading } - size={ size === 'tiny' || size === 'small' || buttonSmall ? '14' : '16' } + name={icon} + data-hidden={loading} + size={size === 'tiny' || size === 'small' || buttonSmall ? '14' : '16'} /> - } - { label && <span className={ cn(stl.label, icon || loading ? 'ml-2' : '') }>{ label }</span> } + )} + {label && <span className={cn(stl.label, icon || loading ? 'ml-2' : '')}>{label}</span>} </button> - </Popup> -)); + </Tooltip> + ) +); -IconButton.displayName = "IconButton"; +IconButton.displayName = 'IconButton'; export default IconButton; diff --git a/frontend/app/components/ui/Input/Input.tsx b/frontend/app/components/ui/Input/Input.tsx index 1c36f7a8a..13ee8d0b1 100644 --- a/frontend/app/components/ui/Input/Input.tsx +++ b/frontend/app/components/ui/Input/Input.tsx @@ -9,10 +9,12 @@ interface Props { leadingButton?: React.ReactNode; type?: string; rows?: number; + height?: number; + width?: number; [x: string]: any; } const Input = React.forwardRef((props: Props, ref: any) => { - const { className = '', leadingButton = '', wrapperClassName = '', icon = '', type = 'text', rows = 4, ...rest } = props; + const { height = 36, width = 0, className = '', leadingButton = '', wrapperClassName = '', icon = '', type = 'text', rows = 4, ...rest } = props; return ( <div className={cn({ relative: icon || leadingButton }, wrapperClassName)}> {icon && <Icon name={icon} className="absolute top-0 bottom-0 my-auto ml-4" size="14" />} @@ -29,7 +31,7 @@ const Input = React.forwardRef((props: Props, ref: any) => { <input ref={ref} type={type} - style={{ height: '36px' }} + style={{ height: `${height}px`, width: width? `${width}px` : '' }} className={cn('p-2 border border-gray-light bg-white w-full rounded', className, { 'pl-10': icon })} {...rest} /> diff --git a/frontend/app/components/ui/ItemMenu/ItemMenu.js b/frontend/app/components/ui/ItemMenu/ItemMenu.js deleted file mode 100644 index 442bcac50..000000000 --- a/frontend/app/components/ui/ItemMenu/ItemMenu.js +++ /dev/null @@ -1,81 +0,0 @@ -import React from 'react'; -import { Icon } from 'UI'; -import styles from './itemMenu.module.css'; -import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; -import cn from 'classnames'; - -export default class ItemMenu extends React.PureComponent { - state = { - displayed: false, - }; - - handleEsc = (e) => e.key === 'Escape' && this.closeMenu(); - - componentDidMount() { - document.addEventListener('keydown', this.handleEsc, false); - } - componentWillUnmount() { - document.removeEventListener('keydown', this.handleEsc, false); - } - - onClick = (callback) => (e) => { - e.stopPropagation(); - callback(e); - }; - - toggleMenu = (e) => { - this.setState({ displayed: !this.state.displayed }); - }; - - closeMenu = () => this.setState({ displayed: false }); - - render() { - const { items, label = '', bold } = this.props; - const { displayed } = this.state; - const parentStyles = label ? 'rounded px-2 py-2 hover:bg-gray-light' : ''; - - return ( - <div className={styles.wrapper}> - <OutsideClickDetectingDiv onClickOutside={this.closeMenu}> - <div - onClick={this.toggleMenu} - className={cn('flex items-center cursor-pointer select-none', parentStyles, { 'bg-gray-light': displayed && label })} - > - {label && <span className={cn('mr-1', bold ? 'font-medium color-gray-darkest' : 'color-gray-medium')}>{label}</span>} - <div - ref={(ref) => { - this.menuBtnRef = ref; - }} - className={cn('rounded-full flex items-center justify-center', { 'bg-gray-light': displayed, 'w-10 h-10': !label })} - role="button" - > - <Icon name="ellipsis-v" size="16" /> - </div> - </div> - </OutsideClickDetectingDiv> - <div className={cn(styles.menu, { [styles.menuDim]: !bold })} data-displayed={displayed}> - {items - .filter(({ hidden }) => !hidden) - .map(({ onClick, text, icon, disabled = false, disabledMessage = '' }) => ( - <div - key={text} - onClick={!disabled ? this.onClick(onClick) : () => {}} - className={disabled ? 'cursor-not-allowed' : ''} - role="menuitem" - tabIndex="-1" - > - <div className={cn(styles.menuItem, 'text-neutral-700', { disabled: disabled })}> - {icon && ( - <div className={styles.iconWrapper}> - <Icon name={icon} size="13" color="gray-dark" /> - </div> - )} - <div>{text}</div> - </div> - </div> - ))} - </div> - </div> - ); - } -} diff --git a/frontend/app/components/ui/ItemMenu/ItemMenu.tsx b/frontend/app/components/ui/ItemMenu/ItemMenu.tsx new file mode 100644 index 000000000..e2d85a568 --- /dev/null +++ b/frontend/app/components/ui/ItemMenu/ItemMenu.tsx @@ -0,0 +1,125 @@ +import React from 'react'; +import { Icon, Popover } from 'UI'; +import styles from './itemMenu.module.css'; +import cn from 'classnames'; + +interface Item { + icon?: string; + text: string; + onClick: (args: any) => void; + hidden?: boolean; + disabled?: boolean; +} + +interface Props { + bold?: boolean; + flat?: boolean; + items: Item[]; + label?: React.ReactNode; + onToggle?: (args: any) => void; +} + +export default class ItemMenu extends React.PureComponent<Props> { + menuBtnRef: HTMLDivElement = null; + + state = { + displayed: false, + }; + + handleEsc = (e: KeyboardEvent) => e.key === 'Escape' && this.closeMenu(); + + componentDidMount() { + document.addEventListener('keydown', this.handleEsc, false); + } + componentWillUnmount() { + document.removeEventListener('keydown', this.handleEsc, false); + } + + onClick = (callback: Function) => (e: React.MouseEvent<HTMLDivElement>) => { + e.stopPropagation(); + callback(e); + }; + + toggleMenu = () => { + const shouldDisplay = !this.state.displayed; + this.setState({ displayed: shouldDisplay }); + this.props.onToggle?.(shouldDisplay); + }; + + closeMenu = () => { + this.setState({ displayed: false }); + this.props.onToggle?.(false); + }; + + render() { + const { items, label = '', bold } = this.props; + const { displayed } = this.state; + const parentStyles = label ? 'rounded px-2 py-2 hover:bg-gray-light' : ''; + + return ( + <Popover + render={() => ( + <div + className={cn(styles.menu, { [styles.menuDim]: !bold })} + // style={{ + // top: this.props.flat ? 24 : undefined, + // }} + // data-displayed={displayed} + > + {items + .filter(({ hidden }) => !hidden) + .map(({ onClick, text, icon, disabled = false }) => ( + <div + key={text} + onClick={!disabled ? this.onClick(onClick) : () => {}} + className={disabled ? 'cursor-not-allowed' : ''} + role="menuitem" + > + <div className={cn(styles.menuItem, 'text-neutral-700', { disabled: disabled })}> + {icon && ( + <div className={styles.iconWrapper}> + {/* @ts-ignore */} + <Icon name={icon} size="13" color="gray-dark" /> + </div> + )} + <div>{text}</div> + </div> + </div> + ))} + </div> + )} + > + <div + // onClick={this.toggleMenu} + className={cn( + 'flex items-center cursor-pointer select-none hover rounded-full', + !this.props.flat ? parentStyles : '', + { 'bg-gray-light': !this.props.flat && displayed && label } + )} + > + {label && ( + <span + className={cn('mr-1', bold ? 'font-medium color-gray-darkest' : 'color-gray-medium')} + > + {label} + </span> + )} + {this.props.flat ? null : ( + <div + ref={(ref) => { + this.menuBtnRef = ref; + }} + className={cn('rounded-full flex items-center justify-center', { + 'bg-gray-light': displayed, + 'w-10 h-10': !label, + })} + role="button" + > + <Icon name="ellipsis-v" size="16" /> + </div> + )} + </div> + </Popover> + ); + } +} diff --git a/frontend/app/components/ui/ItemMenu/index.js b/frontend/app/components/ui/ItemMenu/index.ts similarity index 100% rename from frontend/app/components/ui/ItemMenu/index.js rename to frontend/app/components/ui/ItemMenu/index.ts diff --git a/frontend/app/components/ui/ItemMenu/itemMenu.module.css b/frontend/app/components/ui/ItemMenu/itemMenu.module.css index 477ef7ffb..7583e9975 100644 --- a/frontend/app/components/ui/ItemMenu/itemMenu.module.css +++ b/frontend/app/components/ui/ItemMenu/itemMenu.module.css @@ -40,9 +40,9 @@ white-space: nowrap; z-index: 20; - position: absolute; - right: 0px; - top: 37px; + /* position: absolute; */ + /* right: 0px; */ + /* top: 37px; */ min-width: 150px; background-color: $white; border-radius: 3px; diff --git a/frontend/app/components/ui/JSONTree/JSONTree.js b/frontend/app/components/ui/JSONTree/JSONTree.js index dc6ab786c..b94324ebd 100644 --- a/frontend/app/components/ui/JSONTree/JSONTree.js +++ b/frontend/app/components/ui/JSONTree/JSONTree.js @@ -8,7 +8,7 @@ function updateObjectLink(obj) { } export default ({ src, ...props }) => ( - <JSONTree + <JSONTree name={ false } collapsed={ 1 } enableClipboard={ false } @@ -21,4 +21,4 @@ export default ({ src, ...props }) => ( iconStle="triangle" { ...props } /> -); \ No newline at end of file +); diff --git a/frontend/app/components/ui/Pagination/Pagination.tsx b/frontend/app/components/ui/Pagination/Pagination.tsx index 6d131fa96..71c249901 100644 --- a/frontend/app/components/ui/Pagination/Pagination.tsx +++ b/frontend/app/components/ui/Pagination/Pagination.tsx @@ -1,76 +1,64 @@ -//@ts-nocheck -import React from 'react' -import { Icon, Popup } from 'UI' -import cn from 'classnames' +import React from 'react'; +import { Icon, Tooltip } from 'UI'; +import cn from 'classnames'; import { debounce } from 'App/utils'; import { numberWithCommas } from 'App/utils'; interface Props { - page: number - totalPages: number - onPageChange: (page: number) => void - limit?: number - debounceRequest?: number + page: number; + totalPages: number; + onPageChange: (page: number) => void; + limit?: number; + debounceRequest?: number; } export default function Pagination(props: Props) { const { page, totalPages, onPageChange, limit = 5, debounceRequest = 0 } = props; const [currentPage, setCurrentPage] = React.useState(page); - React.useMemo( - () => setCurrentPage(page), - [page], - ); + React.useMemo(() => setCurrentPage(page), [page]); const debounceChange = React.useCallback(debounce(onPageChange, debounceRequest), []); - const changePage = (page: number) => { - if (page > 0 && page <= totalPages) { - setCurrentPage(page); - debounceChange(page); - } + const changePage = (page: number) => { + if (page > 0 && page <= totalPages) { + setCurrentPage(page); + debounceChange(page); } - - const isFirstPage = currentPage === 1; - const isLastPage = currentPage === totalPages; - return ( - <div className="flex items-center"> - <Popup - content="Previous Page" - // hideOnClick={true} - animation="none" - delay={1500} - > - <button - className={cn("py-2 px-3", { "opacity-50 cursor-default": isFirstPage })} - disabled={isFirstPage} - onClick={() => changePage(currentPage - 1)} - > - <Icon name="chevron-left" size="18" color={isFirstPage ? 'gray-medium' : 'teal'} /> - </button> - </Popup> - <span className="mr-2 color-gray-medium">Page</span> - <input - type="number" - className={cn("py-1 px-2 bg-white border border-gray-light rounded w-16", { "opacity-50 cursor-default": totalPages === 1 })} - value={currentPage} - min={1} - max={totalPages ? totalPages : 1} - onChange={(e) => changePage(parseInt(e.target.value))} - /> - <span className="mx-3 color-gray-medium">of</span> - <span >{numberWithCommas(totalPages)}</span> - <Popup - content="Next Page" - // hideOnClick={true} - animation="none" - delay={1500} - > - <button - className={cn("py-2 px-3", { "opacity-50 cursor-default": isLastPage })} - disabled={isLastPage} - onClick={() => changePage(currentPage + 1)} - > - <Icon name="chevron-right" size="18" color={isLastPage ? 'gray-medium' : 'teal'} /> - </button> - </Popup> - </div> - ) + }; + + const isFirstPage = currentPage === 1; + const isLastPage = currentPage === totalPages; + return ( + <div className="flex items-center"> + <Tooltip title="Previous Page"> + <button + className={cn('py-2 px-3', { 'opacity-50 cursor-default': isFirstPage })} + disabled={isFirstPage} + onClick={() => changePage(currentPage - 1)} + > + <Icon name="chevron-left" size="18" color={isFirstPage ? 'gray-medium' : 'teal'} /> + </button> + </Tooltip> + <span className="mr-2 color-gray-medium">Page</span> + <input + type="number" + className={cn('py-1 px-2 bg-white border border-gray-light rounded w-16', { + 'opacity-50 cursor-default': totalPages === 1, + })} + value={currentPage} + min={1} + max={totalPages ? totalPages : 1} + onChange={(e) => changePage(parseInt(e.target.value))} + /> + <span className="mx-3 color-gray-medium">of</span> + <span>{numberWithCommas(totalPages)}</span> + <Tooltip title="Next Page"> + <button + className={cn('py-2 px-3', { 'opacity-50 cursor-default': isLastPage })} + disabled={isLastPage} + onClick={() => changePage(currentPage + 1)} + > + <Icon name="chevron-right" size="18" color={isLastPage ? 'gray-medium' : 'teal'} /> + </button> + </Tooltip> + </div> + ); } diff --git a/frontend/app/components/ui/PopMenu/PopMenu.js b/frontend/app/components/ui/PopMenu/PopMenu.js index a73896ed5..d8fde3f2f 100644 --- a/frontend/app/components/ui/PopMenu/PopMenu.js +++ b/frontend/app/components/ui/PopMenu/PopMenu.js @@ -1,56 +1,43 @@ -import React, { useState, useCallback } from 'react'; +import React, { useState } from 'react'; import cn from 'classnames'; -import { Icon, Popup } from 'UI'; +import { Icon, Tooltip } from 'UI'; import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; import cls from './popMenu.module.css'; export default React.memo(function PopMenu({ items }) { - const [ open, setOpen ] = useState(false); + const [open, setOpen] = useState(false); return ( - <OutsideClickDetectingDiv - className={ cls.wrapper } - onClickOutside={() => setOpen(false)} - > - { open && - <div className={ cls.menuItems } > - { items.map(item => ( + <OutsideClickDetectingDiv className={cls.wrapper} onClickOutside={() => setOpen(false)}> + {open && ( + <div className={cls.menuItems}> + {items.map((item) => ( <button - key={ item.label } - onClick={ (e) => { - item.onClick(e); + key={item.label} + onClick={(e) => { + item.onClick(e); setOpen(false); }} - className={ cn("flex items-center justify-end color-green bg-white uppercase overflow-hidden", cls.menuItemButton) } + className={cn( + 'flex items-center justify-end color-green bg-white uppercase overflow-hidden', + cls.menuItemButton + )} > - <div className={ cls.buttonLabel }>{ item.label }</div> - <Icon - name={ item.icon } - size="18" - className={ cls.icon } - color="teal" - /> + <div className={cls.buttonLabel}>{item.label}</div> + <Icon name={item.icon} size="18" className={cls.icon} color="teal" /> </button> ))} </div> - } - <Popup - content={ `Add Step` } - size="tiny" - inverted - position="top center" - > + )} + <Tooltip title="Add Step"> <button - onClick={ () => setOpen(o => !o) } - className={ cn("bg-teal flex items-center justify-center", cls.addStepButton, {[cls.openMenuBtn] : open }) } + onClick={() => setOpen((o) => !o)} + className={cn('bg-teal flex items-center justify-center', cls.addStepButton, { + [cls.openMenuBtn]: open, + })} > - <Icon - name="plus" - size="18" - className={ cls.plusIcon } - color="white" - /> + <Icon name="plus" size="18" className={cls.plusIcon} color="white" /> </button> - </Popup> + </Tooltip> </OutsideClickDetectingDiv> ); }); diff --git a/frontend/app/components/ui/Popover/Popover.tsx b/frontend/app/components/ui/Popover/Popover.tsx new file mode 100644 index 000000000..1c1e2a67e --- /dev/null +++ b/frontend/app/components/ui/Popover/Popover.tsx @@ -0,0 +1,93 @@ +import React, { cloneElement, useEffect, useMemo, useState } from 'react'; +import { + Placement, + offset, + flip, + shift, + autoUpdate, + useFloating, + useInteractions, + useRole, + useDismiss, + useId, + useClick, + FloatingFocusManager, +} from '@floating-ui/react-dom-interactions'; +import { mergeRefs } from 'react-merge-refs'; +import { INDEXES } from 'App/constants/zindex'; + +interface Props { + render: (data: { close: () => void; labelId: string; descriptionId: string }) => React.ReactNode; + placement?: Placement; + children: JSX.Element; + onOpen?: () => void; +} + +const Popover = ({ children, render, placement, onOpen = () => {} }: Props) => { + const [open, setOpen] = useState(false); + + useEffect(() => { + if (open) { + onOpen(); + } + }, [open]); + + const { x, y, reference, floating, strategy, context } = useFloating({ + open, + onOpenChange: setOpen, + middleware: [offset(5), flip(), shift()], + placement, + whileElementsMounted: autoUpdate, + }); + + const id = useId(); + const labelId = `${id}-label`; + const descriptionId = `${id}-description`; + + const { getReferenceProps, getFloatingProps } = useInteractions([ + useClick(context), + useRole(context), + useDismiss(context), + ]); + + // Preserve the consumer's ref + const ref = useMemo(() => mergeRefs([reference, (children as any).ref]), [reference, children]); + + return ( + <> + {cloneElement(children, getReferenceProps({ ref, ...children.props }))} + {open && ( + <FloatingFocusManager + context={context} + modal={false} + order={['reference', 'content']} + returnFocus={false} + > + <div + ref={floating} + className="rounded border shadow" + style={{ + position: strategy, + top: y ?? 0, + left: x ?? 0, + zIndex: INDEXES.TOOLTIP, + }} + aria-labelledby={labelId} + aria-describedby={descriptionId} + {...getFloatingProps()} + > + {render({ + labelId, + descriptionId, + close: () => { + setOpen(false); + }, + })} + </div> + </FloatingFocusManager> + )} + </> + ); +}; + +export default Popover; diff --git a/frontend/app/components/ui/Popover/index.ts b/frontend/app/components/ui/Popover/index.ts new file mode 100644 index 000000000..44c04deaf --- /dev/null +++ b/frontend/app/components/ui/Popover/index.ts @@ -0,0 +1 @@ +export { default } from './Popover'; diff --git a/frontend/app/components/ui/Popup/Popup.stories.js b/frontend/app/components/ui/Popup/Popup.stories.js deleted file mode 100644 index 022c84731..000000000 --- a/frontend/app/components/ui/Popup/Popup.stories.js +++ /dev/null @@ -1,8 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import Popup from '.'; - -storiesOf('Popup', module) - .add('Pure', () => ( - <Popup /> - )) - diff --git a/frontend/app/components/ui/Popup/Popup.tsx b/frontend/app/components/ui/Popup/Popup.tsx deleted file mode 100644 index 0bf9258af..000000000 --- a/frontend/app/components/ui/Popup/Popup.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react'; -import { Tooltip, Theme, Trigger, Position, Animation } from 'react-tippy'; - -interface Props { - content?: any; - title?: any; - trigger?: Trigger; - position?: Position; - className?: string; - delay?: number; - hideDelay?: number; - disabled?: boolean; - arrow?: boolean; - style?: any; - theme?: Theme; - interactive?: boolean; - children?: any; - animation?: Animation; - // [x:string]: any; -} -export default ({ - position = 'top', - title = '', - className = '', - trigger = 'mouseenter', - delay = 0, - hideDelay = 0, - content = '', - disabled = false, - arrow = false, - theme = 'dark', - style = {}, - interactive = false, - children, - animation = 'fade', -}: // ...props -Props) => ( - // @ts-ignore - <Tooltip - animation={animation} - position={position} - className={className} - trigger={trigger} - html={content || title} - disabled={disabled} - arrow={arrow} - delay={delay} - hideOnClick={true} - hideOnScroll={true} - theme={theme} - style={style} - interactive={interactive} - hideDelay={hideDelay} - > - {children} - </Tooltip> -); diff --git a/frontend/app/components/ui/Popup/index.js b/frontend/app/components/ui/Popup/index.js deleted file mode 100644 index ab5f1602c..000000000 --- a/frontend/app/components/ui/Popup/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Popup'; \ No newline at end of file diff --git a/frontend/app/components/ui/QuestionMarkHint/QuestionMarkHint.js b/frontend/app/components/ui/QuestionMarkHint/QuestionMarkHint.js index 793edf95d..6cc7981b7 100644 --- a/frontend/app/components/ui/QuestionMarkHint/QuestionMarkHint.js +++ b/frontend/app/components/ui/QuestionMarkHint/QuestionMarkHint.js @@ -1,16 +1,11 @@ import React from 'react'; -import cn from "classnames"; -import { Icon, Popup } from 'UI'; +import cn from 'classnames'; +import { Icon, Tooltip } from 'UI'; -export default function QuestionMarkHint({ onHover = false, content, ...props }) { - return ( - <Popup - trigger={ onHover ? 'mouseenter' : 'click'} - content={ content } - interactive - { ...props } - > - <Icon name="question-circle" size="18" className={ cn("cursor-pointer") }/> - </Popup> - ); -} \ No newline at end of file +export default function QuestionMarkHint({ content, ...props }) { + return ( + <Tooltip title={content} {...props}> + <Icon name="question-circle" size="18" className={cn('cursor-pointer')} /> + </Tooltip> + ); +} diff --git a/frontend/app/components/ui/SVG.tsx b/frontend/app/components/ui/SVG.tsx index 23aa27e70..50a451917 100644 --- a/frontend/app/components/ui/SVG.tsx +++ b/frontend/app/components/ui/SVG.tsx @@ -1,7 +1,7 @@ import React from 'react'; -export type IconNames = 'alarm-clock' | 'alarm-plus' | 'all-sessions' | 'analytics' | 'anchor' | 'arrow-alt-square-right' | 'arrow-clockwise' | 'arrow-down' | 'arrow-right-short' | 'arrow-square-left' | 'arrow-square-right' | 'arrow-up' | 'arrows-angle-extend' | 'avatar/icn_bear' | 'avatar/icn_beaver' | 'avatar/icn_bird' | 'avatar/icn_bison' | 'avatar/icn_camel' | 'avatar/icn_chameleon' | 'avatar/icn_deer' | 'avatar/icn_dog' | 'avatar/icn_dolphin' | 'avatar/icn_elephant' | 'avatar/icn_fish' | 'avatar/icn_fox' | 'avatar/icn_gorilla' | 'avatar/icn_hippo' | 'avatar/icn_horse' | 'avatar/icn_hyena' | 'avatar/icn_kangaroo' | 'avatar/icn_lemur' | 'avatar/icn_mammel' | 'avatar/icn_monkey' | 'avatar/icn_moose' | 'avatar/icn_panda' | 'avatar/icn_penguin' | 'avatar/icn_porcupine' | 'avatar/icn_quail' | 'avatar/icn_rabbit' | 'avatar/icn_rhino' | 'avatar/icn_sea_horse' | 'avatar/icn_sheep' | 'avatar/icn_snake' | 'avatar/icn_squirrel' | 'avatar/icn_tapir' | 'avatar/icn_turtle' | 'avatar/icn_vulture' | 'avatar/icn_wild1' | 'avatar/icn_wild_bore' | 'ban' | 'bar-chart-line' | 'bar-pencil' | 'bell-plus' | 'bell' | 'binoculars' | 'book' | 'browser/browser' | 'browser/chrome' | 'browser/edge' | 'browser/electron' | 'browser/facebook' | 'browser/firefox' | 'browser/ie' | 'browser/opera' | 'browser/safari' | 'bullhorn' | 'business-time' | 'calendar-alt' | 'calendar-check' | 'calendar-day' | 'calendar' | 'call' | 'camera-alt' | 'camera-video-off' | 'camera-video' | 'camera' | 'caret-down-fill' | 'caret-left-fill' | 'caret-right-fill' | 'caret-up-fill' | 'chat-dots' | 'chat-right-text' | 'chat-square-quote' | 'check-circle' | 'check' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-fill' | 'circle' | 'clipboard-list-check' | 'clock' | 'close' | 'cloud-fog2-fill' | 'code' | 'cog' | 'cogs' | 'collection' | 'columns-gap-filled' | 'columns-gap' | 'console/error' | 'console/exception' | 'console/info' | 'console/warning' | 'console' | 'controller' | 'cookies' | 'copy' | 'credit-card-front' | 'cubes' | 'dashboard-icn' | 'desktop' | 'device' | 'diagram-3' | 'dizzy' | 'doublecheck' | 'download' | 'drag' | 'edit' | 'ellipsis-v' | 'enter' | 'envelope' | 'errors-icon' | 'event/click' | 'event/clickrage' | 'event/code' | 'event/i-cursor' | 'event/input' | 'event/link' | 'event/location' | 'event/resize' | 'event/view' | 'exclamation-circle' | 'expand-wide' | 'explosion' | 'external-link-alt' | 'eye-slash-fill' | 'eye-slash' | 'eye' | 'fetch' | 'file-code' | 'file-medical-alt' | 'file' | 'filter' | 'filters/arrow-return-right' | 'filters/browser' | 'filters/click' | 'filters/clickrage' | 'filters/code' | 'filters/console' | 'filters/country' | 'filters/cpu-load' | 'filters/custom' | 'filters/device' | 'filters/dom-complete' | 'filters/duration' | 'filters/error' | 'filters/fetch-failed' | 'filters/fetch' | 'filters/file-code' | 'filters/graphql' | 'filters/i-cursor' | 'filters/input' | 'filters/lcpt' | 'filters/link' | 'filters/location' | 'filters/memory-load' | 'filters/metadata' | 'filters/os' | 'filters/perfromance-network-request' | 'filters/platform' | 'filters/referrer' | 'filters/resize' | 'filters/rev-id' | 'filters/state-action' | 'filters/ttfb' | 'filters/user-alt' | 'filters/userid' | 'filters/view' | 'flag-na' | 'fullscreen' | 'funnel/cpu-fill' | 'funnel/cpu' | 'funnel/dizzy' | 'funnel/emoji-angry-fill' | 'funnel/emoji-angry' | 'funnel/emoji-dizzy-fill' | 'funnel/exclamation-circle-fill' | 'funnel/exclamation-circle' | 'funnel/file-earmark-break-fill' | 'funnel/file-earmark-break' | 'funnel/file-earmark-minus-fill' | 'funnel/file-earmark-minus' | 'funnel/file-medical-alt' | 'funnel/file-x' | 'funnel/hdd-fill' | 'funnel/hourglass-top' | 'funnel/image-fill' | 'funnel/image' | 'funnel/microchip' | 'funnel/mouse' | 'funnel/patch-exclamation-fill' | 'funnel/sd-card' | 'funnel-fill' | 'funnel-new' | 'funnel' | 'geo-alt-fill-custom' | 'github' | 'graph-up-arrow' | 'graph-up' | 'grid-3x3' | 'grid-check' | 'grid-horizontal' | 'grip-horizontal' | 'hash' | 'hdd-stack' | 'headset' | 'heart-rate' | 'high-engagement' | 'history' | 'hourglass-start' | 'id-card' | 'image' | 'info-circle-fill' | 'info-circle' | 'info-square' | 'info' | 'inspect' | 'integrations/assist' | 'integrations/bugsnag-text' | 'integrations/bugsnag' | 'integrations/cloudwatch-text' | 'integrations/cloudwatch' | 'integrations/datadog' | 'integrations/elasticsearch-text' | 'integrations/elasticsearch' | 'integrations/github' | 'integrations/graphql' | 'integrations/jira-text' | 'integrations/jira' | 'integrations/mobx' | 'integrations/newrelic-text' | 'integrations/newrelic' | 'integrations/ngrx' | 'integrations/openreplay-text' | 'integrations/openreplay' | 'integrations/redux' | 'integrations/rollbar-text' | 'integrations/rollbar' | 'integrations/segment' | 'integrations/sentry-text' | 'integrations/sentry' | 'integrations/slack-bw' | 'integrations/slack' | 'integrations/stackdriver' | 'integrations/sumologic-text' | 'integrations/sumologic' | 'integrations/vuejs' | 'journal-code' | 'layer-group' | 'lightbulb-on' | 'lightbulb' | 'link-45deg' | 'list-alt' | 'list-ul' | 'list' | 'lock-alt' | 'map-marker-alt' | 'memory' | 'mic-mute' | 'mic' | 'minus' | 'mobile' | 'mouse-alt' | 'next1' | 'no-dashboard' | 'no-metrics-chart' | 'no-metrics' | 'os/android' | 'os/chrome_os' | 'os/fedora' | 'os/ios' | 'os/linux' | 'os/mac_os_x' | 'os/other' | 'os/ubuntu' | 'os/windows' | 'os' | 'pause-fill' | 'pause' | 'pdf-download' | 'pencil-stop' | 'pencil' | 'percent' | 'performance-icon' | 'person-fill' | 'person' | 'pie-chart-fill' | 'pin-fill' | 'play-circle-light' | 'play-circle' | 'play-fill-new' | 'play-fill' | 'play-hover' | 'play' | 'plus-circle' | 'plus' | 'prev1' | 'puzzle-piece' | 'question-circle' | 'question-lg' | 'quote-left' | 'quote-right' | 'redo-back' | 'redo' | 'remote-control' | 'replay-10' | 'resources-icon' | 'safe-fill' | 'safe' | 'sandglass' | 'search' | 'search_notification' | 'server' | 'share-alt' | 'shield-lock' | 'signup' | 'skip-forward-fill' | 'skip-forward' | 'slack' | 'slash-circle' | 'sliders' | 'social/slack' | 'social/trello' | 'spinner' | 'star-solid' | 'star' | 'step-forward' | 'stopwatch' | 'store' | 'sync-alt' | 'table-new' | 'table' | 'tablet-android' | 'tachometer-slow' | 'tachometer-slowest' | 'tags' | 'team-funnel' | 'telephone-fill' | 'telephone' | 'text-paragraph' | 'tools' | 'trash' | 'turtle' | 'user-alt' | 'user-circle' | 'user-friends' | 'users' | 'vendors/graphql' | 'vendors/mobx' | 'vendors/ngrx' | 'vendors/redux' | 'vendors/vuex' | 'web-vitals' | 'wifi' | 'window-alt' | 'window-restore' | 'window-x' | 'window' | 'zoom-in'; +export type IconNames = 'alarm-clock' | 'alarm-plus' | 'all-sessions' | 'analytics' | 'anchor' | 'arrow-alt-square-right' | 'arrow-bar-left' | 'arrow-clockwise' | 'arrow-down-short' | 'arrow-down' | 'arrow-repeat' | 'arrow-right-short' | 'arrow-square-left' | 'arrow-square-right' | 'arrow-up-short' | 'arrow-up' | 'arrows-angle-extend' | 'avatar/icn_bear' | 'avatar/icn_beaver' | 'avatar/icn_bird' | 'avatar/icn_bison' | 'avatar/icn_camel' | 'avatar/icn_chameleon' | 'avatar/icn_deer' | 'avatar/icn_dog' | 'avatar/icn_dolphin' | 'avatar/icn_elephant' | 'avatar/icn_fish' | 'avatar/icn_fox' | 'avatar/icn_gorilla' | 'avatar/icn_hippo' | 'avatar/icn_horse' | 'avatar/icn_hyena' | 'avatar/icn_kangaroo' | 'avatar/icn_lemur' | 'avatar/icn_mammel' | 'avatar/icn_monkey' | 'avatar/icn_moose' | 'avatar/icn_panda' | 'avatar/icn_penguin' | 'avatar/icn_porcupine' | 'avatar/icn_quail' | 'avatar/icn_rabbit' | 'avatar/icn_rhino' | 'avatar/icn_sea_horse' | 'avatar/icn_sheep' | 'avatar/icn_snake' | 'avatar/icn_squirrel' | 'avatar/icn_tapir' | 'avatar/icn_turtle' | 'avatar/icn_vulture' | 'avatar/icn_wild1' | 'avatar/icn_wild_bore' | 'ban' | 'bar-chart-line' | 'bar-pencil' | 'bell-fill' | 'bell-plus' | 'bell-slash' | 'bell' | 'binoculars' | 'book' | 'browser/browser' | 'browser/chrome' | 'browser/edge' | 'browser/electron' | 'browser/facebook' | 'browser/firefox' | 'browser/ie' | 'browser/opera' | 'browser/safari' | 'bullhorn' | 'business-time' | 'calendar-alt' | 'calendar-check' | 'calendar-day' | 'calendar' | 'call' | 'camera-alt' | 'camera-video-off' | 'camera-video' | 'camera' | 'caret-down-fill' | 'caret-left-fill' | 'caret-right-fill' | 'caret-up-fill' | 'chat-dots' | 'chat-right-text' | 'chat-square-quote' | 'check-circle-fill' | 'check-circle' | 'check' | 'chevron-double-left' | 'chevron-double-right' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'circle-fill' | 'circle' | 'clipboard-list-check' | 'clock' | 'close' | 'cloud-fog2-fill' | 'code' | 'cog' | 'cogs' | 'collection' | 'columns-gap-filled' | 'columns-gap' | 'console/error' | 'console/exception' | 'console/info' | 'console/warning' | 'console' | 'controller' | 'cookies' | 'copy' | 'credit-card-front' | 'cubes' | 'dash' | 'dashboard-icn' | 'desktop' | 'device' | 'diagram-3' | 'dizzy' | 'door-closed' | 'doublecheck' | 'download' | 'drag' | 'edit' | 'ellipsis-v' | 'enter' | 'envelope' | 'errors-icon' | 'event/click' | 'event/clickrage' | 'event/code' | 'event/i-cursor' | 'event/input' | 'event/link' | 'event/location' | 'event/resize' | 'event/view' | 'exclamation-circle' | 'expand-wide' | 'explosion' | 'external-link-alt' | 'eye-slash-fill' | 'eye-slash' | 'eye' | 'fetch' | 'file-code' | 'file-medical-alt' | 'file-pdf' | 'file' | 'filter' | 'filters/arrow-return-right' | 'filters/browser' | 'filters/click' | 'filters/clickrage' | 'filters/code' | 'filters/console' | 'filters/country' | 'filters/cpu-load' | 'filters/custom' | 'filters/device' | 'filters/dom-complete' | 'filters/duration' | 'filters/error' | 'filters/fetch-failed' | 'filters/fetch' | 'filters/file-code' | 'filters/graphql' | 'filters/i-cursor' | 'filters/input' | 'filters/lcpt' | 'filters/link' | 'filters/location' | 'filters/memory-load' | 'filters/metadata' | 'filters/os' | 'filters/perfromance-network-request' | 'filters/platform' | 'filters/referrer' | 'filters/resize' | 'filters/rev-id' | 'filters/state-action' | 'filters/ttfb' | 'filters/user-alt' | 'filters/userid' | 'filters/view' | 'flag-na' | 'folder-plus' | 'folder2' | 'fullscreen' | 'funnel/cpu-fill' | 'funnel/cpu' | 'funnel/dizzy' | 'funnel/emoji-angry-fill' | 'funnel/emoji-angry' | 'funnel/emoji-dizzy-fill' | 'funnel/exclamation-circle-fill' | 'funnel/exclamation-circle' | 'funnel/file-earmark-break-fill' | 'funnel/file-earmark-break' | 'funnel/file-earmark-minus-fill' | 'funnel/file-earmark-minus' | 'funnel/file-medical-alt' | 'funnel/file-x' | 'funnel/hdd-fill' | 'funnel/hourglass-top' | 'funnel/image-fill' | 'funnel/image' | 'funnel/microchip' | 'funnel/mouse' | 'funnel/patch-exclamation-fill' | 'funnel/sd-card' | 'funnel-fill' | 'funnel-new' | 'funnel' | 'gear-fill' | 'gear' | 'geo-alt-fill-custom' | 'github' | 'graph-up-arrow' | 'graph-up' | 'grid-3x3' | 'grid-check' | 'grid-horizontal' | 'grip-horizontal' | 'hash' | 'hdd-stack' | 'headset' | 'heart-rate' | 'high-engagement' | 'history' | 'hourglass-start' | 'id-card' | 'image' | 'info-circle-fill' | 'info-circle' | 'info-square' | 'info' | 'inspect' | 'integrations/assist' | 'integrations/bugsnag-text' | 'integrations/bugsnag' | 'integrations/cloudwatch-text' | 'integrations/cloudwatch' | 'integrations/datadog' | 'integrations/elasticsearch-text' | 'integrations/elasticsearch' | 'integrations/github' | 'integrations/graphql' | 'integrations/jira-text' | 'integrations/jira' | 'integrations/mobx' | 'integrations/newrelic-text' | 'integrations/newrelic' | 'integrations/ngrx' | 'integrations/openreplay-text' | 'integrations/openreplay' | 'integrations/redux' | 'integrations/rollbar-text' | 'integrations/rollbar' | 'integrations/segment' | 'integrations/sentry-text' | 'integrations/sentry' | 'integrations/slack-bw' | 'integrations/slack' | 'integrations/stackdriver' | 'integrations/sumologic-text' | 'integrations/sumologic' | 'integrations/vuejs' | 'journal-code' | 'layer-group' | 'lightbulb-on' | 'lightbulb' | 'link-45deg' | 'list-alt' | 'list-arrow' | 'list-ul' | 'list' | 'lock-alt' | 'magic' | 'map-marker-alt' | 'memory' | 'mic-mute' | 'mic' | 'minus' | 'mobile' | 'mouse-alt' | 'network' | 'next1' | 'no-dashboard' | 'no-metrics-chart' | 'no-metrics' | 'os/android' | 'os/chrome_os' | 'os/fedora' | 'os/ios' | 'os/linux' | 'os/mac_os_x' | 'os/other' | 'os/ubuntu' | 'os/windows' | 'os' | 'pause-fill' | 'pause' | 'pdf-download' | 'pencil-stop' | 'pencil' | 'percent' | 'performance-icon' | 'person-fill' | 'person' | 'pie-chart-fill' | 'pin-fill' | 'play-circle-light' | 'play-circle' | 'play-fill-new' | 'play-fill' | 'play-hover' | 'play' | 'plus-circle' | 'plus' | 'prev1' | 'puzzle-piece' | 'puzzle' | 'question-circle' | 'question-lg' | 'quote-left' | 'quote-right' | 'quotes' | 'redo-back' | 'redo' | 'remote-control' | 'replay-10' | 'resources-icon' | 'safe-fill' | 'safe' | 'sandglass' | 'search' | 'search_notification' | 'server' | 'share-alt' | 'shield-lock' | 'signup' | 'skip-forward-fill' | 'skip-forward' | 'slack' | 'slash-circle' | 'sliders' | 'social/slack' | 'social/trello' | 'spinner' | 'star-solid' | 'star' | 'step-forward' | 'stopwatch' | 'store' | 'sync-alt' | 'table-new' | 'table' | 'tablet-android' | 'tachometer-slow' | 'tachometer-slowest' | 'tags' | 'team-funnel' | 'telephone-fill' | 'telephone' | 'text-paragraph' | 'tools' | 'trash' | 'turtle' | 'user-alt' | 'user-circle' | 'user-friends' | 'users' | 'vendors/graphql' | 'vendors/mobx' | 'vendors/ngrx' | 'vendors/redux' | 'vendors/vuex' | 'web-vitals' | 'wifi' | 'window-alt' | 'window-restore' | 'window-x' | 'window' | 'zoom-in'; interface Props { name: IconNames; @@ -21,11 +21,15 @@ const SVG = (props: Props) => { case 'analytics': return <svg viewBox="0 0 576 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M80 352H16c-8.84 0-16 7.16-16 16v128c0 8.84 7.16 16 16 16h64c8.84 0 16-7.16 16-16V368c0-8.84-7.16-16-16-16zM64 480H32v-96h32v96zm496-288h-64c-8.84 0-16 7.16-16 16v288c0 8.84 7.16 16 16 16h64c8.84 0 16-7.16 16-16V208c0-8.84-7.16-16-16-16zm-16 288h-32V224h32v256zM502.77 88.68C510.12 93.24 518.71 96 528 96c26.51 0 48-21.49 48-48S554.51 0 528 0s-48 21.49-48 48c0 5.51 1.12 10.71 2.83 15.64l-89.6 71.68c-7.35-4.57-15.94-7.33-25.23-7.33s-17.88 2.76-25.23 7.33l-89.6-71.68C254.88 58.72 256 53.51 256 48c0-26.51-21.49-48-48-48s-48 21.49-48 48c0 7.4 1.81 14.32 4.8 20.58L68.58 164.8C62.32 161.81 55.4 160 48 160c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-7.4-1.81-14.32-4.8-20.58l96.22-96.22C193.68 94.19 200.6 96 208 96c9.29 0 17.88-2.76 25.23-7.33l89.6 71.68c-1.71 4.93-2.83 10.14-2.83 15.65 0 26.51 21.49 48 48 48s48-21.49 48-48c0-5.51-1.12-10.72-2.83-15.65l89.6-71.67zM528 32c8.82 0 16 7.18 16 16s-7.18 16-16 16-16-7.18-16-16 7.18-16 16-16zM48 224c-8.82 0-16-7.18-16-16s7.18-16 16-16 16 7.18 16 16-7.18 16-16 16zM208 64c-8.82 0-16-7.18-16-16s7.18-16 16-16 16 7.18 16 16-7.18 16-16 16zm160 128c-8.82 0-16-7.18-16-16s7.18-16 16-16 16 7.18 16 16-7.18 16-16 16zm-128 0h-64c-8.84 0-16 7.16-16 16v288c0 8.84 7.16 16 16 16h64c8.84 0 16-7.16 16-16V208c0-8.84-7.16-16-16-16zm-16 288h-32V224h32v256zm176-160h-64c-8.84 0-16 7.16-16 16v160c0 8.84 7.16 16 16 16h64c8.84 0 16-7.16 16-16V336c0-8.84-7.16-16-16-16zm-16 160h-32V352h32v128z"/></svg>; case 'anchor': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M5 2V0H0v5h2v6H0v5h5v-2h6v2h5v-5h-2V5h2V0h-5v2H5zm6 1v2h2v6h-2v2H5v-2H3V5h2V3h6zm1-2h3v3h-3V1zm3 11v3h-3v-3h3zM4 15H1v-3h3v3zM1 4V1h3v3H1z"/></svg>; case 'arrow-alt-square-right': return <svg viewBox="0 0 448 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48H48C21.5 32 0 53.5 0 80zm400-16c8.8 0 16 7.2 16 16v352c0 8.8-7.2 16-16 16H48c-8.8 0-16-7.2-16-16V80c0-8.8 7.2-16 16-16h352zm-208 64v64H88c-13.2 0-24 10.8-24 24v80c0 13.2 10.8 24 24 24h104v64c0 28.4 34.5 42.8 54.6 22.6l128-128c12.5-12.5 12.5-32.8 0-45.3l-128-128c-20.1-20-54.6-5.8-54.6 22.7zm160 128L224 384v-96H96v-64h128v-96l128 128z"/></svg>; + case 'arrow-bar-left': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M12.5 15a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5zM10 8a.5.5 0 0 1-.5.5H3.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L3.707 7.5H9.5a.5.5 0 0 1 .5.5z"/></svg>; case 'arrow-clockwise': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/><path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/></svg>; + case 'arrow-down-short': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 4a.5.5 0 0 1 .5.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5A.5.5 0 0 1 8 4z"/></svg>; case 'arrow-down': return <svg viewBox="0 0 448 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="m443.5 248.5-7.1-7.1c-4.7-4.7-12.3-4.7-17 0L241 419.9V44c0-6.6-5.4-12-12-12h-10c-6.6 0-12 5.4-12 12v375.9L28.5 241.4c-4.7-4.7-12.3-4.7-17 0l-7.1 7.1c-4.7 4.7-4.7 12.3 0 17l211 211.1c4.7 4.7 12.3 4.7 17 0l211-211.1c4.8-4.8 4.8-12.3.1-17z"/></svg>; + case 'arrow-repeat': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41zm-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9z"/><path d="M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5.002 5.002 0 0 0 8 3zM3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9H3.1z"/></svg>; case 'arrow-right-short': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M4 8a.5.5 0 0 1 .5-.5h5.793L8.146 5.354a.5.5 0 1 1 .708-.708l3 3a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708-.708L10.293 8.5H4.5A.5.5 0 0 1 4 8z"/></svg>; case 'arrow-square-left': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M15 2a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V2zM0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2zm11.5 5.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H11.5z"/></svg>; case 'arrow-square-right': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M15 2a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V2zM0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2zm4.5 5.5a.5.5 0 0 0 0 1h5.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5H4.5z"/></svg>; + case 'arrow-up-short': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 12a.5.5 0 0 0 .5-.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 .5.5z"/></svg>; case 'arrow-up': return <svg viewBox="0 0 448 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="m4.465 263.536 7.07 7.071c4.686 4.686 12.284 4.686 16.971 0L207 92.113V468c0 6.627 5.373 12 12 12h10c6.627 0 12-5.373 12-12V92.113l178.494 178.493c4.686 4.686 12.284 4.686 16.971 0l7.07-7.071c4.686-4.686 4.686-12.284 0-16.97l-211.05-211.05c-4.686-4.686-12.284-4.686-16.971 0L4.465 246.566c-4.687 4.686-4.687 12.284 0 16.97z"/></svg>; case 'arrows-angle-extend': return <svg viewBox="0 0 27 27" width={ `${ width }px` } height={ `${ height }px` } ><path clipRule="evenodd" d="M9.804 17.143a.845.845 0 0 0-1.195 0l-6.92 6.92v-4.676a.845.845 0 0 0-1.689 0v6.715a.845.845 0 0 0 .845.845H7.56a.844.844 0 1 0 0-1.69H2.884l6.92-6.92a.845.845 0 0 0 0-1.194Zm7.339-7.34a.845.845 0 0 0 1.194 0l6.92-6.92V7.56a.845.845 0 0 0 1.69 0V.845A.844.844 0 0 0 26.102 0h-6.715a.845.845 0 0 0 0 1.69h4.676l-6.92 6.92a.845.845 0 0 0 0 1.194Z"/></svg>; case 'avatar/icn_bear': return <svg viewBox="0 0 100 100" width={ `${ width }px` } height={ `${ height }px` } ><path d="M89.8 37.7c-.3-1.5-1.4-5.1-4.7-7.4-1-.7-2-1.3-2.9-1.8.1-.4.2-.7.2-1.1 0-2.4-2-4.4-4.6-4.4-2.3 0-4.2 1.6-4.5 3.7h-9.4l-11.7-4.6-11.5 3-5.9-.3c-.6 0-1.2-.1-1.8-.3-3.7-.9-12.9-2.6-20 2.4-4.6 3.3-7.3 8.6-8 16v.2c0 .4.2 8.8 3.4 17.8 2.7 7.4 3.7 12.6 4 13.7v10.6h20.8v-9.4l-4.9-2.1 1-6.7c4 .4 11.8 1 17.8-.4l1.5 5.5v13.1h19.2v-9.5l-5.2-2.5c.2-1.7.4-4.3.8-7.1 1.2-7.9 2.3-9.7 2.5-9.9 2.4-1.6 3-1.5 4.8-1.2 2.4.3 8.9-1.4 12.8-2.6l7.4.1 4-7.2-5.1-7.6z"/></svg>; @@ -67,7 +71,9 @@ const SVG = (props: Props) => { case 'ban': return <svg viewBox="0 0 512 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zM103.265 408.735c-80.622-80.622-84.149-208.957-10.9-293.743l304.644 304.643c-84.804 73.264-213.138 69.706-293.744-10.9zm316.37-11.727L114.992 92.365c84.804-73.263 213.137-69.705 293.743 10.9 80.622 80.621 84.149 208.957 10.9 293.743z"/></svg>; case 'bar-chart-line': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M11 2a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v12h.5a.5.5 0 0 1 0 1H.5a.5.5 0 0 1 0-1H1v-3a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3h1V7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7h1V2zm1 12h2V2h-2v12zm-3 0V7H7v7h2zm-5 0v-3H2v3h2z"/></svg>; case 'bar-pencil': return <svg viewBox="0 0 59 66" width={ `${ width }px` } height={ `${ height }px` } ><g clipPath="url(#a)"><path d="M40.27 15.736a3.59 3.59 0 0 1 3.591-3.59h7.18a3.59 3.59 0 0 1 3.591 3.59V58.82h1.795a1.796 1.796 0 0 1 0 3.59H2.573a1.795 1.795 0 1 1 0-3.59h1.795V48.05a3.59 3.59 0 0 1 3.59-3.59h7.18a3.59 3.59 0 0 1 3.591 3.59v10.77h3.59V33.687a3.59 3.59 0 0 1 3.59-3.59h7.181a3.59 3.59 0 0 1 3.59 3.59V58.82h3.59V15.736Zm3.591 43.083h7.18V15.736h-7.18V58.82Zm-10.77 0V33.687H25.91V58.82h7.18Zm-17.952 0V48.05h-7.18v10.77h7.18Z"/></g><g clipPath="url(#b)"><path d="M28.613.335a1.145 1.145 0 0 1 1.622 0L37.11 7.21a1.146 1.146 0 0 1 0 1.622L14.193 31.749c-.11.109-.24.195-.385.252L2.35 36.584a1.147 1.147 0 0 1-1.49-1.49l4.584-11.458c.057-.144.143-.275.252-.385L28.613.335ZM26.46 5.729l5.254 5.255 2.963-2.963-5.254-5.255-2.963 2.963Zm3.634 6.875L24.84 7.35 9.945 22.245v.672h1.145a1.146 1.146 0 0 1 1.146 1.145v1.146h1.146a1.146 1.146 0 0 1 1.146 1.146V27.5h.671l14.896-14.896ZM7.726 24.464l-.243.242-3.501 8.757 8.756-3.502.243-.243a1.146 1.146 0 0 1-.745-1.072V27.5H11.09a1.146 1.146 0 0 1-1.145-1.146v-1.146H8.799a1.146 1.146 0 0 1-1.073-.744Z"/></g><defs><clipPath id="a"><path fill="#fff" transform="translate(.778 8.556)" d="M0 0h57.444v57.444H0z"/></clipPath><clipPath id="b"><path fill="#fff" transform="translate(.778)" d="M0 0h36.667v36.667H0z"/></clipPath></defs></svg>; + case 'bell-fill': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zm.995-14.901a1 1 0 1 0-1.99 0A5.002 5.002 0 0 0 3 6c0 1.098-.5 6-2 7h14c-1.5-1-2-5.902-2-7 0-2.42-1.72-4.44-4.005-4.901z"/></svg>; case 'bell-plus': return <svg viewBox="0 0 448 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M224 480a32 32 0 0 1-32-32h-32a64 64 0 1 0 128 0h-32a32 32 0 0 1-32 32zm209.37-145.19c-28-26.62-49.34-54.48-49.34-148.9 0-79.6-63.37-144.5-144-152.36V16a16 16 0 0 0-32 0v17.56C127.35 41.41 64 106.31 64 185.91c0 94.4-21.41 122.28-49.35 148.9a46.47 46.47 0 0 0-11.27 51.24A47.68 47.68 0 0 0 48 416h352a47.67 47.67 0 0 0 44.62-30 46.47 46.47 0 0 0-11.25-51.19zM400 384H48c-14.22 0-21.35-16.47-11.32-26C71.54 324.8 96 287.66 96 185.91 96 118.53 153.22 64 224 64s128 54.52 128 121.91c0 101.34 24.22 138.68 59.28 172.07C421.37 367.56 414.16 384 400 384zM296 224h-56v-56a8 8 0 0 0-8-8h-16a8 8 0 0 0-8 8v56h-56a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h56v56a8 8 0 0 0 8 8h16a8 8 0 0 0 8-8v-56h56a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8z"/></svg>; + case 'bell-slash': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M5.164 14H15c-.299-.199-.557-.553-.78-1-.9-1.8-1.22-5.12-1.22-6 0-.264-.02-.523-.06-.776l-.938.938c.02.708.157 2.154.457 3.58.161.767.377 1.566.663 2.258H6.164l-1 1zm5.581-9.91a3.986 3.986 0 0 0-1.948-1.01L8 2.917l-.797.161A4.002 4.002 0 0 0 4 7c0 .628-.134 2.197-.459 3.742-.05.238-.105.479-.166.718l-1.653 1.653c.02-.037.04-.074.059-.113C2.679 11.2 3 7.88 3 7c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0c.942.19 1.788.645 2.457 1.284l-.707.707zM10 15a2 2 0 1 1-4 0h4zm-9.375.625a.53.53 0 0 0 .75.75l14.75-14.75a.53.53 0 0 0-.75-.75L.625 15.625z"/></svg>; case 'bell': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"/></svg>; case 'binoculars': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M3 2.5A1.5 1.5 0 0 1 4.5 1h1A1.5 1.5 0 0 1 7 2.5V5h2V2.5A1.5 1.5 0 0 1 10.5 1h1A1.5 1.5 0 0 1 13 2.5v2.382a.5.5 0 0 0 .276.447l.895.447A1.5 1.5 0 0 1 15 7.118V14.5a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 14.5v-3a.5.5 0 0 1 .146-.354l.854-.853V9.5a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5v.793l.854.853A.5.5 0 0 1 7 11.5v3A1.5 1.5 0 0 1 5.5 16h-3A1.5 1.5 0 0 1 1 14.5V7.118a1.5 1.5 0 0 1 .83-1.342l.894-.447A.5.5 0 0 0 3 4.882V2.5zM4.5 2a.5.5 0 0 0-.5.5V3h2v-.5a.5.5 0 0 0-.5-.5h-1zM6 4H4v.882a1.5 1.5 0 0 1-.83 1.342l-.894.447A.5.5 0 0 0 2 7.118V13h4v-1.293l-.854-.853A.5.5 0 0 1 5 10.5v-1A1.5 1.5 0 0 1 6.5 8h3A1.5 1.5 0 0 1 11 9.5v1a.5.5 0 0 1-.146.354l-.854.853V13h4V7.118a.5.5 0 0 0-.276-.447l-.895-.447A1.5 1.5 0 0 1 12 4.882V4h-2v1.5a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5V4zm4-1h2v-.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5V3zm4 11h-4v.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5V14zm-8 0H2v.5a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5V14z"/></svg>; case 'book': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M5 0h8a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2 2 2 0 0 1-2 2H3a2 2 0 0 1-2-2h1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1H1a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v9a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1H3a2 2 0 0 1 2-2z"/><path d="M1 6v-.5a.5.5 0 0 1 1 0V6h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 3v-.5a.5.5 0 0 1 1 0V9h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1H1zm0 2.5v.5H.5a.5.5 0 0 0 0 1h2a.5.5 0 0 0 0-1H2v-.5a.5.5 0 0 0-1 0z"/></svg>; @@ -94,10 +100,11 @@ const SVG = (props: Props) => { case 'caret-down-fill': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z"/></svg>; case 'caret-left-fill': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="m3.86 8.753 5.482 4.796c.646.566 1.658.106 1.658-.753V3.204a1 1 0 0 0-1.659-.753l-5.48 4.796a1 1 0 0 0 0 1.506z"/></svg>; case 'caret-right-fill': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/></svg>; - case 'caret-up-fill': return <svg viewBox="0 0 320 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M288.662 352H31.338c-17.818 0-26.741-21.543-14.142-34.142l128.662-128.662c7.81-7.81 20.474-7.81 28.284 0l128.662 128.662c12.6 12.599 3.676 34.142-14.142 34.142z"/></svg>; + case 'caret-up-fill': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="m7.247 4.86-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z"/></svg>; case 'chat-dots': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M5 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm4 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/><path d="m2.165 15.803.02-.004c1.83-.363 2.948-.842 3.468-1.105A9.06 9.06 0 0 0 8 15c4.418 0 8-3.134 8-7s-3.582-7-8-7-8 3.134-8 7c0 1.76.743 3.37 1.97 4.6a10.437 10.437 0 0 1-.524 2.318l-.003.011a10.722 10.722 0 0 1-.244.637c-.079.186.074.394.273.362a21.673 21.673 0 0 0 .693-.125zm.8-3.108a1 1 0 0 0-.287-.801C1.618 10.83 1 9.468 1 8c0-3.192 3.004-6 7-6s7 2.808 7 6c0 3.193-3.004 6-7 6a8.06 8.06 0 0 1-2.088-.272 1 1 0 0 0-.711.074c-.387.196-1.24.57-2.634.893a10.97 10.97 0 0 0 .398-2z"/></svg>; case 'chat-right-text': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M2 1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h9.586a2 2 0 0 1 1.414.586l2 2V2a1 1 0 0 0-1-1H2zm12-1a2 2 0 0 1 2 2v12.793a.5.5 0 0 1-.854.353l-2.853-2.853a1 1 0 0 0-.707-.293H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12z"/><path d="M3 3.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zM3 6a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9A.5.5 0 0 1 3 6zm0 2.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5z"/></svg>; case 'chat-square-quote': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M14 1a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1h-2.5a2 2 0 0 0-1.6.8L8 14.333 6.1 11.8a2 2 0 0 0-1.6-.8H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2.5a1 1 0 0 1 .8.4l1.9 2.533a1 1 0 0 0 1.6 0l1.9-2.533a1 1 0 0 1 .8-.4H14a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/><path d="M7.066 4.76A1.665 1.665 0 0 0 4 5.668a1.667 1.667 0 0 0 2.561 1.406c-.131.389-.375.804-.777 1.22a.417.417 0 1 0 .6.58c1.486-1.54 1.293-3.214.682-4.112zm4 0A1.665 1.665 0 0 0 8 5.668a1.667 1.667 0 0 0 2.561 1.406c-.131.389-.375.804-.777 1.22a.417.417 0 1 0 .6.58c1.486-1.54 1.293-3.214.682-4.112z"/></svg>; + case 'check-circle-fill': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/></svg>; case 'check-circle': return <svg viewBox="0 0 512 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 464c-118.664 0-216-96.055-216-216 0-118.663 96.055-216 216-216 118.664 0 216 96.055 216 216 0 118.663-96.055 216-216 216zm141.63-274.961L217.15 376.071c-4.705 4.667-12.303 4.637-16.97-.068l-85.878-86.572c-4.667-4.705-4.637-12.303.068-16.97l8.52-8.451c4.705-4.667 12.303-4.637 16.97.068l68.976 69.533 163.441-162.13c4.705-4.667 12.303-4.637 16.97.068l8.451 8.52c4.668 4.705 4.637 12.303-.068 16.97z"/></svg>; case 'check': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z"/></svg>; case 'chevron-double-left': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8.354 1.646a.5.5 0 0 1 0 .708L2.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/><path d="M12.354 1.646a.5.5 0 0 1 0 .708L6.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/></svg>; @@ -128,11 +135,13 @@ const SVG = (props: Props) => { case 'copy': return <svg viewBox="0 0 448 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="m433.941 65.941-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM352 32.491a15.88 15.88 0 0 1 7.431 4.195l51.882 51.883A15.885 15.885 0 0 1 415.508 96H352V32.491zM288 464c0 8.822-7.178 16-16 16H48c-8.822 0-16-7.178-16-16V144c0-8.822 7.178-16 16-16h80v240c0 26.51 21.49 48 48 48h112v48zm128-96c0 8.822-7.178 16-16 16H176c-8.822 0-16-7.178-16-16V48c0-8.822 7.178-16 16-16h144v72c0 13.2 10.8 24 24 24h72v240z"/></svg>; case 'credit-card-front': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v1h14V4a1 1 0 0 0-1-1H2zm13 4H1v5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V7z"/><path d="M2 10a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1v-1z"/></svg>; case 'cubes': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M13 1a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h10zM3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3H3z"/><path d="M5.5 4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm-8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/></svg>; - case 'dashboard-icn': return <svg viewBox="0 0 276 241" width={ `${ width }px` } height={ `${ height }px` } ><g filter="url(#a)"><rect x="6" y="4" width="264" height="229" rx="6" fill="#fff"/></g><g opacity=".7"><rect x="141" y="14" width="119" height="101" rx="4.244" fill="#000" fill-opacity=".08"/><rect x="141.5" y="14.5" width="118" height="100" rx="3.744" stroke="#000" stroke-opacity=".12"/></g><g opacity=".3"><rect x="16" y="14" width="119" height="101" rx="4.244" fill="#000" fill-opacity=".08"/><rect x="16.5" y="14.5" width="118" height="100" rx="3.744" stroke="#000" stroke-opacity=".12"/></g><g opacity=".46"><rect x="16" y="122" width="244" height="99" rx="4.244" fill="#000" fill-opacity=".08"/><rect x="16.5" y="122.5" width="243" height="98" rx="3.744" stroke="#000" stroke-opacity=".12"/></g><rect opacity=".2" x="149" y="85" width="15" height="20" rx="2" fill="#3EAAAF"/><rect opacity=".4" x="178" y="54" width="15" height="51" rx="2" fill="#3EAAAF"/><rect opacity=".6" x="207" y="62" width="15" height="43" rx="2" fill="#3EAAAF"/><rect opacity=".4" x="236" y="45" width="15" height="60" rx="2" fill="#3EAAAF"/><path opacity=".6" d="M109 62a32.997 32.997 0 0 1-56.334 23.335l9.16-9.162A20.044 20.044 0 0 0 96.045 62H109Z" fill="#3EAAAF"/><path opacity=".2" d="M51.09 83.645a33.002 33.002 0 0 1-6.892-30.457l12.582 3.486a19.945 19.945 0 0 0 4.165 18.408l-9.855 8.563Z" fill="#3EAAAF"/><path opacity=".4" d="M44.652 51.688a33 33 0 0 1 64.32 8.95l-12.948.535a20.04 20.04 0 0 0-39.061-5.435l-12.31-4.05Z" fill="#3EAAAF"/><path d="M150.176 79.433a1 1 0 0 0 1.648 1.134l-1.648-1.134ZM247 29l-11.457 1.437 6.972 9.204L247 29Zm-35.954 23.046-.552.834.552-.834Zm5.777-.185-.604-.797.604.797Zm-36.606-14.317-.823-.567.823.567Zm6.877-1.336-.551.834.551-.834Zm-35.27 44.359 29.217-42.457-1.647-1.133-29.218 42.456 1.648 1.134Zm34.719-43.525 23.951 15.838 1.103-1.668-23.951-15.839-1.103 1.669Zm30.884 15.616 23.003-17.426-1.208-1.594-23.003 17.426 1.208 1.594Zm-6.933.222a6 6 0 0 0 6.933-.222l-1.208-1.594a4 4 0 0 1-4.622.148l-1.103 1.668Zm-29.453-14.77a4 4 0 0 1 5.502-1.068l1.103-1.669a6 6 0 0 0-8.252 1.604l1.647 1.133Z" fill="#3EAAAF"/><rect opacity=".2" x="60" y="102" width="7" height="3" rx="1.5" fill="#3EAAAF"/><rect opacity=".3" x="72" y="102" width="7" height="3" rx="1.5" fill="#3EAAAF"/><rect opacity=".6" x="84" y="102" width="7" height="3" rx="1.5" fill="#3EAAAF"/><path clipRule="evenodd" d="M17 187.928c0-1.01 1.326-1.383 1.853-.522l1.777 2.906c3.63 5.938 11.092 17.813 18.352 19 7.26 1.188 14.721-8.312 21.981-20.187C68.425 177.25 75.685 163 82.945 163c7.462 0 14.722 14.25 21.982 21.375 7.461 7.125 14.721 7.125 21.981 2.375 7.462-4.75 14.722-14.25 22.184-14.25 7.26 0 14.52 9.5 21.981 16.625 7.26 7.125 14.52 11.875 21.982 8.313 7.26-3.563 14.52-15.438 21.982-14.25 7.26 1.187 14.721 15.437 21.981 16.624 7.26 1.188 14.722-10.687 18.352-16.624l1.777-2.907c.527-.861 1.853-.488 1.853.522V217a3 3 0 0 1-3 3H20a3 3 0 0 1-3-3v-29.072Z" fill="url(#b)"/><path d="M258 180.5c-7 11-17.882 29.121-29 14-12.5-17-21.333-11.5-24.5-8-16.5 21.5-30.5 10.5-43-6-10-13.2-19.833-7.833-23.5-3.5-22.5 28-35.5 3.5-48.5-11.5C79 154 67 179 59 194c-8 13.5-21 29.5-41-6.5" stroke="#3EAAAF" stroke-width="2" stroke-linecap="round"/><circle cx="42" cy="206" r="7" fill="#fff" stroke="#3EAAAF" stroke-width="2"/><circle cx="117" cy="187" r="7" fill="#fff" stroke="#3EAAAF" stroke-width="2"/><circle cx="212" cy="183" r="7" fill="#fff" stroke="#3EAAAF" stroke-width="2"/><defs><linearGradient id="b" x1="138" y1="163" x2="138.49" y2="224" gradientUnits="userSpaceOnUse"><stop stop-color="#86C6C9"/><stop offset="1" stop-color="#F6F6F6"/></linearGradient><filter id="a" x="0" y="0" width="276" height="241" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/><feOffset dy="2"/><feGaussianBlur stdDeviation="3"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_59_3139"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_59_3139" result="shape"/></filter></defs></svg>; + case 'dash': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"/></svg>; + case 'dashboard-icn': return <svg viewBox="0 0 276 241" width={ `${ width }px` } height={ `${ height }px` } ><g filter="url(#a)"><rect x="6" y="4" width="264" height="229" rx="6" fill="#fff"/></g><g opacity=".7"><rect x="141" y="14" width="119" height="101" rx="4.244" fill="#000" fillOpacity=".08"/><rect x="141.5" y="14.5" width="118" height="100" rx="3.744" stroke="#000" stroke-opacity=".12"/></g><g opacity=".3"><rect x="16" y="14" width="119" height="101" rx="4.244" fill="#000" fillOpacity=".08"/><rect x="16.5" y="14.5" width="118" height="100" rx="3.744" stroke="#000" stroke-opacity=".12"/></g><g opacity=".46"><rect x="16" y="122" width="244" height="99" rx="4.244" fill="#000" fillOpacity=".08"/><rect x="16.5" y="122.5" width="243" height="98" rx="3.744" stroke="#000" stroke-opacity=".12"/></g><rect opacity=".2" x="149" y="85" width="15" height="20" rx="2" fill="#3EAAAF"/><rect opacity=".4" x="178" y="54" width="15" height="51" rx="2" fill="#3EAAAF"/><rect opacity=".6" x="207" y="62" width="15" height="43" rx="2" fill="#3EAAAF"/><rect opacity=".4" x="236" y="45" width="15" height="60" rx="2" fill="#3EAAAF"/><path opacity=".6" d="M109 62a32.997 32.997 0 0 1-56.334 23.335l9.16-9.162A20.044 20.044 0 0 0 96.045 62H109Z" fill="#3EAAAF"/><path opacity=".2" d="M51.09 83.645a33.002 33.002 0 0 1-6.892-30.457l12.582 3.486a19.945 19.945 0 0 0 4.165 18.408l-9.855 8.563Z" fill="#3EAAAF"/><path opacity=".4" d="M44.652 51.688a33 33 0 0 1 64.32 8.95l-12.948.535a20.04 20.04 0 0 0-39.061-5.435l-12.31-4.05Z" fill="#3EAAAF"/><path d="M150.176 79.433a1 1 0 0 0 1.648 1.134l-1.648-1.134ZM247 29l-11.457 1.437 6.972 9.204L247 29Zm-35.954 23.046-.552.834.552-.834Zm5.777-.185-.604-.797.604.797Zm-36.606-14.317-.823-.567.823.567Zm6.877-1.336-.551.834.551-.834Zm-35.27 44.359 29.217-42.457-1.647-1.133-29.218 42.456 1.648 1.134Zm34.719-43.525 23.951 15.838 1.103-1.668-23.951-15.839-1.103 1.669Zm30.884 15.616 23.003-17.426-1.208-1.594-23.003 17.426 1.208 1.594Zm-6.933.222a6 6 0 0 0 6.933-.222l-1.208-1.594a4 4 0 0 1-4.622.148l-1.103 1.668Zm-29.453-14.77a4 4 0 0 1 5.502-1.068l1.103-1.669a6 6 0 0 0-8.252 1.604l1.647 1.133Z" fill="#3EAAAF"/><rect opacity=".2" x="60" y="102" width="7" height="3" rx="1.5" fill="#3EAAAF"/><rect opacity=".3" x="72" y="102" width="7" height="3" rx="1.5" fill="#3EAAAF"/><rect opacity=".6" x="84" y="102" width="7" height="3" rx="1.5" fill="#3EAAAF"/><path clipRule="evenodd" d="M17 187.928c0-1.01 1.326-1.383 1.853-.522l1.777 2.906c3.63 5.938 11.092 17.813 18.352 19 7.26 1.188 14.721-8.312 21.981-20.187C68.425 177.25 75.685 163 82.945 163c7.462 0 14.722 14.25 21.982 21.375 7.461 7.125 14.721 7.125 21.981 2.375 7.462-4.75 14.722-14.25 22.184-14.25 7.26 0 14.52 9.5 21.981 16.625 7.26 7.125 14.52 11.875 21.982 8.313 7.26-3.563 14.52-15.438 21.982-14.25 7.26 1.187 14.721 15.437 21.981 16.624 7.26 1.188 14.722-10.687 18.352-16.624l1.777-2.907c.527-.861 1.853-.488 1.853.522V217a3 3 0 0 1-3 3H20a3 3 0 0 1-3-3v-29.072Z" fill="url(#b)"/><path d="M258 180.5c-7 11-17.882 29.121-29 14-12.5-17-21.333-11.5-24.5-8-16.5 21.5-30.5 10.5-43-6-10-13.2-19.833-7.833-23.5-3.5-22.5 28-35.5 3.5-48.5-11.5C79 154 67 179 59 194c-8 13.5-21 29.5-41-6.5" stroke="#3EAAAF" stroke-width="2" stroke-linecap="round"/><circle cx="42" cy="206" r="7" fill="#fff" stroke="#3EAAAF" stroke-width="2"/><circle cx="117" cy="187" r="7" fill="#fff" stroke="#3EAAAF" stroke-width="2"/><circle cx="212" cy="183" r="7" fill="#fff" stroke="#3EAAAF" stroke-width="2"/><defs><linearGradient id="b" x1="138" y1="163" x2="138.49" y2="224" gradientUnits="userSpaceOnUse"><stop stopColor="#86C6C9"/><stop offset="1" stopColor="#F6F6F6"/></linearGradient><filter id="a" x="0" y="0" width="276" height="241" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/><feOffset dy="2"/><feGaussianBlur stdDeviation="3"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_59_3139"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_59_3139" result="shape"/></filter></defs></svg>; case 'desktop': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M0 4s0-2 2-2h12s2 0 2 2v6s0 2-2 2h-4c0 .667.083 1.167.25 1.5H11a.5.5 0 0 1 0 1H5a.5.5 0 0 1 0-1h.75c.167-.333.25-.833.25-1.5H2s-2 0-2-2V4zm1.398-.855a.758.758 0 0 0-.254.302A1.46 1.46 0 0 0 1 4.01V10c0 .325.078.502.145.602.07.105.17.188.302.254a1.464 1.464 0 0 0 .538.143L2.01 11H14c.325 0 .502-.078.602-.145a.758.758 0 0 0 .254-.302 1.464 1.464 0 0 0 .143-.538L15 9.99V4c0-.325-.078-.502-.145-.602a.757.757 0 0 0-.302-.254A1.46 1.46 0 0 0 13.99 3H2c-.325 0-.502.078-.602.145z"/></svg>; case 'device': return <svg viewBox="0 0 1000 1000" width={ `${ width }px` } height={ `${ height }px` } ><path d="M702.5 826.7H598V722.1h107.8v-68.6H78.6V157h816.7v277.7h55.5c3.3 0 9.8 0 13.1 3.3V134.1c0-26.1-19.6-45.7-45.7-45.7H55.7C29.6 88.4 10 108 10 134.1v542.3c0 26.1 19.6 45.7 45.7 45.7h323.4v104.5H255c-22.9 0-42.5 19.6-42.5 42.5s19.6 42.5 42.5 42.5h460.6c-6.5-9.8-9.8-19.6-9.8-29.4v-55.5h-3.3z"/><path d="M960.6 457.5H767.9c-16.3 0-29.4 13.1-29.4 29.4v392c0 16.3 13.1 29.4 29.4 29.4h192.7c16.3 0 29.4-13.1 29.4-29.4v-392c0-13-13.1-29.4-29.4-29.4zm-98 434.5c-6.5 0-13.1-6.5-13.1-13.1s6.5-13.1 13.1-13.1c6.5 0 13.1 6.5 13.1 13.1s-6.6 13.1-13.1 13.1zm107.8-42.5H754.8V522.9h215.6v326.6z"/></svg>; case 'diagram-3': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M6 3.5A1.5 1.5 0 0 1 7.5 2h1A1.5 1.5 0 0 1 10 3.5v1A1.5 1.5 0 0 1 8.5 6v1H14a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 2 7h5.5V6A1.5 1.5 0 0 1 6 4.5v-1zM8.5 5a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1zM0 11.5A1.5 1.5 0 0 1 1.5 10h1A1.5 1.5 0 0 1 4 11.5v1A1.5 1.5 0 0 1 2.5 14h-1A1.5 1.5 0 0 1 0 12.5v-1zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1zm4.5.5A1.5 1.5 0 0 1 7.5 10h1a1.5 1.5 0 0 1 1.5 1.5v1A1.5 1.5 0 0 1 8.5 14h-1A1.5 1.5 0 0 1 6 12.5v-1zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1zm4.5.5a1.5 1.5 0 0 1 1.5-1.5h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1a1.5 1.5 0 0 1-1.5-1.5v-1zm1.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1z"/></svg>; case 'dizzy': return <svg viewBox="0 0 496 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 464c-119.1 0-216-96.9-216-216S128.9 40 248 40s216 96.9 216 216-96.9 216-216 216zm0-184c-35.3 0-64 28.7-64 64s28.7 64 64 64 64-28.7 64-64-28.7-64-64-64zm0 96c-17.6 0-32-14.4-32-32s14.4-32 32-32 32 14.4 32 32-14.4 32-32 32zm-28.7-140.7c6.2-6.2 6.2-16.4 0-22.6L190.6 192l28.7-28.7c6.2-6.2 6.2-16.4 0-22.6s-16.4-6.2-22.6 0L168 169.4l-28.7-28.7c-6.2-6.2-16.4-6.2-22.6 0s-6.2 16.4 0 22.6l28.7 28.7-28.7 28.7c-6.2 6.2-6.2 16.4 0 22.6 6.2 6.2 16.4 6.3 22.6 0l28.7-28.7 28.7 28.7c6.2 6.3 16.4 6.3 22.6 0zm160-102.6c-6.2-6.2-16.4-6.2-22.6 0L328 169.4l-28.7-28.7c-6.2-6.2-16.4-6.2-22.6 0s-6.2 16.4 0 22.6l28.7 28.7-28.7 28.7c-6.2 6.2-6.2 16.4 0 22.6 6.2 6.2 16.4 6.3 22.6 0l28.7-28.7 28.7 28.7c6.2 6.2 16.4 6.3 22.6 0 6.2-6.2 6.2-16.4 0-22.6L350.6 192l28.7-28.7c6.3-6.2 6.3-16.4 0-22.6z"/></svg>; + case 'door-closed': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v13h1.5a.5.5 0 0 1 0 1h-13a.5.5 0 0 1 0-1H3V2zm1 13h8V2H4v13z"/><path d="M9 9a1 1 0 1 0 2 0 1 1 0 0 0-2 0z"/></svg>; case 'doublecheck': return <svg viewBox="0 0 1000 1000" width={ `${ width }px` } height={ `${ height }px` } ><path d="M671.31 244.15c-3.06 1.53-104.71 101.08-225.5 221.1-120.8 120.22-220.34 218.42-221.3 218.42-.77 0-38.67-36.56-84.23-81.17-60.68-59.53-84.61-81.93-89.59-83.65-25.08-8.23-49 17.8-37.9 41.16 3.25 6.89 187.22 188.75 196.79 194.68 7.66 4.59 21.44 4.79 29.48.19 7.66-4.21 469-462.68 472.64-469.57 6.32-12.63 1.72-29.29-11.1-38.67-6.51-4.78-21.64-6.12-29.29-2.49zM946.77 244.15c-3.07 1.34-104.71 100.88-225.69 221.1C599.9 585.28 500.17 683.67 499.4 683.67c-.96 0-10.72-8.42-21.63-18.76-24.69-22.97-29.48-25.84-41.54-24.7-21.25 1.91-34.84 25.08-25.27 43.26 3.64 7.28 70.06 70.45 76.57 72.94 8.04 3.06 20.48 2.3 27.18-1.72 9.95-6.13 469.19-463.45 472.64-470.72 11.3-23.93-15.69-50.54-40.58-39.82z"/></svg>; case 'download': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M7.646 10.854a.5.5 0 0 0 .708 0l2-2a.5.5 0 0 0-.708-.708L8.5 9.293V5.5a.5.5 0 0 0-1 0v3.793L6.354 8.146a.5.5 0 1 0-.708.708l2 2z"/><path d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"/></svg>; case 'drag': return <svg viewBox="0 0 26 26" width={ `${ width }px` } height={ `${ height }px` } ><path d="M13 0 9 4h8ZM0 7v2h26V7Zm0 5v2h26v-2Zm0 5v2h26v-2Zm9 5 4 4 4-4Z"/></svg>; @@ -160,6 +169,7 @@ const SVG = (props: Props) => { case 'fetch': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1 11.5a.5.5 0 0 0 .5.5h11.793l-3.147 3.146a.5.5 0 0 0 .708.708l4-4a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 11H1.5a.5.5 0 0 0-.5.5zm14-7a.5.5 0 0 1-.5.5H2.707l3.147 3.146a.5.5 0 1 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 4H14.5a.5.5 0 0 1 .5.5z"/></svg>; case 'file-code': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/><path d="M8.646 6.646a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0 1-.708-.708L10.293 9 8.646 7.354a.5.5 0 0 1 0-.708zm-1.292 0a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0 0 .708l2 2a.5.5 0 0 0 .708-.708L5.707 9l1.647-1.646a.5.5 0 0 0 0-.708z"/></svg>; case 'file-medical-alt': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/><path d="m10.273 2.513-.921-.944.715-.698.622.637.89-.011a2.89 2.89 0 0 1 2.924 2.924l-.01.89.636.622a2.89 2.89 0 0 1 0 4.134l-.637.622.011.89a2.89 2.89 0 0 1-2.924 2.924l-.89-.01-.622.636a2.89 2.89 0 0 1-4.134 0l-.622-.637-.89.011a2.89 2.89 0 0 1-2.924-2.924l.01-.89-.636-.622a2.89 2.89 0 0 1 0-4.134l.637-.622-.011-.89a2.89 2.89 0 0 1 2.924-2.924l.89.01.622-.636a2.89 2.89 0 0 1 4.134 0l-.715.698a1.89 1.89 0 0 0-2.704 0l-.92.944-1.32-.016a1.89 1.89 0 0 0-1.911 1.912l.016 1.318-.944.921a1.89 1.89 0 0 0 0 2.704l.944.92-.016 1.32a1.89 1.89 0 0 0 1.912 1.911l1.318-.016.921.944a1.89 1.89 0 0 0 2.704 0l.92-.944 1.32.016a1.89 1.89 0 0 0 1.911-1.912l-.016-1.318.944-.921a1.89 1.89 0 0 0 0-2.704l-.944-.92.016-1.32a1.89 1.89 0 0 0-1.912-1.911l-1.318.016z"/></svg>; + case 'file-pdf': return <svg viewBox="0 0 13 14" width={ `${ width }px` } height={ `${ height }px` } ><g clipPath="url(#a)"><path d="M3.493.662A1.584 1.584 0 0 0 1.91 2.247v9.506a1.584 1.584 0 0 0 1.584 1.585h6.338a1.584 1.584 0 0 0 1.585-1.585V2.247A1.585 1.585 0 0 0 9.83.662H3.493Zm0 .792h6.338a.792.792 0 0 1 .792.793v9.506a.792.792 0 0 1-.792.793H3.493a.792.792 0 0 1-.792-.793V2.247a.792.792 0 0 1 .792-.793Z" fillOpacity=".6"/><path d="M3.971 10.238a.641.641 0 0 1-.347-.333c-.154-.307-.103-.615.063-.873.157-.243.417-.45.711-.623a6.084 6.084 0 0 1 1.174-.511c.317-.57.598-1.16.841-1.765a5.759 5.759 0 0 1-.34-1.026c-.068-.317-.095-.63-.037-.9.06-.28.217-.532.515-.652.152-.06.317-.095.477-.06a.555.555 0 0 1 .378.289c.07.13.095.282.1.426a2.54 2.54 0 0 1-.037.486c-.066.404-.213.899-.411 1.421.218.468.478.915.776 1.336a4.558 4.558 0 0 1 1.057.04c.288.051.581.154.76.368a.67.67 0 0 1 .159.41.922.922 0 0 1-.11.447.824.824 0 0 1-.28.33.678.678 0 0 1-.404.108c-.262-.01-.518-.155-.74-.33a4.528 4.528 0 0 1-.721-.753 9.223 9.223 0 0 0-1.582.322 8.96 8.96 0 0 1-.809 1.196c-.23.278-.482.52-.734.624a.628.628 0 0 1-.459.023Zm1.092-1.506c-.131.06-.253.123-.363.188-.26.154-.429.304-.513.434-.074.115-.076.198-.031.286a.18.18 0 0 0 .02.035.213.213 0 0 0 .028-.01c.108-.044.281-.186.503-.453a6.48 6.48 0 0 0 .356-.48Zm1.3-1.054c.264-.062.531-.113.8-.153a9.243 9.243 0 0 1-.404-.68c-.124.281-.256.559-.396.832v.001Zm1.938.357c.118.128.234.237.344.324.19.151.323.2.395.203a.085.085 0 0 0 .055-.012.243.243 0 0 0 .075-.099.345.345 0 0 0 .046-.158.075.075 0 0 0-.02-.05c-.041-.05-.159-.12-.41-.166a3.075 3.075 0 0 0-.485-.042ZM6.724 5.257c.067-.215.12-.434.158-.656.025-.149.034-.272.03-.368a.486.486 0 0 0-.025-.157.41.41 0 0 0-.115.032c-.069.027-.125.084-.155.224-.032.152-.024.371.036.651.02.088.043.18.072.274h-.001Z"/></g><defs><clipPath id="a"><path fill="#fff" transform="translate(.324 .662)" d="M0 0h12.676v12.676H0z"/></clipPath></defs></svg>; case 'file': return <svg viewBox="0 0 384 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M369.9 97.9 286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zm-22.6 22.7c2.1 2.1 3.5 4.6 4.2 7.4H256V32.5c2.8.7 5.3 2.1 7.4 4.2l83.9 83.9zM336 480H48c-8.8 0-16-7.2-16-16V48c0-8.8 7.2-16 16-16h176v104c0 13.3 10.7 24 24 24h104v304c0 8.8-7.2 16-16 16z"/></svg>; case 'filter': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2h-11z"/></svg>; case 'filters/arrow-return-right': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1.5 1.5A.5.5 0 0 0 1 2v4.8a2.5 2.5 0 0 0 2.5 2.5h9.793l-3.347 3.346a.5.5 0 0 0 .708.708l4.2-4.2a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 8.3H3.5A1.5 1.5 0 0 1 2 6.8V2a.5.5 0 0 0-.5-.5z"/></svg>; @@ -198,6 +208,8 @@ const SVG = (props: Props) => { case 'filters/userid': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/></svg>; case 'filters/view': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/><path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/></svg>; case 'flag-na': return <svg viewBox="0 0 22 14" width={ `${ width }px` } height={ `${ height }px` } ><path clipRule="evenodd" d="M2 0a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2Zm9.076 10V3.602H9.98v4.592L7.103 3.602H6V10h1.103V5.417L9.973 10h1.103Zm3.964-6.398h.263L17.72 10h-1.16l-.518-1.499h-2.477L13.05 10h-1.156l2.408-6.398h.739Zm-1.173 4.025h1.873l-.938-2.714-.935 2.714Z" fill="#C4C4C4"/></svg>; + case 'folder-plus': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="m.5 3 .04.87a1.99 1.99 0 0 0-.342 1.311l.637 7A2 2 0 0 0 2.826 14H9v-1H2.826a1 1 0 0 1-.995-.91l-.637-7A1 1 0 0 1 2.19 4h11.62a1 1 0 0 1 .996 1.09L14.54 8h1.005l.256-2.819A2 2 0 0 0 13.81 3H9.828a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 6.172 1H2.5a2 2 0 0 0-2 2zm5.672-1a1 1 0 0 1 .707.293L7.586 3H2.19c-.24 0-.47.042-.683.12L1.5 2.98a1 1 0 0 1 1-.98h3.672z"/><path d="M13.5 10a.5.5 0 0 1 .5.5V12h1.5a.5.5 0 1 1 0 1H14v1.5a.5.5 0 1 1-1 0V13h-1.5a.5.5 0 0 1 0-1H13v-1.5a.5.5 0 0 1 .5-.5z"/></svg>; + case 'folder2': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1 3.5A1.5 1.5 0 0 1 2.5 2h2.764c.958 0 1.76.56 2.311 1.184C7.985 3.648 8.48 4 9 4h4.5A1.5 1.5 0 0 1 15 5.5v7a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 1 12.5v-9zM2.5 3a.5.5 0 0 0-.5.5V6h12v-.5a.5.5 0 0 0-.5-.5H9c-.964 0-1.71-.629-2.174-1.154C6.374 3.334 5.82 3 5.264 3H2.5zM14 7H2v5.5a.5.5 0 0 0 .5.5h11a.5.5 0 0 0 .5-.5V7z"/></svg>; case 'fullscreen': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1.5 1a.5.5 0 0 0-.5.5v4a.5.5 0 0 1-1 0v-4A1.5 1.5 0 0 1 1.5 0h4a.5.5 0 0 1 0 1h-4zM10 .5a.5.5 0 0 1 .5-.5h4A1.5 1.5 0 0 1 16 1.5v4a.5.5 0 0 1-1 0v-4a.5.5 0 0 0-.5-.5h-4a.5.5 0 0 1-.5-.5zM.5 10a.5.5 0 0 1 .5.5v4a.5.5 0 0 0 .5.5h4a.5.5 0 0 1 0 1h-4A1.5 1.5 0 0 1 0 14.5v-4a.5.5 0 0 1 .5-.5zm15 0a.5.5 0 0 1 .5.5v4a1.5 1.5 0 0 1-1.5 1.5h-4a.5.5 0 0 1 0-1h4a.5.5 0 0 0 .5-.5v-4a.5.5 0 0 1 .5-.5z"/></svg>; case 'funnel/cpu-fill': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/><path d="M5.5.5a.5.5 0 0 0-1 0V2A2.5 2.5 0 0 0 2 4.5H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2A2.5 2.5 0 0 0 4.5 14v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14a2.5 2.5 0 0 0 2.5-2.5h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14A2.5 2.5 0 0 0 11.5 2V.5a.5.5 0 0 0-1 0V2h-1V.5a.5.5 0 0 0-1 0V2h-1V.5a.5.5 0 0 0-1 0V2h-1V.5zm1 4.5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3A1.5 1.5 0 0 1 6.5 5z"/></svg>; case 'funnel/cpu': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/></svg>; @@ -224,6 +236,8 @@ const SVG = (props: Props) => { case 'funnel-fill': return <svg width={ `${ width }px` } height={ `${ height }px` } ><path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2z"/></svg>; case 'funnel-new': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2h-11z"/></svg>; case 'funnel': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2h-11z"/></svg>; + case 'gear-fill': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"/></svg>; + case 'gear': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z"/><path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z"/></svg>; case 'geo-alt-fill-custom': return <svg viewBox="0 0 12 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M6 16s6-5.686 6-10A6 6 0 1 0 0 6c0 4.314 6 10 6 10Z"/></svg>; case 'github': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>; case 'graph-up-arrow': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M0 0h1v15h15v1H0V0Zm10 3.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-1 0V4.9l-3.613 4.417a.5.5 0 0 1-.74.037L7.06 6.767l-3.656 5.027a.5.5 0 0 1-.808-.588l4-5.5a.5.5 0 0 1 .758-.06l2.609 2.61L13.445 4H10.5a.5.5 0 0 1-.5-.5Z"/></svg>; @@ -242,7 +256,7 @@ const SVG = (props: Props) => { case 'id-card': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h13zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z"/><path d="M3 8.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5zm0-5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5v-1z"/></svg>; case 'image': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M4.502 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/><path d="M14.002 13a2 2 0 0 1-2 2h-10a2 2 0 0 1-2-2V5A2 2 0 0 1 2 3a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v8a2 2 0 0 1-1.998 2zM14 2H4a1 1 0 0 0-1 1h9.002a2 2 0 0 1 2 2v7A1 1 0 0 0 15 11V3a1 1 0 0 0-1-1zM2.002 4a1 1 0 0 0-1 1v8l2.646-2.354a.5.5 0 0 1 .63-.062l2.66 1.773 3.71-3.71a.5.5 0 0 1 .577-.094l1.777 1.947V5a1 1 0 0 0-1-1h-10z"/></svg>; case 'info-circle-fill': return <svg viewBox="0 0 36 36" width={ `${ width }px` } height={ `${ height }px` } ><path d="M17.75 35.5a17.75 17.75 0 1 0 0-35.5 17.75 17.75 0 0 0 0 35.5Zm2.064-20.883-2.22 10.44c-.155.754.065 1.182.675 1.182.43 0 1.08-.155 1.522-.546l-.195.923c-.637.768-2.041 1.327-3.25 1.327-1.56 0-2.224-.937-1.793-2.927l1.637-7.694c.142-.65.014-.886-.637-1.043l-1-.18.182-.845 5.08-.637h-.002Zm-2.064-2.414a2.219 2.219 0 1 1 0-4.437 2.219 2.219 0 0 1 0 4.437Z"/></svg>; - case 'info-circle': return <svg viewBox="0 0 35 35" width={ `${ width }px` } height={ `${ height }px` } ><g clipPath="url(#a)"><path d="M17.5 32.813a15.313 15.313 0 1 1 0-30.626 15.313 15.313 0 0 1 0 30.625Zm0 2.187a17.5 17.5 0 1 0 0-35 17.5 17.5 0 0 0 0 35Z"/><path clipRule="evenodd" d="M17.5 13a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm1.5 2.877a1.5 1.5 0 1 0-3 0V24.5a1.5 1.5 0 0 0 3 0v-8.623Z"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h35v35H0z"/></clipPath></defs></svg>; + case 'info-circle': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/><path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/></svg>; case 'info-square': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/><path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/></svg>; case 'info': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/><path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/></svg>; case 'inspect': return <svg viewBox="0 0 512 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M506 240h-34.591C463.608 133.462 378.538 48.392 272 40.591V6a6 6 0 0 0-6-6h-20a6 6 0 0 0-6 6v34.591C133.462 48.392 48.392 133.462 40.591 240H6a6 6 0 0 0-6 6v20a6 6 0 0 0 6 6h34.591C48.392 378.538 133.462 463.608 240 471.409V506a6 6 0 0 0 6 6h20a6 6 0 0 0 6-6v-34.591C378.538 463.608 463.608 378.538 471.409 272H506a6 6 0 0 0 6-6v-20a6 6 0 0 0-6-6zM272 439.305V374a6 6 0 0 0-6-6h-20a6 6 0 0 0-6 6v65.305C151.282 431.711 80.315 361.031 72.695 272H138a6 6 0 0 0 6-6v-20a6 6 0 0 0-6-6H72.695C80.289 151.282 150.969 80.316 240 72.695V138a6 6 0 0 0 6 6h20a6 6 0 0 0 6-6V72.695C360.718 80.289 431.685 150.969 439.305 240H374a6 6 0 0 0-6 6v20a6 6 0 0 0 6 6h65.305C431.711 360.718 361.031 431.684 272 439.305zM280 256c0 13.255-10.745 24-24 24s-24-10.745-24-24 10.745-24 24-24 24 10.745 24 24z"/></svg>; @@ -256,11 +270,11 @@ const SVG = (props: Props) => { case 'integrations/elasticsearch': return <svg viewBox="0 0 256 256" preserveAspectRatio="xMinYMin meet" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><path d="M255.96 134.393c0-21.521-13.373-40.117-33.223-47.43a75.239 75.239 0 0 0 1.253-13.791c0-39.909-32.386-72.295-72.295-72.295-23.193 0-44.923 11.074-58.505 30.088-6.686-5.224-14.835-7.94-23.402-7.94-21.104 0-38.446 17.133-38.446 38.446 0 4.597.836 9.194 2.298 13.373C13.582 81.739 0 100.962 0 122.274c0 21.522 13.373 40.327 33.431 47.64-.835 4.388-1.253 8.985-1.253 13.79 0 39.7 32.386 72.087 72.086 72.087 23.402 0 44.924-11.283 58.505-30.088 6.686 5.223 15.044 8.149 23.611 8.149 21.104 0 38.446-17.134 38.446-38.446 0-4.597-.836-9.194-2.298-13.373 19.64-7.104 33.431-26.327 33.431-47.64z" fill="#FFF"/><path d="m100.085 110.364 57.043 26.119 57.669-50.565a64.312 64.312 0 0 0 1.253-12.746c0-35.52-28.834-64.355-64.355-64.355-21.313 0-41.162 10.447-53.072 27.998l-9.612 49.73 11.074 23.82z" fill="#F4BD19"/><path d="M40.953 170.75c-.835 4.179-1.253 8.567-1.253 12.955 0 35.52 29.043 64.564 64.564 64.564 21.522 0 41.372-10.656 53.49-28.208l9.403-49.729-12.746-24.238-57.251-26.118-56.207 50.774z" fill="#3CBEB1"/><path d="m40.536 71.918 39.073 9.194 8.775-44.506c-5.432-4.179-11.91-6.268-18.805-6.268-16.925 0-30.924 13.79-30.924 30.924 0 3.552.627 7.313 1.88 10.656z" fill="#E9478C"/><path d="M37.192 81.32c-17.551 5.642-29.67 22.567-29.67 40.954 0 17.97 11.074 34.059 27.79 40.327l54.953-49.73-10.03-21.52-43.043-10.03z" fill="#2C458F"/><path d="M167.784 219.852c5.432 4.18 11.91 6.478 18.596 6.478 16.925 0 30.924-13.79 30.924-30.924 0-3.761-.627-7.314-1.88-10.657l-39.073-9.193-8.567 44.296z" fill="#95C63D"/><path d="m175.724 165.317 43.043 10.03c17.551-5.85 29.67-22.566 29.67-40.954 0-17.97-11.074-33.849-27.79-40.326l-56.415 49.311 11.492 21.94z" fill="#176655"/></svg>; case 'integrations/github': return <svg viewBox="0 0 496 512" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>; case 'integrations/graphql': return <svg viewBox="0 0 120 120" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><rect fill="#fff" height="120" rx="6.01" width="120"/><path d="m66.84 29.17 16.44 9.5a7 7 0 0 1 1.62-1.28A7.13 7.13 0 1 1 92 49.74a7 7 0 0 1-1.9.76v19a7.13 7.13 0 1 1-5.25 13.11 6.85 6.85 0 0 1-1.76-1.43l-16.32 9.44a7.26 7.26 0 0 1 .36 2.25 7.13 7.13 0 1 1-14-2l-16.42-9.51a7 7 0 0 1-1.59 1.25 7.13 7.13 0 1 1-5.25-13.11v-19a7 7 0 0 1-1.9-.76 7.13 7.13 0 1 1 7.13-12.35 7 7 0 0 1 1.61 1.27l16.45-9.5a7.22 7.22 0 0 1-.29-2 7.13 7.13 0 1 1 14.26 0 7.24 7.24 0 0 1-.29 2.01zm-1.72 2.92 16.49 9.52a7.12 7.12 0 0 0 5.13 8.87v19l-.27.07-21.54-37.27zm-10.05.2-21.53 37.3-.28-.08v-19a7.06 7.06 0 0 0 4.45-3.35 7.15 7.15 0 0 0 .68-5.53l16.48-9.51a1.89 1.89 0 0 1 .2.17zM62 34l21.52 37.27a7.09 7.09 0 0 0-1.25 1.6 6.84 6.84 0 0 0-.75 1.88h-43a6.84 6.84 0 0 0-.75-1.88 7.26 7.26 0 0 0-1.25-1.59L58 34a7.21 7.21 0 0 0 4 0zm3.28 54.09 16.38-9.46c0-.16-.09-.31-.13-.47h-43c0 .09 0 .19-.08.28l16.46 9.5a7.14 7.14 0 0 1 10.41.15z" fill="#e535ab"/></svg>; - case 'integrations/jira-text': return <svg viewBox="0 0 254.6 150" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><defs><linearGradient id="a" x1="55.29" y1="50.91" x2="40.58" y2="66.08" gradientUnits="userSpaceOnUse"><stop offset=".18" stop-color="#0052cc"/><stop offset="1" stop-color="#2684ff"/></linearGradient><linearGradient id="b" x1="39.15" y1="68.24" x2="22.14" y2="84.79" xlinkHref="#a"/></defs><path d="M109.87 42.62h7.92v40.22c0 10.64-4.66 18-15.57 18a28.19 28.19 0 0 1-9.51-1.5v-7.7a22.4 22.4 0 0 0 8.19 1.49c6.69 0 9-4 9-9.77ZM132.23 39.54a4.94 4.94 0 0 1 5.27 5.28 5.28 5.28 0 1 1-10.55 0 4.94 4.94 0 0 1 5.28-5.28Zm-3.88 16.9h7.57v44h-7.57ZM154.75 100.44h-7.39v-44h7.39v7.74c2.55-5.19 6.95-8.89 15.58-8.36v7.39c-9.68-1-15.58 1.94-15.58 11.27ZM205.79 92.52c-2.81 5.8-8.09 8.8-14.87 8.8-11.7 0-17.6-9.95-17.6-22.88 0-12.41 6.16-22.88 18.48-22.88 6.42 0 11.35 2.9 14 8.62v-7.74h7.57v44h-7.57Zm-12.85 1.76c6.78 0 12.85-4.32 12.85-14.08v-3.52c0-9.77-5.54-14.08-12-14.08-8.53 0-12.93 5.63-12.93 15.84.03 10.56 4.25 15.84 12.08 15.84Z"/><path d="M70.14 33.62H35.56a15.61 15.61 0 0 0 15.61 15.61h6.36v6.15A15.6 15.6 0 0 0 73.14 71V36.62a3 3 0 0 0-3-3Z"/><path d="M53 50.85H18.44a15.61 15.61 0 0 0 15.61 15.61h6.37v6.14A15.61 15.61 0 0 0 56 88.21V53.85a3 3 0 0 0-3-3Z"/><path d="M35.91 68.08H1.33a15.6 15.6 0 0 0 15.6 15.61h6.37v6.14a15.61 15.61 0 0 0 15.61 15.61V71.08a3 3 0 0 0-3-3Z"/></svg>; - case 'integrations/jira': return <svg viewBox="0 0 74 76" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><defs><linearGradient x1="67.68%" y1="40.328%" x2="40.821%" y2="81.66%" id="a"><stop stop-color="#777" offset="18%"/><stop stop-color="#999" offset="100%"/></linearGradient><linearGradient x1="32.656%" y1="59.166%" x2="59.343%" y2="17.99%" id="b"><stop stop-color="#777" offset="18%"/><stop stop-color="#999" offset="100%"/></linearGradient></defs><g fill="none"><path d="M72.4 35.76 39.8 3.16 36.64 0 12.1 24.54.88 35.76a3 3 0 0 0 0 4.24L23.3 62.42l13.34 13.34 24.54-24.54.38-.38L72.4 40a3 3 0 0 0 0-4.24ZM36.64 49.08l-11.2-11.2 11.2-11.2 11.2 11.2-11.2 11.2Z" fill="#999"/><path d="M36.64 26.68c-7.333-7.334-7.369-19.212-.08-26.59l-24.51 24.5 13.34 13.34 11.25-11.25Z" fill="url(#a)"/><path d="M47.87 37.85 36.64 49.08a18.86 18.86 0 0 1 0 26.68l24.57-24.57-13.34-13.34Z" fill="url(#b)"/></g></svg>; + case 'integrations/jira-text': return <svg viewBox="0 0 254.6 150" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><defs><linearGradient id="a" x1="55.29" y1="50.91" x2="40.58" y2="66.08" gradientUnits="userSpaceOnUse"><stop offset=".18" stopColor="#0052cc"/><stop offset="1" stopColor="#2684ff"/></linearGradient><linearGradient id="b" x1="39.15" y1="68.24" x2="22.14" y2="84.79" xlinkHref="#a"/></defs><path d="M109.87 42.62h7.92v40.22c0 10.64-4.66 18-15.57 18a28.19 28.19 0 0 1-9.51-1.5v-7.7a22.4 22.4 0 0 0 8.19 1.49c6.69 0 9-4 9-9.77ZM132.23 39.54a4.94 4.94 0 0 1 5.27 5.28 5.28 5.28 0 1 1-10.55 0 4.94 4.94 0 0 1 5.28-5.28Zm-3.88 16.9h7.57v44h-7.57ZM154.75 100.44h-7.39v-44h7.39v7.74c2.55-5.19 6.95-8.89 15.58-8.36v7.39c-9.68-1-15.58 1.94-15.58 11.27ZM205.79 92.52c-2.81 5.8-8.09 8.8-14.87 8.8-11.7 0-17.6-9.95-17.6-22.88 0-12.41 6.16-22.88 18.48-22.88 6.42 0 11.35 2.9 14 8.62v-7.74h7.57v44h-7.57Zm-12.85 1.76c6.78 0 12.85-4.32 12.85-14.08v-3.52c0-9.77-5.54-14.08-12-14.08-8.53 0-12.93 5.63-12.93 15.84.03 10.56 4.25 15.84 12.08 15.84Z"/><path d="M70.14 33.62H35.56a15.61 15.61 0 0 0 15.61 15.61h6.36v6.15A15.6 15.6 0 0 0 73.14 71V36.62a3 3 0 0 0-3-3Z"/><path d="M53 50.85H18.44a15.61 15.61 0 0 0 15.61 15.61h6.37v6.14A15.61 15.61 0 0 0 56 88.21V53.85a3 3 0 0 0-3-3Z"/><path d="M35.91 68.08H1.33a15.6 15.6 0 0 0 15.6 15.61h6.37v6.14a15.61 15.61 0 0 0 15.61 15.61V71.08a3 3 0 0 0-3-3Z"/></svg>; + case 'integrations/jira': return <svg viewBox="0 0 74 76" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><defs><linearGradient x1="67.68%" y1="40.328%" x2="40.821%" y2="81.66%" id="a"><stop stopColor="#777" offset="18%"/><stop stopColor="#999" offset="100%"/></linearGradient><linearGradient x1="32.656%" y1="59.166%" x2="59.343%" y2="17.99%" id="b"><stop stopColor="#777" offset="18%"/><stop stopColor="#999" offset="100%"/></linearGradient></defs><g fill="none"><path d="M72.4 35.76 39.8 3.16 36.64 0 12.1 24.54.88 35.76a3 3 0 0 0 0 4.24L23.3 62.42l13.34 13.34 24.54-24.54.38-.38L72.4 40a3 3 0 0 0 0-4.24ZM36.64 49.08l-11.2-11.2 11.2-11.2 11.2 11.2-11.2 11.2Z" fill="#999"/><path d="M36.64 26.68c-7.333-7.334-7.369-19.212-.08-26.59l-24.51 24.5 13.34 13.34 11.25-11.25Z" fill="url(#a)"/><path d="M47.87 37.85 36.64 49.08a18.86 18.86 0 0 1 0 26.68l24.57-24.57-13.34-13.34Z" fill="url(#b)"/></g></svg>; case 'integrations/mobx': return <svg viewBox="0 0 256 256" preserveAspectRatio="xMidYMid" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><path d="M256 236.394V19.607c0-8.894-5.923-16.4-14.037-18.8l-9.215 5.514-102.265 109.037-3.206 10.021-1.873 9.62 31.89 119.18 4.933 1.82h74.167c10.828 0 19.606-8.777 19.606-19.605" fill="#EA6618"/><path d="M0 19.606v216.787c0 6.705 3.367 12.62 8.5 16.155l6.287-3.01 108.246-115.894 4.244-8.265.159-7.99L97.976 5.306 93.513 0H19.606C8.778 0 0 8.778 0 19.606" fill="#d65813"/><path d="M127.277 125.38 241.963.806a19.595 19.595 0 0 0-5.57-.807H93.515l33.763 125.38z" fill="#e05e11"/><path d="M19.606 256h142.622l-34.951-130.621L8.499 252.549A19.511 19.511 0 0 0 19.606 256" fill="#de5c16"/><path d="M94.918 97.03h14.225c5.668 21.386 12.119 40.152 19.316 57.085 8.152-19.05 14.127-37.83 19.185-57.086h13.442c-6.02 23.926-15.868 48.04-27.132 72.93h-11.89c-10.82-23.586-20.03-47.837-27.146-72.93zm-46.92-37.055h31.63v135.637h-31.77v-10.456H67.33V70.152H47.998V59.975zm160.169 10.177h-19.332v115.004h19.47v10.456h-31.769V59.975h31.63v10.177z" fill="#FFF"/></svg>; case 'integrations/newrelic-text': return <svg viewBox="0 0 737.94 132.03" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><path d="m257.96 103.98-20.19-42.32c-4.82-10-9.77-21.36-11.46-26.7l-.39.39c.65 7.55.78 17.06.91 25l.52 43.63h-14.71V13.86h16.93l21.88 44a164.12 164.12 0 0 1 9.25 23.18l.39-.39c-.39-4.56-1.3-17.45-1.3-25.66l-.26-41.15h14.2v90.12ZM300.54 74.94v1c0 9.12 3.39 18.75 16.28 18.75 6.12 0 11.46-2.21 16.41-6.51l5.6 8.73a35.6 35.6 0 0 1-23.7 8.73c-18.62 0-30.34-13.41-30.34-34.51 0-11.59 2.47-19.28 8.21-25.79 5.34-6.12 11.85-8.86 20.19-8.86a25.45 25.45 0 0 1 18.1 6.77c5.73 5.21 8.6 13.28 8.6 28.65v3Zm12.63-27.61c-8.07 0-12.5 6.38-12.5 17.06h24.35c0-10.66-4.68-17.06-11.85-17.06ZM416.1 104.24h-13.46l-8.07-30.34c-2.08-7.81-4.3-18-4.3-18h-.26s-1 6.51-4.3 18.62l-7.94 29.69h-13.42l-18-65.25 14.2-2 7.16 31.91c1.82 8.2 3.39 17.32 3.39 17.32h.39a178.91 178.91 0 0 1 3.78-17.71l8.47-30.47h14.07l7.43 29.72c2.74 10.68 4.17 18.75 4.17 18.75h.39s1.56-10 3.26-17.71l6.77-30.74h14.85ZM518.15 103.98l-7.81-13.94c-6.24-11.06-10.42-17.31-15.37-22.31a7.64 7.64 0 0 0-5.87-2.69v38.94h-14.71V13.86h27.48c20.19 0 29.3 11.72 29.3 25.79 0 12.89-8.33 24.75-22.4 24.75 3.26 1.69 9.25 10.42 13.93 18l13.28 21.62Zm-20.84-78h-8.21V54.5h7.68c7.81 0 12-1 14.72-3.78 2.47-2.47 4-6.25 4-10.94.05-9.12-4.9-13.81-18.19-13.81ZM555.65 74.94v1c0 9.12 3.39 18.75 16.28 18.75 6.12 0 11.46-2.21 16.41-6.51l5.6 8.73a35.6 35.6 0 0 1-23.7 8.73c-18.62 0-30.34-13.41-30.34-34.51 0-11.59 2.47-19.28 8.21-25.79 5.34-6.12 11.85-8.86 20.19-8.86a25.45 25.45 0 0 1 18.1 6.77c5.73 5.21 8.6 13.28 8.6 28.65v3Zm12.64-27.61c-8.07 0-12.5 6.38-12.5 17.06h24.31c0-10.66-4.65-17.06-11.81-17.06ZM621.81 105.42c-14.46 0-14.46-13-14.46-18.62V30.66a106.73 106.73 0 0 0-1.25-19.27l14.72-3.26c1 4 1.17 9.51 1.17 18.1V82.1c0 8.86.39 10.29 1.43 11.85a4 4 0 0 0 4.69 1l2.34 8.86a22.44 22.44 0 0 1-8.64 1.61ZM646.68 28.32a9.34 9.34 0 0 1-9.25-9.51 9.44 9.44 0 1 1 9.25 9.51Zm-7.16 75.67V39.13l14.46-2.61v67.46ZM695 105.68c-18 0-28-12.63-28-33.86 0-24 14.33-35.42 29-35.42 7.16 0 12.37 1.69 18.23 7.16l-7.13 9.5c-3.91-3.52-7.29-5.08-11.07-5.08a11.2 11.2 0 0 0-10.42 6.64c-2 4-2.73 10.16-2.73 18.36 0 9 1.43 14.72 4.43 18a11.58 11.58 0 0 0 8.73 3.78c4.56 0 9-2.21 13.28-6.51l6.77 8.73c-5.99 5.96-12.24 8.7-21.09 8.7ZM728.31 105.43a9.67 9.67 0 1 1 9.62-9.67 9.63 9.63 0 0 1-9.62 9.67Zm0-17.42a7.78 7.78 0 1 0 7.44 7.75 7.55 7.55 0 0 0-7.44-7.76Zm1.9 13.11c-.42-.73-.6-1-1-1.8-1.07-1.95-1.4-2.5-1.79-2.65a.74.74 0 0 0-.34-.08v4.53h-2.13V90.27h4a3 3 0 0 1 3.2 3.17 2.78 2.78 0 0 1-2.42 3 2.49 2.49 0 0 1 .44.47c.62.78 2.6 4.21 2.6 4.21Zm-1.11-8.95a4.35 4.35 0 0 0-1.22-.16h-.78v2.94h.73c.94 0 1.35-.11 1.64-.37a1.53 1.53 0 0 0 .42-1.09 1.28 1.28 0 0 0-.79-1.32Z"/><path d="M168.72 55.82C161.07 20.67 118.92 0 74.56 9.64S.45 55.6 8.09 90.74s49.8 55.83 94.15 46.18 74.12-45.92 66.48-81.1Zm-80.31 49.86a32.4 32.4 0 1 1 32.4-32.4 32.4 32.4 0 0 1-32.4 32.4Z" transform="translate(-6.9 -7.27)"/><path d="M95.57 27.92a46.52 46.52 0 1 0 46.53 46.52 46.52 46.52 0 0 0-46.53-46.52Zm-7.17 73.66a28.3 28.3 0 1 1 28.3-28.3 28.3 28.3 0 0 1-28.29 28.3Z" transform="translate(-6.9 -7.27)"/></svg>; - case 'integrations/newrelic': return <svg fill="none" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><g clipPath="url(#a)"><path d="M57.048 28.04v24.921l-21.73 12.463V81L70.64 60.752V20.25l-13.592 7.79Z" fill="#00AC69"/><path d="m35.322 15.581 21.73 12.458 13.591-7.79L35.321 0 0 20.248l13.587 7.791 21.735-12.458Z" fill="#1CE783"/><path d="M21.735 48.294v24.92L35.322 81V40.503L0 20.25v15.58l21.735 12.464Z" fill="#000" fill-opacity=".87"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h70.874v81H0z"/></clipPath></defs></svg>; + case 'integrations/newrelic': return <svg fill="none" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><g clipPath="url(#a)"><path d="M57.048 28.04v24.921l-21.73 12.463V81L70.64 60.752V20.25l-13.592 7.79Z" fill="#00AC69"/><path d="m35.322 15.581 21.73 12.458 13.591-7.79L35.321 0 0 20.248l13.587 7.791 21.735-12.458Z" fill="#1CE783"/><path d="M21.735 48.294v24.92L35.322 81V40.503L0 20.25v15.58l21.735 12.464Z" fill="#000" fillOpacity=".87"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h70.874v81H0z"/></clipPath></defs></svg>; case 'integrations/ngrx': return <svg viewBox="0 0 120 120" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><rect fill="#fff" height="120" rx="6.01" width="120"/><g><path d="M60.08 20.79 22.71 33.76l5.35 49.58 32.02 17.45z" fill="#412846"/><path d="m59.92 20.79 37.37 12.97-5.35 49.58-32.02 17.45z" fill="#4b314f"/><path d="M78.63 48.16a10.08 10.08 0 0 1 2.63 6.77 15 15 0 0 1-2.65 8.25c1.36-1.06 2.93-3.34 4.71-6.82q1.16 10.59-8.58 16.08c2.07-.19 4.83-1.55 8.24-4.1q-5.46 13.17-20.1 13.89a24.42 24.42 0 0 1-15.53-5.67 22.92 22.92 0 0 1-8-11.39C37 62.62 37 62.35 36.76 61.34s.15-1.3.83-2.29a3.7 3.7 0 0 0 .33-2.83 7.12 7.12 0 0 1-1-3.76 3.68 3.68 0 0 1 1.65-2.61 8.47 8.47 0 0 0 2-2.11 10.37 10.37 0 0 0 .21-3.43c0-2 1.1-3.08 3.32-3.26 3.33-.26 5.22-2.77 6.26-3.91a4 4 0 0 1 3-1.13 6.34 6.34 0 0 1 4.94 2.07 20.12 20.12 0 0 1 11 2.87q7.97 4.71 8.7 10.18-.85 7.2-19.29-.37-9.65 2.73-9.49 11.84 0 8.35 8.07 12.14c-2.62-2.58-3.74-4.74-3.36-6.53q8.18 9.69 18.62 7.24a8.78 8.78 0 0 1-7.32-3c4.7-.12 9.14-2.3 13.32-6.58a9.29 9.29 0 0 1-7.61 2.19q10.86-8.51 7.69-19.9zm-13.15-.87a1.07 1.07 0 1 0-1.06-1.07 1.06 1.06 0 0 0 1.06 1.07z" fill="#ba2bd2"/></g></svg>; case 'integrations/openreplay-text': return <svg viewBox="0 0 179 30" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><g fill="none"><path d="M22.426 15 3.296 3.773v22.454L22.426 15Zm2.61-2.32a2.68 2.68 0 0 1 1.33 2.32 2.68 2.68 0 0 1-1.33 2.32L4.065 29.633C2.35 30.639 0 29.488 0 27.31V2.689C0 .512 2.35-.639 4.064.37l20.973 12.31Z" fill="#394EFF"/><path d="M13.752 14.381a.713.713 0 0 1 0 1.238l-5.656 3.283C7.634 19.17 7 18.864 7 18.282v-6.565c0-.58.634-.887 1.096-.619l5.656 3.283Z" fill="#3EAAAF"/><path d="M60.027 8.769c1.076 0 2.064.241 2.965.725.9.484 1.62 1.26 2.157 2.325.538 1.067.807 2.478.807 4.234 0 1.72-.293 3.165-.88 4.334a5.865 5.865 0 0 1-2.615 2.648c-1.157.596-2.586.894-4.289.894-.332 0-.665-.014-1.002-.04a21.19 21.19 0 0 1-.934-.094v5.779H52.7V8.997h2.985l.215 1.586h.175l.167-.2a4.8 4.8 0 0 1 1.48-1.117c.667-.332 1.436-.497 2.305-.497Zm77.203-.003c1.076 0 2.064.242 2.965.726.9.483 1.62 1.258 2.157 2.325.538 1.066.807 2.477.807 4.233 0 1.72-.294 3.165-.88 4.335a5.865 5.865 0 0 1-2.615 2.647c-1.157.596-2.586.894-4.29.894-.33 0-.665-.013-1-.04a21.19 21.19 0 0 1-.935-.094v5.779h-3.536V8.994h2.985l.215 1.586h.175l.167-.2a4.8 4.8 0 0 1 1.48-1.117c.667-.331 1.436-.497 2.305-.497Zm29.642.228 3.873 11.604 3.965-11.604h3.495l-7.434 20.577h-3.482l2.15-5.914h-.98l-5.284-14.663h3.697ZM73.829 8.77c1.317 0 2.431.284 3.34.853.91.569 1.598 1.422 2.064 2.56.466 1.138.7 2.554.7 4.247v.955h-9.065l.002.04c.042.822.188 1.496.438 2.023.3.631.787 1.084 1.459 1.357.672.273 1.573.41 2.702.41.565 0 1.156-.045 1.775-.134.618-.09 1.254-.215 1.909-.377v2.702l-.447.106a16.661 16.661 0 0 1-3.72.418c-1.73 0-3.162-.262-4.296-.786a5.176 5.176 0 0 1-2.534-2.467c-.556-1.12-.834-2.571-.834-4.354 0-1.658.258-3.047.773-4.167.516-1.12 1.257-1.964 2.225-2.533.968-.569 2.138-.853 3.509-.853Zm48.255-.003c1.318 0 2.431.284 3.34.853.91.57 1.598 1.423 2.065 2.56.466 1.138.699 2.554.699 4.248v.954h-9.064l.002.04c.041.822.187 1.496.437 2.023.3.632.787 1.084 1.459 1.357.672.274 1.573.41 2.702.41.565 0 1.156-.045 1.775-.134.618-.09 1.255-.215 1.909-.376v2.701l-.447.106a16.661 16.661 0 0 1-3.72.418c-1.73 0-3.162-.262-4.296-.786a5.176 5.176 0 0 1-2.534-2.466c-.556-1.12-.834-2.572-.834-4.355 0-1.658.258-3.046.773-4.166.516-1.12 1.257-1.965 2.225-2.534.968-.569 2.138-.853 3.51-.853ZM41.641 3.513c1.81 0 3.388.363 4.732 1.09 1.345.725 2.389 1.843 3.133 3.352.744 1.51 1.116 3.43 1.116 5.76 0 2.33-.372 4.249-1.116 5.759-.744 1.51-1.79 2.627-3.14 3.353-1.348.726-2.923 1.088-4.725 1.088-1.801 0-3.374-.362-4.719-1.088-1.344-.726-2.39-1.841-3.139-3.347-.748-1.505-1.122-3.427-1.122-5.766 0-2.338.374-4.26 1.122-5.765.749-1.506 1.795-2.621 3.14-3.347 1.344-.726 2.917-1.089 4.718-1.089Zm114.414 5.253c1.443 0 2.633.181 3.57.544.936.363 1.633.972 2.09 1.828.457.856.685 2.018.685 3.488v9.031h-2.917l-.255-1.518h-.175l-.154.194a4.046 4.046 0 0 1-1.574 1.143 5.9 5.9 0 0 1-2.279.437c-1.46 0-2.6-.379-3.421-1.136-.82-.757-1.23-1.763-1.23-3.017 0-1.344.46-2.395 1.378-3.152l.032-.026c.92-.742 2.391-1.188 4.411-1.338l2.73-.26v-.573l-.005-.242c-.024-.63-.141-1.134-.352-1.512-.238-.426-.614-.726-1.13-.9-.515-.176-1.185-.263-2.01-.263-.555 0-1.187.05-1.895.148-.708.098-1.398.25-2.07.457V9.397l.422-.117c.573-.15 1.187-.267 1.843-.353a17.79 17.79 0 0 1 2.306-.161Zm-66.65.003c.95 0 1.795.183 2.534.55.74.368 1.32.957 1.741 1.768.422.81.632 1.893.632 3.246v9.327h-3.535v-9.126l-.004-.228c-.03-.89-.245-1.518-.642-1.882-.43-.394-1.021-.591-1.774-.591-.359 0-.73.05-1.116.148a4.172 4.172 0 0 0-1.116.47 3.371 3.371 0 0 0-.941.847V23.66h-3.536V8.997h2.93l.243 1.546h.175l.216-.21a5.794 5.794 0 0 1 1.76-1.107 6.425 6.425 0 0 1 2.433-.457Zm16.525-5.231c2.778 0 4.86.504 6.244 1.512 1.385 1.008 2.077 2.578 2.077 4.71 0 1.38-.329 2.536-.988 3.468-.658.932-1.608 1.633-2.85 2.103l-.065.025a8.939 8.939 0 0 1-.404.138h-.001l5.922 8.163h-3.98l-5.456-7.627-.056.001a24.77 24.77 0 0 1-1.68-.021l-1.116-.054v7.701h-3.536V4.17l.43-.085c.437-.084.895-.163 1.372-.237a26.486 26.486 0 0 1 4.087-.31Zm42.642-1.6v21.72h-3.536V1.937h3.536Zm10.373 15.12-2.393.215-.25.028c-.812.104-1.405.318-1.78.644-.412.359-.618.852-.618 1.479 0 .636.188 1.124.564 1.465.377.34.932.51 1.667.51.484 0 .973-.094 1.466-.282l.049-.02c.474-.189.905-.496 1.295-.92v-3.12Zm-99.9-5.373c-.519 0-1.03.1-1.532.302a3.037 3.037 0 0 0-1.277.975v8.037l.21.04c.216.037.456.07.718.101.35.04.69.06 1.021.06 1.399 0 2.45-.376 3.153-1.128.704-.753 1.055-1.998 1.055-3.737 0-1.21-.143-2.15-.43-2.822-.287-.672-.681-1.145-1.183-1.418-.502-.273-1.08-.41-1.734-.41Zm77.204-.003c-.52 0-1.03.101-1.533.303a3.037 3.037 0 0 0-1.277.974v8.037l.21.04c.216.037.455.071.718.101.35.04.69.06 1.021.06 1.399 0 2.45-.376 3.153-1.128.704-.753 1.055-1.998 1.055-3.736 0-1.21-.143-2.15-.43-2.823-.287-.672-.681-1.145-1.183-1.418-.502-.273-1.08-.41-1.734-.41ZM41.64 6.457c-1.075 0-2.01.235-2.803.705-.793.47-1.405 1.232-1.835 2.285-.43 1.053-.645 2.449-.645 4.187 0 1.792.215 3.225.645 4.3.43 1.076 1.04 1.85 1.828 2.326.79.475 1.726.712 2.81.712 1.094 0 2.035-.237 2.823-.712.79-.475 1.396-1.239 1.822-2.292.426-1.053.639-2.444.639-4.173 0-1.783-.215-3.212-.646-4.287-.43-1.075-1.04-1.853-1.828-2.332-.789-.48-1.725-.72-2.81-.72ZM73.79 11.08c-.619 0-1.148.14-1.587.417-.439.278-.773.744-1.001 1.398l-.015.042c-.195.579-.303 1.332-.324 2.259l-.002.064h5.763l-.001-.051c-.02-.95-.127-1.716-.32-2.3-.214-.655-.533-1.123-.954-1.405-.421-.283-.94-.424-1.56-.424Zm48.255-.003c-.619 0-1.147.14-1.587.417-.439.278-.773.744-1.001 1.398l-.015.042c-.195.579-.303 1.332-.324 2.259l-.001.064h5.762l-.001-.05c-.02-.95-.127-1.717-.32-2.302-.214-.654-.532-1.122-.954-1.404-.421-.282-.94-.424-1.56-.424Zm-15.765-4.851c-.538 0-1.02.022-1.445.067-.426.045-.845.103-1.257.175V13.2l.28.025a20.1 20.1 0 0 0 2.113.096c1.685 0 2.922-.285 3.71-.854.79-.568 1.184-1.471 1.184-2.708 0-.824-.164-1.496-.491-2.016-.327-.52-.83-.902-1.506-1.149-.676-.246-1.54-.37-2.588-.37Z" fill="#000"/></g></svg>; case 'integrations/openreplay': return <svg viewBox="0 0 52 59" width={ `${ width }px` } height={ `${ height }px` } fill={ `${ fill }` }><g fill="none"><path d="M44.229 29.5 6.5 7.42v44.16L44.23 29.5Zm5.148-4.564A5.268 5.268 0 0 1 52 29.5c0 1.886-1 3.627-2.623 4.564L8.015 58.275C4.635 60.255 0 57.993 0 53.711V5.29C0 1.007 4.635-1.256 8.015.725l41.362 24.21Z" fill="#394EFF"/><path d="m29.416 28.457-14.623-8.312A1.2 1.2 0 0 0 13 21.19v16.623a1.2 1.2 0 0 0 1.793 1.043l14.623-8.312a1.2 1.2 0 0 0 0-2.086Z" fill="#27A2A8"/></g></svg>; @@ -282,9 +296,11 @@ const SVG = (props: Props) => { case 'lightbulb': return <svg viewBox="0 0 384 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M192 80c0 8.837-7.164 16-16 16-35.29 0-64 28.71-64 64 0 8.837-7.164 16-16 16s-16-7.163-16-16c0-52.935 43.065-96 96-96 8.836 0 16 7.163 16 16zm176 96c0 101.731-51.697 91.541-90.516 192.674a23.722 23.722 0 0 1-5.484 8.369V464h-.018a23.99 23.99 0 0 1-5.241 14.574l-19.535 24.419A24 24 0 0 1 228.465 512h-72.93a24 24 0 0 1-18.741-9.007l-19.535-24.419A23.983 23.983 0 0 1 112.018 464H112v-86.997a24.153 24.153 0 0 1-5.54-8.478c-38.977-101.401-90.897-90.757-90.457-193.822C16.415 78.01 95.306 0 192 0c97.195 0 176 78.803 176 176zM240 448h-96v12.775L159.38 480h65.24L240 460.775V448zm0-64h-96v32h96v-32zm96-208c0-79.59-64.424-144-144-144-79.59 0-144 64.423-144 144 0 87.475 44.144 70.908 86.347 176h115.306C291.779 247.101 336 263.222 336 176z"/></svg>; case 'link-45deg': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M4.715 6.542 3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 8.586 5.5L8 6.086a1.002 1.002 0 0 0-.154.199 2 2 0 0 1 .861 3.337L6.88 11.45a2 2 0 1 1-2.83-2.83l.793-.792a4.018 4.018 0 0 1-.128-1.287z"/><path d="M6.586 4.672A3 3 0 0 0 7.414 9.5l.775-.776a2 2 0 0 1-.896-3.346L9.12 3.55a2 2 0 1 1 2.83 2.83l-.793.792c.112.42.155.855.128 1.287l1.372-1.372a3 3 0 1 0-4.243-4.243L6.586 4.672z"/></svg>; case 'list-alt': return <svg viewBox="0 0 512 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M464 64c8.823 0 16 7.178 16 16v352c0 8.822-7.177 16-16 16H48c-8.823 0-16-7.178-16-16V80c0-8.822 7.177-16 16-16h416m0-32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zm-336 96c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0 96c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0 96c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm288-148v-24a6 6 0 0 0-6-6H198a6 6 0 0 0-6 6v24a6 6 0 0 0 6 6h212a6 6 0 0 0 6-6zm0 96v-24a6 6 0 0 0-6-6H198a6 6 0 0 0-6 6v24a6 6 0 0 0 6 6h212a6 6 0 0 0 6-6zm0 96v-24a6 6 0 0 0-6-6H198a6 6 0 0 0-6 6v24a6 6 0 0 0 6 6h212a6 6 0 0 0 6-6z"/></svg>; + case 'list-arrow': return <svg preserveAspectRatio="none" viewBox="0 0 338 247" width={ `${ width }px` } height={ `${ height }px` } ><path d="m260.695 120.004-1.29-.764 1.29.764ZM337.938.008l-15.364 7.997 14.608 9.307.756-17.304ZM147.764 210.533l-1.056 1.066 1.056-1.066ZM1.136 246.494c15.445-1.408 33.125-1.007 51.104-.905 17.926.101 36.122-.097 52.4-2.747 16.27-2.649 30.811-7.774 41.287-17.672 10.525-9.946 16.759-24.527 16.759-45.666h-3c0 20.506-6.021 34.227-15.819 43.485-9.848 9.305-23.701 14.286-39.709 16.892-16 2.604-33.966 2.809-51.901 2.708-17.883-.101-35.763-.508-51.393.917l.272 2.988Zm145.572-34.895c6.319 6.26 14.176 8.174 22.945 6.375 8.68-1.781 18.247-7.19 28.282-15.504 20.085-16.641 42.501-45.306 64.051-81.702l-2.581-1.528c-21.473 36.264-43.681 64.595-63.384 80.92-9.86 8.169-18.979 13.235-26.972 14.875-7.904 1.622-14.706-.095-20.229-5.567l-2.112 2.131Zm115.278-90.831c54.766-92.492 52.962-82.74 69.951-108.55l-2.506-1.649c-16.82 25.553-15.232 16.13-70.026 108.671l2.581 1.528Zm-99.3 58.736c0-1.051-.102-1.975-.335-2.749-.231-.769-.627-1.5-1.293-1.999-1.453-1.088-3.159-.444-4.313.284-2.441 1.542-5.298 5.158-7.689 9.371-2.423 4.271-4.524 9.428-5.304 14.279-.771 4.793-.305 9.678 2.956 12.909l2.112-2.131c-2.225-2.204-2.823-5.845-2.106-10.302.708-4.4 2.648-9.216 4.951-13.274 2.336-4.116 4.892-7.185 6.682-8.315.962-.608 1.076-.297.914-.419-.02-.015.097.062.217.462.12.396.208 1.003.208 1.884h3Z"/></svg>; case 'list-ul': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M5 11.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm-3 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>; case 'list': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/></svg>; case 'lock-alt': return <svg viewBox="0 0 448 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M224 420c-11 0-20-9-20-20v-64c0-11 9-20 20-20s20 9 20 20v64c0 11-9 20-20 20zm224-148v192c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V272c0-26.5 21.5-48 48-48h16v-64C64 71.6 136-.3 224.5 0 312.9.3 384 73.1 384 161.5V224h16c26.5 0 48 21.5 48 48zM96 224h256v-64c0-70.6-57.4-128-128-128S96 89.4 96 160v64zm320 240V272c0-8.8-7.2-16-16-16H48c-8.8 0-16 7.2-16 16v192c0 8.8 7.2 16 16 16h352c8.8 0 16-7.2 16-16z"/></svg>; + case 'magic': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M9.5 2.672a.5.5 0 1 0 1 0V.843a.5.5 0 0 0-1 0v1.829Zm4.5.035A.5.5 0 0 0 13.293 2L12 3.293a.5.5 0 1 0 .707.707L14 2.707ZM7.293 4A.5.5 0 1 0 8 3.293L6.707 2A.5.5 0 0 0 6 2.707L7.293 4Zm-.621 2.5a.5.5 0 1 0 0-1H4.843a.5.5 0 1 0 0 1h1.829Zm8.485 0a.5.5 0 1 0 0-1h-1.829a.5.5 0 0 0 0 1h1.829ZM13.293 10A.5.5 0 1 0 14 9.293L12.707 8a.5.5 0 1 0-.707.707L13.293 10ZM9.5 11.157a.5.5 0 0 0 1 0V9.328a.5.5 0 0 0-1 0v1.829Zm1.854-5.097a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L8.646 5.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0l1.293-1.293Zm-3 3a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L.646 13.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0L8.354 9.06Z"/></svg>; case 'map-marker-alt': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M12.166 8.94c-.524 1.062-1.234 2.12-1.96 3.07A31.493 31.493 0 0 1 8 14.58a31.481 31.481 0 0 1-2.206-2.57c-.726-.95-1.436-2.008-1.96-3.07C3.304 7.867 3 6.862 3 6a5 5 0 0 1 10 0c0 .862-.305 1.867-.834 2.94zM8 16s6-5.686 6-10A6 6 0 0 0 2 6c0 4.314 6 10 6 10z"/><path d="M8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 1a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/></svg>; case 'memory': return <svg viewBox="0 0 640 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M496 272h32V144h-96v128h64zm-32-96h32v64h-32v-64zm-128 96h32V144h-96v128h64zm-32-96h32v64h-32v-64zm-128 96h32V144h-96v128h64zm-32-96h32v64h-32v-64zm488-16h8V96c0-17.67-14.33-32-32-32H32C14.33 64 0 78.33 0 96v64h8c13.26 0 24 10.74 24 24 0 13.25-10.74 24-24 24H0v240h640V208h-8c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24zm-24 256h-80v-16c0-8.84-7.16-16-16-16s-16 7.16-16 16v16h-96v-16c0-8.84-7.16-16-16-16s-16 7.16-16 16v16h-96v-16c0-8.84-7.16-16-16-16s-16 7.16-16 16v16h-96v-16c0-8.84-7.16-16-16-16s-16 7.16-16 16v16H32v-64h576v64zm0-282.59c-18.91 9-32 28.3-32 50.59s13.09 41.59 32 50.59V320H32v-85.41c18.9-9 32-28.3 32-50.59s-13.1-41.59-32-50.59V96h576v37.41z"/></svg>; case 'mic-mute': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M13 8c0 .564-.094 1.107-.266 1.613l-.814-.814A4.02 4.02 0 0 0 12 8V7a.5.5 0 0 1 1 0v1zm-5 4c.818 0 1.578-.245 2.212-.667l.718.719a4.973 4.973 0 0 1-2.43.923V15h3a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1h3v-2.025A5 5 0 0 1 3 8V7a.5.5 0 0 1 1 0v1a4 4 0 0 0 4 4zm3-9v4.879l-1-1V3a2 2 0 0 0-3.997-.118l-.845-.845A3.001 3.001 0 0 1 11 3z"/><path d="m9.486 10.607-.748-.748A2 2 0 0 1 6 8v-.878l-1-1V8a3 3 0 0 0 4.486 2.607zm-7.84-9.253 12 12 .708-.708-12-12-.708.708z"/></svg>; @@ -292,10 +308,11 @@ const SVG = (props: Props) => { case 'minus': return <svg viewBox="0 0 448 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M436 274c6.6 0 12-5.4 12-12v-12c0-6.6-5.4-12-12-12H12c-6.6 0-12 5.4-12 12v12c0 6.6 5.4 12 12 12h424z"/></svg>; case 'mobile': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M11 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6zM5 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H5z"/><path d="M8 14a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>; case 'mouse-alt': return <svg viewBox="0 0 384 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M224 0h-64A160 160 0 0 0 0 160v192a160 160 0 0 0 160 160h64a160 160 0 0 0 160-160V160A160 160 0 0 0 224 0zm128 352a128.14 128.14 0 0 1-128 128h-64A128.14 128.14 0 0 1 32 352V160A128.14 128.14 0 0 1 160 32h64a128.14 128.14 0 0 1 128 128zM192 80a48.05 48.05 0 0 0-48 48v32a48 48 0 0 0 96 0v-32a48.05 48.05 0 0 0-48-48zm16 80a16 16 0 0 1-32 0v-32a16 16 0 0 1 32 0z"/></svg>; + case 'network': return <svg viewBox="0 0 13 14" width={ `${ width }px` } height={ `${ height }px` } ><g clipPath="url(#a)"><path d="M3.649 4.875a.396.396 0 1 0 0-.792.396.396 0 0 0 0 .792ZM2.461 4.48a.396.396 0 1 1-.793 0 .396.396 0 0 1 .793 0Z" fillOpacity=".6"/><path d="M.084 4.083A1.584 1.584 0 0 1 1.668 2.5h9.507a1.584 1.584 0 0 1 1.585 1.584v.792a1.584 1.584 0 0 1-1.585 1.585H6.818v2.377a1.188 1.188 0 0 1 1.188 1.188h4.357a.396.396 0 1 1 0 .792H8.006a1.188 1.188 0 0 1-1.188 1.188h-.792a1.189 1.189 0 0 1-1.189-1.188H.48a.396.396 0 1 1 0-.792h4.357a1.188 1.188 0 0 1 1.189-1.188V6.46H1.668A1.584 1.584 0 0 1 .084 4.875v-.792Zm.792 0v.792a.792.792 0 0 0 .792.793h9.507a.792.792 0 0 0 .792-.793v-.792a.792.792 0 0 0-.792-.792H1.668a.792.792 0 0 0-.792.792Zm4.754 5.942v.792a.396.396 0 0 0 .396.396h.792a.396.396 0 0 0 .396-.396v-.792a.396.396 0 0 0-.396-.396h-.792a.396.396 0 0 0-.396.396Z"/></g><defs><clipPath id="a"><path transform="translate(.084 .914)" d="M0 0h12.676v12.676H0z"/></clipPath></defs></svg>; case 'next1': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/></svg>; - case 'no-dashboard': return <svg viewBox="0 0 100 100" width={ `${ width }px` } height={ `${ height }px` } ><rect width="100" height="100" rx="13.158" fill-opacity=".08"/><g clipPath="url(#a)" fill-opacity=".5"><path d="M27.417 33.333a2.083 2.083 0 1 0 0-4.166 2.083 2.083 0 0 0 0 4.166Zm8.333-2.083a2.083 2.083 0 1 1-4.167 0 2.083 2.083 0 0 1 4.167 0Zm4.167 2.083a2.083 2.083 0 1 0 0-4.166 2.083 2.083 0 0 0 0 4.166Z"/><path d="M25.333 20.833A8.333 8.333 0 0 0 17 29.167v41.666a8.334 8.334 0 0 0 8.333 8.334h50a8.333 8.333 0 0 0 8.334-8.334V29.167a8.333 8.333 0 0 0-8.334-8.334h-50ZM79.5 29.167V37.5H21.167v-8.333A4.167 4.167 0 0 1 25.333 25h50a4.167 4.167 0 0 1 4.167 4.167ZM25.333 75a4.167 4.167 0 0 1-4.166-4.167V41.667H79.5v29.166A4.167 4.167 0 0 1 75.333 75h-50Z"/></g><defs><clipPath id="a"><path fill="#fff" transform="translate(17 20)" d="M0 0h66.667v60H0z"/></clipPath></defs></svg>; + case 'no-dashboard': return <svg viewBox="0 0 100 100" width={ `${ width }px` } height={ `${ height }px` } ><rect width="100" height="100" rx="13.158" fillOpacity=".08"/><g clipPath="url(#a)" fillOpacity=".5"><path d="M27.417 33.333a2.083 2.083 0 1 0 0-4.166 2.083 2.083 0 0 0 0 4.166Zm8.333-2.083a2.083 2.083 0 1 1-4.167 0 2.083 2.083 0 0 1 4.167 0Zm4.167 2.083a2.083 2.083 0 1 0 0-4.166 2.083 2.083 0 0 0 0 4.166Z"/><path d="M25.333 20.833A8.333 8.333 0 0 0 17 29.167v41.666a8.334 8.334 0 0 0 8.333 8.334h50a8.333 8.333 0 0 0 8.334-8.334V29.167a8.333 8.333 0 0 0-8.334-8.334h-50ZM79.5 29.167V37.5H21.167v-8.333A4.167 4.167 0 0 1 25.333 25h50a4.167 4.167 0 0 1 4.167 4.167ZM25.333 75a4.167 4.167 0 0 1-4.166-4.167V41.667H79.5v29.166A4.167 4.167 0 0 1 75.333 75h-50Z"/></g><defs><clipPath id="a"><path fill="#fff" transform="translate(17 20)" d="M0 0h66.667v60H0z"/></clipPath></defs></svg>; case 'no-metrics-chart': return <svg viewBox="0 0 250 78" width={ `${ width }px` } height={ `${ height }px` } ><path clipRule="evenodd" d="m239.854 9.853-58.513 58.8L93.005 29.55 9.44 68.51l-.422-.906L92.995 28.45l88.122 39.01 58.029-58.314.708.706Z" fill="#C2C2C2"/><path d="M9.66 77.694c5.334 0 9.659-4.325 9.659-9.66 0-5.334-4.325-9.66-9.66-9.66C4.325 58.375 0 62.7 0 68.035c0 5.335 4.325 9.66 9.66 9.66Z" fill="#C7CCF9"/><path d="M92.985 38.907c5.334 0 9.659-4.325 9.659-9.66 0-5.334-4.325-9.659-9.66-9.659a9.66 9.66 0 0 0-9.659 9.66 9.66 9.66 0 0 0 9.66 9.66Z" fill="#B4E4E7"/><path d="M180.31 77.694c5.335 0 9.659-4.325 9.659-9.66 0-5.334-4.324-9.66-9.659-9.66-5.335 0-9.66 4.326-9.66 9.66 0 5.335 4.325 9.66 9.66 9.66Z" fill="#C7CCF9"/><path d="M239.659 19.319c5.335 0 9.66-4.325 9.66-9.66 0-5.334-4.325-9.659-9.66-9.659C234.325 0 230 4.325 230 9.66c0 5.334 4.325 9.659 9.659 9.659Z" fill="#B4E4E7"/></svg>; - case 'no-metrics': return <svg viewBox="0 0 100 100" width={ `${ width }px` } height={ `${ height }px` } ><rect width="100" height="100" rx="13.158" fill-opacity=".08"/><g clipPath="url(#a)" fill-opacity=".5"><path d="M36.875 65A1.875 1.875 0 0 1 35 63.125v-7.5a1.875 1.875 0 0 1 1.875-1.875h3.75a1.875 1.875 0 0 1 1.875 1.875v7.5A1.875 1.875 0 0 1 40.625 65h-3.75Zm11.25 0a1.875 1.875 0 0 1-1.875-1.875v-15a1.875 1.875 0 0 1 1.875-1.875h3.75a1.875 1.875 0 0 1 1.875 1.875v15A1.875 1.875 0 0 1 51.875 65h-3.75Zm11.25 0a1.875 1.875 0 0 1-1.875-1.875v-22.5a1.875 1.875 0 0 1 1.875-1.875h3.75A1.875 1.875 0 0 1 65 40.625v22.5A1.875 1.875 0 0 1 63.125 65h-3.75Z"/><path d="M35 20a7.5 7.5 0 0 0-7.5 7.5v45A7.5 7.5 0 0 0 35 80h30a7.5 7.5 0 0 0 7.5-7.5v-45A7.5 7.5 0 0 0 65 20H35Zm0 3.75h30a3.75 3.75 0 0 1 3.75 3.75v45A3.75 3.75 0 0 1 65 76.25H35a3.75 3.75 0 0 1-3.75-3.75v-45A3.75 3.75 0 0 1 35 23.75Z"/></g><defs><clipPath id="a"><path fill="#fff" transform="translate(20 20)" d="M0 0h60v60H0z"/></clipPath></defs></svg>; + case 'no-metrics': return <svg viewBox="0 0 100 100" width={ `${ width }px` } height={ `${ height }px` } ><rect width="100" height="100" rx="13.158" fillOpacity=".08"/><g clipPath="url(#a)" fillOpacity=".5"><path d="M36.875 65A1.875 1.875 0 0 1 35 63.125v-7.5a1.875 1.875 0 0 1 1.875-1.875h3.75a1.875 1.875 0 0 1 1.875 1.875v7.5A1.875 1.875 0 0 1 40.625 65h-3.75Zm11.25 0a1.875 1.875 0 0 1-1.875-1.875v-15a1.875 1.875 0 0 1 1.875-1.875h3.75a1.875 1.875 0 0 1 1.875 1.875v15A1.875 1.875 0 0 1 51.875 65h-3.75Zm11.25 0a1.875 1.875 0 0 1-1.875-1.875v-22.5a1.875 1.875 0 0 1 1.875-1.875h3.75A1.875 1.875 0 0 1 65 40.625v22.5A1.875 1.875 0 0 1 63.125 65h-3.75Z"/><path d="M35 20a7.5 7.5 0 0 0-7.5 7.5v45A7.5 7.5 0 0 0 35 80h30a7.5 7.5 0 0 0 7.5-7.5v-45A7.5 7.5 0 0 0 65 20H35Zm0 3.75h30a3.75 3.75 0 0 1 3.75 3.75v45A3.75 3.75 0 0 1 65 76.25H35a3.75 3.75 0 0 1-3.75-3.75v-45A3.75 3.75 0 0 1 35 23.75Z"/></g><defs><clipPath id="a"><path fill="#fff" transform="translate(20 20)" d="M0 0h60v60H0z"/></clipPath></defs></svg>; case 'os/android': return <svg viewBox="0 0 419 519" width={ `${ width }px` } height={ `${ height }px` } ><path d="M271.926 51.66C315.852 74.373 345.991 120.142 346 172.9c0 5.033-4.077 9.1-9.1 9.1H82.1a9.097 9.097 0 0 1-9.1-9.1c0-52.767 30.148-98.537 74.074-121.24L124.351 13.79c-2.584-4.313-1.192-9.9 3.122-12.484 4.313-2.585 9.9-1.202 12.485 3.12l23.978 39.965c14.278-5.077 29.566-7.99 45.564-7.99 15.998 0 31.286 2.913 45.564 7.99l23.978-39.964a9.08 9.08 0 0 1 12.485-3.121c4.314 2.584 5.706 8.17 3.122 12.484L271.926 51.66ZM91.546 163.801h235.908C322.795 102.808 271.671 54.61 209.5 54.61c-62.171 0-113.295 48.2-117.954 109.192ZM273.993 104a6.006 6.006 0 0 1 6.007 6v12c0 3.314-2.685 6-5.998 6h-12.004a5.998 5.998 0 0 1-5.998-6v-12c0-3.314 2.685-6 5.998-6h11.995Zm-116.99 0a5.998 5.998 0 0 1 5.997 6v12c0 3.314-2.685 6-5.998 6h-12.004a5.998 5.998 0 0 1-5.998-6v-12c0-3.314 2.685-6 5.998-6h12.004ZM336.9 191c5.032 0 9.1 4.073 9.1 9.111v183.78c0 24.263-19.729 43.998-43.99 43.998H291.4v54.721c0 20.063-16.325 36.39-36.4 36.39s-36.4-16.327-36.4-36.39V427.89h-18.2v54.721c0 20.063-16.325 36.39-36.4 36.39s-36.4-16.327-36.4-36.39V427.89h-10.61c-24.252 0-43.99-19.735-43.99-43.998v-183.78c0-5.038 4.077-9.111 9.1-9.111h254.8Zm-9.1 192.891V209.222H91.2v174.67c0 14.204 11.575 25.775 25.799 25.775H136.7c5.023 0 9.1 4.072 9.1 9.11v63.833c0 10.013 8.163 18.168 18.2 18.168 10.037 0 18.2-8.146 18.2-18.168v-63.832c0-5.039 4.077-9.111 9.1-9.111h36.4c5.023 0 9.1 4.072 9.1 9.11v63.833c0 10.013 8.163 18.168 18.2 18.168 10.037 0 18.2-8.146 18.2-18.168v-63.832c0-5.039 4.077-9.111 9.1-9.111h19.71c14.224 0 25.79-11.562 25.79-25.776ZM387.5 191c17.37 0 31.5 14.298 31.5 31.87v127.26c0 17.572-14.13 31.87-31.5 31.87-17.37 0-31.5-14.298-31.5-31.87V222.87c0-17.572 14.13-31.87 31.5-31.87ZM401 350.13V222.87c0-7.54-6.057-13.68-13.5-13.68s-13.5 6.14-13.5 13.68v127.26c0 7.54 6.057 13.68 13.5 13.68s13.5-6.14 13.5-13.68ZM31.5 191c17.37 0 31.5 14.298 31.5 31.87v127.26C63 367.702 48.87 382 31.5 382 14.13 382 0 367.702 0 350.13V222.87C0 205.298 14.13 191 31.5 191ZM45 350.13V222.87c0-7.54-6.057-13.68-13.5-13.68S18 215.33 18 222.87v127.26c0 7.54 6.057 13.68 13.5 13.68S45 357.67 45 350.13Z"/></svg>; case 'os/chrome_os': return <svg viewBox="0 0 517 517" width={ `${ width }px` } height={ `${ height }px` } ><path d="M148.978 223c8.725-25.136 24.616-44.93 47.674-59.383 23.058-14.453 48.297-21.05 75.718-19.794L464 154.191c-20.565-41.474-50.79-73.835-90.674-97.086C337.181 36.368 298.232 26 256.478 26c-34.275 0-67.304 7.54-99.087 22.622C125.61 63.703 98.811 85.068 77 112.718L148.978 223Zm61.483-37.353c-18.07 11.327-30.15 26.373-36.92 45.879l-17.375 50.057-111.15-170.3 11.571-14.668C77 67 110.845 41.93 146.245 25.132 181.488 8.41 218.321 0 256.478 0c46.292 0 89.702 11.556 129.787 34.553l.155.09c44.282 25.814 78.05 61.971 100.874 107.998l19.794 39.92-236.01-12.77c-22.108-.994-42.08 4.237-60.617 15.856ZM179 258.5c0 21.806 7.583 40.34 22.75 55.604C216.917 329.368 235.333 337 257 337s40.083-7.632 55.25-22.896C327.417 298.84 335 280.306 335 258.5c0-21.806-7.583-40.34-22.75-55.604C297.083 187.632 278.667 180 257 180s-40.083 7.632-55.25 22.896C186.583 218.16 179 236.694 179 258.5Zm-26 0c0-28.647 10.282-53.777 30.307-73.93C203.363 164.384 228.422 154 257 154c28.578 0 53.637 10.384 73.693 30.57C350.718 204.723 361 229.853 361 258.5c0 28.647-10.282 53.777-30.307 73.93C310.637 352.616 285.578 363 257 363c-28.578 0-53.637-10.384-73.693-30.57C163.282 312.277 153 287.147 153 258.5ZM474.853 175l-129.839 6.535c17.437 20.54 26.466 44.348 27.089 71.424.623 27.075-6.539 52.128-21.484 75.157L246 489.636c46.082 2.49 89.05-7.78 128.905-30.81 33.005-19.296 59.47-44.504 79.398-75.625 19.928-31.121 31.76-65.043 35.496-101.766 3.736-36.724-1.245-72.201-14.946-106.435Zm24.14-11.66c15.26 38.132 20.834 79.828 16.672 120.726-4.149 40.78-17.341 78.602-39.466 113.155-22.164 34.616-51.648 62.698-88.172 84.05l-.113.067c-44.226 25.555-92.201 37.021-143.317 34.26-10.485-.58-18.184-1.113-23.097-1.598-5.048-.498-12.29-1.44-21.725-2.824l24.403-35.675 104.63-161.538c12.111-18.661 17.804-38.576 17.302-60.406-.486-21.128-7.342-39.204-20.917-55.195l-34.08-40.146 200.98-10.117 6.9 15.24ZM151.164 304.41 63.363 132C38.454 170.73 26 213.207 26 259.433c0 38.105 8.562 73.555 25.687 106.35 17.124 32.796 40.632 60.125 70.522 81.989 29.89 21.863 63.205 35.606 99.945 41.228L281 371.874c-26.154 4.997-51.218 1.093-75.192-11.713-23.975-12.805-42.189-31.39-54.643-55.752Zm66.892 32.818c18.76 10.02 37.782 12.983 58.063 9.108l51.778-9.894L239.5 516.5l-21.279-1.8c-40.865-6.253-78.097-21.61-111.362-45.943-33.108-24.217-59.249-54.608-78.22-90.94C9.56 341.28 0 301.698 0 259.434c0-51.208 13.886-98.568 41.495-141.497L70.5 79.5l103.824 213.092c10.042 19.637 24.454 34.338 43.733 44.636Z"/></svg>; case 'os/fedora': return <svg viewBox="0 0 204.7 200.9" width={ `${ width }px` } height={ `${ height }px` } ><path d="M102.7 1.987c-55.41 0-100.3 44.21-100.4 98.79h-.018v76.47H2.3c.027 12.38 10.22 22.4 22.8 22.4h77.58c55.42-.035 100.3-44.24 100.3-98.79 0-54.58-44.91-98.79-100.4-98.79zm20.39 40.68c16.85 0 32.76 12.7 32.76 30.23 0 1.625.01 3.252-.26 5.095-.467 4.662-4.794 8.012-9.505 7.355-4.711-.665-7.909-5.07-7.037-9.679.08-.526.108-1.352.108-2.772 0-9.938-8.257-13.77-16.06-13.77-7.805 0-14.84 6.462-14.85 13.77.135 8.455 0 16.84 0 25.29l14.49-.107c11.31-.23 11.44 16.54.13 16.46l-14.61.107c-.035 6.801.054 5.571.019 8.996 0 0 .122 8.318-.13 14.62-1.749 18.52-17.76 33.32-37 33.32-20.4 0-37.2-16.41-37.2-36.54.612-20.7 17.38-36.99 38.5-36.8l11.78-.087v16.43l-11.78.106h-.062c-11.6.338-21.55 8.1-21.74 20.34 0 11.15 9.148 20.08 20.5 20.08 11.34 0 20.42-8.124 20.42-20.06l-.018-62.23c.006-1.155.044-2.073.173-3.347 1.914-15.22 15.74-26.82 31.39-26.82z"/></svg>; @@ -327,10 +344,12 @@ const SVG = (props: Props) => { case 'plus': return <svg viewBox="0 0 8 8" width={ `${ width }px` } height={ `${ height }px` } ><path d="M4 0a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 4 0Z"/></svg>; case 'prev1': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/></svg>; case 'puzzle-piece': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M6.75 1a.75.75 0 0 1 .75.75V8a.5.5 0 0 0 1 0V5.467l.086-.004c.317-.012.637-.008.816.027.134.027.294.096.448.182.077.042.15.147.15.314V8a.5.5 0 1 0 1 0V6.435a4.9 4.9 0 0 1 .106-.01c.316-.024.584-.01.708.04.118.046.3.207.486.43.081.096.15.19.2.259V8.5a.5.5 0 0 0 1 0v-1h.342a1 1 0 0 1 .995 1.1l-.271 2.715a2.5 2.5 0 0 1-.317.991l-1.395 2.442a.5.5 0 0 1-.434.252H6.035a.5.5 0 0 1-.416-.223l-1.433-2.15a1.5 1.5 0 0 1-.243-.666l-.345-3.105a.5.5 0 0 1 .399-.546L5 8.11V9a.5.5 0 0 0 1 0V1.75A.75.75 0 0 1 6.75 1zM8.5 4.466V1.75a1.75 1.75 0 1 0-3.5 0v5.34l-1.2.24a1.5 1.5 0 0 0-1.196 1.636l.345 3.106a2.5 2.5 0 0 0 .405 1.11l1.433 2.15A1.5 1.5 0 0 0 6.035 16h6.385a1.5 1.5 0 0 0 1.302-.756l1.395-2.441a3.5 3.5 0 0 0 .444-1.389l.271-2.715a2 2 0 0 0-1.99-2.199h-.581a5.114 5.114 0 0 0-.195-.248c-.191-.229-.51-.568-.88-.716-.364-.146-.846-.132-1.158-.108l-.132.012a1.26 1.26 0 0 0-.56-.642 2.632 2.632 0 0 0-.738-.288c-.31-.062-.739-.058-1.05-.046l-.048.002zm2.094 2.025z"/></svg>; + case 'puzzle': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M3.112 3.645A1.5 1.5 0 0 1 4.605 2H7a.5.5 0 0 1 .5.5v.382c0 .696-.497 1.182-.872 1.469a.459.459 0 0 0-.115.118.113.113 0 0 0-.012.025L6.5 4.5v.003l.003.01c.004.01.014.028.036.053a.86.86 0 0 0 .27.194C7.09 4.9 7.51 5 8 5c.492 0 .912-.1 1.19-.24a.86.86 0 0 0 .271-.194.213.213 0 0 0 .039-.063v-.009a.112.112 0 0 0-.012-.025.459.459 0 0 0-.115-.118c-.375-.287-.872-.773-.872-1.469V2.5A.5.5 0 0 1 9 2h2.395a1.5 1.5 0 0 1 1.493 1.645L12.645 6.5h.237c.195 0 .42-.147.675-.48.21-.274.528-.52.943-.52.568 0 .947.447 1.154.862C15.877 6.807 16 7.387 16 8s-.123 1.193-.346 1.638c-.207.415-.586.862-1.154.862-.415 0-.733-.246-.943-.52-.255-.333-.48-.48-.675-.48h-.237l.243 2.855A1.5 1.5 0 0 1 11.395 14H9a.5.5 0 0 1-.5-.5v-.382c0-.696.497-1.182.872-1.469a.459.459 0 0 0 .115-.118.113.113 0 0 0 .012-.025L9.5 11.5v-.003a.214.214 0 0 0-.039-.064.859.859 0 0 0-.27-.193C8.91 11.1 8.49 11 8 11c-.491 0-.912.1-1.19.24a.859.859 0 0 0-.271.194.214.214 0 0 0-.039.063v.003l.001.006a.113.113 0 0 0 .012.025c.016.027.05.068.115.118.375.287.872.773.872 1.469v.382a.5.5 0 0 1-.5.5H4.605a1.5 1.5 0 0 1-1.493-1.645L3.356 9.5h-.238c-.195 0-.42.147-.675.48-.21.274-.528.52-.943.52-.568 0-.947-.447-1.154-.862C.123 9.193 0 8.613 0 8s.123-1.193.346-1.638C.553 5.947.932 5.5 1.5 5.5c.415 0 .733.246.943.52.255.333.48.48.675.48h.238l-.244-2.855zM4.605 3a.5.5 0 0 0-.498.55l.001.007.29 3.4A.5.5 0 0 1 3.9 7.5h-.782c-.696 0-1.182-.497-1.469-.872a.459.459 0 0 0-.118-.115.112.112 0 0 0-.025-.012L1.5 6.5h-.003a.213.213 0 0 0-.064.039.86.86 0 0 0-.193.27C1.1 7.09 1 7.51 1 8c0 .491.1.912.24 1.19.07.14.14.225.194.271a.213.213 0 0 0 .063.039H1.5l.006-.001a.112.112 0 0 0 .025-.012.459.459 0 0 0 .118-.115c.287-.375.773-.872 1.469-.872H3.9a.5.5 0 0 1 .498.542l-.29 3.408a.5.5 0 0 0 .497.55h1.878c-.048-.166-.195-.352-.463-.557-.274-.21-.52-.528-.52-.943 0-.568.447-.947.862-1.154C6.807 10.123 7.387 10 8 10s1.193.123 1.638.346c.415.207.862.586.862 1.154 0 .415-.246.733-.52.943-.268.205-.415.39-.463.557h1.878a.5.5 0 0 0 .498-.55l-.001-.007-.29-3.4A.5.5 0 0 1 12.1 8.5h.782c.696 0 1.182.497 1.469.872.05.065.091.099.118.115.013.008.021.01.025.012a.02.02 0 0 0 .006.001h.003a.214.214 0 0 0 .064-.039.86.86 0 0 0 .193-.27c.14-.28.24-.7.24-1.191 0-.492-.1-.912-.24-1.19a.86.86 0 0 0-.194-.271.215.215 0 0 0-.063-.039H14.5l-.006.001a.113.113 0 0 0-.025.012.459.459 0 0 0-.118.115c-.287.375-.773.872-1.469.872H12.1a.5.5 0 0 1-.498-.543l.29-3.407a.5.5 0 0 0-.497-.55H9.517c.048.166.195.352.463.557.274.21.52.528.52.943 0 .568-.447.947-.862 1.154C9.193 5.877 8.613 6 8 6s-1.193-.123-1.638-.346C5.947 5.447 5.5 5.068 5.5 4.5c0-.415.246-.733.52-.943.268-.205.415-.39.463-.557H4.605z"/></svg>; case 'question-circle': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/><path d="M5.255 5.786a.237.237 0 0 0 .241.247h.825c.138 0 .248-.113.266-.25.09-.656.54-1.134 1.342-1.134.686 0 1.314.343 1.314 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.003.217a.25.25 0 0 0 .25.246h.811a.25.25 0 0 0 .25-.25v-.105c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.267 0-2.655.59-2.75 2.286zm1.557 5.763c0 .533.425.927 1.01.927.609 0 1.028-.394 1.028-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94z"/></svg>; case 'question-lg': return <svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M4.475 5.458c-.284 0-.514-.237-.47-.517C4.28 3.24 5.576 2 7.825 2c2.25 0 3.767 1.36 3.767 3.215 0 1.344-.665 2.288-1.79 2.973-1.1.659-1.414 1.118-1.414 2.01v.03a.5.5 0 0 1-.5.5h-.77a.5.5 0 0 1-.5-.495l-.003-.2c-.043-1.221.477-2.001 1.645-2.712 1.03-.632 1.397-1.135 1.397-2.028 0-.979-.758-1.698-1.926-1.698-1.009 0-1.71.529-1.938 1.402-.066.254-.278.461-.54.461h-.777ZM7.496 14c.622 0 1.095-.474 1.095-1.09 0-.618-.473-1.092-1.095-1.092-.606 0-1.087.474-1.087 1.091S6.89 14 7.496 14Z"/></svg>; case 'quote-left': return <svg viewBox="0 0 512 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M464 256h-80v-64c0-35.3 28.7-64 64-64h8c13.3 0 24-10.7 24-24V56c0-13.3-10.7-24-24-24h-8c-88.4 0-160 71.6-160 160v240c0 26.5 21.5 48 48 48h128c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48zm-288 0H96v-64c0-35.3 28.7-64 64-64h8c13.3 0 24-10.7 24-24V56c0-13.3-10.7-24-24-24h-8C71.6 32 0 103.6 0 192v240c0 26.5 21.5 48 48 48h128c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48z"/></svg>; case 'quote-right': return <svg viewBox="0 0 512 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z"/></svg>; + case 'quotes': return <svg viewBox="0 0 29 19" width={ `${ width }px` } height={ `${ height }px` } ><path opacity=".7" d="M11.636 2.905A6.318 6.318 0 0 0 0 6.35a6.326 6.326 0 0 0 9.719 5.336c-.497 1.476-1.423 3.051-2.949 4.63a1.583 1.583 0 1 0 2.277 2.201c5.64-5.844 4.907-12.197 2.588-15.605v-.007Zm15.18 0A6.318 6.318 0 0 0 15.18 6.35a6.326 6.326 0 0 0 9.719 5.336c-.497 1.476-1.423 3.051-2.949 4.63a1.583 1.583 0 1 0 2.277 2.201c5.64-5.844 4.907-12.197 2.588-15.605v-.007Z"/></svg>; case 'redo-back': return <svg viewBox="0 0 496 496" width={ `${ width }px` } height={ `${ height }px` } ><path d="M12 0h10c6.627 0 12 5.373 12 12v110.625C77.196 49.047 157.239-.285 248.793.001 385.18.428 496.213 112.009 496 248.396 495.786 385.181 384.834 496 248 496c-63.926 0-122.202-24.187-166.178-63.908-5.113-4.618-5.354-12.561-.482-17.433l7.069-7.069c4.503-4.503 11.749-4.714 16.482-.454C142.782 441.238 192.935 462 248 462c117.744 0 214-95.331 214-214 0-117.744-95.331-214-214-214-82.862 0-154.737 47.077-190.289 116H172c6.627 0 12 5.373 12 12v10c0 6.627-5.373 12-12 12H12c-6.627 0-12-5.373-12-12V12C0 5.373 5.373 0 12 0Z"/></svg>; case 'redo': return <svg viewBox="0 0 512 512" width={ `${ width }px` } height={ `${ height }px` } ><path d="M492 8h-10c-6.627 0-12 5.373-12 12v110.625C426.804 57.047 346.761 7.715 255.207 8.001 118.82 8.428 7.787 120.009 8 256.396 8.214 393.181 119.166 504 256 504c63.926 0 122.202-24.187 166.178-63.908 5.113-4.618 5.354-12.561.482-17.433l-7.069-7.069c-4.503-4.503-11.749-4.714-16.482-.454C361.218 449.238 311.065 470 256 470c-117.744 0-214-95.331-214-214 0-117.744 95.331-214 214-214 82.862 0 154.737 47.077 190.289 116H332c-6.627 0-12 5.373-12 12v10c0 6.627 5.373 12 12 12h160c6.627 0 12-5.373 12-12V20c0-6.627-5.373-12-12-12z"/></svg>; case 'remote-control': return <svg viewBox="0 0 16 14" width={ `${ width }px` } height={ `${ height }px` } ><path d="M.59.59A2 2 0 0 0 0 2v8a2 2 0 0 0 .59 1.41A2 2 0 0 0 2 12h5.5a.5.5 0 0 0 0-1H2a1 1 0 0 1-.71-.29A1 1 0 0 1 1 10V5h13v1a.5.5 0 0 0 1 0V2a2 2 0 0 0-2-2H2A2 2 0 0 0 .59.59ZM14 4H1V2a1 1 0 0 1 .29-.71A1 1 0 0 1 2 1h11a1 1 0 0 1 1 1ZM2.85 2.85a.48.48 0 0 1-.7 0 .48.48 0 0 1 0-.7.48.48 0 0 1 .7 0 .48.48 0 0 1 0 .7Zm1.5 0a.5.5 0 1 1-.7-.7.5.5 0 1 1 .7.7Zm1.5 0a.5.5 0 1 0-.7-.7.5.5 0 1 0 .7.7ZM15 13a3.48 3.48 0 1 0-2.47 1A3.46 3.46 0 0 0 15 13Zm-4.2-4.46a.31.31 0 0 1 .19 0l3.33 1.34a.33.33 0 0 1 .15.11.34.34 0 0 1 0 .37.3.3 0 0 1-.13.12l-.92.46 1 1a.35.35 0 0 1 .1.24.34.34 0 0 1-.1.23.33.33 0 0 1-.23.1.35.35 0 0 1-.24-.1l-1-1-.46.92a.3.3 0 0 1-.12.13.34.34 0 0 1-.37 0 .33.33 0 0 1-.11-.15L10.52 9a.31.31 0 0 1 0-.19.33.33 0 0 1 .26-.26Z"/></svg>; diff --git a/frontend/app/components/ui/SegmentSelection/SegmentSelection.js b/frontend/app/components/ui/SegmentSelection/SegmentSelection.js index 97db6cef1..d3c71b6cf 100644 --- a/frontend/app/components/ui/SegmentSelection/SegmentSelection.js +++ b/frontend/app/components/ui/SegmentSelection/SegmentSelection.js @@ -1,44 +1,62 @@ import React from 'react'; -import { Icon, Popup } from 'UI'; +import { Icon, Tooltip } from 'UI'; import cn from 'classnames'; import styles from './segmentSelection.module.css'; class SegmentSelection extends React.Component { setActiveItem = (item) => { this.props.onSelect(null, { name: this.props.name, value: item.value }); - } + }; render() { - const { className, list, small = false, extraSmall = false, primary = false, size = "normal", icons = false, disabled = false, disabledMessage = 'Not Allowed', outline } = this.props; + const { + className, + list, + small = false, + extraSmall = false, + primary = false, + size = 'normal', + icons = false, + disabled = false, + disabledMessage = 'Not Allowed', + outline, + } = this.props; return ( - <Popup - content={disabledMessage} - disabled={!disabled} - > - <div className={ cn(styles.wrapper, { - [styles.primary] : primary, - [styles.small] : size === 'small' || small, - [styles.extraSmall] : size === 'extraSmall' || extraSmall, - [styles.icons] : icons === true, - [styles.disabled] : disabled, - [styles.outline]: outline, - }, className) } + <Tooltip title={disabledMessage} disabled={!disabled}> + <div + className={cn( + styles.wrapper, + { + [styles.primary]: primary, + [styles.small]: size === 'small' || small, + [styles.extraSmall]: size === 'extraSmall' || extraSmall, + [styles.icons]: icons === true, + [styles.disabled]: disabled, + [styles.outline]: outline, + }, + className + )} > - { list.map(item => ( - <div - key={ item.name } - className={ cn(styles.item, 'w-full', { 'opacity-25 cursor-default' : item.disabled }) } - data-active={ this.props.value && this.props.value.value === item.value } - onClick={ () => !item.disabled && this.setActiveItem(item) } - > - { item.icon && <Icon name={ item.icon } size={(size === "extraSmall" || icons) ? 14 : 20} marginRight={ item.name ? "6" : "" } /> } - <div className="leading-none">{ item.name }</div> - </div> - )) - } + {list.map((item) => ( + <div + key={item.name} + className={cn(styles.item, 'w-full', { 'opacity-25 cursor-default': item.disabled })} + data-active={this.props.value && this.props.value.value === item.value} + onClick={() => !item.disabled && this.setActiveItem(item)} + > + {item.icon && ( + <Icon + name={item.icon} + size={size === 'extraSmall' || icons ? 14 : 20} + marginRight={item.name ? '6' : ''} + /> + )} + <div className="leading-none">{item.name}</div> + </div> + ))} </div> - </Popup> + </Tooltip> ); } } diff --git a/frontend/app/components/ui/SideMenuitem/SideMenuitem.js b/frontend/app/components/ui/SideMenuitem/SideMenuitem.js index 7c8e8272a..8538a9a63 100644 --- a/frontend/app/components/ui/SideMenuitem/SideMenuitem.js +++ b/frontend/app/components/ui/SideMenuitem/SideMenuitem.js @@ -1,5 +1,5 @@ import React from 'react'; -import { Icon, Popup } from 'UI'; +import { Icon, Tooltip } from 'UI'; import cn from 'classnames'; import stl from './sideMenuItem.module.css'; @@ -18,12 +18,10 @@ function SideMenuitem({ ...props }) { return ( - <Popup + <Tooltip disabled={ !disabled } - content={ 'No recordings' } - size="tiny" - inverted - position="left center" + title={ 'No recordings' } + placement="left" > <div className={ cn( @@ -51,7 +49,7 @@ function SideMenuitem({ <div onClick={deleteHandler} className={stl.actions}><Icon name="trash" size="14" /></div> } </div> - </Popup> + </Tooltip> ) } diff --git a/frontend/app/components/ui/Tabs/Tabs.js b/frontend/app/components/ui/Tabs/Tabs.js index cd9921161..248dae3dd 100644 --- a/frontend/app/components/ui/Tabs/Tabs.js +++ b/frontend/app/components/ui/Tabs/Tabs.js @@ -2,7 +2,7 @@ import React from 'react'; import cn from 'classnames'; import stl from './tabs.module.css'; -const Tabs = ({ tabs, active, onClick, border = true, className }) => ( +const Tabs = ({ tabs, active, onClick, border = true, className = '' }) => ( <div className={ cn(stl.tabs, className, { [ stl.bordered ]: border }) } role="tablist" > { tabs.map(({ key, text, hidden = false, disabled = false }) => ( <div diff --git a/frontend/app/components/ui/TextEllipsis/TextEllipsis.js b/frontend/app/components/ui/TextEllipsis/TextEllipsis.js index 036d12d46..7cd51e39f 100644 --- a/frontend/app/components/ui/TextEllipsis/TextEllipsis.js +++ b/frontend/app/components/ui/TextEllipsis/TextEllipsis.js @@ -1,10 +1,10 @@ import React from 'react'; import { useState, useRef, useEffect, forwardRef } from 'react'; import cn from 'classnames'; -import { Popup } from 'UI'; +import { Tooltip } from 'UI'; import styles from './textEllipsis.module.css'; -/** calculates text width in pixels +/** calculates text width in pixels * by creating a hidden element with * text and counting its width * @param text String - text string @@ -12,96 +12,100 @@ import styles from './textEllipsis.module.css'; * @returns width number */ function findTextWidth(text, fontProp) { - const tag = document.createElement('div') + const tag = document.createElement('div'); - tag.style.position = 'absolute' - tag.style.left = '-99in' - tag.style.whiteSpace = 'nowrap' - tag.style.font = fontProp - tag.innerHTML = text + tag.style.position = 'absolute'; + tag.style.left = '-99in'; + tag.style.whiteSpace = 'nowrap'; + tag.style.font = fontProp; + tag.innerHTML = text; - document.body.appendChild(tag) - const result = tag.clientWidth - document.body.removeChild(tag) + document.body.appendChild(tag); + const result = tag.clientWidth; + document.body.removeChild(tag); - return result; + return result; } const Trigger = forwardRef(({ textOrChildren, maxWidth, style, className, ...rest }, ref) => ( - <div - className={ cn(styles.textEllipsis, className) } - style={{ maxWidth, ...style }} - ref={ref} - { ...rest } - > - { textOrChildren } - </div> -)) + <div + className={cn(styles.textEllipsis, className)} + style={{ maxWidth, ...style }} + ref={ref} + {...rest} + > + {textOrChildren} + </div> +)); -const TextEllipsis = ({ - text, - hintText = text, - children = null, - maxWidth="auto", - style = {}, - className="", - noHint=false, - popupProps={}, - hintProps={}, - ...props +const TextEllipsis = ({ + text, + hintText = text, + children = null, + maxWidth = 'auto', + style = {}, + className = '', + noHint = false, + popupProps = {}, + hintProps = {}, + ...props }) => { - const [showPopup, setShowPopup] = useState(false) - const [computed, setComputed] = useState(false) - const textRef = useRef(null); + const [showPopup, setShowPopup] = useState(false); + const [computed, setComputed] = useState(false); + const textRef = useRef(null); - const textOrChildren = text || children; - - const popupId = (Math.random() + 1).toString(36).substring(2); + const textOrChildren = text || children; - useEffect(() => { - if (computed) return; - if (textRef.current) { - const element = textRef.current; + const popupId = (Math.random() + 1).toString(36).substring(2); - const fontSize = window.getComputedStyle(element, null).getPropertyValue('font-size'); - - const textWidth = findTextWidth(element.innerText, fontSize) - if (textWidth > element.clientWidth) setShowPopup(true) - else setShowPopup(false) - setComputed(true) - } - - }, [textRef.current, computed]) + useEffect(() => { + if (computed) return; + if (textRef.current) { + const element = textRef.current; - if (noHint || !showPopup) return ( - <Trigger - className={className} - maxWidth={maxWidth} - style={style} - textOrChildren={textOrChildren} - ref={textRef} - {...props} - /> - ) + const fontSize = window.getComputedStyle(element, null).getPropertyValue('font-size'); - return ( - <Popup - content={ <div className="customPopupText" { ...hintProps } >{ hintText || textOrChildren }</div> } - { ...popupProps } - > - <Trigger - className={className} - maxWidth={maxWidth} - style={style} - textOrChildren={textOrChildren} - id={popupId} - ref={textRef} - {...props} - /> - </Popup> - ); + const textWidth = findTextWidth(element.innerText, fontSize); + if (textWidth > element.clientWidth) setShowPopup(true); + else setShowPopup(false); + setComputed(true); + } + }, [textRef.current, computed]); + + if (noHint || !showPopup) + return ( + <Trigger + className={className} + maxWidth={maxWidth} + style={style} + textOrChildren={textOrChildren} + ref={textRef} + {...props} + /> + ); + + return ( + <Tooltip + title={ + <div className="customPopupText" {...hintProps}> + {hintText || textOrChildren} + </div> + } + {...popupProps} + > + <Trigger + className={className} + maxWidth={maxWidth} + style={style} + textOrChildren={textOrChildren} + id={popupId} + ref={textRef} + {...props} + /> + </Tooltip> + ); }; -TextEllipsis.displayName ="TextEllipsis"; +TextEllipsis.displayName = 'TextEllipsis'; export default TextEllipsis; diff --git a/frontend/app/components/ui/TextLabel/TextLabel.js b/frontend/app/components/ui/TextLabel/TextLabel.js index cdadce948..dbd855d66 100644 --- a/frontend/app/components/ui/TextLabel/TextLabel.js +++ b/frontend/app/components/ui/TextLabel/TextLabel.js @@ -1,6 +1,6 @@ import React from 'react'; import cn from 'classnames'; -import { Icon, Popup } from 'UI'; +import { Icon, Tooltip } from 'UI'; import styles from './textLabel.module.css'; export default function TextLabel({ @@ -12,26 +12,27 @@ export default function TextLabel({ textTransform = '', color = 'gray-medium', iconColor = color, -}) { +}) { return ( - <div className={ cn("flex items-center", styles.sessionLabel) } style={ { minWidth: `${ minWidth }` } }> - <Icon name={ icon } size="16" color={ iconColor } /> - { popupLabel ? - <Popup - content={ popupLabel } - size="mini" - inverted - > - <div style={ { maxWidth: `${ maxWidth }px` } } className={textTransform}>{ label }</div> - </Popup> - : + <div + className={cn('flex items-center', styles.sessionLabel)} + style={{ minWidth: `${minWidth}` }} + > + <Icon name={icon} size="16" color={iconColor} /> + {popupLabel ? ( + <Tooltip title={popupLabel}> + <div style={{ maxWidth: `${maxWidth}px` }} className={textTransform}> + {label} + </div> + </Tooltip> + ) : ( <div - style={ { maxWidth: `${ maxWidth }px`, lineHeight: '16px' } } + style={{ maxWidth: `${maxWidth}px`, lineHeight: '16px' }} className={cn(`color-${color}`, textTransform)} // textTransform by tailwind > - { label } + {label} </div> - } + )} </div> ); } diff --git a/frontend/app/components/ui/TimelinePointer/TimelinePointer.js b/frontend/app/components/ui/TimelinePointer/TimelinePointer.js index 00ac7fff7..56791d057 100644 --- a/frontend/app/components/ui/TimelinePointer/TimelinePointer.js +++ b/frontend/app/components/ui/TimelinePointer/TimelinePointer.js @@ -1,24 +1,19 @@ -import React from 'react' -import { Icon, Popup } from 'UI' -import stl from './timelinePointer.module.css' -import cn from 'classnames' +import React from 'react'; +import { Icon, Tooltip } from 'UI'; +import stl from './timelinePointer.module.css'; +import cn from 'classnames'; function TimelinePointer({ icon, content }) { return ( - <Popup - // offset={20} - // pinned - distance={15} - content={content} - > - <div className={cn(stl.wrapper, 'flex items-center justify-center relative')}> + <Tooltip title={content}> + <div className={cn(stl.wrapper, 'flex items-center justify-center relative')}> <div className={stl.pin} /> - <div style={{ top: '3px' }} className={stl.icon} > + <div style={{ top: '3px' }} className={stl.icon}> <Icon name={icon} size="18" style={{ fill: '#D3545F' }} /> </div> </div> - </Popup> - ) + </Tooltip> + ); } -export default TimelinePointer +export default TimelinePointer; diff --git a/frontend/app/components/ui/Toggler/Toggler.js b/frontend/app/components/ui/Toggler/Toggler.js index 7aa670743..2fcb31f0d 100644 --- a/frontend/app/components/ui/Toggler/Toggler.js +++ b/frontend/app/components/ui/Toggler/Toggler.js @@ -5,7 +5,7 @@ export default ({ onChange, name, className = '', checked, label = '', plain = f <div className={className}> <label className={styles.label}> <div className={plain ? styles.switchPlain : styles.switch}> - <input type={styles.checkbox} onClick={onChange} name={name} checked={checked} /> + <input type={styles.checkbox} onClick={onChange} name={name} defaultChecked={checked} /> <span className={`${plain ? styles.sliderPlain : styles.slider} ${checked ? styles.checked : ''}`} /> </div> {label && <span>{label}</span>} diff --git a/frontend/app/components/ui/Tooltip/FloatingTooltip.tsx b/frontend/app/components/ui/Tooltip/FloatingTooltip.tsx new file mode 100644 index 000000000..c157940de --- /dev/null +++ b/frontend/app/components/ui/Tooltip/FloatingTooltip.tsx @@ -0,0 +1,173 @@ +import * as React from 'react'; +import { mergeRefs } from 'react-merge-refs'; +import { + useFloating, + autoUpdate, + offset as _offset, + flip, + shift, + useHover, + useFocus, + useDismiss, + useRole, + useInteractions, + FloatingPortal, + arrow, + computePosition, +} from '@floating-ui/react-dom-interactions'; +import type { Placement } from '@floating-ui/react-dom-interactions'; +import { INDEXES } from 'App/constants/zindex'; + +export function useTooltipState({ + disabled = false, + initialOpen = false, + placement = 'top', + offset = 5, + delay, + arrowRef = null, +}: { + disabled?: boolean; + initialOpen?: boolean; + placement?: Placement; + offset?: number; + delay?: number; + arrowRef?: any; +} = {}) { + const [open, setOpen] = React.useState(initialOpen); + const staticSide = mapPlacementSideToCSSProperty(placement); + + React.useEffect(() => { + if (disabled) { + setOpen(false); + } + }, [disabled]); + + const data = useFloating({ + placement, + open, + onOpenChange: setOpen, + whileElementsMounted: autoUpdate, + middleware: [_offset(offset), flip(), shift(), arrow({ element: arrowRef })], + }); + + const context = data.context; + + const hover = useHover(context, { move: false, restMs: delay, enabled: !disabled }); + const focus = useFocus(context); + const dismiss = useDismiss(context); + const role = useRole(context, { role: 'tooltip' }); + const interactions = useInteractions([hover, focus, dismiss, role]); + + return React.useMemo( + () => ({ + open, + setOpen, + arrowRef, + ...interactions, + ...data, + staticSide, + }), + [open, setOpen, interactions, data] + ); +} + +type TooltipState = ReturnType<typeof useTooltipState>; + +export const TooltipAnchor = React.forwardRef< + HTMLElement, + React.HTMLProps<HTMLElement> & { + state: TooltipState; + asChild?: boolean; + } +>(function TooltipAnchor({ children, state, asChild = false, ...props }, propRef) { + const childrenRef = (children as any).ref; + + const ref = React.useMemo( + () => mergeRefs([state.reference, propRef, childrenRef]), + [state.reference, propRef, childrenRef] + ); + + // `asChild` allows the user to pass any element as the anchor + if (asChild && React.isValidElement(children)) { + return React.cloneElement( + children, + state.getReferenceProps({ ref, ...props, ...children.props }) + ); + } + + return ( + <div ref={ref} {...state.getReferenceProps(props)}> + {children} + </div> + ); +}); + +export const FloatingTooltip = React.forwardRef< + HTMLDivElement, + React.HTMLProps<HTMLDivElement> & { state: TooltipState } +>(function Tooltip({ state, ...props }, propRef) { + const ref = React.useMemo(() => mergeRefs([state.floating, propRef]), [state.floating, propRef]); + + return ( + <FloatingPortal> + {state.open && ( + <div + ref={ref} + style={{ + position: state.strategy, + top: state.y ?? 0, + left: state.x ?? 0, + visibility: state.x == null ? 'hidden' : 'visible', + transition: 'opacity 1s', + zIndex: INDEXES.TOOLTIP, + ...props.style, + }} + {...state.getFloatingProps(props)} + /> + )} + </FloatingPortal> + ); +}); + +function mapPlacementSideToCSSProperty(placement: Placement) { + const staticSide = { + top: 'bottom', + right: 'left', + bottom: 'top', + left: 'right', + }[placement.split('-')[0]]; + + return staticSide; +} + +export const FloatingArrow = React.forwardRef< + HTMLDivElement, + React.HTMLProps<HTMLDivElement> & { state: TooltipState } +>(function Tooltip({ state, ...props }, propRef) { + const ref = React.useMemo(() => state.arrowRef, [state.arrowRef, propRef]); + const { x: arrowX, y: arrowY } = state.middlewareData?.arrow || { x: 0, y: 0 }; + const staticSide = state.staticSide; + + return ( + <FloatingPortal> + {state.open && ( + <div + ref={ref} + style={{ + width: '20px', + height: '20px', + backgroundColor: 'white', + position: state.strategy, + left: arrowX != null ? `${arrowX + state.x}px` : '', + top: arrowY != null ? `${arrowY + state.y}px` : '', + [staticSide]: '-10px', + zIndex: INDEXES.TOOLTIP - 1, + transform: 'rotate(45deg)', + ...props.style, + }} + {...state.getFloatingProps(props)} + /> + )} + </FloatingPortal> + ); +}); diff --git a/frontend/app/components/ui/Tooltip/Tooltip.tsx b/frontend/app/components/ui/Tooltip/Tooltip.tsx index 6a14ce3f7..5cc7a021c 100644 --- a/frontend/app/components/ui/Tooltip/Tooltip.tsx +++ b/frontend/app/components/ui/Tooltip/Tooltip.tsx @@ -1,51 +1,53 @@ import React from 'react'; -import { Popup } from 'UI'; +import { useTooltipState, TooltipAnchor, FloatingTooltip, FloatingArrow } from './FloatingTooltip'; +import type { Placement } from '@floating-ui/react-dom-interactions'; +import cn from 'classnames'; interface Props { - timeout: number - position: string - tooltip: string - trigger: React.ReactNode + title?: any; + children: any; + disabled?: boolean; + open?: boolean; + placement?: Placement; + className?: string; + delay?: number; + style?: any; + offset?: number; +} +function Tooltip(props: Props) { + const { + title, + disabled = false, + open = false, + placement, + className = '', + delay = 500, + style = {}, + offset = 5, + } = props; + const arrowRef = React.useRef(null); + + const state = useTooltipState({ + disabled: disabled, + placement, + delay, + initialOpen: open, + offset, + arrowRef, + }); + + return ( + <div className="relative"> + <TooltipAnchor state={state}>{props.children}</TooltipAnchor> + <FloatingTooltip + state={state} + className={cn('bg-gray-darkest color-white rounded py-1 px-2 animate-fade', className)} + > + {title} + {/* <FloatingArrow state={state} className="" /> */} + </FloatingTooltip> + </div> + ); } -export default class Tooltip extends React.PureComponent<Props> { - static defaultProps = { - timeout: 500, - } - state = { - open: false, - } - mouseOver = false - onMouseEnter = () => { - this.mouseOver = true; - setTimeout(() => { - if (this.mouseOver) this.setState({ open: true }); - }, this.props.timeout) - } - onMouseLeave = () => { - this.mouseOver = false; - this.setState({ - open: false, - }); - } - - render() { - const { trigger, tooltip, position } = this.props; - const { open } = this.state; - return ( - <Popup - open={open} - content={tooltip} - disabled={!tooltip} - position={position} - > - <span //TODO: no wrap component around - onMouseEnter={ this.onMouseEnter } - onMouseLeave={ this.onMouseLeave } - > - { trigger } - </span> - </Popup> - ); - } -} \ No newline at end of file +export default Tooltip; diff --git a/frontend/app/components/ui/index.js b/frontend/app/components/ui/index.js index db7ea7d37..7b18e3c64 100644 --- a/frontend/app/components/ui/index.js +++ b/frontend/app/components/ui/index.js @@ -3,7 +3,6 @@ export { default as Link } from './Link'; // export { default as Dropdown } from './Dropdown'; export { default as Button } from './Button'; export { default as Label } from './Label'; -export { default as Popup } from './Popup'; export { default as Progress } from './Progress'; export { default as SlideModal } from './SlideModal'; export { default as NoContent } from './NoContent'; @@ -57,3 +56,4 @@ export { default as Input } from './Input'; export { default as Form } from './Form'; export { default as Modal } from './Modal'; export { default as Message } from './Message'; +export { default as Popover } from './Popover'; diff --git a/frontend/app/constants/countries.js b/frontend/app/constants/countries.js index 9927066da..d78494729 100644 --- a/frontend/app/constants/countries.js +++ b/frontend/app/constants/countries.js @@ -62,7 +62,6 @@ export default { CX: 'Christmas Island', CY: 'Cyprus', CZ: 'Czech Republic', - DD: 'Germany', DE: 'Germany', DG: 'Diego Garcia', DJ: 'Djibouti', diff --git a/frontend/app/constants/storageKeys.ts b/frontend/app/constants/storageKeys.ts index be644872a..58a5ae70c 100644 --- a/frontend/app/constants/storageKeys.ts +++ b/frontend/app/constants/storageKeys.ts @@ -2,4 +2,5 @@ export const SKIP_TO_ISSUE = "__$session-skipToIssue$__" export const TIMEZONE = "__$session-timezone$__" export const DURATION_FILTER = "__$session-durationFilter$__" export const SESSION_FILTER = "__$session-filter$__" -export const GLOBAL_DESTINATION_PATH = "__$global-destinationPath$__" \ No newline at end of file +export const GLOBAL_DESTINATION_PATH = "__$global-destinationPath$__" +export const GLOBAL_HAS_NO_RECORDINGS = "__$global-hasNoRecordings$__" \ No newline at end of file diff --git a/frontend/app/constants/zindex.ts b/frontend/app/constants/zindex.ts index 807223caf..f70b77d56 100644 --- a/frontend/app/constants/zindex.ts +++ b/frontend/app/constants/zindex.ts @@ -1,10 +1,13 @@ export const INDEXES = { - POPUP_GUIDE_BG: 99998, - POPUP_GUIDE_BTN: 99999, PLAYER_REQUEST_WINDOW: 10, -} + BUG_REPORT_PICKER: 19, + BUG_REPORT: 20, + POPUP_GUIDE_BG: 99997, + POPUP_GUIDE_BTN: 99998, + TOOLTIP: 99999, +}; export const getHighest = () => { - const allIndexes = Object.values(INDEXES) - return allIndexes[allIndexes.length - 1] + 1 -} + const allIndexes = Object.values(INDEXES); + return allIndexes[allIndexes.length - 1] + 1; +}; diff --git a/frontend/app/date.ts b/frontend/app/date.ts index 59704ad2d..3403abfd6 100644 --- a/frontend/app/date.ts +++ b/frontend/app/date.ts @@ -24,6 +24,12 @@ export function durationFromMsFormatted(ms: number): string { return durationFormatted(Duration.fromMillis(ms || 0)); } +export function durationFromMs(ms: number): string { + const dur = Duration.fromMillis(ms) + + return dur.toFormat('hh:mm:ss') +} + export const durationFormattedFull = (duration: Duration): string => { if (duration.as('minutes') < 1) { // show in seconds let d = duration.toFormat('s'); diff --git a/frontend/app/dev/components/InternalErrorButton.js b/frontend/app/dev/components/InternalErrorButton.js index 388a79302..591eb3b21 100644 --- a/frontend/app/dev/components/InternalErrorButton.js +++ b/frontend/app/dev/components/InternalErrorButton.js @@ -1,3 +1,4 @@ +import React from 'react'; function sendWrongEvent() { const a = {}; diff --git a/frontend/app/duck/alerts.js b/frontend/app/duck/alerts.js index dcc3c1633..6591ae7e7 100644 --- a/frontend/app/duck/alerts.js +++ b/frontend/app/duck/alerts.js @@ -41,7 +41,7 @@ const reducer = (state = initialState, action = {}) => { export function save(instance) { return { types: crudDuck.actionTypes.SAVE.toArray(), - call: client => client.put( instance[idKey] ? `/alerts/${ instance[idKey] }` : '/alerts', instance.toData()), + call: client => client.post( instance[idKey] ? `/alerts/${ instance[idKey] }` : '/alerts', instance.toData()), }; } diff --git a/frontend/app/duck/assignments.js b/frontend/app/duck/assignments.js index 0892df161..3abb99fb7 100644 --- a/frontend/app/duck/assignments.js +++ b/frontend/app/duck/assignments.js @@ -48,7 +48,7 @@ const reducer = (state = initialState, action = {}) => { return state.set('activeIssue', Assignment({ ...action.data, users})); case FETCH_META.SUCCESS: issueTypes = action.data.issueTypes - var issueTypeIcons = {} + var issueTypeIcons = {} issueTypes.forEach(iss => { issueTypeIcons[iss.id] = iss.iconUrl }) @@ -96,28 +96,28 @@ export function fetchMeta(projectId) { export function fetchAssignments(sessionId) { return { types: FETCH_ASSIGNMENTS.toArray(), - call: client => client.get(`/sessions2/${ sessionId }/assign`) + call: client => client.get(`/sessions/${ sessionId }/assign`) } } export function fetchAssigment(sessionId, id) { return { types: FETCH_ASSIGNMENT.toArray(), - call: client => client.get(`/sessions2/${ sessionId }/assign/${ id }`) + call: client => client.get(`/sessions/${ sessionId }/assign/${ id }`) } } export function addActivity(sessionId, params) { - const data = { ...params, assignee: params.assignee.value, issueType: params.issueType.value } + const data = { ...params, assignee: params.assignee, issueType: params.issueType } return { types: ADD_ACTIVITY.toArray(), - call: client => client.post(`/sessions2/${ sessionId }/assign/projects/${params.projectId.value}`, data), + call: client => client.post(`/sessions/${ sessionId }/assign/projects/${params.projectId}`, data), } } export function addMessage(sessionId, assignmentId, params) { return { types: ADD_MESSAGE.toArray(), - call: client => client.post(`/sessions2/${ sessionId }/assign/${ assignmentId }/comment`, params), + call: client => client.post(`/sessions/${ sessionId }/assign/${ assignmentId }/comment`, params), } } diff --git a/frontend/app/duck/issues.js b/frontend/app/duck/issues.js index fcd6d9584..6c2c70733 100644 --- a/frontend/app/duck/issues.js +++ b/frontend/app/duck/issues.js @@ -84,7 +84,7 @@ export const edit = createEdit(name); export function fetchAssignments(sessionId) { return { types: FETCH_ASSIGNMENTS.toArray(), - call: client => client.get(`/sessions2/${ sessionId }/assign`) + call: client => client.get(`/sessions/${ sessionId }/assign`) } } @@ -104,7 +104,7 @@ export function fetchProjects() { export function fetchIssue(sessionId, id) { return { types: FETCH_ISSUE.toArray(), - call: client => client.get(`/sessions2/${ sessionId }/assign/jira/${ id }`) + call: client => client.get(`/sessions/${ sessionId }/assign/jira/${ id }`) } } @@ -118,13 +118,13 @@ export function fetchMeta(projectId) { export function addActivity(sessionId, params) { return { types: ADD_ACTIVITY.toArray(), - call: client => client.post(`/sessions2/${ sessionId }/assign`, params.toCreate()), + call: client => client.post(`/sessions/${ sessionId }/assign`, params.toCreate()), } } export function addMessage(sessionId, assignmentId, params) { return { types: ADD_MESSAGE.toArray(), - call: client => client.post(`/sessions2/${ sessionId }/assign/${ assignmentId }/comment`, params), + call: client => client.post(`/sessions/${ sessionId }/assign/${ assignmentId }/comment`, params), } -} \ No newline at end of file +} diff --git a/frontend/app/duck/roles.js b/frontend/app/duck/roles.js index 139e3c29e..3015d556c 100644 --- a/frontend/app/duck/roles.js +++ b/frontend/app/duck/roles.js @@ -5,7 +5,7 @@ import { reduceDucks } from 'Duck/tools'; import { createListUpdater } from './funcTools/tools'; const crudDuck = crudDuckGenerator('client/role', Role, { idKey: 'roleId' }); -export const { fetchList, init, edit, remove, } = crudDuck.actions; +export const { fetchList, init, edit, remove } = crudDuck.actions; const RESET_ERRORS = 'roles/RESET_ERRORS'; @@ -18,23 +18,24 @@ const initialState = Map({ { text: 'Dashboard', value: 'METRICS' }, { text: 'Assist (Live)', value: 'ASSIST_LIVE' }, { text: 'Assist (Call)', value: 'ASSIST_CALL' }, - ]) + ]), }); // const name = "role"; -const idKey = "roleId"; +const idKey = 'roleId'; const updateItemInList = createListUpdater(idKey); -const updateInstance = (state, instance) => state.getIn([ "instance", idKey ]) === instance[ idKey ] - ? state.mergeIn([ "instance" ], instance) - : state; +const updateInstance = (state, instance) => + state.getIn(['instance', idKey]) === instance[idKey] + ? state.mergeIn(['instance'], instance) + : state; const reducer = (state = initialState, action = {}) => { switch (action.type) { case RESET_ERRORS: return state.setIn(['removeRequest', 'errors'], null); case crudDuck.actionTypes.SAVE.SUCCESS: - return updateItemInList(updateInstance(state, action.data), action.data); + return updateItemInList(updateInstance(state, action.data), Role(action.data)); } return state; }; @@ -42,14 +43,17 @@ const reducer = (state = initialState, action = {}) => { export function save(instance) { return { types: crudDuck.actionTypes.SAVE.toArray(), - call: client => instance.roleId ? client.post(`/client/roles/${ instance.roleId }`, instance.toData()) : client.put(`/client/roles`, instance.toData()), + call: (client) => + instance.roleId + ? client.post(`/client/roles/${instance.roleId}`, instance.toData()) + : client.put(`/client/roles`, instance.toData()), }; } export function resetErrors() { return { type: RESET_ERRORS, - } + }; } export default reduceDucks(crudDuck, { initialState, reducer }).reducer; diff --git a/frontend/app/duck/search.js b/frontend/app/duck/search.js index 5876abbb0..569eec435 100644 --- a/frontend/app/duck/search.js +++ b/frontend/app/duck/search.js @@ -5,16 +5,18 @@ import { array, success, createListUpdater, mergeReducers } from './funcTools/to import Filter from 'Types/filter'; import SavedFilter from 'Types/filter/savedFilter'; import { errors as errorsRoute, isRoute } from 'App/routes'; -import { fetchList as fetchSessionList } from './sessions'; +import { fetchList as fetchSessionList, fetchAutoplayList } from './sessions'; import { fetchList as fetchErrorsList } from './errors'; import { FilterCategory, FilterKey } from 'Types/filter/filterType'; import { filtersMap, liveFiltersMap, generateFilterOptions } from 'Types/filter/newFilter'; import { DURATION_FILTER } from 'App/constants/storageKeys'; +import Period, { CUSTOM_RANGE } from 'Types/app/period'; const ERRORS_ROUTE = errorsRoute(); const name = 'search'; const idKey = 'searchId'; +const PER_PAGE = 10; const FETCH_LIST = fetchListType(name); const FETCH_FILTER_SEARCH = fetchListType(`${name}/FILTER_SEARCH`); @@ -33,25 +35,30 @@ const SET_ACTIVE_TAB = `${name}/SET_ACTIVE_TAB`; const SET_SCROLL_POSITION = `${name}/SET_SCROLL_POSITION`; const REFRESH_FILTER_OPTIONS = 'filters/REFRESH_FILTER_OPTIONS'; +const CHECK_LATEST = fetchListType(`${name}/CHECK_LATEST`); +const UPDATE_LATEST_REQUEST_TIME = 'filters/UPDATE_LATEST_REQUEST_TIME' -function chartWrapper(chart = []) { - return chart.map((point) => ({ ...point, count: Math.max(point.count, 0) })); -} +// function chartWrapper(chart = []) { +// return chart.map((point) => ({ ...point, count: Math.max(point.count, 0) })); +// } -const savedSearchIdKey = 'searchId'; -const updateItemInList = createListUpdater(savedSearchIdKey); -const updateInstance = (state, instance) => - state.getIn(['savedSearch', savedSearchIdKey]) === instance[savedSearchIdKey] ? state.mergeIn(['savedSearch'], SavedFilter(instance)) : state; +// const savedSearchIdKey = 'searchId'; +// const updateItemInList = createListUpdater(savedSearchIdKey); +// const updateInstance = (state, instance) => +// state.getIn(['savedSearch', savedSearchIdKey]) === instance[savedSearchIdKey] ? state.mergeIn(['savedSearch'], SavedFilter(instance)) : state; const initialState = Map({ filterList: generateFilterOptions(filtersMap), filterListLive: generateFilterOptions(liveFiltersMap), list: List(), + latestRequestTime: null, + latestList: List(), alertMetricId: null, instance: new Filter({ filters: [] }), savedSearch: new SavedFilter({}), filterSearchList: {}, currentPage: 1, + pageSize: PER_PAGE, activeTab: { name: 'All', type: 'all' }, scrollY: 0, }); @@ -73,6 +80,10 @@ function reducer(state = initialState, action = {}) { 'list', List(data.map(SavedFilter)).sortBy((i) => i.searchId) ); + case UPDATE_LATEST_REQUEST_TIME: + return state.set('latestRequestTime', Date.now()).set('latestList', []) + case success(CHECK_LATEST): + return state.set('latestList', action.data) case success(FETCH_FILTER_SEARCH): const groupedList = action.data.reduce((acc, item) => { const { projectId, type, value } = item; @@ -131,50 +142,69 @@ export const filterMap = ({ category, value, key, operator, sourceOperator, sour filters: filters ? filters.map(filterMap) : [], }); + +const getFilters = (state) => { + const filter = state.getIn(['search', 'instance']).toData(); + const activeTab = state.getIn(['search', 'activeTab']); + if (activeTab.type !== 'all' && activeTab.type !== 'bookmark' && activeTab.type !== 'vault') { + const tmpFilter = filtersMap[FilterKey.ISSUE]; + tmpFilter.value = [activeTab.type]; + filter.filters = filter.filters.concat(tmpFilter); + } + + if (activeTab.type === 'bookmark' || activeTab.type === 'vault') { + filter.bookmarked = true; + } + + filter.filters = filter.filters.map(filterMap); + + // duration filter from local storage + if (!filter.filters.find((f) => f.type === FilterKey.DURATION)) { + const durationFilter = JSON.parse(localStorage.getItem(DURATION_FILTER) || '{"count": 0}'); + let durationValue = parseInt(durationFilter.count); + if (durationValue > 0) { + const value = [0]; + durationValue = durationFilter.countType === 'min' ? durationValue * 60 * 1000 : durationValue * 1000; + if (durationFilter.operator === '<') { + value[0] = durationValue; + } else if (durationFilter.operator === '>') { + value[1] = durationValue; + } + + filter.filters = filter.filters.concat({ + type: FilterKey.DURATION, + operator: 'is', + value, + }); + } + } + + return filter; +} + export const reduceThenFetchResource = (actionCreator) => (...args) => (dispatch, getState) => { dispatch(actionCreator(...args)); - const filter = getState().getIn(['search', 'instance']).toData(); - const activeTab = getState().getIn(['search', 'activeTab']); - if (activeTab.type !== 'all' && activeTab.type !== 'bookmark' && activeTab.type !== 'vault') { - const tmpFilter = filtersMap[FilterKey.ISSUE]; - tmpFilter.value = [activeTab.type]; - filter.filters = filter.filters.concat(tmpFilter); - } - - if (activeTab.type === 'bookmark' || activeTab.type === 'vault') { - filter.bookmarked = true; - } - - filter.filters = filter.filters.map(filterMap); - filter.limit = 10; + if (activeTab.type === 'notes') return; + + const filter = getFilters(getState()); + filter.limit = PER_PAGE; filter.page = getState().getIn(['search', 'currentPage']); + const forceFetch = filter.filters.length === 0 || args[1] === true; - // duration filter from local storage - if (!filter.filters.find((f) => f.type === FilterKey.DURATION)) { - const durationFilter = JSON.parse(localStorage.getItem(DURATION_FILTER) || '{"count": 0}'); - let durationValue = parseInt(durationFilter.count); - if (durationValue > 0) { - const value = [0]; - durationValue = durationFilter.countType === 'min' ? durationValue * 60 * 1000 : durationValue * 1000; - if (durationFilter.operator === '<') { - value[0] = durationValue; - } else if (durationFilter.operator === '>') { - value[1] = durationValue; - } - - filter.filters = filter.filters.concat({ - type: FilterKey.DURATION, - operator: 'is', - value, - }); - } + // reset the timestamps to latest + if (filter.rangeValue !== CUSTOM_RANGE) { + const period = new Period({ rangeName: filter.rangeValue }) + const newTimestamps = period.toJSON(); + filter.startDate = newTimestamps.startDate + filter.endDate = newTimestamps.endDate } + dispatch(updateLatestRequestTime()) return isRoute(ERRORS_ROUTE, window.location.pathname) ? dispatch(fetchErrorsList(filter)) : dispatch(fetchSessionList(filter, forceFetch)); }; @@ -351,3 +381,33 @@ export const setScrollPosition = (scrollPosition) => { scrollPosition, }; }; + +export const updateLatestRequestTime = () => { + return { + type: UPDATE_LATEST_REQUEST_TIME + } +} + +export const checkForLatestSessions = () => (dispatch, getState) => { + const state = getState(); + const filter = getFilters(state); + const latestRequestTime = state.getIn(['search', 'latestRequestTime']) + if (!!latestRequestTime) { + const period = new Period({ rangeName: CUSTOM_RANGE, start: latestRequestTime, end: Date.now() }) + const newTimestamps = period.toJSON(); + filter.startDate = newTimestamps.startDate + filter.endDate = newTimestamps.endDate + } + + return dispatch({ + types: array(CHECK_LATEST), + call: (client) => client.post(`/sessions/search/ids`, filter), + }); +} + +export const fetchAutoplaySessions = (page) => (dispatch, getState) => { + const filter = getFilters(getState()); + filter.page = page; + filter.limit = PER_PAGE; + return dispatch(fetchAutoplayList(filter)); +} \ No newline at end of file diff --git a/frontend/app/duck/sessions.js b/frontend/app/duck/sessions.js index d2556fce3..ecce3d713 100644 --- a/frontend/app/duck/sessions.js +++ b/frontend/app/duck/sessions.js @@ -11,6 +11,7 @@ import { getDateRangeFromValue } from 'App/dateRange'; const name = 'sessions'; const INIT = 'sessions/INIT'; const FETCH_LIST = new RequestTypes('sessions/FETCH_LIST'); +const FETCH_AUTOPLAY_LIST = new RequestTypes('sessions/FETCH_AUTOPLAY_LIST'); const FETCH = new RequestTypes('sessions/FETCH'); const FETCH_FAVORITE_LIST = new RequestTypes('sessions/FETCH_FAVORITE_LIST'); const FETCH_LIVE_LIST = new RequestTypes('sessions/FETCH_LIVE_LIST'); @@ -27,6 +28,12 @@ const SET_FUNNEL_PAGE_FLAG = 'sessions/SET_FUNNEL_PAGE_FLAG'; const SET_TIMELINE_POINTER = 'sessions/SET_TIMELINE_POINTER'; const SET_TIMELINE_HOVER_POINTER = 'sessions/SET_TIMELINE_HOVER_POINTER'; +const SET_CREATE_NOTE_TOOLTIP = 'sessions/SET_CREATE_NOTE_TOOLTIP' +const SET_EDIT_NOTE_TOOLTIP = 'sessions/SET_EDIT_NOTE_TOOLTIP' +const FILTER_OUT_NOTE = 'sessions/FILTER_OUT_NOTE' +const ADD_NOTE = 'sessions/ADD_NOTE' +const UPDATE_NOTE = 'sessions/UPDATE_NOTE' + const SET_SESSION_PATH = 'sessions/SET_SESSION_PATH'; const LAST_PLAYED_SESSION_ID = `${name}/LAST_PLAYED_SESSION_ID`; const SET_ACTIVE_TAB = 'sessions/SET_ACTIVE_TAB'; @@ -63,7 +70,8 @@ const initialState = Map({ timelinePointer: null, sessionPath: {}, lastPlayedSessionId: null, - timeLineTooltip: { time: 0, offset: 0, isVisible: false } + timeLineTooltip: { time: 0, offset: 0, isVisible: false }, + createNoteTooltip: { time: 0, isVisible: false, isEdit: false, note: null }, }); const reducer = (state = initialState, action = {}) => { @@ -89,6 +97,10 @@ const reducer = (state = initialState, action = {}) => { list.filter(({ favorite }) => favorite) ) .set('total', total); + case FETCH_AUTOPLAY_LIST.SUCCESS: + let sessionIds = state.get('sessionIds'); + sessionIds = sessionIds.concat(action.data.map(i => i.sessionId + '')) + return state.set('sessionIds', sessionIds.filter((i, index) => sessionIds.indexOf(i) === index )) case SET_AUTOPLAY_VALUES: { const sessionIds = state.get('sessionIds'); const currentSessionId = state.get('current').sessionId; @@ -152,11 +164,11 @@ const reducer = (state = initialState, action = {}) => { const wasInFavorite = state.get('favoriteList').findIndex(({ sessionId }) => sessionId === id) > -1; return state - .update('list', (list) => list.map((session) => (session.sessionId === id ? session.set('favorite', !wasInFavorite) : session))) - .update('favoriteList', (list) => - wasInFavorite ? list.filter(({ sessionId }) => sessionId !== id) : list.push(session.set('favorite', true)) - ) - .update('current', (session) => (session.sessionId === id ? session.set('favorite', !wasInFavorite) : session)); + .update('current', (currentSession) => (currentSession.sessionId === id ? currentSession.set('favorite', !wasInFavorite) : currentSession)) + .update('list', (list) => list.map((listSession) => (listSession.sessionId === id ? listSession.set('favorite', !wasInFavorite) : listSession))) + .update('favoriteList', (list) => session ? + wasInFavorite ? list.filter(({ sessionId }) => sessionId !== id) : list.push(session.set('favorite', true)) : list + ); } case SORT: { const comparator = (s1, s2) => { @@ -192,6 +204,26 @@ const reducer = (state = initialState, action = {}) => { return state.set('timelinePointer', action.pointer); case SET_TIMELINE_HOVER_POINTER: return state.set('timeLineTooltip', action.timeLineTooltip); + case SET_CREATE_NOTE_TOOLTIP: + return state.set('createNoteTooltip', action.noteTooltip); + case SET_EDIT_NOTE_TOOLTIP: + return state.set('createNoteTooltip', action.noteTooltip); + case FILTER_OUT_NOTE: + return state.updateIn(['current', 'notesWithEvents'], (list) => + list.filter(evt => !evt.noteId || evt.noteId !== action.noteId) + ) + case ADD_NOTE: + return state.updateIn(['current', 'notesWithEvents'], (list) => + list.push(action.note).sort((a, b) => { + const aTs = a.time || a.timestamp + const bTs = b.time || b.timestamp + + return aTs - bTs + }) + ) + case UPDATE_NOTE: + const index = state.getIn(['current', 'notesWithEvents']).findIndex(item => item.noteId === action.note.noteId) + return state.setIn(['current', 'notesWithEvents', index], action.note) case SET_SESSION_PATH: return state.set('sessionPath', action.path); case LAST_PLAYED_SESSION_ID: @@ -230,7 +262,7 @@ function init(session) { export const fetchList = (params = {}, force = false) => - (dispatch, getState) => { + (dispatch) => { if (!force) { // compare with the last fetched filter const oldFilters = getSessionFilter(); if (compareJsonObjects(oldFilters, cleanSessionFilters(params))) { @@ -241,15 +273,28 @@ export const fetchList = setSessionFilter(cleanSessionFilters(params)); return dispatch({ types: FETCH_LIST.toArray(), - call: (client) => client.post('/sessions/search2', params), + call: (client) => client.post('/sessions/search', params), params: cleanParams(params), }); }; +export const fetchAutoplayList = + (params = {}) => + (dispatch) => { + setSessionFilter(cleanSessionFilters(params)); + return dispatch({ + types: FETCH_AUTOPLAY_LIST.toArray(), + call: (client) => client.post('/sessions/search/ids', params), + params: cleanParams(params), + }); + }; + + + export function fetchErrorStackList(sessionId, errorId) { return { types: FETCH_ERROR_STACK.toArray(), - call: (client) => client.get(`/sessions2/${sessionId}/errors/${errorId}/sourcemaps`), + call: (client) => client.get(`/sessions/${sessionId}/errors/${errorId}/sourcemaps`), }; } @@ -258,7 +303,7 @@ export const fetch = (dispatch, getState) => { dispatch({ types: FETCH.toArray(), - call: (client) => client.get(isLive ? `/assist/sessions/${sessionId}` : `/sessions2/${sessionId}`), + call: (client) => client.get(isLive ? `/assist/sessions/${sessionId}` : `/sessions/${sessionId}`), filter: getState().getIn(['filters', 'appliedFilter']), }); }; @@ -266,7 +311,7 @@ export const fetch = export function toggleFavorite(sessionId) { return { types: TOGGLE_FAVORITE.toArray(), - call: (client) => client.get(`/sessions2/${sessionId}/favorite`), + call: (client) => client.get(`/sessions/${sessionId}/favorite`), sessionId, }; } @@ -274,7 +319,7 @@ export function toggleFavorite(sessionId) { export function fetchFavoriteList() { return { types: FETCH_FAVORITE_LIST.toArray(), - call: (client) => client.get('/sessions2/favorite'), + call: (client) => client.get('/sessions/favorite'), }; } @@ -362,6 +407,41 @@ export function setTimelineHoverTime(timeLineTooltip) { }; } +export function setCreateNoteTooltip(noteTooltip) { + return { + type: SET_CREATE_NOTE_TOOLTIP, + noteTooltip + } +} + +export function setEditNoteTooltip(noteTooltip) { + return { + type: SET_EDIT_NOTE_TOOLTIP, + noteTooltip + } +} + +export function filterOutNote(noteId) { + return { + type: FILTER_OUT_NOTE, + noteId + } +} + +export function addNote(note) { + return { + type: ADD_NOTE, + note + } +} + +export function updateNote(note) { + return { + type: UPDATE_NOTE, + note + } +} + export function setSessionPath(path) { return { type: SET_SESSION_PATH, @@ -374,4 +454,4 @@ export function updateLastPlayedSession(sessionId) { type: LAST_PLAYED_SESSION_ID, sessionId, }; -} +} \ No newline at end of file diff --git a/frontend/app/duck/site.js b/frontend/app/duck/site.js index 08d04b70e..e1a4b9ea6 100644 --- a/frontend/app/duck/site.js +++ b/frontend/app/duck/site.js @@ -20,6 +20,7 @@ import { } from './funcTools/crud'; import { createRequestReducer } from './funcTools/request'; import { Map, List, fromJS } from "immutable"; +import { GLOBAL_HAS_NO_RECORDINGS } from 'App/constants/storageKeys'; const SITE_ID_STORAGE_KEY = "__$user-siteId$__"; const storedSiteId = localStorage.getItem(SITE_ID_STORAGE_KEY); @@ -54,7 +55,6 @@ const reducer = (state = initialState, action = {}) => { case FETCH_GDPR_SUCCESS: return state.mergeIn([ 'instance', 'gdpr' ], action.data); case success(SAVE): - console.log(action) const newSite = Site(action.data); return updateItemInList(state, newSite) .set('siteId', newSite.get('id')) @@ -65,17 +65,27 @@ const reducer = (state = initialState, action = {}) => { case FETCH_LIST_SUCCESS: let siteId = state.get("siteId"); const siteExists = action.data.map(s => s.projectId).includes(siteId); - if (!siteId || !siteExists) { + if (action.siteIdFromPath) { + siteId = action.siteIdFromPath; + } else if (!siteId || !siteExists) { siteId = !!action.data.find(s => s.projectId === parseInt(storedSiteId)) ? storedSiteId : action.data[0].projectId; } - return state.set('list', List(action.data.map(Site))) + const list = List(action.data.map(Site)); + const hasRecordings = list.some(s => s.recorded); + if (!hasRecordings) { + localStorage.setItem(GLOBAL_HAS_NO_RECORDINGS, true) + } else { + localStorage.removeItem(GLOBAL_HAS_NO_RECORDINGS) + } + + return state.set('list', list) .set('siteId', siteId) - .set('active', List(action.data.map(Site)).find(s => s.id === parseInt(siteId))); + .set('active', list.find(s => s.id === parseInt(siteId))); case SET_SITE_ID: localStorage.setItem(SITE_ID_STORAGE_KEY, action.siteId) - const site = state.get('list').find(s => s.id === action.siteId); + const site = state.get('list').find(s => parseInt(s.id) == action.siteId); return state.set('siteId', action.siteId).set('active', site); } return state; @@ -102,10 +112,11 @@ export function saveGDPR(siteId, gdpr) { }; } -export function fetchList() { +export function fetchList(siteId) { return { types: array(FETCH_LIST), call: client => client.get('/projects'), + siteIdFromPath: siteId }; } diff --git a/frontend/app/duck/tests/runs.js b/frontend/app/duck/tests/runs.js index 19aed0fd0..e5f1ecc3d 100644 --- a/frontend/app/duck/tests/runs.js +++ b/frontend/app/duck/tests/runs.js @@ -40,7 +40,7 @@ const reducer = (state = initialState, action = {}) => { const test = state.get('list').find(({ testId }) => testId === action.testId); const run = Run({ runId: action.data.id, state: RUNNING, testId: action.testId, name: test.name - }); + }); return updateRun(state, action.testId, run); } case STOP_RUN.SUCCESS: { @@ -73,7 +73,7 @@ export default reduceDucks({ reducer, initialState }, requestDuck); export function generateTest(sessionId, params) { return { types: GEN_TEST.toArray(), - call: client => client.post(`/sessions2/${ sessionId }/gentest`, params), + call: client => client.post(`/sessions/${ sessionId }/gentest`, params), }; } diff --git a/frontend/app/hooks/useInputState.ts b/frontend/app/hooks/useInputState.ts index 88e1221b4..2af6fc169 100644 --- a/frontend/app/hooks/useInputState.ts +++ b/frontend/app/hooks/useInputState.ts @@ -2,11 +2,11 @@ import React, { useState, useCallback } from 'react'; type SupportedElements = HTMLInputElement | HTMLSelectElement; -export default function(state: string = ""): [string, React.ChangeEventHandler<SupportedElements>, (string) => void] { +export default function(state: string = ""): [string, React.ChangeEventHandler<SupportedElements>, (value: string) => void] { const [ value, setValue ] = useState<string>(state); const onChange = useCallback( - ({ target: { value } }: React.ChangeEvent<SupportedElements>) => - setValue(value), + ({ target: { value } }: React.ChangeEvent<SupportedElements>) => + setValue(value), []); return [ value, onChange, setValue ]; -} \ No newline at end of file +} diff --git a/frontend/app/initialize.js b/frontend/app/initialize.js index df7909916..d0eb9fb6e 100644 --- a/frontend/app/initialize.js +++ b/frontend/app/initialize.js @@ -1,25 +1,26 @@ import './styles/index.scss'; import React from 'react'; +import { createRoot } from 'react-dom/client'; import './init'; -import { render } from 'react-dom'; import { Provider } from 'react-redux'; import store from './store'; import Router from './Router'; -import { StoreProvider, RootStore } from './mstore'; +import { StoreProvider, RootStore } from './mstore'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { DndProvider } from 'react-dnd'; document.addEventListener('DOMContentLoaded', () => { - render( - ( - <Provider store={ store }> - <StoreProvider store={new RootStore()}> - <DndProvider backend={HTML5Backend}> - <Router /> - </DndProvider> - </StoreProvider> - </Provider> - ), - document.getElementById('app'), - ); + const container = document.getElementById('app'); + const root = createRoot(container); + root.render( + <Provider store={store}> + <StoreProvider store={new RootStore()}> + <DndProvider backend={HTML5Backend}> + {/* <React.StrictMode> */} + <Router /> + {/* </React.StrictMode> */} + </DndProvider> + </StoreProvider> + </Provider> + ); }); diff --git a/frontend/app/logger/index.js b/frontend/app/logger/index.js index d119c139d..8b6d7168f 100644 --- a/frontend/app/logger/index.js +++ b/frontend/app/logger/index.js @@ -1,27 +1,45 @@ import { options } from 'App/dev/console'; function log(...args) { - if (options.verbose) { - console.log(...args); - } + if (options.verbose) { + if (Object.keys(groupTm).length > 0) { + console.groupEnd(); + } + console.log(...args); + } } function warn(...args) { - if (!window.env.PRODUCTION || options.verbose) { - console.warn(...args); - } + if (!window.env.PRODUCTION || options.verbose) { + console.warn(...args); + } } function error(...args) { - if (!window.env.PRODUCTION || options.verbose) { - console.error(...args); - } + if (!window.env.PRODUCTION || options.verbose) { + console.error(...args); + } } +let groupTm = {}; + +function group(groupName, ...args) { + if (!window.env.PRODUCTION || options.verbose) { + if (!groupTm[groupName]) { + groupTm[groupName] = setTimeout(() => { + console.groupEnd() + delete groupTm[groupName] + }, 500); + console.groupCollapsed(groupName); + } + console.log(...args); + } +} export default { - info: log, - log, - warn, - error, -} + info: log, + log, + warn, + error, + group, +}; diff --git a/frontend/app/mstore/bugReportStore.ts b/frontend/app/mstore/bugReportStore.ts new file mode 100644 index 000000000..abb3f5e84 --- /dev/null +++ b/frontend/app/mstore/bugReportStore.ts @@ -0,0 +1,144 @@ +import { makeAutoObservable } from 'mobx'; +import { BugReportPdf, ReportDefaults, Step, Activity } from 'Components/Session_/BugReport/types'; +import { SubItem } from 'App/components/Session_/BugReport/components/StepsComponents/SubModalItems'; + +export enum SeverityLevels { + Low, + Medium, + High, +} + +export default class BugReportStore { + reportTitle = 'Untitled Report'; + comment = ''; + severity = SeverityLevels.High; + + isCommentEdit = false; + isTitleEdit = false; + isSubStepModalOpen = false; + + bugReport: Partial<BugReportPdf>; + sessionEventSteps: Step[] = []; + chosenEventSteps: Step[] = []; + subModalType: 'note' | 'network' | 'error'; + targetStep: string + pickedSubItems: Record<string, Map<string, SubItem>> = {} + + constructor() { + makeAutoObservable(this); + } + + clearStore() { + this.reportTitle = 'Untitled Report'; + this.comment = ''; + this.severity = SeverityLevels.High; + + this.isCommentEdit = false; + this.isTitleEdit = false; + + this.bugReport = undefined; + this.sessionEventSteps = []; + this.chosenEventSteps = []; + this.subModalType = undefined; + this.isSubStepModalOpen = false; + this.targetStep = undefined; + this.pickedSubItems = {}; + } + + toggleTitleEdit(isEdit: boolean) { + this.isTitleEdit = isEdit; + } + + setTitle(title: string) { + if (title.length < 40) { + this.reportTitle = title; + this.bugReport = Object.assign(this.bugReport, { title: this.reportTitle }); + } + } + + setSeverity(severity: SeverityLevels) { + this.severity = severity; + + this.bugReport = Object.assign(this.bugReport, { severity: this.severity }); + } + + toggleCommentEditing(isEdit: boolean) { + this.isCommentEdit = isEdit; + } + + setComment(comment: string) { + this.comment = comment; + + this.bugReport = Object.assign(this.bugReport, { + comment: this.comment.length > 0 ? this.comment : undefined, + }); + } + + updateReportDefaults(defaults: ReportDefaults) { + this.bugReport = Object.assign(this.bugReport || {}, defaults); + } + + composeReport(activity: Activity) { + const reportObj = { + title: this.reportTitle, + comment: this.comment, + severity: this.severity, + steps: this.chosenEventSteps, + activity + } + this.bugReport = Object.assign(this.bugReport, reportObj) + + return this.bugReport + } + + setDefaultSteps(steps: Step[]) { + this.sessionEventSteps = steps; + } + + setSteps(steps: Step[]) { + this.chosenEventSteps = steps.map(step => ({ ...step, substeps: undefined })); + this.pickedSubItems = {}; + } + + removeStep(step: Step) { + this.chosenEventSteps = this.chosenEventSteps.filter( + (chosenStep) => chosenStep.key !== step.key + ); + if (this.pickedSubItems[step.key]) this.pickedSubItems[step.key] = new Map() + } + + toggleSubStepModal(isOpen: boolean, type: 'note' | 'network' | 'error', stepKey?: string) { + this.isSubStepModalOpen = isOpen; + this.subModalType = type; + this.targetStep = stepKey + if (!this.pickedSubItems[this.targetStep]) this.pickedSubItems[this.targetStep] = new Map() + } + + toggleSubItem(isAdded: boolean, item: SubItem) { + if (isAdded) { + this.pickedSubItems[this.targetStep].set(item.key, item) + } else { + this.pickedSubItems[this.targetStep].delete(item.key) + } + } + + isSubItemChecked(item: SubItem) { + return this.pickedSubItems[this.targetStep]?.get(item.key) !== undefined + } + + saveSubItems() { + const targetIndex = this.chosenEventSteps.findIndex(step => step.key === this.targetStep) + const eventStepsCopy = this.chosenEventSteps + const step = this.chosenEventSteps[targetIndex] + if (this.pickedSubItems[this.targetStep].size > 0) { + step.substeps = Array.from(this.pickedSubItems[this.targetStep], ([name, value]) => ({ ...value })); + } + eventStepsCopy[targetIndex] = step + + return this.chosenEventSteps = eventStepsCopy + } + + resetSteps() { + this.chosenEventSteps = []; + } +} diff --git a/frontend/app/mstore/dashboardStore.ts b/frontend/app/mstore/dashboardStore.ts index 2fc6f696c..9b2a98220 100644 --- a/frontend/app/mstore/dashboardStore.ts +++ b/frontend/app/mstore/dashboardStore.ts @@ -1,6 +1,7 @@ import { makeAutoObservable, runInAction, + computed, } from "mobx"; import Dashboard from "./types/dashboard"; import Widget from "./types/widget"; @@ -31,6 +32,7 @@ export default class DashboardStore { drillDownPeriod: Record<string, any> = Period({ rangeName: LAST_7_DAYS }); startTimestamp: number = 0; endTimestamp: number = 0; + pendingRequests: number = 0; // Metrics metricsPage: number = 1; @@ -64,6 +66,11 @@ export default class DashboardStore { this.drillDownFilter.updateKey("endTimestamp", timeStamps.endTimestamp); } + @computed + get sortedDashboards() { + return [...this.dashboards].sort((a, b) => b.createdAt - a.createdAt) + } + toggleAllSelectedWidgets(isSelected: boolean) { if (isSelected) { const allWidgets = this.widgetCategories.reduce((acc, cat) => { @@ -89,7 +96,7 @@ export default class DashboardStore { } removeSelectedWidgetByCategory = (category: any) => { - const categoryWidgetIds = category.widgets.map((w) => w.metricId); + const categoryWidgetIds = category.widgets.map((w: Widget) => w.metricId); this.selectedWidgets = this.selectedWidgets.filter( (widget: any) => !categoryWidgetIds.includes(widget.metricId) ); @@ -119,7 +126,8 @@ export default class DashboardStore { this.selectedWidgets = []; } - updateKey(key: any, value: any) { + updateKey(key: string, value: any) { + // @ts-ignore this[key] = value; } @@ -138,7 +146,7 @@ export default class DashboardStore { .getDashboards() .then((list: any) => { runInAction(() => { - this.dashboards = list.map((d) => + this.dashboards = list.map((d: Record<string, any>) => new Dashboard().fromJson(d) ); }); @@ -168,7 +176,7 @@ export default class DashboardStore { this.fetchingDashboard = value; } - save(dashboard: IDashboard): Promise<any> { + save(dashboard: Dashboard): Promise<any> { this.isSaving = true; const isCreating = !dashboard.dashboardId; @@ -205,7 +213,7 @@ export default class DashboardStore { }); } - saveMetric(metric: IWidget, dashboardId: string): Promise<any> { + saveMetric(metric: Widget, dashboardId: string): Promise<any> { const isCreating = !metric.widgetId; return dashboardService .saveMetric(metric, dashboardId) @@ -252,7 +260,7 @@ export default class DashboardStore { fromJson(json: any) { runInAction(() => { - this.dashboards = json.dashboards.map((d) => + this.dashboards = json.dashboards.map((d: Record<string, any>) => new Dashboard().fromJson(d) ); }); @@ -367,7 +375,7 @@ export default class DashboardStore { }); } - addWidgetToDashboard(dashboard: IDashboard, metricIds: any): Promise<any> { + addWidgetToDashboard(dashboard: Dashboard, metricIds: any): Promise<any> { this.isSaving = true; return dashboardService .addWidget(dashboard, metricIds) @@ -399,7 +407,7 @@ export default class DashboardStore { } fetchMetricChartData( - metric: IWidget, + metric: Widget, data: any, isWidget: boolean = false, period: Record<string, any> @@ -414,6 +422,7 @@ export default class DashboardStore { } return new Promise((resolve, reject) => { + this.pendingRequests += 1 return metricService .getMetricChartData(metric, params, isWidget) .then((data: any) => { @@ -491,6 +500,10 @@ export default class DashboardStore { }) .catch((err: any) => { reject(err); + }).finally(() => { + setTimeout(() => { + this.pendingRequests = this.pendingRequests - 1 + }, 100) }); }); } diff --git a/frontend/app/mstore/index.tsx b/frontend/app/mstore/index.tsx index 26533ee4f..1d6d758a1 100644 --- a/frontend/app/mstore/index.tsx +++ b/frontend/app/mstore/index.tsx @@ -5,56 +5,70 @@ import UserStore from './userStore'; import RoleStore from './roleStore'; import APIClient from 'App/api_client'; import FunnelStore from './funnelStore'; -import { dashboardService, metricService, sessionService, userService, auditService, funnelService, errorService } from 'App/services'; +import { + dashboardService, + metricService, + sessionService, + userService, + auditService, + funnelService, + errorService, + notesService, +} from 'App/services'; import SettingsStore from './settingsStore'; import AuditStore from './auditStore'; import NotificationStore from './notificationStore'; import ErrorStore from './errorStore'; import SessionStore from './sessionStore'; +import NotesStore from './notesStore'; +import BugReportStore from './bugReportStore' export class RootStore { - dashboardStore: DashboardStore; - metricStore: MetricStore; - funnelStore: FunnelStore; - settingsStore: SettingsStore; - userStore: UserStore; - roleStore: RoleStore; - auditStore: AuditStore; - errorStore: ErrorStore; - notificationStore: NotificationStore - sessionStore: SessionStore; + dashboardStore: DashboardStore; + metricStore: MetricStore; + funnelStore: FunnelStore; + settingsStore: SettingsStore; + userStore: UserStore; + roleStore: RoleStore; + auditStore: AuditStore; + errorStore: ErrorStore; + notificationStore: NotificationStore; + sessionStore: SessionStore; + notesStore: NotesStore; + bugReportStore: BugReportStore - constructor() { - this.dashboardStore = new DashboardStore(); - this.metricStore = new MetricStore(); - this.funnelStore = new FunnelStore(); - this.settingsStore = new SettingsStore(); - this.userStore = new UserStore(); - this.roleStore = new RoleStore(); - this.auditStore = new AuditStore(); - this.errorStore = new ErrorStore(); - this.notificationStore = new NotificationStore(); - this.sessionStore = new SessionStore(); - } + constructor() { + this.dashboardStore = new DashboardStore(); + this.metricStore = new MetricStore(); + this.funnelStore = new FunnelStore(); + this.settingsStore = new SettingsStore(); + this.userStore = new UserStore(); + this.roleStore = new RoleStore(); + this.auditStore = new AuditStore(); + this.errorStore = new ErrorStore(); + this.notificationStore = new NotificationStore(); + this.sessionStore = new SessionStore(); + this.notesStore = new NotesStore(); + this.bugReportStore = new BugReportStore(); + } - initClient() { - const client = new APIClient(); - dashboardService.initClient(client) - metricService.initClient(client) - funnelService.initClient(client) - sessionService.initClient(client) - userService.initClient(client) - auditService.initClient(client) - errorService.initClient(client) - } + initClient() { + const client = new APIClient(); + dashboardService.initClient(client); + metricService.initClient(client); + funnelService.initClient(client); + sessionService.initClient(client); + userService.initClient(client); + auditService.initClient(client); + errorService.initClient(client); + notesService.initClient(client) + } } const StoreContext = React.createContext<RootStore>({} as RootStore); export const StoreProvider = ({ children, store }: any) => { - return ( - <StoreContext.Provider value={store}>{children}</StoreContext.Provider> - ); + return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>; }; export const useStore = () => React.useContext(StoreContext); diff --git a/frontend/app/mstore/metricStore.ts b/frontend/app/mstore/metricStore.ts index 9baa8e274..11bcf8894 100644 --- a/frontend/app/mstore/metricStore.ts +++ b/frontend/app/mstore/metricStore.ts @@ -1,5 +1,5 @@ -import { makeAutoObservable, runInAction, observable, action, reaction, computed } from "mobx" -import Widget, { IWidget } from "./types/widget"; +import { makeAutoObservable, computed } from "mobx" +import Widget from "./types/widget"; import { metricService, errorService } from "App/services"; import { toast } from 'react-toastify'; import Error from "./types/error"; @@ -8,8 +8,8 @@ export default class MetricStore { isLoading: boolean = false isSaving: boolean = false - metrics: IWidget[] = [] - instance: IWidget = new Widget() + metrics: Widget[] = [] + instance = new Widget() page: number = 1 pageSize: number = 10 @@ -20,41 +20,21 @@ export default class MetricStore { sessionsPageSize: number = 10 constructor() { - makeAutoObservable(this, { - isLoading: observable, - metrics: observable, - instance: observable, - page: observable, - pageSize: observable, - metricsSearch: observable, - sort: observable, + makeAutoObservable(this) + } - init: action, - updateKey: action, - merge: action, - reset: action, - addToList: action, - updateInList: action, - findById: action, - removeById: action, - - save: action, - fetchList: action, - fetch: action, - delete: action, - - fetchError: action, - - paginatedList: computed, - }) + @computed + get sortedWidgets() { + return [...this.metrics].sort((a, b) => b.lastModified - a.lastModified) } // State Actions - init(metric?: IWidget|null) { + init(metric?: Widget | null) { this.instance.update(metric || new Widget()) } updateKey(key: string, value: any) { + // @ts-ignore this[key] = value } @@ -70,33 +50,36 @@ export default class MetricStore { } } - addToList(metric: IWidget) { + addToList(metric: Widget) { this.metrics.push(metric) } - updateInList(metric: IWidget) { - const index = this.metrics.findIndex((m: IWidget) => m[Widget.ID_KEY] === metric[Widget.ID_KEY]) + updateInList(metric: Widget) { + // @ts-ignore + const index = this.metrics.findIndex((m: Widget) => m[Widget.ID_KEY] === metric[Widget.ID_KEY]) if (index >= 0) { this.metrics[index] = metric } } findById(id: string) { + // @ts-ignore return this.metrics.find(m => m[Widget.ID_KEY] === id) } removeById(id: string): void { + // @ts-ignore this.metrics = this.metrics.filter(m => m[Widget.ID_KEY] !== id) } - get paginatedList(): IWidget[] { + get paginatedList(): Widget[] { const start = (this.page - 1) * this.pageSize const end = start + this.pageSize return this.metrics.slice(start, end) } // API Communication - save(metric: IWidget, dashboardId?: string): Promise<any> { + save(metric: Widget, dashboardId?: string): Promise<any> { const wasCreating = !metric.exists() this.isSaving = true return new Promise((resolve, reject) => { @@ -143,10 +126,12 @@ export default class MetricStore { }) } - delete(metric: IWidget) { + delete(metric: Widget) { this.isSaving = true + // @ts-ignore return metricService.deleteMetric(metric[Widget.ID_KEY]) .then(() => { + // @ts-ignore this.removeById(metric[Widget.ID_KEY]) toast.success('Metric deleted successfully') }).finally(() => { diff --git a/frontend/app/mstore/notesStore.ts b/frontend/app/mstore/notesStore.ts new file mode 100644 index 000000000..46d7fc652 --- /dev/null +++ b/frontend/app/mstore/notesStore.ts @@ -0,0 +1,137 @@ +import { makeAutoObservable } from "mobx" +import { notesService } from "App/services" +import { Note, WriteNote, iTag, NotesFilter } from 'App/services/NotesService' + +interface SessionNotes { + [sessionId: string]: Note[] +} + +export default class NotesStore { + notes: Note[] = [] + sessionNotes: SessionNotes = {} + loading: boolean + page = 1 + pageSize = 10 + activeTags: iTag[] = [] + sort = 'createdAt' + order: 'DESC' | 'ASC' = 'DESC' + ownOnly = false + + constructor() { + makeAutoObservable(this) + } + + async fetchNotes() { + const filter: NotesFilter = { + page: this.page, + limit: this.pageSize, + sort: this.sort, + order: this.order, + tags: this.activeTags, + mineOnly: this.ownOnly, + sharedOnly: false + } + + this.loading = true + try { + const notes = await notesService.fetchNotes(filter) + this.notes = notes; + return notes; + } catch (e) { + console.error(e) + } finally { + this.loading = false + } + } + + async fetchSessionNotes(sessionId: string) { + this.loading = true + try { + const notes = await notesService.getNotesBySessionId(sessionId) + this.sessionNotes[sessionId] = notes + return notes; + } catch (e) { + console.error(e) + } finally { + this.loading = false + } + } + + async addNote(sessionId: string, note: WriteNote) { + this.loading = true + try { + const addedNote = await notesService.addNote(sessionId, note) + return addedNote + } catch (e) { + console.error(e) + } finally { + this.loading = false + } + } + + async deleteNote(noteId: number) { + this.loading = true + try { + const deleted = await notesService.deleteNote(noteId) + return deleted + } catch (e) { + console.error(e) + } finally { + this.loading = false + } + } + + async updateNote(noteId: string, note: WriteNote) { + this.loading = true + try { + const updated = await notesService.updateNote(noteId, note) + return updated + } catch (e) { + console.error(e) + } finally { + this.loading = false + } + } + + getNoteById(noteId: number, notes?: Note[]) { + const notesSource = notes ? notes : this.notes + + return notesSource.find(note => note.noteId === noteId) + } + + changePage(page: number) { + this.page = page + } + + toggleTag(tag?: iTag) { + if (!tag) { + this.activeTags = [] + this.fetchNotes() + } else { + this.activeTags = [tag] + this.fetchNotes() + } + } + + toggleShared(ownOnly: boolean) { + this.ownOnly = ownOnly + this.fetchNotes() + } + + toggleSort(sort: string) { + const sortOrder = sort.split('-')[1] + // @ts-ignore + this.order = sortOrder + + this.fetchNotes() + } + + async sendSlackNotification(noteId: string, webhook: string) { + try { + const resp = await notesService.sendSlackNotification(noteId, webhook) + return resp + } catch (e) { + console.error(e) + } + } +} diff --git a/frontend/app/mstore/sessionStore.ts b/frontend/app/mstore/sessionStore.ts index 98a7061e6..d055a9aa8 100644 --- a/frontend/app/mstore/sessionStore.ts +++ b/frontend/app/mstore/sessionStore.ts @@ -5,75 +5,105 @@ import Session from './types/session'; import Record, { LAST_7_DAYS } from 'Types/app/period'; class UserFilter { - endDate: number = new Date().getTime(); - startDate: number = new Date().getTime() - 24 * 60 * 60 * 1000; - rangeName: string = LAST_7_DAYS; - filters: any = []; - page: number = 1; - limit: number = 10; - period: any = Record({ rangeName: LAST_7_DAYS }); + endDate: number = new Date().getTime(); + startDate: number = new Date().getTime() - 24 * 60 * 60 * 1000; + rangeName: string = LAST_7_DAYS; + filters: any = []; + page: number = 1; + limit: number = 10; + period: any = Record({ rangeName: LAST_7_DAYS }); - constructor() { - makeAutoObservable(this, { - page: observable, - update: action, - }); + constructor() { + makeAutoObservable(this, { + page: observable, + update: action, + }); + } + + update(key: string, value: any) { + // @ts-ignore + this[key] = value; + + if (key === 'period') { + this.startDate = this.period.start; + this.endDate = this.period.end; } + } - update(key: string, value: any) { - this[key] = value; + setFilters(filters: any[]) { + this.filters = filters; + } - if (key === 'period') { - this.startDate = this.period.start; - this.endDate = this.period.end; - } - } + setPage(page: number) { + this.page = page; + } - setFilters(filters: any[]) { - this.filters = filters; - } + toJson() { + return { + endDate: this.period.end, + startDate: this.period.start, + filters: this.filters.map(filterMap), + page: this.page, + limit: this.limit, + }; + } +} - setPage(page: number) { - this.page = page; - } +interface BaseDevState { + index: number; + filter: string; + activeTab: string; + isError: boolean; +} - toJson() { - return { - endDate: this.period.end, - startDate: this.period.start, - filters: this.filters.map(filterMap), - page: this.page, - limit: this.limit, - }; - } +class DevTools { + network: BaseDevState; + stackEvent: BaseDevState; + console: BaseDevState; + + constructor() { + this.network = { index: 0, filter: '', activeTab: 'ALL', isError: false }; + this.stackEvent = { index: 0, filter: '', activeTab: 'ALL', isError: false }; + this.console = { index: 0, filter: '', activeTab: 'ALL', isError: false }; + makeAutoObservable(this, { + update: action, + }); + } + + update(key: string, value: any) { + // @ts-ignore + this[key] = Object.assign(this[key], value); + } } export default class SessionStore { - userFilter: UserFilter = new UserFilter(); + userFilter: UserFilter = new UserFilter(); + devTools: DevTools = new DevTools(); - constructor() { - makeAutoObservable(this, { - userFilter: observable, + constructor() { + makeAutoObservable(this, { + userFilter: observable, + devTools: observable, + }); + } + + resetUserFilter() { + this.userFilter = new UserFilter(); + } + + getSessions(filter: any): Promise<any> { + return new Promise((resolve, reject) => { + sessionService + .getSessions(filter.toJson()) + .then((response: any) => { + resolve({ + sessions: response.sessions.map((session: any) => new Session().fromJson(session)), + total: response.total, + }); + }) + .catch((error: any) => { + reject(error); }); - } - - resetUserFilter() { - this.userFilter = new UserFilter(); - } - - getSessions(filter: any): Promise<any> { - return new Promise((resolve, reject) => { - sessionService - .getSessions(filter.toJson()) - .then((response: any) => { - resolve({ - sessions: response.sessions.map((session: any) => new Session().fromJson(session)), - total: response.total, - }); - }) - .catch((error: any) => { - reject(error); - }); - }); - } + }); + } } diff --git a/frontend/app/mstore/types/dashboard.ts b/frontend/app/mstore/types/dashboard.ts index eed78a02b..0213f9b0d 100644 --- a/frontend/app/mstore/types/dashboard.ts +++ b/frontend/app/mstore/types/dashboard.ts @@ -15,7 +15,7 @@ export default class Dashboard { isValid: boolean = false currentWidget: Widget = new Widget() config: any = {} - createdAt: Date = new Date() + createdAt: number = new Date().getTime() constructor() { makeAutoObservable(this) diff --git a/frontend/app/mstore/types/funnel.ts b/frontend/app/mstore/types/funnel.ts index 1b9cf9a71..3cf4f675b 100644 --- a/frontend/app/mstore/types/funnel.ts +++ b/frontend/app/mstore/types/funnel.ts @@ -10,6 +10,7 @@ export default class Funnel { isPublic: boolean = false stages: FunnelStage[] = [] raw: any = null + totalDropDueToIssues: number = 0; constructor() { } @@ -18,6 +19,7 @@ export default class Funnel { if (!this.raw) { this.raw = json } + this.totalDropDueToIssues = json.totalDropDueToIssues; if (json.stages.length >= 1) { const firstStage = json.stages[0] diff --git a/frontend/app/mstore/types/funnelStage.ts b/frontend/app/mstore/types/funnelStage.ts index c1a98035f..7d79bb402 100644 --- a/frontend/app/mstore/types/funnelStage.ts +++ b/frontend/app/mstore/types/funnelStage.ts @@ -12,7 +12,9 @@ export default class FunnelStage { label: string = ''; isActive: boolean = true; completedPercentage: number = 0; + completedPercentageTotal: number = 0; droppedCount: number = 0; + droppedPercentage: number = 0; constructor() { makeAutoObservable(this, { @@ -22,17 +24,20 @@ export default class FunnelStage { } fromJSON(json: any, total: number = 0, previousSessionCount: number = 0) { - this.dropDueToIssues = json.dropDueToIssues; + previousSessionCount = previousSessionCount || 0; + this.dropDueToIssues = json.dropDueToIssues || 0; this.dropPct = json.dropPct; this.operator = json.operator; - this.sessionsCount = json.sessionsCount; + this.sessionsCount = json.sessionsCount || 0; this.usersCount = json.usersCount; this.value = json.value; this.type = json.type; this.label = filterLabelMap[json.type] || json.type; - this.completedPercentage = total ? Math.round((this.sessionsCount / total) * 100) : 0; + this.completedPercentage = total ? Math.round((this.sessionsCount / previousSessionCount) * 100) : 0; + this.completedPercentageTotal = total ? Math.round((this.sessionsCount / total) * 100) : 0; this.dropDueToIssuesPercentage = total ? Math.round((this.dropDueToIssues / total) * 100) : 0; this.droppedCount = previousSessionCount - this.sessionsCount; + this.droppedPercentage = this.droppedCount ? Math.round((this.droppedCount / previousSessionCount) * 100) : 0; return this; } diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index 01afcdc30..62371fde3 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -6,7 +6,7 @@ import Session from "App/mstore/types/session"; import Funnelissue from 'App/mstore/types/funnelIssue'; import { issueOptions } from 'App/constants/filterOptions'; import { FilterKey } from 'Types/filter/filterType'; -import Period, { LAST_24_HOURS, LAST_30_DAYS } from 'Types/app/period'; +import Period, { LAST_24_HOURS } from 'Types/app/period'; export default class Widget { public static get ID_KEY():string { return "metricId" } @@ -24,7 +24,7 @@ export default class Widget { sessions: [] = [] isPublic: boolean = true owner: string = "" - lastModified: Date = new Date() + lastModified: number = new Date().getTime() dashboards: any[] = [] dashboardIds: any[] = [] config: any = {} @@ -131,7 +131,7 @@ export default class Widget { series: this.series.map((series: any) => series.toJson()), config: { ...this.config, - col: this.metricType === 'funnel' || this.metricOf === FilterKey.ERRORS || this.metricOf === FilterKey.SESSIONS ? 4 : this.config.col + col: (this.metricType === 'funnel' || this.metricOf === FilterKey.ERRORS || this.metricOf === FilterKey.SESSIONS) ? 4 : 2 }, } } diff --git a/frontend/app/player/MessageDistributor/Lists.ts b/frontend/app/player/MessageDistributor/Lists.ts index a65eff52f..bae8d46de 100644 --- a/frontend/app/player/MessageDistributor/Lists.ts +++ b/frontend/app/player/MessageDistributor/Lists.ts @@ -1,23 +1,76 @@ -import type { Message } from './messages' import ListWalker from './managers/ListWalker'; +import ListWalkerWithMarks from './managers/ListWalkerWithMarks'; -export const LIST_NAMES = ["redux", "mobx", "vuex", "zustand", "ngrx", "graphql", "exceptions", "profiles", "longtasks"] as const; +import type { Message } from './messages' -export const INITIAL_STATE = {} -LIST_NAMES.forEach(name => { - INITIAL_STATE[`${name}ListNow`] = [] - INITIAL_STATE[`${name}List`] = [] -}) +const SIMPLE_LIST_NAMES = [ "event", "redux", "mobx", "vuex", "zustand", "ngrx", "graphql", "exceptions", "profiles"] as const; +const MARKED_LIST_NAMES = [ "log", "resource", "fetch", "stack" ] as const; +//const entityNamesSimple = [ "event", "profile" ]; +const LIST_NAMES = [...SIMPLE_LIST_NAMES, ...MARKED_LIST_NAMES ]; -type ListsObject = { - [key in typeof LIST_NAMES[number]]: ListWalker<any> -} +// TODO: provide correct types -export function initLists(): ListsObject { - const lists: Partial<ListsObject> = {}; - for (var i = 0; i < LIST_NAMES.length; i++) { - lists[LIST_NAMES[i]] = new ListWalker(); +export const INITIAL_STATE = LIST_NAMES.reduce((state, name) => { + state[`${name}List`] = [] + state[`${name}ListNow`] = [] + if (MARKED_LIST_NAMES.includes(name)) { + state[`${name}MarkedCountNow`] = 0 + state[`${name}MarkedCount`] = 0 } - return lists as ListsObject; + return state +}, {}) + + +type SimpleListsObject = { + [key in typeof SIMPLE_LIST_NAMES[number]]: ListWalker<any> } +type MarkedListsObject = { + [key in typeof MARKED_LIST_NAMES[number]]: ListWalkerWithMarks<any> +} +type ListsObject = SimpleListsObject & MarkedListsObject + +type InitialLists = { + [key in typeof LIST_NAMES[number]]: any[] +} + +export default class Lists { + lists: ListsObject + constructor(initialLists: Partial<InitialLists> = {}) { + const lists: Partial<ListsObject> = {} + for (const name of SIMPLE_LIST_NAMES) { + lists[name] = new ListWalker(initialLists[name]) + } + for (const name of MARKED_LIST_NAMES) { + // TODO: provide types + lists[name] = new ListWalkerWithMarks((el) => el.isRed(), initialLists[name]) + } + this.lists = lists as ListsObject + } + + getFullListsState() { + return LIST_NAMES.reduce((state, name) => { + state[`${name}List`] = this.lists[name].list + return state + }, MARKED_LIST_NAMES.reduce((state, name) => { + state[`${name}MarkedCount`] = this.lists[name].markedCount + return state + }, {}) + ) + } + + moveGetState(t: number)/* : Partial<State> */ { + return LIST_NAMES.reduce((state, name) => { + const lastMsg = this.lists[name].moveGetLast(t) // index: name === 'exceptions' ? undefined : index); + if (lastMsg != null) { + state[`${name}ListNow`] = this.lists[name].listNow + } + return state + }, MARKED_LIST_NAMES.reduce((state, name) => { + state[`${name}MarkedCountNow`] = this.lists[name].markedCountNow + return state + }, {}) + ); + } + +} \ No newline at end of file diff --git a/frontend/app/player/MessageDistributor/MessageDistributor.ts b/frontend/app/player/MessageDistributor/MessageDistributor.ts index 7d4ed9f33..e1b59940a 100644 --- a/frontend/app/player/MessageDistributor/MessageDistributor.ts +++ b/frontend/app/player/MessageDistributor/MessageDistributor.ts @@ -9,12 +9,6 @@ import Log from 'Types/session/log'; import { update } from '../store'; import { toast } from 'react-toastify'; -import { - init as initListsDepr, - append as listAppend, - setStartTime as setListsStartTime -} from '../lists'; - import StatedScreen from './StatedScreen/StatedScreen'; import ListWalker from './managers/ListWalker'; @@ -27,11 +21,12 @@ import ActivityManager from './managers/ActivityManager'; import AssistManager from './managers/AssistManager'; import MFileReader from './messages/MFileReader'; -import { loadFiles, checkUnprocessedMobs } from './network/loadFiles'; +import { loadFiles, requestEFSDom, requestEFSDevtools } from './network/loadFiles'; +import { decryptSessionBytes } from './network/crypto'; import { INITIAL_STATE as SUPER_INITIAL_STATE, State as SuperState } from './StatedScreen/StatedScreen'; import { INITIAL_STATE as ASSIST_INITIAL_STATE, State as AssistState } from './managers/AssistManager'; -import { INITIAL_STATE as LISTS_INITIAL_STATE , LIST_NAMES, initLists } from './Lists'; +import Lists, { INITIAL_STATE as LISTS_INITIAL_STATE } from './Lists'; import type { PerformanceChartPoint } from './managers/PerformanceTrackManager'; import type { SkipInterval } from './managers/ActivityManager'; @@ -49,6 +44,7 @@ export interface State extends SuperState, AssistState { domBuildingTime?: any, loadTime?: any, error: boolean, + devtoolsLoading: boolean } export const INITIAL_STATE: State = { ...SUPER_INITIAL_STATE, @@ -56,7 +52,8 @@ export const INITIAL_STATE: State = { ...ASSIST_INITIAL_STATE, performanceChartData: [], skipIntervals: [], - error: false + error: false, + devtoolsLoading: false, }; @@ -69,7 +66,15 @@ import type { MouseClick, } from './messages'; -import type { Timed } from './messages/timed'; +const visualChanges = [ + "mouse_move", + "mouse_click", + "create_element_node", + "set_input_value", + "set_input_checked", + "set_viewport_size", + "set_viewport_scroll", +] export default class MessageDistributor extends StatedScreen { // TODO: consistent with the other data-lists @@ -89,15 +94,14 @@ export default class MessageDistributor extends StatedScreen { private scrollManager: ListWalker<SetViewportScroll> = new ListWalker(); private readonly decoder = new Decoder(); - private readonly lists = initLists(); + private readonly lists: Lists; private activityManager: ActivityManager | null = null; - private fileReader: MFileReader; private sessionStart: number; private navigationStartOffset: number = 0; private lastMessageTime: number = 0; - private lastRecordedMessageTime: number = 0; + private lastMessageInFileTime: number = 0; constructor(private readonly session: any /*Session*/, config: any, live: boolean) { super(); @@ -108,69 +112,44 @@ export default class MessageDistributor extends StatedScreen { this.sessionStart = this.session.startedAt; if (live) { - initListsDepr({}) - this.assistManager.connect(); + this.lists = new Lists() + this.assistManager.connect(this.session.agentToken); } else { this.activityManager = new ActivityManager(this.session.duration.milliseconds); /* == REFACTOR_ME == */ - const eventList = this.session.events.toJSON(); - initListsDepr({ - event: eventList, - stack: this.session.stackEvents.toJSON(), - resource: this.session.resources.toJSON(), - }); - + const eventList = session.events.toJSON(); // TODO: fix types for events, remove immutable js eventList.forEach((e: Record<string, string>) => { if (e.type === EVENT_TYPES.LOCATION) { //TODO type system this.locationEventManager.append(e); } - }); - this.session.errors.forEach((e: Record<string, string>) => { - this.lists.exceptions.append(e); - }); + }) + + this.lists = new Lists({ + event: eventList, + stack: session.stackEvents.toJSON(), + resource: session.resources.toJSON(), + exceptions: session.errors.toJSON(), + }) + /* === */ this.loadMessages(); } } - private waitingForFiles: boolean = false - - private onFileSuccessRead() { - this.windowNodeCounter.reset() - - if (this.activityManager) { - this.activityManager.end() - update({ - skipIntervals: this.activityManager.list - }) - } - - this.waitingForFiles = false - this.setMessagesLoading(false) - } - - private readAndDistributeMessages(byteArray: Uint8Array, onReadCb?: (msg: Message) => void) { + private parseAndDistributeMessages(fileReader: MFileReader, onMessage?: (msg: Message) => void) { const msgs: Array<Message> = [] - if (!this.fileReader) { - this.fileReader = new MFileReader(new Uint8Array(), this.sessionStart) - } - - this.fileReader.append(byteArray) let next: ReturnType<MFileReader['next']> - while (next = this.fileReader.next()) { + while (next = fileReader.next()) { const [msg, index] = next this.distributeMessage(msg, index) msgs.push(msg) - onReadCb?.(msg) + onMessage?.(msg) } logger.info("Messages count: ", msgs.length, msgs) - return msgs - } - private processStateUpdates(msgs: Message[]) { // @ts-ignore Hack for upet (TODO: fix ordering in one mutation in tracker(removes first)) const headChildrenIds = msgs.filter(m => m.parentID === 1).map(m => m.id); this.pagesManager.sortPages((m1, m2) => { @@ -195,87 +174,103 @@ export default class MessageDistributor extends StatedScreen { } return 0; }) + } - const stateToUpdate: {[key:string]: any} = { + + private waitingForFiles: boolean = false + private onFileReadSuccess = () => { + const stateToUpdate = { performanceChartData: this.performanceTrackManager.chartData, performanceAvaliability: this.performanceTrackManager.avaliability, + ...this.lists.getFullListsState() } - LIST_NAMES.forEach(key => { - stateToUpdate[ `${ key }List` ] = this.lists[ key ].list - }) + if (this.activityManager) { + this.activityManager.end() + stateToUpdate.skipIntervals = this.activityManager.list + } + update(stateToUpdate) + } + private onFileReadFailed = (e: any) => { + logger.error(e) + update({ error: true }) + toast.error('Error requesting a session file') + } + private onFileReadFinally = () => { + this.incomingMessages + .filter(msg => msg.time >= this.lastMessageInFileTime) + .forEach(msg => this.distributeMessage(msg, 0)) + + this.waitingForFiles = false this.setMessagesLoading(false) } private loadMessages() { + // TODO: reuseable decryptor instance + const createNewParser = (shouldDecrypt=true) => { + const decrypt = shouldDecrypt && this.session.fileKey + ? (b: Uint8Array) => decryptSessionBytes(b, this.session.fileKey) + : (b: Uint8Array) => Promise.resolve(b) + // Each time called - new fileReader created + const fileReader = new MFileReader(new Uint8Array(), this.sessionStart) + return (b: Uint8Array) => decrypt(b).then(b => { + fileReader.append(b) + this.parseAndDistributeMessages(fileReader) + this.setMessagesLoading(false) + }) + } this.setMessagesLoading(true) this.waitingForFiles = true - const onData = (byteArray: Uint8Array) => { - const msgs = this.readAndDistributeMessages(byteArray) - this.processStateUpdates(msgs) - } - - loadFiles(this.session.mobsUrl, - onData + loadFiles(this.session.domURL, createNewParser()) + .catch(() => // do if only the first file missing (404) (?) + requestEFSDom(this.session.sessionId) + .then(createNewParser(false)) + // Fallback to back Compatability with mobsUrl + .catch(e => + loadFiles(this.session.mobsUrl, createNewParser(false)) + ) ) - .then(() => this.onFileSuccessRead()) - .catch(async () => { - checkUnprocessedMobs(this.session.sessionId) - .then(file => file ? onData(file) : Promise.reject('No session file')) - .then(() => this.onFileSuccessRead()) - .catch((e) => { - logger.error(e) - update({ error: true }) - toast.error('Error getting a session replay file') - }) - .finally(() => { - this.waitingForFiles = false - this.setMessagesLoading(false) - }) + .then(this.onFileReadSuccess) + .catch(this.onFileReadFailed) + .finally(this.onFileReadFinally) - }) + // load devtools + if (this.session.devtoolsURL.length) { + update({ devtoolsLoading: true }) + loadFiles(this.session.devtoolsURL, createNewParser()) + .catch(() => + requestEFSDevtools(this.session.sessionId) + .then(createNewParser(false)) + ) + //.catch() // not able to download the devtools file + .finally(() => update({ devtoolsLoading: false })) + } } - public async reloadWithUnprocessedFile() { - // assist will pause and skip messages to prevent timestamp related errors - this.assistManager.toggleTimeTravelJump() - this.reloadMessageManagers() - - this.setMessagesLoading(true) - this.waitingForFiles = true - + reloadWithUnprocessedFile() { const onData = (byteArray: Uint8Array) => { - const onReadCallback = () => this.setLastRecordedMessageTime(this.lastMessageTime) - const msgs = this.readAndDistributeMessages(byteArray, onReadCallback) - this.processStateUpdates(msgs) + const onMessage = (msg: Message) => { this.lastMessageInFileTime = msg.time } + this.parseAndDistributeMessages(new MFileReader(byteArray, this.sessionStart), onMessage) } - - // unpausing assist - const unpauseAssist = () => { - this.assistManager.toggleTimeTravelJump() + const updateState = () => update({ liveTimeTravel: true, }); - } - try { - const unprocessedFile = await checkUnprocessedMobs(this.session.sessionId) - - Promise.resolve(onData(unprocessedFile)) - .then(() => this.onFileSuccessRead()) - .then(unpauseAssist) - } catch (unprocessedFilesError) { - logger.error(unprocessedFilesError) - update({ error: true }) - toast.error('Error getting a session replay file') - this.assistManager.toggleTimeTravelJump() - } finally { - this.waitingForFiles = false - this.setMessagesLoading(false) - } + // assist will pause and skip messages to prevent timestamp related errors + this.reloadMessageManagers() + this.windowNodeCounter.reset() + this.setMessagesLoading(true) + this.waitingForFiles = true + return requestEFSDom(this.session.sessionId) + .then(onData) + .then(updateState) + .then(this.onFileReadSuccess) + .catch(this.onFileReadFailed) + .finally(this.onFileReadFinally) } private reloadMessageManagers() { @@ -299,7 +294,6 @@ export default class MessageDistributor extends StatedScreen { /* == REFACTOR_ME == */ const lastLoadedLocationMsg = this.loadedLocationManager.moveGetLast(t, index); if (!!lastLoadedLocationMsg) { - setListsStartTime(lastLoadedLocationMsg.time) this.navigationStartOffset = lastLoadedLocationMsg.navigationStart - this.sessionStart; } const llEvent = this.locationEventManager.moveGetLast(t, index); @@ -335,14 +329,7 @@ export default class MessageDistributor extends StatedScreen { stateToUpdate.performanceChartTime = lastPerformanceTrackMessage.time; } - LIST_NAMES.forEach(key => { - const lastMsg = this.lists[key].moveGetLast(t, key === 'exceptions' ? undefined : index); - if (lastMsg != null) { - // @ts-ignore TODO: fix types - stateToUpdate[`${key}ListNow`] = this.lists[key].listNow; - } - }); - + Object.assign(stateToUpdate, this.lists.moveGetState(t)) Object.keys(stateToUpdate).length > 0 && update(stateToUpdate); /* Sequence of the managers is important here */ @@ -372,7 +359,7 @@ export default class MessageDistributor extends StatedScreen { } } - private decodeMessage(msg: any, keys: Array<string>) { + private decodeStateMessage(msg: any, keys: Array<string>) { const decoded = {}; try { keys.forEach(key => { @@ -386,37 +373,38 @@ export default class MessageDistributor extends StatedScreen { return { ...msg, ...decoded }; } - /* Binded */ - distributeMessage(msg: Message, index: number): void { + private readonly incomingMessages: Message[] = [] + appendMessage(msg: Message, index: number) { + // @ts-ignore + // msg.time = this.md.getLastRecordedMessageTime() + msg.time\ + //TODO: put index in message type + this.incomingMessages.push(msg) + if (!this.waitingForFiles) { + this.distributeMessage(msg, index) + } + } + + private distributeMessage(msg: Message, index: number): void { const lastMessageTime = Math.max(msg.time, this.lastMessageTime) this.lastMessageTime = lastMessageTime - if ([ - "mouse_move", - "mouse_click", - "create_element_node", // not a user activity, though visual change - "set_input_value", - "set_input_checked", - "set_viewport_size", - "set_viewport_scroll", - ].includes(msg.tp)) { + if (visualChanges.includes(msg.tp)) { this.activityManager?.updateAcctivity(msg.time); } - //const index = i + index; //? let decoded; const time = msg.time; switch (msg.tp) { /* Lists: */ case "console_log": if (msg.level === 'debug') break; - listAppend("log", Log({ + this.lists.lists.log.append(Log({ level: msg.level, value: msg.value, time, index, - })); + })) break; case "fetch": - listAppend("fetch", Resource({ + this.lists.lists.fetch.append(Resource({ method: msg.method, url: msg.url, payload: msg.request, @@ -460,51 +448,45 @@ export default class MessageDistributor extends StatedScreen { this.decoder.set(msg.key, msg.value); break; case "redux": - decoded = this.decodeMessage(msg, ["state", "action"]); - logger.log(decoded) + decoded = this.decodeStateMessage(msg, ["state", "action"]); + logger.log('redux', decoded) if (decoded != null) { - this.lists.redux.append(decoded); + this.lists.lists.redux.append(decoded); } break; case "ng_rx": - decoded = this.decodeMessage(msg, ["state", "action"]); - logger.log(decoded) + decoded = this.decodeStateMessage(msg, ["state", "action"]); + logger.log('ngrx', decoded) if (decoded != null) { - this.lists.ngrx.append(decoded); + this.lists.lists.ngrx.append(decoded); } break; case "vuex": - decoded = this.decodeMessage(msg, ["state", "mutation"]); - logger.log(decoded) + decoded = this.decodeStateMessage(msg, ["state", "mutation"]); + logger.log('vuex', decoded) if (decoded != null) { - this.lists.vuex.append(decoded); + this.lists.lists.vuex.append(decoded); } break; case "zustand": - decoded = this.decodeMessage(msg, ["state", "mutation"]) - logger.log(decoded) + decoded = this.decodeStateMessage(msg, ["state", "mutation"]) + logger.log('zustand', decoded) if (decoded != null) { - this.lists.zustand.append(decoded) + this.lists.lists.zustand.append(decoded) } case "mob_x": - decoded = this.decodeMessage(msg, ["payload"]); - logger.log(decoded) + decoded = this.decodeStateMessage(msg, ["payload"]); + logger.log('mobx', decoded) if (decoded != null) { - this.lists.mobx.append(decoded); + this.lists.lists.mobx.append(decoded); } break; case "graph_ql": - this.lists.graphql.append(msg); + this.lists.lists.graphql.append(msg); break; case "profiler": - this.lists.profiles.append(msg); - break; - case "long_task": - this.lists.longtasks.append({ - ...msg, - time: msg.timestamp - this.sessionStart, - }); + this.lists.lists.profiles.append(msg); break; default: switch (msg.tp) { @@ -545,13 +527,7 @@ export default class MessageDistributor extends StatedScreen { super.clean(); update(INITIAL_STATE); this.assistManager.clear(); + this.incomingMessages.length = 0 } - public setLastRecordedMessageTime(time: number) { - this.lastRecordedMessageTime = time; - } - - public getLastRecordedMessageTime(): number { - return this.lastRecordedMessageTime; - } } diff --git a/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts b/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts index 39dda161d..d86284851 100644 --- a/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts +++ b/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts @@ -23,7 +23,7 @@ function getElementsFromInternalPoint(doc: Document, { x, y }: Point): Element[] } if (typeof doc.elementsFromPoint === 'function') { - return doc.elementsFromPoint(x, y) + return doc.elementsFromPoint(x, y) } const el = doc.elementFromPoint(x, y) return el ? [ el ] : [] @@ -53,10 +53,13 @@ function isIframe(el: Element): el is HTMLIFrameElement { } export default abstract class BaseScreen { - public readonly overlay: HTMLDivElement; - private readonly iframe: HTMLIFrameElement; - protected readonly screen: HTMLDivElement; + public readonly overlay: HTMLDivElement; + + private readonly iframe: HTMLIFrameElement; + protected readonly screen: HTMLDivElement; + protected readonly controlButton: HTMLDivElement; protected parentElement: HTMLElement | null = null; + constructor() { const iframe = document.createElement('iframe'); iframe.className = styles.iframe; @@ -76,14 +79,15 @@ export default abstract class BaseScreen { attach(parentElement: HTMLElement) { if (this.parentElement) { - throw new Error("BaseScreen: Trying to attach an attached screen."); + this.parentElement = undefined + console.error("BaseScreen: Trying to attach an attached screen."); } parentElement.appendChild(this.screen); this.parentElement = parentElement; // parentElement.onresize = this.scale; - window.addEventListener('resize', this.scale); + window.addEventListener('resize', this.scale); this.scale(); /* == For the Inspecting Document content == */ @@ -101,6 +105,11 @@ export default abstract class BaseScreen { }) } + toggleRemoteControlStatus(isEnabled: boolean ) { + const styles = isEnabled ? { border: '2px dashed blue' } : { border: 'unset'} + return Object.assign(this.screen.style, styles) + } + get window(): WindowProxy | null { return this.iframe.contentWindow; } @@ -145,7 +154,7 @@ export default abstract class BaseScreen { } getElementFromInternalPoint({ x, y }: Point): Element | null { - // elementFromPoint && elementFromPoints require viewpoint-related coordinates, + // elementFromPoint && elementFromPoints require viewpoint-related coordinates, // not document-related return this.document?.elementFromPoint(x, y) || null; } diff --git a/frontend/app/player/MessageDistributor/StatedScreen/Screen/screen.module.css b/frontend/app/player/MessageDistributor/StatedScreen/Screen/screen.module.css index 696b38e7a..f9a2d2d8a 100644 --- a/frontend/app/player/MessageDistributor/StatedScreen/Screen/screen.module.css +++ b/frontend/app/player/MessageDistributor/StatedScreen/Screen/screen.module.css @@ -18,5 +18,5 @@ left: 0; right: 0; bottom: 0; - z-index: 10; -} \ No newline at end of file + z-index: 10; +} diff --git a/frontend/app/player/MessageDistributor/StatedScreen/StatedScreen.ts b/frontend/app/player/MessageDistributor/StatedScreen/StatedScreen.ts index 29fead989..45028f88f 100644 --- a/frontend/app/player/MessageDistributor/StatedScreen/StatedScreen.ts +++ b/frontend/app/player/MessageDistributor/StatedScreen/StatedScreen.ts @@ -34,8 +34,6 @@ export interface MarkedTarget { export interface State extends SuperState { messagesLoading: boolean, cssLoading: boolean, - disconnected: boolean, - userPageLoading: boolean, markedTargets: MarkedTarget[] | null, activeTargetIndex: number, } @@ -44,8 +42,6 @@ export const INITIAL_STATE: State = { ...SUPER_INITIAL_STATE, messagesLoading: false, cssLoading: false, - disconnected: false, - userPageLoading: false, markedTargets: null, activeTargetIndex: 0 }; @@ -63,21 +59,13 @@ export default class StatedScreen extends Screen { update({ cssLoading }); } - setDisconnected(disconnected: boolean) { - if (!getState().live) return; //? - this.display(!disconnected); - update({ disconnected }); - } - - setUserPageLoading(userPageLoading: boolean) { - this.display(!userPageLoading); - update({ userPageLoading }); - } - setSize({ height, width }: { height: number, width: number }) { update({ width, height }); this.scale(); + this.updateMarketTargets() + } + updateMarketTargets() { const { markedTargets } = getState(); if (markedTargets) { update({ diff --git a/frontend/app/player/MessageDistributor/managers/ActivityManager.ts b/frontend/app/player/MessageDistributor/managers/ActivityManager.ts index b70e4aefd..412fefdce 100644 --- a/frontend/app/player/MessageDistributor/managers/ActivityManager.ts +++ b/frontend/app/player/MessageDistributor/managers/ActivityManager.ts @@ -7,12 +7,12 @@ class SkipIntervalCls { get time(): number { return this.start; } - contains(ts) { + contains(ts: number) { return ts > this.start && ts < this.end; } } -export type SkipInterval = InstanceType<typeof SkipIntervalCls>; +export type SkipInterval = InstanceType<typeof SkipIntervalCls>; // exporting only class' type export default class ActivityManager extends ListWalker<SkipInterval> { diff --git a/frontend/app/player/MessageDistributor/managers/AssistManager.ts b/frontend/app/player/MessageDistributor/managers/AssistManager.ts index a72c9c0c8..897d8dfba 100644 --- a/frontend/app/player/MessageDistributor/managers/AssistManager.ts +++ b/frontend/app/player/MessageDistributor/managers/AssistManager.ts @@ -72,11 +72,10 @@ export const INITIAL_STATE: State = { const MAX_RECONNECTION_COUNT = 4; - export default class AssistManager { - private timeTravelJump = false; - private jumped = false; + private videoStreams: Record<string, MediaStreamTrack> = {} + // TODO: Session type constructor(private session: any, private md: MessageDistributor, private config: any) {} private setStatus(status: ConnectionStatus) { @@ -119,9 +118,9 @@ export default class AssistManager { } private socket: Socket | null = null - connect() { + connect(agentToken: string) { const jmr = new JSONRawMessageReader() - const reader = new MStreamReader(jmr) + const reader = new MStreamReader(jmr, this.session.startedAt) let waitingForMessages = true let disconnectTimeout: ReturnType<typeof setTimeout> | undefined let inactiveTimeout: ReturnType<typeof setTimeout> | undefined @@ -143,13 +142,18 @@ export default class AssistManager { // @ts-ignore const urlObject = new URL(window.env.API_EDP || window.location.origin) // does it handle ssl automatically? - // @ts-ignore WTF, socket.io ??? const socket: Socket = this.socket = io(urlObject.origin, { path: '/ws-assist/socket', + auth: { + token: agentToken + }, query: { peerId: this.peerID, identity: "agent", - //agentInfo: JSON.stringify({}) + agentInfo: JSON.stringify({ + ...this.session.agentInfo, + query: document.location.search + }) } }) socket.on("connect", () => { @@ -161,7 +165,7 @@ export default class AssistManager { update({ calling: CallingState.NoCall }) }) socket.on('messages', messages => { - !this.timeTravelJump && jmr.append(messages) // as RawMessage[] + jmr.append(messages) // as RawMessage[] if (waitingForMessages) { waitingForMessages = false // TODO: more explicit @@ -173,18 +177,9 @@ export default class AssistManager { } } - if (this.timeTravelJump) { - return; - } - for (let msg = reader.readNext();msg !== null;msg = reader.readNext()) { - //@ts-ignore - if (this.jumped) { - // @ts-ignore - msg.time = this.md.getLastRecordedMessageTime() + msg.time - } // @ts-ignore TODO: fix msg types in generator - this.md.distributeMessage(msg, msg._index) + this.md.appendMessage(msg, msg._index) } }) socket.on("control_granted", id => { @@ -211,6 +206,14 @@ export default class AssistManager { } } }) + socket.on('videofeed', ({ streamId, enabled }) => { + console.log(streamId, enabled) + console.log(this.videoStreams) + if (this.videoStreams[streamId]) { + this.videoStreams[streamId].enabled = enabled + } + console.log(this.videoStreams) + }) socket.on('SESSION_DISCONNECTED', e => { waitingForMessages = true clearDisconnectTimeout() @@ -295,11 +298,13 @@ export default class AssistManager { this.md.overlay.addEventListener("mousemove", this.onMouseMove) this.md.overlay.addEventListener("click", this.onMouseClick) this.md.overlay.addEventListener("wheel", this.onWheel) + this.md.toggleRemoteControlStatus(true) update({ remoteControl: RemoteControlStatus.Enabled }) } else { this.md.overlay.removeEventListener("mousemove", this.onMouseMove) this.md.overlay.removeEventListener("click", this.onMouseClick) this.md.overlay.removeEventListener("wheel", this.onWheel) + this.md.toggleRemoteControlStatus(false) update({ remoteControl: RemoteControlStatus.Disabled }) this.toggleAnnotation(false) } @@ -311,7 +316,10 @@ export default class AssistManager { if (remoteControl === RemoteControlStatus.Requesting) { return } if (remoteControl === RemoteControlStatus.Disabled) { update({ remoteControl: RemoteControlStatus.Requesting }) - this.socket.emit("request_control") + this.socket.emit("request_control", JSON.stringify({ + ...this.session.agentInfo, + query: document.location.search + })) // setTimeout(() => { // if (getState().remoteControl !== RemoteControlStatus.Requesting) { return } // this.socket?.emit("release_control") @@ -370,6 +378,7 @@ export default class AssistManager { }) call.on('stream', stream => { + this.videoStreams[call.peer] = stream.getVideoTracks()[0] this.callArgs && this.callArgs.onStream(stream) }); // call.peerConnection.addEventListener("track", e => console.log('newtrack',e.track)) @@ -501,6 +510,9 @@ export default class AssistManager { call.on('stream', stream => { getState().calling !== CallingState.OnCall && update({ calling: CallingState.OnCall }) + + this.videoStreams[call.peer] = stream.getVideoTracks()[0] + this.callArgs && this.callArgs.onStream(stream) }); // call.peerConnection.addEventListener("track", e => console.log('newtrack',e.track)) @@ -555,13 +567,14 @@ export default class AssistManager { } } - private annot: AnnotationCanvas | null = null - - toggleTimeTravelJump() { - this.jumped = true; - this.timeTravelJump = !this.timeTravelJump; + toggleVideoLocalStream(enabled: boolean) { + this.getPeer().then((peer) => { + this.socket.emit('videofeed', { streamId: peer.id, enabled }) + }) } + private annot: AnnotationCanvas | null = null + /* ==== Cleaning ==== */ private cleaned: boolean = false clear() { diff --git a/frontend/app/player/MessageDistributor/managers/DOM/DOMManager.ts b/frontend/app/player/MessageDistributor/managers/DOM/DOMManager.ts index 39c1dab87..2688abb14 100644 --- a/frontend/app/player/MessageDistributor/managers/DOM/DOMManager.ts +++ b/frontend/app/player/MessageDistributor/managers/DOM/DOMManager.ts @@ -5,6 +5,7 @@ import type { Message, SetNodeScroll, CreateElementNode } from '../../messages'; import ListWalker from '../ListWalker'; import StylesManager, { rewriteNodeStyleSheet } from './StylesManager'; +import FocusManager from './FocusManager'; import { VElement, VText, @@ -15,6 +16,7 @@ import { PostponedStyleSheet, } from './VirtualDOM'; import type { StyleElement } from './VirtualDOM'; +import { insertRule, deleteRule } from './safeCSSRules'; type HTMLElementWithValue = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement @@ -32,32 +34,11 @@ const ATTR_NAME_REGEXP = /([^\t\n\f \/>"'=]+)/; // regexp costs ~ // .replace(/\-webkit\-/g, "") // } -function insertRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { rule: string, index: number }) { - try { - sheet.insertRule(msg.rule, msg.index) - } catch (e) { - logger.warn(e, msg) - try { - sheet.insertRule(msg.rule, 0) - logger.warn("Inserting rule into 0-index", e, msg) - } catch (e) { - logger.warn("Cannot insert rule.", e, msg) - } - } -} - -function deleteRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { index: number }) { - try { - sheet.deleteRule(msg.index) - } catch (e) { - logger.warn(e, msg) - } -} export default class DOMManager extends ListWalker<Message> { - private vTexts: Map<number, VText> = new Map() // map vs object here? - private vElements: Map<number, VElement> = new Map() - private vRoots: Map<number, VShadowRoot | VDocument> = new Map() + private readonly vTexts: Map<number, VText> = new Map() // map vs object here? + private readonly vElements: Map<number, VElement> = new Map() + private readonly vRoots: Map<number, VShadowRoot | VDocument> = new Map() private activeIframeRoots: Map<number, number> = new Map() private styleSheets: Map<number, CSSStyleSheet> = new Map() private ppStyleSheets: Map<number, PostponedStyleSheet> = new Map() @@ -66,6 +47,7 @@ export default class DOMManager extends ListWalker<Message> { private upperBodyId: number = -1; private nodeScrollManagers: Map<number, ListWalker<SetNodeScroll>> = new Map() private stylesManager: StylesManager + private focusManager: FocusManager = new FocusManager(this.vElements) constructor( @@ -75,7 +57,6 @@ export default class DOMManager extends ListWalker<Message> { ) { super() this.stylesManager = new StylesManager(screen) - logger.log(this.vElements) } append(m: Message): void { @@ -88,6 +69,10 @@ export default class DOMManager extends ListWalker<Message> { scrollManager.append(m) return } + if (m.tp === "set_node_focus") { + this.focusManager.append(m) + return + } if (m.tp === "create_element_node") { if(m.tag === "BODY" && this.upperBodyId === -1) { this.upperBodyId = m.id @@ -147,7 +132,7 @@ export default class DOMManager extends ListWalker<Message> { parent.insertChildAt(child, index) } - private applyMessage = (msg: Message): void => { + private applyMessage = (msg: Message): Promise<any> | undefined => { let node: Node | undefined let vn: VNode | undefined let doc: Document | null @@ -166,12 +151,15 @@ export default class DOMManager extends ListWalker<Message> { fRoot.innerText = ''; vn = new VElement(fRoot) - this.vElements = new Map([[0, vn]]) + this.vElements.clear() + this.vElements.set(0, vn) const vDoc = new VDocument(doc) vDoc.insertChildAt(vn, 0) - this.vRoots = new Map([[0, vDoc]]) // watchout: id==0 for both Document and documentElement + this.vRoots.clear() + this.vRoots.set(0, vDoc) // watchout: id==0 for both Document and documentElement // this is done for the AdoptedCSS logic // todo: start from 0 (sync logic with tracker) + this.vTexts.clear() this.stylesManager.reset() this.activeIframeRoots.clear() return @@ -361,7 +349,7 @@ export default class DOMManager extends ListWalker<Message> { if (!vn) { // non-constructed case vn = this.vElements.get(msg.id) - if (!vn) { logger.error("Node not found", msg); return } + if (!vn) { logger.error("Node not found", msg); return } if (!(vn instanceof VStyleElement)) { logger.error("Non-style owner", msg); return } this.ppStyleSheets.set(msg.sheetID, new PostponedStyleSheet(vn.node)) return @@ -392,20 +380,37 @@ export default class DOMManager extends ListWalker<Message> { //@ts-ignore vn.node.adoptedStyleSheets = [...vn.node.adoptedStyleSheets].filter(s => s !== styleSheet) return + case "load_font_face": + vn = this.vRoots.get(msg.parentID) + if (!vn) { logger.error("Node not found", msg); return } + if (vn instanceof VShadowRoot) { logger.error(`Node ${vn} expected to be a Document`, msg); return } + let descr: Object + try { + descr = JSON.parse(msg.descriptors) + descr = typeof descr === 'object' ? descr : undefined + } catch { + logger.warn("Can't parse font-face descriptors: ", msg) + } + const ff = new FontFace(msg.family, msg.source, descr) + vn.node.fonts.add(ff) + return ff.load() } } - moveReady(t: number): Promise<void> { + async moveReady(t: number): Promise<void> { // MBTODO (back jump optimisation): // - store intemediate virtual dom state // - cancel previous moveReady tasks (is it possible?) if new timestamp is less - this.moveApply(t, this.applyMessage) // This function autoresets pointer if necessary (better name?) - + // This function autoresets pointer if necessary (better name?) + + await this.moveWait(t, this.applyMessage) this.vRoots.forEach(rt => rt.applyChanges()) // MBTODO (optimisation): affected set // Thinkabout (read): css preload // What if we go back before it is ready? We'll have two handlres? return this.stylesManager.moveReady(t).then(() => { + // Apply focus + this.focusManager.move(t) // Apply all scrolls after the styles got applied this.nodeScrollManagers.forEach(manager => { const msg = manager.moveGetLast(t) diff --git a/frontend/app/player/MessageDistributor/managers/DOM/FocusManager.ts b/frontend/app/player/MessageDistributor/managers/DOM/FocusManager.ts new file mode 100644 index 000000000..6f80ed16c --- /dev/null +++ b/frontend/app/player/MessageDistributor/managers/DOM/FocusManager.ts @@ -0,0 +1,26 @@ +import logger from 'App/logger'; +import type { SetNodeFocus } from '../../messages'; +import type { VElement } from './VirtualDOM'; +import ListWalker from '../ListWalker'; + + +const FOCUS_CLASS = "-openreplay-focus" + +export default class FocusManager extends ListWalker<SetNodeFocus> { + constructor(private readonly vElements: Map<number, VElement>) {super()} + private focused: Element | null = null + move(t: number) { + const msg = this.moveGetLast(t) + if (!msg) {return} + this.focused?.classList.remove(FOCUS_CLASS) + if (msg.id === -1) { + this.focused = null + return + } + const vn = this.vElements.get(msg.id) + if (!vn) { logger.error("Node not found", msg); return } + this.focused = vn.node + this.focused.classList.add(FOCUS_CLASS) + } + +} \ No newline at end of file diff --git a/frontend/app/player/MessageDistributor/managers/DOM/StylesManager.ts b/frontend/app/player/MessageDistributor/managers/DOM/StylesManager.ts index f26d8e5ea..b6dddcdd9 100644 --- a/frontend/app/player/MessageDistributor/managers/DOM/StylesManager.ts +++ b/frontend/app/player/MessageDistributor/managers/DOM/StylesManager.ts @@ -1,7 +1,7 @@ import type StatedScreen from '../../StatedScreen'; -import type { CssInsertRule, CssDeleteRule, ReplaceVcss } from '../../messages'; +import type { CssInsertRule, CssDeleteRule } from '../../messages'; -type CSSRuleMessage = CssInsertRule | CssDeleteRule | ReplaceVcss; +type CSSRuleMessage = CssInsertRule | CssDeleteRule; import ListWalker from '../ListWalker'; diff --git a/frontend/app/player/MessageDistributor/managers/DOM/VirtualDOM.ts b/frontend/app/player/MessageDistributor/managers/DOM/VirtualDOM.ts index 5efa2ddf1..1be12d68c 100644 --- a/frontend/app/player/MessageDistributor/managers/DOM/VirtualDOM.ts +++ b/frontend/app/player/MessageDistributor/managers/DOM/VirtualDOM.ts @@ -2,6 +2,8 @@ type VChild = VElement | VText export type VNode = VDocument | VShadowRoot | VElement | VText +import { insertRule, deleteRule } from './safeCSSRules'; + abstract class VParent { abstract node: Node | null protected children: VChild[] = [] @@ -182,11 +184,11 @@ export class PostponedStyleSheet { } insertRule(rule: string, index: number) { - this.applyCallback(s => s.insertRule(rule, index)) + this.applyCallback(s => insertRule(s, { rule, index })) } deleteRule(index: number) { - this.applyCallback(s => s.deleteRule(index)) + this.applyCallback(s => deleteRule(s, { index })) } } diff --git a/frontend/app/player/MessageDistributor/managers/DOM/safeCSSRules.ts b/frontend/app/player/MessageDistributor/managers/DOM/safeCSSRules.ts new file mode 100644 index 000000000..a65c0cf6c --- /dev/null +++ b/frontend/app/player/MessageDistributor/managers/DOM/safeCSSRules.ts @@ -0,0 +1,25 @@ +import logger from 'App/logger'; + +export type { PostponedStyleSheet } from './VirtualDOM' + +export function insertRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { rule: string, index: number }) { + try { + sheet.insertRule(msg.rule, msg.index) + } catch (e) { + logger.warn(e, msg) + try { + sheet.insertRule(msg.rule, 0) + logger.warn("Inserting rule into 0-index", e, msg) + } catch (e) { + logger.warn("Cannot insert rule.", e, msg) + } + } +} + +export function deleteRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { index: number }) { + try { + sheet.deleteRule(msg.index) + } catch (e) { + logger.warn(e, msg) + } +} diff --git a/frontend/app/player/MessageDistributor/managers/ListWalker.ts b/frontend/app/player/MessageDistributor/managers/ListWalker.ts index acf7b70aa..c0d59c354 100644 --- a/frontend/app/player/MessageDistributor/managers/ListWalker.ts +++ b/frontend/app/player/MessageDistributor/managers/ListWalker.ts @@ -9,7 +9,7 @@ export default class ListWalker<T extends Timed> { console.error("Trying to append message with the less time then the list tail: ", m) return } - this._list.push(m); + this.list.push(m); } reset(): void { @@ -18,53 +18,53 @@ export default class ListWalker<T extends Timed> { sort(comparator: (a: T, b: T) => number): void { // @ts-ignore - this._list.sort((m1,m2) => comparator(m1,m2) || (m1._index - m2._index) ); // indexes for sort stability (TODO: fix types???) + this.list.sort((m1,m2) => comparator(m1,m2) || (m1._index - m2._index) ); // indexes for sort stability (TODO: fix types???) } forEach(f: (item: T) => void):void { - this._list.forEach(f); + this.list.forEach(f); } get last(): T | null { - if (this._list.length === 0) { + if (this.list.length === 0) { return null; } - return this._list[ this._list.length - 1 ]; + return this.list[ this.list.length - 1 ]; } get current(): T | null { if (this.p === 0) { return null; } - return this._list[ this.p - 1 ]; + return this.list[ this.p - 1 ]; } get timeNow(): number { if (this.p === 0) { return 0; } - return this._list[ this.p - 1 ].time; + return this.list[ this.p - 1 ].time; } get length(): number { - return this._list.length; + return this.list.length; } get maxTime(): number { if (this.length === 0) { return 0; } - return this._list[ this.length - 1 ].time; + return this.list[ this.length - 1 ].time; } get minTime(): number { if (this.length === 0) { return 0; } - return this._list[ 0 ].time; + return this.list[ 0 ].time; } get listNow(): Array<T> { - return this._list.slice(0, this.p); + return this.list.slice(0, this.p); } get list(): Array<T> { @@ -79,6 +79,23 @@ export default class ListWalker<T extends Timed> { return this.p; } + private hasNext() { + return this.p < this.length + } + private hasPrev() { + return this.p > 0 + } + protected moveNext(): T | null { + return this.hasNext() + ? this.list[ this.p++ ] + : null + } + protected movePrev(): T | null { + return this.hasPrev() + ? this.list[ --this.p ] + : null + } + /* Returns last message with the time <= t. Assumed that the current message is already handled so @@ -93,28 +110,42 @@ export default class ListWalker<T extends Timed> { } let changed = false; - while (this.p < this.length && this._list[this.p][key] <= val) { - this.p++; + while (this.p < this.length && this.list[this.p][key] <= val) { + this.moveNext() changed = true; } - while (this.p > 0 && this._list[ this.p - 1 ][key] > val) { - this.p--; + while (this.p > 0 && this.list[ this.p - 1 ][key] > val) { + this.movePrev() changed = true; } - return changed ? this._list[ this.p - 1 ] : null; + return changed ? this.list[ this.p - 1 ] : null; } - moveApply(t: number, fn: (T) => void, fnBack?: (T) => void): void { + moveApply(t: number, fn: (msg: T) => void, fnBack?: (msg: T) => void): void { // Applying only in increment order for now if (t < this.timeNow) { this.reset(); } - while (!!this._list[this.p] && this._list[this.p].time <= t) { - fn(this._list[ this.p++ ]); + const list = this.list + while (list[this.p] && list[this.p].time <= t) { + fn(this.moveNext()) } - while (fnBack && this.p > 0 && this._list[ this.p - 1 ].time > t) { - fnBack(this._list[ --this.p ]); + while (fnBack && this.p > 0 && list[ this.p - 1 ].time > t) { + fnBack(this.movePrev()); + } + } + + async moveWait(t: number, fn: (msg: T) => Promise<any> | undefined): Promise<void> { + // Applying only in increment order for now + if (t < this.timeNow) { + this.reset(); + } + + const list = this.list + while (list[this.p] && list[this.p].time <= t) { + const ret = fn(this.list[ this.p++ ]); + if (ret) { await ret } } } diff --git a/frontend/app/player/MessageDistributor/managers/ListWalkerWithMarks.ts b/frontend/app/player/MessageDistributor/managers/ListWalkerWithMarks.ts new file mode 100644 index 000000000..d2f2ccee3 --- /dev/null +++ b/frontend/app/player/MessageDistributor/managers/ListWalkerWithMarks.ts @@ -0,0 +1,42 @@ +import type { Timed } from '../messages/timed'; +import ListWalker from './ListWalker' + + +type CheckFn<T> = (t: T) => boolean + + +export default class ListWalkerWithMarks<T extends Timed> extends ListWalker<T> { + private _markCountNow: number = 0 + private _markCount: number = 0 + constructor(private isMarked: CheckFn<T>, initialList: T[] = []) { + super(initialList) + this._markCount = initialList.reduce((n, item) => isMarked(item) ? n+1 : n, 0) + } + + append(item: T) { + if (this.isMarked(item)) { this._markCount++ } + super.append(item) + } + + protected moveNext() { + const val = super.moveNext() + if (val && this.isMarked(val)) { + this._markCountNow++ + } + return val + } + protected movePrev() { + const val = super.movePrev() + if (val && this.isMarked(val)) { + this._markCountNow-- + } + return val + } + get markedCountNow(): number { + return this._markCountNow + } + get markedCount(): number { + return this._markCount + } + +} \ No newline at end of file diff --git a/frontend/app/player/MessageDistributor/managers/LocalStream.ts b/frontend/app/player/MessageDistributor/managers/LocalStream.ts index 360033c7f..e7d3bae15 100644 --- a/frontend/app/player/MessageDistributor/managers/LocalStream.ts +++ b/frontend/app/player/MessageDistributor/managers/LocalStream.ts @@ -18,7 +18,7 @@ function dummyTrack(): MediaStreamTrack { return canvas.captureStream(60).getTracks()[0]; } -export default function RequestLocalStream(): Promise<LocalStream> { +export function RequestLocalStream(): Promise<LocalStream> { return navigator.mediaDevices.getUserMedia({ audio:true }) .then(aStream => { const aTrack = aStream.getAudioTracks()[0] diff --git a/frontend/app/player/MessageDistributor/messages/MFileReader.ts b/frontend/app/player/MessageDistributor/messages/MFileReader.ts index 9db9c2cff..1b4bb5751 100644 --- a/frontend/app/player/MessageDistributor/messages/MFileReader.ts +++ b/frontend/app/player/MessageDistributor/messages/MFileReader.ts @@ -4,7 +4,7 @@ import logger from 'App/logger'; import RawMessageReader from './RawMessageReader'; // TODO: composition instead of inheritance -// needSkipMessage() and next() methods here use buf and p protected properties, +// needSkipMessage() and next() methods here use buf and p protected properties, // which should be probably somehow incapsulated export default class MFileReader extends RawMessageReader { private pLastMessageID: number = 0 @@ -18,12 +18,20 @@ export default class MFileReader extends RawMessageReader { if (this.p === 0) return false for (let i = 7; i >= 0; i--) { if (this.buf[ this.p + i ] !== this.buf[ this.pLastMessageID + i ]) { - return this.buf[ this.p + i ] - this.buf[ this.pLastMessageID + i ] < 0 + return this.buf[ this.p + i ] < this.buf[ this.pLastMessageID + i ] } } return false } + private getLastMessageID(): number { + let id = 0 + for (let i = 0; i< 8; i++) { + id += this.buf[ this.p + i ] * 2**(8*i) + } + return id + } + private readRawMessage(): RawMessage | null { this.skip(8) try { @@ -49,7 +57,7 @@ export default class MFileReader extends RawMessageReader { if (!skippedMessage) { return null } - logger.log("Skipping message: ", skippedMessage) + logger.group("Openreplay: Skipping messages ", skippedMessage) } this.pLastMessageID = this.p @@ -65,13 +73,14 @@ export default class MFileReader extends RawMessageReader { } this.currentTime = rMsg.timestamp - this.startTime return this.next() - } + } + const index = this.getLastMessageID() const msg = Object.assign(rMsg, { time: this.currentTime, - _index: this.pLastMessageID, + _index: index, }) - return [msg, this.pLastMessageID] + return [msg, index] } } diff --git a/frontend/app/player/MessageDistributor/messages/RawMessageReader.ts b/frontend/app/player/MessageDistributor/messages/RawMessageReader.ts index f459c9369..80ebb30b1 100644 --- a/frontend/app/player/MessageDistributor/messages/RawMessageReader.ts +++ b/frontend/app/player/MessageDistributor/messages/RawMessageReader.ts @@ -17,7 +17,7 @@ export default class RawMessageReader extends PrimitiveReader { if (tp === null) { return resetPointer() } switch (tp) { - + case 0: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } return { @@ -25,7 +25,7 @@ export default class RawMessageReader extends PrimitiveReader { timestamp, }; } - + case 4: { const url = this.readString(); if (url === null) { return resetPointer() } const referrer = this.readString(); if (referrer === null) { return resetPointer() } @@ -37,7 +37,7 @@ export default class RawMessageReader extends PrimitiveReader { navigationStart, }; } - + case 5: { const width = this.readUint(); if (width === null) { return resetPointer() } const height = this.readUint(); if (height === null) { return resetPointer() } @@ -47,7 +47,7 @@ export default class RawMessageReader extends PrimitiveReader { height, }; } - + case 6: { const x = this.readInt(); if (x === null) { return resetPointer() } const y = this.readInt(); if (y === null) { return resetPointer() } @@ -57,7 +57,7 @@ export default class RawMessageReader extends PrimitiveReader { y, }; } - + case 7: { return { @@ -65,7 +65,7 @@ export default class RawMessageReader extends PrimitiveReader { }; } - + case 8: { const id = this.readUint(); if (id === null) { return resetPointer() } const parentID = this.readUint(); if (parentID === null) { return resetPointer() } @@ -81,7 +81,7 @@ export default class RawMessageReader extends PrimitiveReader { svg, }; } - + case 9: { const id = this.readUint(); if (id === null) { return resetPointer() } const parentID = this.readUint(); if (parentID === null) { return resetPointer() } @@ -93,7 +93,7 @@ export default class RawMessageReader extends PrimitiveReader { index, }; } - + case 10: { const id = this.readUint(); if (id === null) { return resetPointer() } const parentID = this.readUint(); if (parentID === null) { return resetPointer() } @@ -105,7 +105,7 @@ export default class RawMessageReader extends PrimitiveReader { index, }; } - + case 11: { const id = this.readUint(); if (id === null) { return resetPointer() } return { @@ -113,7 +113,7 @@ export default class RawMessageReader extends PrimitiveReader { id, }; } - + case 12: { const id = this.readUint(); if (id === null) { return resetPointer() } const name = this.readString(); if (name === null) { return resetPointer() } @@ -125,7 +125,7 @@ export default class RawMessageReader extends PrimitiveReader { value, }; } - + case 13: { const id = this.readUint(); if (id === null) { return resetPointer() } const name = this.readString(); if (name === null) { return resetPointer() } @@ -135,7 +135,7 @@ export default class RawMessageReader extends PrimitiveReader { name, }; } - + case 14: { const id = this.readUint(); if (id === null) { return resetPointer() } const data = this.readString(); if (data === null) { return resetPointer() } @@ -145,7 +145,7 @@ export default class RawMessageReader extends PrimitiveReader { data, }; } - + case 15: { const id = this.readUint(); if (id === null) { return resetPointer() } const data = this.readString(); if (data === null) { return resetPointer() } @@ -155,7 +155,7 @@ export default class RawMessageReader extends PrimitiveReader { data, }; } - + case 16: { const id = this.readUint(); if (id === null) { return resetPointer() } const x = this.readInt(); if (x === null) { return resetPointer() } @@ -167,7 +167,7 @@ export default class RawMessageReader extends PrimitiveReader { y, }; } - + case 18: { const id = this.readUint(); if (id === null) { return resetPointer() } const value = this.readString(); if (value === null) { return resetPointer() } @@ -179,7 +179,7 @@ export default class RawMessageReader extends PrimitiveReader { mask, }; } - + case 19: { const id = this.readUint(); if (id === null) { return resetPointer() } const checked = this.readBoolean(); if (checked === null) { return resetPointer() } @@ -189,7 +189,7 @@ export default class RawMessageReader extends PrimitiveReader { checked, }; } - + case 20: { const x = this.readUint(); if (x === null) { return resetPointer() } const y = this.readUint(); if (y === null) { return resetPointer() } @@ -199,7 +199,7 @@ export default class RawMessageReader extends PrimitiveReader { y, }; } - + case 22: { const level = this.readString(); if (level === null) { return resetPointer() } const value = this.readString(); if (value === null) { return resetPointer() } @@ -209,7 +209,7 @@ export default class RawMessageReader extends PrimitiveReader { value, }; } - + case 37: { const id = this.readUint(); if (id === null) { return resetPointer() } const rule = this.readString(); if (rule === null) { return resetPointer() } @@ -221,7 +221,7 @@ export default class RawMessageReader extends PrimitiveReader { index, }; } - + case 38: { const id = this.readUint(); if (id === null) { return resetPointer() } const index = this.readUint(); if (index === null) { return resetPointer() } @@ -231,7 +231,7 @@ export default class RawMessageReader extends PrimitiveReader { index, }; } - + case 39: { const method = this.readString(); if (method === null) { return resetPointer() } const url = this.readString(); if (url === null) { return resetPointer() } @@ -251,7 +251,7 @@ export default class RawMessageReader extends PrimitiveReader { duration, }; } - + case 40: { const name = this.readString(); if (name === null) { return resetPointer() } const duration = this.readUint(); if (duration === null) { return resetPointer() } @@ -265,7 +265,7 @@ export default class RawMessageReader extends PrimitiveReader { result, }; } - + case 41: { const key = this.readString(); if (key === null) { return resetPointer() } const value = this.readString(); if (value === null) { return resetPointer() } @@ -275,7 +275,7 @@ export default class RawMessageReader extends PrimitiveReader { value, }; } - + case 44: { const action = this.readString(); if (action === null) { return resetPointer() } const state = this.readString(); if (state === null) { return resetPointer() } @@ -287,7 +287,7 @@ export default class RawMessageReader extends PrimitiveReader { duration, }; } - + case 45: { const mutation = this.readString(); if (mutation === null) { return resetPointer() } const state = this.readString(); if (state === null) { return resetPointer() } @@ -297,7 +297,7 @@ export default class RawMessageReader extends PrimitiveReader { state, }; } - + case 46: { const type = this.readString(); if (type === null) { return resetPointer() } const payload = this.readString(); if (payload === null) { return resetPointer() } @@ -307,7 +307,7 @@ export default class RawMessageReader extends PrimitiveReader { payload, }; } - + case 47: { const action = this.readString(); if (action === null) { return resetPointer() } const state = this.readString(); if (state === null) { return resetPointer() } @@ -319,7 +319,7 @@ export default class RawMessageReader extends PrimitiveReader { duration, }; } - + case 48: { const operationKind = this.readString(); if (operationKind === null) { return resetPointer() } const operationName = this.readString(); if (operationName === null) { return resetPointer() } @@ -333,7 +333,7 @@ export default class RawMessageReader extends PrimitiveReader { response, }; } - + case 49: { const frames = this.readInt(); if (frames === null) { return resetPointer() } const ticks = this.readInt(); if (ticks === null) { return resetPointer() } @@ -347,7 +347,7 @@ export default class RawMessageReader extends PrimitiveReader { usedJSHeapSize, }; } - + case 54: { const downlink = this.readUint(); if (downlink === null) { return resetPointer() } const type = this.readString(); if (type === null) { return resetPointer() } @@ -357,7 +357,7 @@ export default class RawMessageReader extends PrimitiveReader { type, }; } - + case 55: { const hidden = this.readBoolean(); if (hidden === null) { return resetPointer() } return { @@ -365,7 +365,29 @@ export default class RawMessageReader extends PrimitiveReader { hidden, }; } - + + case 57: { + const parentID = this.readUint(); if (parentID === null) { return resetPointer() } + const family = this.readString(); if (family === null) { return resetPointer() } + const source = this.readString(); if (source === null) { return resetPointer() } + const descriptors = this.readString(); if (descriptors === null) { return resetPointer() } + return { + tp: "load_font_face", + parentID, + family, + source, + descriptors, + }; + } + + case 58: { + const id = this.readInt(); if (id === null) { return resetPointer() } + return { + tp: "set_node_focus", + id, + }; + } + case 59: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } const duration = this.readUint(); if (duration === null) { return resetPointer() } @@ -385,7 +407,7 @@ export default class RawMessageReader extends PrimitiveReader { containerName, }; } - + case 60: { const id = this.readUint(); if (id === null) { return resetPointer() } const name = this.readString(); if (name === null) { return resetPointer() } @@ -399,7 +421,7 @@ export default class RawMessageReader extends PrimitiveReader { baseURL, }; } - + case 61: { const id = this.readUint(); if (id === null) { return resetPointer() } const data = this.readString(); if (data === null) { return resetPointer() } @@ -411,7 +433,7 @@ export default class RawMessageReader extends PrimitiveReader { baseURL, }; } - + case 67: { const id = this.readUint(); if (id === null) { return resetPointer() } const rule = this.readString(); if (rule === null) { return resetPointer() } @@ -425,7 +447,7 @@ export default class RawMessageReader extends PrimitiveReader { baseURL, }; } - + case 69: { const id = this.readUint(); if (id === null) { return resetPointer() } const hesitationTime = this.readUint(); if (hesitationTime === null) { return resetPointer() } @@ -439,7 +461,7 @@ export default class RawMessageReader extends PrimitiveReader { selector, }; } - + case 70: { const frameID = this.readUint(); if (frameID === null) { return resetPointer() } const id = this.readUint(); if (id === null) { return resetPointer() } @@ -449,7 +471,7 @@ export default class RawMessageReader extends PrimitiveReader { id, }; } - + case 71: { const sheetID = this.readUint(); if (sheetID === null) { return resetPointer() } const text = this.readString(); if (text === null) { return resetPointer() } @@ -461,7 +483,7 @@ export default class RawMessageReader extends PrimitiveReader { baseURL, }; } - + case 72: { const sheetID = this.readUint(); if (sheetID === null) { return resetPointer() } const text = this.readString(); if (text === null) { return resetPointer() } @@ -471,7 +493,7 @@ export default class RawMessageReader extends PrimitiveReader { text, }; } - + case 73: { const sheetID = this.readUint(); if (sheetID === null) { return resetPointer() } const rule = this.readString(); if (rule === null) { return resetPointer() } @@ -485,7 +507,7 @@ export default class RawMessageReader extends PrimitiveReader { baseURL, }; } - + case 74: { const sheetID = this.readUint(); if (sheetID === null) { return resetPointer() } const rule = this.readString(); if (rule === null) { return resetPointer() } @@ -497,7 +519,7 @@ export default class RawMessageReader extends PrimitiveReader { index, }; } - + case 75: { const sheetID = this.readUint(); if (sheetID === null) { return resetPointer() } const index = this.readUint(); if (index === null) { return resetPointer() } @@ -507,7 +529,7 @@ export default class RawMessageReader extends PrimitiveReader { index, }; } - + case 76: { const sheetID = this.readUint(); if (sheetID === null) { return resetPointer() } const id = this.readUint(); if (id === null) { return resetPointer() } @@ -517,7 +539,7 @@ export default class RawMessageReader extends PrimitiveReader { id, }; } - + case 77: { const sheetID = this.readUint(); if (sheetID === null) { return resetPointer() } const id = this.readUint(); if (id === null) { return resetPointer() } @@ -527,7 +549,7 @@ export default class RawMessageReader extends PrimitiveReader { id, }; } - + case 79: { const mutation = this.readString(); if (mutation === null) { return resetPointer() } const state = this.readString(); if (state === null) { return resetPointer() } @@ -537,7 +559,7 @@ export default class RawMessageReader extends PrimitiveReader { state, }; } - + case 90: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } const projectID = this.readUint(); if (projectID === null) { return resetPointer() } @@ -563,7 +585,7 @@ export default class RawMessageReader extends PrimitiveReader { userCountry, }; } - + case 93: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } const length = this.readUint(); if (length === null) { return resetPointer() } @@ -577,7 +599,7 @@ export default class RawMessageReader extends PrimitiveReader { payload, }; } - + case 96: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } const length = this.readUint(); if (length === null) { return resetPointer() } @@ -595,7 +617,7 @@ export default class RawMessageReader extends PrimitiveReader { height, }; } - + case 100: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } const length = this.readUint(); if (length === null) { return resetPointer() } @@ -611,7 +633,7 @@ export default class RawMessageReader extends PrimitiveReader { y, }; } - + case 102: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } const length = this.readUint(); if (length === null) { return resetPointer() } @@ -625,7 +647,7 @@ export default class RawMessageReader extends PrimitiveReader { value, }; } - + case 103: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } const length = this.readUint(); if (length === null) { return resetPointer() } @@ -639,7 +661,7 @@ export default class RawMessageReader extends PrimitiveReader { content, }; } - + case 105: { const timestamp = this.readUint(); if (timestamp === null) { return resetPointer() } const length = this.readUint(); if (length === null) { return resetPointer() } @@ -663,7 +685,7 @@ export default class RawMessageReader extends PrimitiveReader { status, }; } - + default: throw new Error(`Unrecognizable message type: ${ tp }; Pointer at the position ${this.p} of ${this.buf.length}`) return null; diff --git a/frontend/app/player/MessageDistributor/messages/message.ts b/frontend/app/player/MessageDistributor/messages/message.ts index 4b82c27e7..3925fb235 100644 --- a/frontend/app/player/MessageDistributor/messages/message.ts +++ b/frontend/app/player/MessageDistributor/messages/message.ts @@ -35,6 +35,8 @@ import type { RawPerformanceTrack, RawConnectionInformation, RawSetPageVisibility, + RawLoadFontFace, + RawSetNodeFocus, RawLongTask, RawSetNodeAttributeURLBased, RawSetCssDataURLBased, @@ -123,6 +125,10 @@ export type ConnectionInformation = RawConnectionInformation & Timed export type SetPageVisibility = RawSetPageVisibility & Timed +export type LoadFontFace = RawLoadFontFace & Timed + +export type SetNodeFocus = RawSetNodeFocus & Timed + export type LongTask = RawLongTask & Timed export type SetNodeAttributeURLBased = RawSetNodeAttributeURLBased & Timed diff --git a/frontend/app/player/MessageDistributor/messages/raw.ts b/frontend/app/player/MessageDistributor/messages/raw.ts index 69ef5877f..0d744e2fd 100644 --- a/frontend/app/player/MessageDistributor/messages/raw.ts +++ b/frontend/app/player/MessageDistributor/messages/raw.ts @@ -207,6 +207,19 @@ export interface RawSetPageVisibility { hidden: boolean, } +export interface RawLoadFontFace { + tp: "load_font_face", + parentID: number, + family: string, + source: string, + descriptors: string, +} + +export interface RawSetNodeFocus { + tp: "set_node_focus", + id: number, +} + export interface RawLongTask { tp: "long_task", timestamp: number, @@ -378,4 +391,4 @@ export interface RawIosNetworkCall { } -export type RawMessage = RawTimestamp | RawSetPageLocation | RawSetViewportSize | RawSetViewportScroll | RawCreateDocument | RawCreateElementNode | RawCreateTextNode | RawMoveNode | RawRemoveNode | RawSetNodeAttribute | RawRemoveNodeAttribute | RawSetNodeData | RawSetCssData | RawSetNodeScroll | RawSetInputValue | RawSetInputChecked | RawMouseMove | RawConsoleLog | RawCssInsertRule | RawCssDeleteRule | RawFetch | RawProfiler | RawOTable | RawRedux | RawVuex | RawMobX | RawNgRx | RawGraphQl | RawPerformanceTrack | RawConnectionInformation | RawSetPageVisibility | RawLongTask | RawSetNodeAttributeURLBased | RawSetCssDataURLBased | RawCssInsertRuleURLBased | RawMouseClick | RawCreateIFrameDocument | RawAdoptedSsReplaceURLBased | RawAdoptedSsReplace | RawAdoptedSsInsertRuleURLBased | RawAdoptedSsInsertRule | RawAdoptedSsDeleteRule | RawAdoptedSsAddOwner | RawAdoptedSsRemoveOwner | RawZustand | RawIosSessionStart | RawIosCustomEvent | RawIosScreenChanges | RawIosClickEvent | RawIosPerformanceEvent | RawIosLog | RawIosNetworkCall; +export type RawMessage = RawTimestamp | RawSetPageLocation | RawSetViewportSize | RawSetViewportScroll | RawCreateDocument | RawCreateElementNode | RawCreateTextNode | RawMoveNode | RawRemoveNode | RawSetNodeAttribute | RawRemoveNodeAttribute | RawSetNodeData | RawSetCssData | RawSetNodeScroll | RawSetInputValue | RawSetInputChecked | RawMouseMove | RawConsoleLog | RawCssInsertRule | RawCssDeleteRule | RawFetch | RawProfiler | RawOTable | RawRedux | RawVuex | RawMobX | RawNgRx | RawGraphQl | RawPerformanceTrack | RawConnectionInformation | RawSetPageVisibility | RawLoadFontFace | RawSetNodeFocus | RawLongTask | RawSetNodeAttributeURLBased | RawSetCssDataURLBased | RawCssInsertRuleURLBased | RawMouseClick | RawCreateIFrameDocument | RawAdoptedSsReplaceURLBased | RawAdoptedSsReplace | RawAdoptedSsInsertRuleURLBased | RawAdoptedSsInsertRule | RawAdoptedSsDeleteRule | RawAdoptedSsAddOwner | RawAdoptedSsRemoveOwner | RawZustand | RawIosSessionStart | RawIosCustomEvent | RawIosScreenChanges | RawIosClickEvent | RawIosPerformanceEvent | RawIosLog | RawIosNetworkCall; diff --git a/frontend/app/player/MessageDistributor/messages/tracker-legacy.ts b/frontend/app/player/MessageDistributor/messages/tracker-legacy.ts index 1cc6af93d..a6cfec8f0 100644 --- a/frontend/app/player/MessageDistributor/messages/tracker-legacy.ts +++ b/frontend/app/player/MessageDistributor/messages/tracker-legacy.ts @@ -26,7 +26,7 @@ export const TP_MAP = { 22: "console_log", 23: "page_load_timing", 24: "page_render_timing", - 25: "js_exception", + 25: "js_exception_deprecated", 27: "raw_custom_event", 28: "user_id", 29: "user_anonymous_id", @@ -46,6 +46,8 @@ export const TP_MAP = { 53: "resource_timing", 54: "connection_information", 55: "set_page_visibility", + 57: "load_font_face", + 58: "set_node_focus", 59: "long_task", 60: "set_node_attribute_url_based", 61: "set_css_data_url_based", @@ -62,6 +64,7 @@ export const TP_MAP = { 76: "adopted_ss_add_owner", 77: "adopted_ss_remove_owner", 79: "zustand", + 78: "js_exception", 90: "ios_session_start", 93: "ios_custom_event", 96: "ios_screen_changes", diff --git a/frontend/app/player/MessageDistributor/messages/tracker.ts b/frontend/app/player/MessageDistributor/messages/tracker.ts index 7381670c7..41e36f466 100644 --- a/frontend/app/player/MessageDistributor/messages/tracker.ts +++ b/frontend/app/player/MessageDistributor/messages/tracker.ts @@ -153,7 +153,7 @@ type TrPageRenderTiming = [ timeToInteractive: number, ] -type TrJSException = [ +type TrJSExceptionDeprecated = [ type: 25, name: string, message: string, @@ -290,6 +290,19 @@ type TrSetPageVisibility = [ hidden: boolean, ] +type TrLoadFontFace = [ + type: 57, + parentID: number, + family: string, + source: string, + descriptors: string, +] + +type TrSetNodeFocus = [ + type: 58, + id: number, +] + type TrLongTask = [ type: 59, timestamp: number, @@ -389,8 +402,16 @@ type TrZustand = [ state: string, ] +type TrJSException = [ + type: 78, + name: string, + message: string, + payload: string, + metadata: string, +] -export type TrackerMessage = TrBatchMetadata | TrPartitionedMessage | TrTimestamp | TrSetPageLocation | TrSetViewportSize | TrSetViewportScroll | TrCreateDocument | TrCreateElementNode | TrCreateTextNode | TrMoveNode | TrRemoveNode | TrSetNodeAttribute | TrRemoveNodeAttribute | TrSetNodeData | TrSetNodeScroll | TrSetInputTarget | TrSetInputValue | TrSetInputChecked | TrMouseMove | TrConsoleLog | TrPageLoadTiming | TrPageRenderTiming | TrJSException | TrRawCustomEvent | TrUserID | TrUserAnonymousID | TrMetadata | TrCSSInsertRule | TrCSSDeleteRule | TrFetch | TrProfiler | TrOTable | TrStateAction | TrRedux | TrVuex | TrMobX | TrNgRx | TrGraphQL | TrPerformanceTrack | TrResourceTiming | TrConnectionInformation | TrSetPageVisibility | TrLongTask | TrSetNodeAttributeURLBased | TrSetCSSDataURLBased | TrTechnicalInfo | TrCustomIssue | TrCSSInsertRuleURLBased | TrMouseClick | TrCreateIFrameDocument | TrAdoptedSSReplaceURLBased | TrAdoptedSSInsertRuleURLBased | TrAdoptedSSDeleteRule | TrAdoptedSSAddOwner | TrAdoptedSSRemoveOwner | TrZustand + +export type TrackerMessage = TrBatchMetadata | TrPartitionedMessage | TrTimestamp | TrSetPageLocation | TrSetViewportSize | TrSetViewportScroll | TrCreateDocument | TrCreateElementNode | TrCreateTextNode | TrMoveNode | TrRemoveNode | TrSetNodeAttribute | TrRemoveNodeAttribute | TrSetNodeData | TrSetNodeScroll | TrSetInputTarget | TrSetInputValue | TrSetInputChecked | TrMouseMove | TrConsoleLog | TrPageLoadTiming | TrPageRenderTiming | TrJSExceptionDeprecated | TrRawCustomEvent | TrUserID | TrUserAnonymousID | TrMetadata | TrCSSInsertRule | TrCSSDeleteRule | TrFetch | TrProfiler | TrOTable | TrStateAction | TrRedux | TrVuex | TrMobX | TrNgRx | TrGraphQL | TrPerformanceTrack | TrResourceTiming | TrConnectionInformation | TrSetPageVisibility | TrLoadFontFace | TrSetNodeFocus | TrLongTask | TrSetNodeAttributeURLBased | TrSetCSSDataURLBased | TrTechnicalInfo | TrCustomIssue | TrCSSInsertRuleURLBased | TrMouseClick | TrCreateIFrameDocument | TrAdoptedSSReplaceURLBased | TrAdoptedSSInsertRuleURLBased | TrAdoptedSSDeleteRule | TrAdoptedSSAddOwner | TrAdoptedSSRemoveOwner | TrZustand | TrJSException export default function translate(tMsg: TrackerMessage): RawMessage | null { switch(tMsg[0]) { @@ -654,6 +675,23 @@ export default function translate(tMsg: TrackerMessage): RawMessage | null { } } + case 57: { + return { + tp: "load_font_face", + parentID: tMsg[1], + family: tMsg[2], + source: tMsg[3], + descriptors: tMsg[4], + } + } + + case 58: { + return { + tp: "set_node_focus", + id: tMsg[1], + } + } + case 59: { return { tp: "long_task", diff --git a/frontend/app/player/MessageDistributor/messages/urlResolve.ts b/frontend/app/player/MessageDistributor/messages/urlResolve.ts index 71d1cbda8..6f76d6d15 100644 --- a/frontend/app/player/MessageDistributor/messages/urlResolve.ts +++ b/frontend/app/player/MessageDistributor/messages/urlResolve.ts @@ -50,6 +50,14 @@ function rewriteCSSLinks(css: string, rewriter: (rawurl: string) => string): str return css } +function rewritePseudoclasses(css: string): string { + return css + .replace(/:hover/g, ".-openreplay-hover") + .replace(/:focus/g, ".-openreplay-focus") +} + export function resolveCSS(baseURL: string, css: string): string { - return rewriteCSSLinks(css, rawurl => resolveURL(baseURL, rawurl)); + return rewritePseudoclasses( + rewriteCSSLinks(css, rawurl => resolveURL(baseURL, rawurl)) + ); } \ No newline at end of file diff --git a/frontend/app/player/MessageDistributor/network/crypto.ts b/frontend/app/player/MessageDistributor/network/crypto.ts new file mode 100644 index 000000000..0c9de001e --- /dev/null +++ b/frontend/app/player/MessageDistributor/network/crypto.ts @@ -0,0 +1,24 @@ + +const u8aFromHex = (hexString:string) => + Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))) + +const is16BitHex = (maybeHex: string | undefined) => + maybeHex && maybeHex.length % 2 === 0 && !/[^a-fA-F0-9]/u.test(maybeHex) + +export function decryptSessionBytes(cypher: Uint8Array, keyString: string): Promise<Uint8Array> { + if (keyString.length !== 64) { + return Promise.reject("Wrong key string format") + } + const [hexKey, hexIV] = keyString.match(/.{32}/g) + if (!is16BitHex(hexIV) || !is16BitHex(hexKey)) { + return Promise.reject("Wrong key/iv pair") + } + const byteKey = u8aFromHex(hexKey) + const iv = u8aFromHex(hexIV) + + return crypto.subtle.importKey("raw", byteKey, { name: "AES-CBC" }, false, ["decrypt"]) + .then(key => crypto.subtle.decrypt({ name: "AES-CBC", iv: iv}, key, cypher)) + .then((bArray: ArrayBuffer) => new Uint8Array(bArray)) //?? TS doesn not catch the `decrypt`` returning type +} + + diff --git a/frontend/app/player/MessageDistributor/network/loadFiles.ts b/frontend/app/player/MessageDistributor/network/loadFiles.ts index ff9e62de0..6b34c3261 100644 --- a/frontend/app/player/MessageDistributor/network/loadFiles.ts +++ b/frontend/app/player/MessageDistributor/network/loadFiles.ts @@ -3,13 +3,9 @@ import APIClient from 'App/api_client'; const NO_NTH_FILE = "nnf" const NO_UNPROCESSED_FILES = "nuf" -const getUnprocessedFileLink = (sessionId: string) => '/unprocessed/' + sessionId - -type onDataCb = (data: Uint8Array) => void - export const loadFiles = ( urls: string[], - onData: onDataCb, + onData: (data: Uint8Array) => void, ): Promise<void> => { const firstFileURL = urls[0] urls = urls.slice(1) @@ -41,28 +37,32 @@ export const loadFiles = ( }) } -export const checkUnprocessedMobs = async (sessionId: string) => { - try { - const api = new APIClient() - const res = await api.fetch(getUnprocessedFileLink(sessionId)) - if (res.status >= 400) { - throw NO_UNPROCESSED_FILES - } - const byteArray = await processAPIStreamResponse(res, false) - return byteArray - } catch (e) { - throw e - } + +export async function requestEFSDom(sessionId: string) { + return await requestEFSMobFile(sessionId, "dom.mob") } -const processAPIStreamResponse = (response: Response, isFirstFile: boolean) => { +export async function requestEFSDevtools(sessionId: string) { + return await requestEFSMobFile(sessionId, "devtools.mob") +} + +async function requestEFSMobFile(sessionId: string, filename: string) { + const api = new APIClient() + const res = await api.fetch('/unprocessed/' + sessionId + '/' + filename) + if (res.status >= 400) { + throw NO_UNPROCESSED_FILES + } + return await processAPIStreamResponse(res, false) +} + +const processAPIStreamResponse = (response: Response, isMainFile: boolean) => { return new Promise<ArrayBuffer>((res, rej) => { - if (response.status === 404 && !isFirstFile) { + if (response.status === 404 && !isMainFile) { return rej(NO_NTH_FILE) } if (response.status >= 400) { return rej( - isFirstFile ? `no start file. status code ${ response.status }` + isMainFile ? `no start file. status code ${ response.status }` : `Bad endfile status code ${response.status}` ) } diff --git a/frontend/app/player/Player.ts b/frontend/app/player/Player.ts index 870c5046e..369f854ea 100644 --- a/frontend/app/player/Player.ts +++ b/frontend/app/player/Player.ts @@ -1,6 +1,6 @@ -import { goTo as listsGoTo } from './lists'; import { update, getState } from './store'; import MessageDistributor, { INITIAL_STATE as SUPER_INITIAL_STATE } from './MessageDistributor/MessageDistributor'; +import { Note } from 'App/services/NotesService'; const fps = 60; const performance = window.performance || { now: Date.now.bind(Date) }; @@ -46,6 +46,7 @@ export const INITIAL_STATE = { live: false, livePlay: false, liveTimeTravel: false, + notes: [], } as const; @@ -66,7 +67,6 @@ export default class Player extends MessageDistributor { completed: false, }); super.move(time, index); - listsGoTo(time, index); } private _startAnimation() { @@ -156,10 +156,10 @@ export default class Player extends MessageDistributor { } } - jump(time = getState().time, index: number) { + jump(setTime: number, index: number) { const { live, liveTimeTravel, endTime } = getState(); if (live && !liveTimeTravel) return; - + const time = setTime ? setTime : getState().time if (getState().playing) { cancelAnimationFrame(this._animationFrameRequestId); // this._animationFrameRequestId = requestAnimationFrame(() => { @@ -214,12 +214,6 @@ export default class Player extends MessageDistributor { update({ skipToIssue }); } - updateSkipToIssue() { - const skipToIssue = localStorage.getItem(SKIP_TO_ISSUE_STORAGE_KEY) === 'true'; - update({ skipToIssue }); - return skipToIssue; - } - toggleAutoplay() { const autoplay = !getState().autoplay; localStorage.setItem(AUTOPLAY_STORAGE_KEY, `${autoplay}`); @@ -269,6 +263,15 @@ export default class Player extends MessageDistributor { this.cursor.toggleUserName(name) } + injectNotes(notes: Note[]) { + update({ notes }) + } + + filterOutNote(noteId: number) { + const { notes } = getState() + update({ notes: notes.filter((note: Note) => note.noteId !== noteId) }) + } + clean() { this.pause(); super.clean(); diff --git a/frontend/app/player/index.js b/frontend/app/player/index.js index 70b02ae53..c49d75294 100644 --- a/frontend/app/player/index.js +++ b/frontend/app/player/index.js @@ -1,2 +1,4 @@ -export { PlayerProvider, connectPlayer } from './store'; -export * from './singletone'; \ No newline at end of file +export * from './store'; +export * from './singletone'; +export * from './MessageDistributor/managers/AssistManager'; +export * from './MessageDistributor/managers/LocalStream'; \ No newline at end of file diff --git a/frontend/app/player/lists/ListReader.js b/frontend/app/player/lists/ListReader.js deleted file mode 100644 index 641d3341a..000000000 --- a/frontend/app/player/lists/ListReader.js +++ /dev/null @@ -1,124 +0,0 @@ -export default class ListReader { - _callback; - _p = -1; - _list = []; - _offset = 0; - - constructor(callback = Function.prototype) { - if (typeof callback !== 'function') { - return console.error("List Reader: wrong constructor argument. `callback` must be a function."); - } - this._callback = callback; - } - - static checkItem(item) { - if(typeof item !== 'object' || item === null) { - console.error("List Reader: expected item to be not null object but got ", item); - return false; - } - if (typeof item.time !== 'number') { - console.error("List Reader: expected item to have number property 'time', ", item); - return false; - } - // if (typeof item.index !== 'number') { - // console.error("List Reader: expected item to have number property 'index', ", item); - // return false; - // } // future: All will have index - return true; - } - /* EXTENDABLE METHODS */ - _onIncrement() {} - _onDecrement() {} - _onStartTimeChange() {} - - inc() { - const item = this._list[ ++this._p ]; - this._onIncrement(item); - return item; - } - - dec() { - const item = this._list[ this._p-- ]; - this._onDecrement(item); - return item - } - - get _goToReturn() { - return { listNow: this.listNow }; - } - - goTo(time) { - const prevPointer = this._p; - while (!!this._list[ this._p + 1 ] && this._list[ this._p + 1 ].time <= time) { - this.inc(); - } - while (this._p >= 0 && this._list[ this._p ].time > time) { - this.dec(); - } - if (prevPointer !== this._p) { - //this._notify([ "listNow" ]); - return this._goToReturn; - } - } - - goToIndex(index) { // thinkaboutit - const prevPointer = this._p; - while (!!this._list[ this._p + 1 ] && - this._list[ this._p + 1 ].index <= index - ) { - this.inc(); - } - while (this._p >= 0 && this._list[ this._p ].index > index) { - this.dec(); - } - if (prevPointer !== this._p) { - //this._notify([ "listNow" ]); - return this._goToReturn; - } - } - - // happens rare MBTODO only in class ResourceListReader extends ListReaderWithRed - set startTime(time) { - const prevOffset = this._offset; - const prevPointer = this._p; - this._offset = this._list.findIndex(({ time, duration = 0 }) => time + duration >= time); // TODO: strict for duration rrrrr - this._p = Math.max(this._p, this._offset - 1); - if (prevOffset !== this._offset || prevPointer !== this._p) { - this._notify([ "listNow" ]); - } - this._onStartTimeChange(); - } - - get list() { - return this._list; - } - get count() { - return this._list.length; - } - get listNow() { - return this._list.slice(this._offset, this._p + 1); - } - - set list(_list) { - if (!Array.isArray(_list)) { - console.error("List Reader: wrong list value.", _list) - } - const valid = _list.every(this.constructor.checkItem); - if (!valid) return; - this._list = _list; // future: time + index sort - this._notify([ "list", "count" ]); - } - - append(item) { - if (!this.constructor.checkItem(item)) return; - this._list.push(item); // future: time + index sort - this._notify([ "count" ]); // list is the same by ref, CAREFULL - } - - _notify(propertyList) { - const changedState = {}; - propertyList.forEach(p => changedState[ p ] = this[ p ]); - this._callback(changedState); - } - -} \ No newline at end of file diff --git a/frontend/app/player/lists/ListReaderWithRed.js b/frontend/app/player/lists/ListReaderWithRed.js deleted file mode 100644 index 84da42138..000000000 --- a/frontend/app/player/lists/ListReaderWithRed.js +++ /dev/null @@ -1,48 +0,0 @@ -import ListReader from './ListReader'; - -export default class ListReaderWithRed extends ListReader { - _redCountNow = 0; - - static checkItem(item) { - const superCheckResult = super.checkItem(item); - if (typeof item.isRed !== 'function') { - console.error("List Reader With Red: expected item to have method 'isRed', ", item); - return false; - } - return superCheckResult; - } - - get _goToReturn() { - return { - listNow: this.listNow, - redCountNow: this.redCountNow, - } - } - - _onIncrement(item) { - if (item.isRed()) { - this._redCountNow++; - //this._notify([ "redCountNow" ]); - } - } - - _onDecrement(item) { - if (item.isRed()) { - this._redCountNow--; - //this._notify([ "redCountNow" ]); - } - } - - _onStartTimeChange() { - this._redCountNow = this._list - .slice(this._offset, this._p + 1) - .filter(item => item.isRed()) - .length; - this._notify([ "redCountNow" ]); - } - - get redCountNow() { - return this._redCountNow; - } - -} \ No newline at end of file diff --git a/frontend/app/player/lists/ReduxListReader.js b/frontend/app/player/lists/ReduxListReader.js deleted file mode 100644 index 5671d7171..000000000 --- a/frontend/app/player/lists/ReduxListReader.js +++ /dev/null @@ -1,51 +0,0 @@ -import { applyChange, revertChange } from 'deep-diff'; -import ListReader from './ListReader'; - -export default class ReduxListReader extends ListReader { - #state = {}; - #finalStates = []; - - get _goToReturn() { - return { - listNow: this.listNow, - state: { ...this.#state }, - }; - } - - _onIncrement(item) { - this._processRedux(item, true); - } - - _onDecrement(item) { - this._processRedux(item, false); - } - - _processRedux(action, forward) { - if (forward) { - if (!!action.state) { - this.#finalStates.push(this.#state); - this.#state = JSON.parse(JSON.stringify(action.state)); // Deep clone :( - } else { - action.diff.forEach(d => { - try { - applyChange(this.#state, d); - } catch (e) { - //console.warn("Deepdiff error") - } - }); - } - } else { - if (!!action.state) { - this.#state = this.#finalStates.pop(); - } else { - action.diff.forEach(d => { - try { - revertChange(this.#state, 1, d); // bad lib :( TODO: write our own diff - } catch (e) { - //console.warn("Deepdiff error") - } - }); - } - } - } -} \ No newline at end of file diff --git a/frontend/app/player/lists/index.js b/frontend/app/player/lists/index.js deleted file mode 100644 index bcaeb5ec6..000000000 --- a/frontend/app/player/lists/index.js +++ /dev/null @@ -1,69 +0,0 @@ -import ListReader from './ListReader'; -import ListReaderWithRed from './ListReaderWithRed'; -import ReduxListReader from './ReduxListReader'; -import { update as updateStore } from '../store'; - -const l = n => `${ n }List`; -const c = n => `${ n }Count`; -const ln = n => `${ n }ListNow`; -const rcn = n => `${ n }RedCountNow`; - -const entityNamesWithRed = [ "log", "resource", "fetch", "stack" ]; -const entityNamesSimple = [ "event", "profile" ]; -const entityNames = /*[ "redux" ].*/entityNamesWithRed.concat(entityNamesSimple); - -const is = {}; -entityNames.forEach(n => { - is[ l(n) ] = []; - is[ c(n) ] = 0; - is[ ln(n) ] = []; - if (entityNamesWithRed.includes(n)) { - is[ rcn(n) ] = 0; - } -}); -//is["reduxState"] = {}; -//is["reduxFinalStates"] = []; - - -const createCallback = n => { - const entityfy = s => `${ n }${ s[ 0 ].toUpperCase() }${ s.slice(1) }`; - return state => { - if (!state) return; - const namedState = {}; - Object.keys(state).forEach(key => { - namedState[ entityfy(key) ] = state[ key ]; - }); - return updateStore(namedState); - } -} - -let readers = null; - -export function init(lists) { - readers = {}; - entityNamesSimple.forEach(n => readers[ n ] = new ListReader(createCallback(n))); - entityNamesWithRed.forEach(n => readers[ n ] = new ListReaderWithRed(createCallback(n))); - //readers.redux = new ReduxListReader(createCallback("redux")); - entityNames.forEach(n => readers[ n ].list = lists[ n ] || []); -} -export function append(name, item) { - readers[ name ].append(item); -} -export function setStartTime(time) { - readers.resource.startTime = time; -} -const byTimeNames = [ "event", "stack" ]; // TEMP -const byIndexNames = entityNames.filter(n => !byTimeNames.includes(n)); -export function goTo(time, index) { - if (readers === null) return; - if (typeof index === 'number') { - byTimeNames.forEach(n => readers[ n ] && readers[ n ]._callback(readers[ n ].goTo(time))); - byIndexNames.forEach(n => readers[ n ] && readers[ n ]._callback(readers[ n ].goToIndex(index))); - } else { - entityNames.forEach(n => readers[ n ] && readers[ n ]._callback(readers[ n ].goTo(time))); - } -} -export function clean() { - entityNames.forEach(n => delete readers[ n ]); -} -export const INITIAL_STATE = is; diff --git a/frontend/app/player/singletone.js b/frontend/app/player/singletone.js index 8bf470658..357c76a90 100644 --- a/frontend/app/player/singletone.js +++ b/frontend/app/player/singletone.js @@ -1,6 +1,5 @@ import Player from './Player'; -import { update, clean as cleanStore, getState } from './store'; -import { clean as cleanLists } from './lists'; +import { update, cleanStore, getState } from './store'; /** @type {Player} */ let instance = null; @@ -29,7 +28,6 @@ document.addEventListener("visibilitychange", function() { }); export function init(session, config, live = false) { - // const live = session.live; const endTime = !live && session.duration.valueOf(); instance = new Player(session, config, live); @@ -50,7 +48,6 @@ export function clean() { if (instance === null) return; instance.clean(); cleanStore(); - cleanLists(); instance = null; } export const jump = initCheck((...args) => instance.jump(...args)); @@ -59,7 +56,6 @@ export const togglePlay = initCheck((...args) => instance.togglePlay(...args)); export const pause = initCheck((...args) => instance.pause(...args)); export const toggleSkip = initCheck((...args) => instance.toggleSkip(...args)); export const toggleSkipToIssue = initCheck((...args) => instance.toggleSkipToIssue(...args)); -export const updateSkipToIssue = initCheck((...args) => instance.updateSkipToIssue(...args)); export const toggleAutoplay = initCheck((...args) => instance.toggleAutoplay(...args)); export const toggleSpeed = initCheck((...args) => instance.toggleSpeed(...args)); export const toggleEvents = initCheck((...args) => instance.toggleEvents(...args)); @@ -84,6 +80,10 @@ export const toggleAnnotation = initCheck((...args) => instance.assistManager.to export const toggleTimetravel = initCheck((...args) => instance.toggleTimetravel(...args)) export const jumpToLive = initCheck((...args) => instance.jumpToLive(...args)) export const toggleUserName = initCheck((...args) => instance.toggleUserName(...args)) +export const injectNotes = initCheck((...args) => instance.injectNotes(...args)) +export const filterOutNote = initCheck((...args) => instance.filterOutNote(...args)) +/** @type {Player.assistManager.toggleVideoLocalStream} */ +export const toggleVideoLocalStream = initCheck((...args) => instance.assistManager.toggleVideoLocalStream(...args)) export const Controls = { jump, @@ -91,7 +91,6 @@ export const Controls = { pause, toggleSkip, toggleSkipToIssue, - updateSkipToIssue, toggleAutoplay, toggleEvents, toggleSpeed, diff --git a/frontend/app/player/store/duck.js b/frontend/app/player/store/duck.js index faf77041c..f57a0ed54 100644 --- a/frontend/app/player/store/duck.js +++ b/frontend/app/player/store/duck.js @@ -1,5 +1,4 @@ import { applyChange, revertChange } from 'deep-diff'; -import { INITIAL_STATE as listsInitialState } from '../lists'; import { INITIAL_STATE as playerInitialState, INITIAL_NON_RESETABLE_STATE as playerInitialNonResetableState } from '../Player'; const UPDATE = 'player/UPDATE'; @@ -7,7 +6,6 @@ const CLEAN = 'player/CLEAN'; const REDUX = 'player/REDUX'; const resetState = { - ...listsInitialState, ...playerInitialState, initialized: false, }; diff --git a/frontend/app/player/store/store.js b/frontend/app/player/store/store.js index a09ba881a..fd4fed5c0 100644 --- a/frontend/app/player/store/store.js +++ b/frontend/app/player/store/store.js @@ -1,7 +1,7 @@ import { createStore } from 'redux'; -import reducer, { - update as updateAction, - clean as cleanAction, +import reducer, { + update as updateAction, + clean as cleanAction, } from './duck'; const store = createStore(reducer); @@ -9,10 +9,11 @@ const store = createStore(reducer); export const getState = store.getState.bind(store); export function update(...args) { - return store.dispatch(updateAction(...args)); + const action = updateAction(...args) + return store.dispatch(action); } -export function clean() { +export function cleanStore() { return store.dispatch(cleanAction()); } diff --git a/frontend/app/services/NotesService.ts b/frontend/app/services/NotesService.ts new file mode 100644 index 000000000..dc4ed28b3 --- /dev/null +++ b/frontend/app/services/NotesService.ts @@ -0,0 +1,122 @@ +import APIClient from 'App/api_client'; + + +export const tagProps = { + 'ISSUE': '#CC0000', + 'QUERY': '#3EAAAF', + 'TASK': '#7986CB', + 'OTHER': 'rgba(0, 0, 0, 0.6)', +} + +export type iTag = keyof typeof tagProps | "ALL" + +export const TAGS = Object.keys(tagProps) as unknown as (keyof typeof tagProps)[] + +export interface WriteNote { + message: string + tag: iTag + isPublic: boolean + timestamp: number + noteId?: string + author?: string +} + +export interface Note { + createdAt: string + deletedAt: string | null + isPublic: boolean + message: string + noteId: number + projectId: number + sessionId: string + tag: iTag + timestamp: number + userId: number +} + +export interface NotesFilter { + page: number + limit: number + sort: string + order: 'DESC' | 'ASC' + tags: iTag[] + sharedOnly: boolean + mineOnly: boolean +} + +export default class NotesService { + private client: APIClient; + + constructor(client?: APIClient) { + this.client = client ? client : new APIClient(); + } + + initClient(client?: APIClient) { + this.client = client || new APIClient(); + } + + fetchNotes(filter: NotesFilter): Promise<Note[]> { + return this.client.post('/notes', filter).then(r => { + if (r.ok) { + return r.json().then(r => r.data) + } else { + throw new Error('Error getting notes: ' + r.status) + } + }) + } + + getNotesBySessionId(sessionID: string): Promise<Note[]> { + return this.client.get(`/sessions/${sessionID}/notes`) + .then(r => { + if (r.ok) { + return r.json().then(r => r.data) + } else { + throw new Error('Error getting notes for ' +sessionID + ' cuz: ' + r.status) + } + }) + } + + addNote(sessionID: string, note: WriteNote): Promise<Note> { + return this.client.post(`/sessions/${sessionID}/notes`, note) + .then(r => { + if (r.ok) { + return r.json().then(r => r.data) + } else { + throw new Error('Error adding note: ' + r.status) + } + }) + } + + updateNote(noteID: string, note: WriteNote): Promise<Note> { + return this.client.post(`/notes/${noteID}`, note) + .then(r => { + if (r.ok) { + return r.json().then(r => r.data) + } else { + throw new Error('Error updating note: ' + r.status) + } + }) + } + + deleteNote(noteID: number) { + return this.client.delete(`/notes/${noteID}`) + .then(r => { + if (r.ok) { + return r.json().then(r => r.data) + } else { + throw new Error('Error deleting note: ' + r.status) + } + }) + } + + sendSlackNotification(noteId: string, webhook: string) { + return this.client.get(`/notes/${noteId}/slack/${webhook}`) + .then(r => { + if (r.ok) { + return r.json().then(r => r.data) + } else { + throw new Error('Error sending slack notif: ' + r.status) + } + }) + } +} diff --git a/frontend/app/services/SessionService.ts b/frontend/app/services/SessionService.ts index 07c623359..01964e41a 100644 --- a/frontend/app/services/SessionService.ts +++ b/frontend/app/services/SessionService.ts @@ -25,7 +25,7 @@ export default class SettingsService { getSessions(filter: any) { return this.client - .post('/sessions/search2', filter) + .post('/sessions/search', filter) .then(fetchErrorCheck) .then((response) => response.data || []); } diff --git a/frontend/app/services/index.ts b/frontend/app/services/index.ts index add371643..6de2d300b 100644 --- a/frontend/app/services/index.ts +++ b/frontend/app/services/index.ts @@ -1,10 +1,11 @@ -import DashboardService, { IDashboardService } from "./DashboardService"; -import MetricService, { IMetricService } from "./MetricService"; -import FunnelService, { IFunnelService } from "./FunnelService"; +import DashboardService from "./DashboardService"; +import MetricService from "./MetricService"; +import FunnelService from "./FunnelService"; import SessionSerivce from "./SessionService"; import UserService from "./UserService"; import AuditService from './AuditService'; import ErrorService from "./ErrorService"; +import NotesService from "./NotesService"; export const dashboardService = new DashboardService(); export const metricService = new MetricService(); @@ -13,3 +14,4 @@ export const userService = new UserService(); export const funnelService = new FunnelService(); export const auditService = new AuditService(); export const errorService = new ErrorService(); +export const notesService = new NotesService(); diff --git a/frontend/app/styles/colors-autogen.css b/frontend/app/styles/colors-autogen.css index 42ae94dab..1af69f93d 100644 --- a/frontend/app/styles/colors-autogen.css +++ b/frontend/app/styles/colors-autogen.css @@ -35,6 +35,7 @@ .fill-light-blue-bg { fill: $light-blue-bg } .fill-white { fill: $white } .fill-borderColor { fill: $borderColor } +.fill-transparent { fill: $transparent } .fill-figmaColors { fill: $figmaColors } /* color */ @@ -72,6 +73,7 @@ .color-light-blue-bg { color: $light-blue-bg } .color-white { color: $white } .color-borderColor { color: $borderColor } +.color-transparent { color: $transparent } .color-figmaColors { color: $figmaColors } /* hover color */ @@ -109,6 +111,7 @@ .hover-light-blue-bg:hover { color: $light-blue-bg } .hover-white:hover { color: $white } .hover-borderColor:hover { color: $borderColor } +.hover-transparent:hover { color: $transparent } .hover-figmaColors:hover { color: $figmaColors } .border-main { border-color: $main } @@ -145,4 +148,5 @@ .border-light-blue-bg { border-color: $light-blue-bg } .border-white { border-color: $white } .border-borderColor { border-color: $borderColor } +.border-transparent { border-color: $transparent } .border-figmaColors { border-color: $figmaColors } diff --git a/frontend/app/styles/general.css b/frontend/app/styles/general.css index 7e072fcd4..a21cfe239 100644 --- a/frontend/app/styles/general.css +++ b/frontend/app/styles/general.css @@ -5,15 +5,24 @@ .info.info.info.info.info { /* BAD HACK >:) */ - background-color: #f2f8ff; + background-color: rgba(242, 248, 255, 0.6); + &:hover { + background-color: rgba(242, 248, 255, 1); + } } .warn.warn.warn.warn { - background-color: #fefaf4; + background-color: rgba(253, 248, 240, 0.6); + &:hover { + background-color: rgba(253, 248, 240, 1); + } } .error.error.error.error { - background-color: #fcf2f2; + background-color: rgba(252, 242, 242, 0.6); + &:hover { + background-color: rgba(252, 242, 242, 1); + } } @@ -316,3 +325,38 @@ p { .recharts-legend-item-text { white-space: nowrap !important; } + +.stripes { + background: repeating-linear-gradient( + 135deg, + transparent, + transparent 2px, + #ccc 2px, + #ccc 4px + ); +} + +.animate-fade { + animation: fade 0.1s cubic-bezier(0.4, 0, 0.6, 1); +} + +@keyframes fade { + 100% { + opacity: 1; + } + 0% { + opacity: 0; + } +} + +#arrow { + position: absolute; + background: #333; + width: 80px; + height: 80px; + transform: rotate(45deg); +} + +.dev-row { + transition: all 0.5s; +} \ No newline at end of file diff --git a/frontend/app/styles/global.scss b/frontend/app/styles/global.scss index 014cfce5f..c25d0cc7b 100644 --- a/frontend/app/styles/global.scss +++ b/frontend/app/styles/global.scss @@ -15,4 +15,10 @@ input.no-focus:focus { .widget-wrapper { @apply rounded border bg-white; -} \ No newline at end of file +} + +@layer base { + img { + @apply inline-block; + } +} diff --git a/frontend/app/styles/main.css b/frontend/app/styles/main.css index 16b06542d..9c071ff9b 100644 --- a/frontend/app/styles/main.css +++ b/frontend/app/styles/main.css @@ -6,7 +6,7 @@ } * { - border-color: #EEEEEE; + border-color: #eeeeee; } .page { padding-top: 50px; @@ -24,23 +24,23 @@ } @media only screen and (max-width: 1380px) { - .container-70 { + .container-70 { width: 90%; } } @media only screen and (min-width: 1380px) { .container-70 { - width: 1280px; + width: 1280px; } } .container-70 { - position: relative; + position: relative; margin: 0 auto; } -.container-90 { +.container-90 { width: 98%; margin: 0 auto; } @@ -62,7 +62,7 @@ } } .side-menu-margined { - margin-left: 260px; + margin-left: 220px; } .top-header { @@ -84,7 +84,7 @@ & .title { margin-right: 15px; - + & span { color: $gray-medium; font-weight: 300; @@ -97,13 +97,13 @@ align-items: center; } -[data-hidden=true] { +[data-hidden='true'] { display: none !important; } -[data-disabled=true] { +[data-disabled='true'] { pointer-events: none; - opacity: .5; + opacity: 0.5; } .form-group { @@ -125,6 +125,27 @@ } } +.hover-teal:hover { + background-color: $active-blue; + color: $teal; + & svg { + fill: $teal; + } +} + +.note-hover { + border: solid thin transparent; + &:hover { + background-color: #FFFEF5; + border-color: $gray-lightest; + } +} +.note-hover-bg { + &:hover { + background-color: #FFFEF5; + } +} + .text-dotted-underline { text-decoration: underline dotted !important; } @@ -138,13 +159,13 @@ .divider-h { height: 1px; width: 100%; - + margin: 25px 0; background-color: $gray-light; } */ -.no-scroll { +.no-scroll { height: 100vh; overflow-y: hidden; padding-right: 15px; -} \ No newline at end of file +} diff --git a/frontend/app/styles/react-tippy-themes.scss b/frontend/app/styles/react-tippy-themes.scss index 32ce9b5e3..9bef74596 100644 --- a/frontend/app/styles/react-tippy-themes.scss +++ b/frontend/app/styles/react-tippy-themes.scss @@ -1,20 +1,7 @@ -.tippy-tooltip.tippy-light-theme { - background-color: white; - color: #333; - text-align: left; - border: 1px solid #ddd; - box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.2); -} - -.tippy-tooltip.tippy-light-theme .arrow-regular { - // border-color: #ddd; - border-bottom-color: white; +.tippy-tooltip.light-theme { + padding: 0; } -.tippy-tooltip.tippy-light-theme[data-animatefill] { - background-color: transparent; -} - -.tippy-tooltip.tippy-light-theme .tippy-backdrop { - background-color: white; +.tippy-tooltip.light-theme[data-animatefill] { + background-color: white !important; } \ No newline at end of file diff --git a/frontend/app/styles/reset.css b/frontend/app/styles/reset.css index 00c96826b..e1cace6ed 100644 --- a/frontend/app/styles/reset.css +++ b/frontend/app/styles/reset.css @@ -30,9 +30,31 @@ input:focus { border: solid thin $teal !important; } -body ::-webkit-scrollbar { +/* body ::-webkit-scrollbar { width: 2px; height: 2px; +} */ + +* { + &::-webkit-scrollbar { + width: 2px; + height: 0; + } + + &::-webkit-scrollbar-thumb { + background: transparent; + } + &::-webkit-scrollbar-track { + background: transparent; + } + &:hover { + &::-webkit-scrollbar-track { + background: #f3f3f3; + } + &::-webkit-scrollbar-thumb { + background: $gray-medium; + } + } } h1, h2, h3, h4, h5 { diff --git a/frontend/app/svg/icons/arrow-bar-left.svg b/frontend/app/svg/icons/arrow-bar-left.svg new file mode 100644 index 000000000..3558e407e --- /dev/null +++ b/frontend/app/svg/icons/arrow-bar-left.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-arrow-bar-left" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M12.5 15a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5zM10 8a.5.5 0 0 1-.5.5H3.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L3.707 7.5H9.5a.5.5 0 0 1 .5.5z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/arrow-down-short.svg b/frontend/app/svg/icons/arrow-down-short.svg new file mode 100644 index 000000000..cd096ca80 --- /dev/null +++ b/frontend/app/svg/icons/arrow-down-short.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M8 4a.5.5 0 0 1 .5.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5A.5.5 0 0 1 8 4z"/> +</svg> diff --git a/frontend/app/svg/icons/arrow-repeat.svg b/frontend/app/svg/icons/arrow-repeat.svg new file mode 100644 index 000000000..07f1230e3 --- /dev/null +++ b/frontend/app/svg/icons/arrow-repeat.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-arrow-repeat" viewBox="0 0 16 16"> + <path d="M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41zm-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9z"/> + <path fill-rule="evenodd" d="M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5.002 5.002 0 0 0 8 3zM3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9H3.1z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/arrow-up-short.svg b/frontend/app/svg/icons/arrow-up-short.svg new file mode 100644 index 000000000..434482f9f --- /dev/null +++ b/frontend/app/svg/icons/arrow-up-short.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"> + <path fill-rule="evenodd" d="M8 12a.5.5 0 0 0 .5-.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 .5.5z"/> +</svg> diff --git a/frontend/app/svg/icons/bell-fill.svg b/frontend/app/svg/icons/bell-fill.svg new file mode 100644 index 000000000..b5fa6a05b --- /dev/null +++ b/frontend/app/svg/icons/bell-fill.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-bell-fill" viewBox="0 0 16 16"> + <path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zm.995-14.901a1 1 0 1 0-1.99 0A5.002 5.002 0 0 0 3 6c0 1.098-.5 6-2 7h14c-1.5-1-2-5.902-2-7 0-2.42-1.72-4.44-4.005-4.901z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/bell-slash.svg b/frontend/app/svg/icons/bell-slash.svg new file mode 100644 index 000000000..7b2a23785 --- /dev/null +++ b/frontend/app/svg/icons/bell-slash.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-bell-slash" viewBox="0 0 16 16"> + <path d="M5.164 14H15c-.299-.199-.557-.553-.78-1-.9-1.8-1.22-5.12-1.22-6 0-.264-.02-.523-.06-.776l-.938.938c.02.708.157 2.154.457 3.58.161.767.377 1.566.663 2.258H6.164l-1 1zm5.581-9.91a3.986 3.986 0 0 0-1.948-1.01L8 2.917l-.797.161A4.002 4.002 0 0 0 4 7c0 .628-.134 2.197-.459 3.742-.05.238-.105.479-.166.718l-1.653 1.653c.02-.037.04-.074.059-.113C2.679 11.2 3 7.88 3 7c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0c.942.19 1.788.645 2.457 1.284l-.707.707zM10 15a2 2 0 1 1-4 0h4zm-9.375.625a.53.53 0 0 0 .75.75l14.75-14.75a.53.53 0 0 0-.75-.75L.625 15.625z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/caret-down-fill.svg b/frontend/app/svg/icons/caret-down-fill.svg index 12557a66e..e0fd6b7aa 100644 --- a/frontend/app/svg/icons/caret-down-fill.svg +++ b/frontend/app/svg/icons/caret-down-fill.svg @@ -1,3 +1,3 @@ -<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-caret-down-fill" viewBox="0 0 16 16"> +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-caret-down-fill" viewBox="0 0 16 16"> <path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z"/> </svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/caret-up-fill.svg b/frontend/app/svg/icons/caret-up-fill.svg index b4c7e5485..3270a7ffa 100644 --- a/frontend/app/svg/icons/caret-up-fill.svg +++ b/frontend/app/svg/icons/caret-up-fill.svg @@ -1 +1,3 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M288.662 352H31.338c-17.818 0-26.741-21.543-14.142-34.142l128.662-128.662c7.81-7.81 20.474-7.81 28.284 0l128.662 128.662c12.6 12.599 3.676 34.142-14.142 34.142z"/></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-caret-up-fill" viewBox="0 0 16 16"> + <path d="m7.247 4.86-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/check-circle-fill.svg b/frontend/app/svg/icons/check-circle-fill.svg new file mode 100644 index 000000000..02213557f --- /dev/null +++ b/frontend/app/svg/icons/check-circle-fill.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"> + <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/> +</svg> diff --git a/frontend/app/svg/icons/dash.svg b/frontend/app/svg/icons/dash.svg new file mode 100644 index 000000000..7a80c4088 --- /dev/null +++ b/frontend/app/svg/icons/dash.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"> + <path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"/> +</svg> diff --git a/frontend/app/svg/icons/door-closed.svg b/frontend/app/svg/icons/door-closed.svg new file mode 100644 index 000000000..5b9db0f13 --- /dev/null +++ b/frontend/app/svg/icons/door-closed.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-door-closed" viewBox="0 0 16 16"> + <path d="M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v13h1.5a.5.5 0 0 1 0 1h-13a.5.5 0 0 1 0-1H3V2zm1 13h8V2H4v13z"/> + <path d="M9 9a1 1 0 1 0 2 0 1 1 0 0 0-2 0z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/file-pdf.svg b/frontend/app/svg/icons/file-pdf.svg new file mode 100644 index 000000000..f6cfbebca --- /dev/null +++ b/frontend/app/svg/icons/file-pdf.svg @@ -0,0 +1,11 @@ +<svg viewBox="0 0 13 14" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_2148_10595)"> +<path d="M3.49328 0.66217C3.07306 0.66217 2.67005 0.829104 2.3729 1.12625C2.07576 1.42339 1.90883 1.8264 1.90883 2.24662V11.7533C1.90883 12.1736 2.07576 12.5766 2.3729 12.8737C2.67005 13.1709 3.07306 13.3378 3.49328 13.3378H9.8311C10.2513 13.3378 10.6543 13.1709 10.9515 12.8737C11.2486 12.5766 11.4156 12.1736 11.4156 11.7533V2.24662C11.4156 1.8264 11.2486 1.42339 10.9515 1.12625C10.6543 0.829104 10.2513 0.66217 9.8311 0.66217H3.49328ZM3.49328 1.4544H9.8311C10.0412 1.4544 10.2427 1.53786 10.3913 1.68644C10.5399 1.83501 10.6233 2.03651 10.6233 2.24662V11.7533C10.6233 11.9635 10.5399 12.165 10.3913 12.3135C10.2427 12.4621 10.0412 12.5456 9.8311 12.5456H3.49328C3.28317 12.5456 3.08167 12.4621 2.93309 12.3135C2.78452 12.165 2.70106 11.9635 2.70106 11.7533V2.24662C2.70106 2.03651 2.78452 1.83501 2.93309 1.68644C3.08167 1.53786 3.28317 1.4544 3.49328 1.4544Z" fill-opacity="0.6"/> +<path d="M3.97099 10.2378C3.81658 10.1761 3.69217 10.0568 3.62399 9.9051C3.46951 9.59772 3.521 9.29033 3.68737 9.03207C3.84423 8.78885 4.10408 8.58208 4.398 8.40859C4.7703 8.19743 5.16384 8.02616 5.57208 7.8976C5.88911 7.32766 6.17011 6.73841 6.41343 6.13331C6.26796 5.80277 6.1539 5.45928 6.07277 5.10738C6.00464 4.79048 5.97849 4.47676 6.03633 4.20741C6.09574 3.92696 6.2534 3.67503 6.55127 3.5554C6.70338 3.4944 6.86816 3.46034 7.02819 3.4944C7.10869 3.51154 7.18437 3.54638 7.24973 3.59639C7.31509 3.64641 7.3685 3.71034 7.40609 3.78356C7.4758 3.91349 7.50115 4.0656 7.5067 4.20978C7.51224 4.35793 7.49719 4.52271 7.46946 4.69621C7.40292 5.10024 7.25556 5.59459 7.05751 6.11746C7.27607 6.58489 7.5359 7.0319 7.83389 7.45316C8.18651 7.42531 8.54117 7.4386 8.89072 7.49277C9.17909 7.54427 9.47221 7.64725 9.65126 7.86116C9.74632 7.97524 9.80416 8.11467 9.8097 8.27153C9.81525 8.42364 9.77247 8.57416 9.70038 8.71755C9.63793 8.85044 9.5411 8.96422 9.41993 9.04712C9.30015 9.12525 9.15873 9.16352 9.01589 9.15645C8.75366 9.14536 8.49777 9.00117 8.27674 8.82609C8.00799 8.60385 7.76581 8.3513 7.55502 8.07347C7.01928 8.13424 6.48989 8.24186 5.97295 8.39512C5.73595 8.81498 5.46545 9.21504 5.16408 9.59138C4.93434 9.86866 4.68241 10.1103 4.43048 10.2149C4.28573 10.2803 4.12155 10.2886 3.97099 10.2378ZM5.06347 8.73181C4.93196 8.79202 4.80996 8.8554 4.69984 8.92036C4.43999 9.07406 4.27124 9.22379 4.18727 9.35371C4.1128 9.46859 4.11121 9.55177 4.15558 9.63971C4.1635 9.65714 4.17142 9.66823 4.17618 9.67456C4.18563 9.67203 4.19489 9.66886 4.2039 9.66506C4.31244 9.62069 4.48514 9.47888 4.70697 9.2119C4.83313 9.05744 4.95209 8.89724 5.06347 8.73181ZM6.36272 7.67815C6.62726 7.61636 6.89419 7.56535 7.16287 7.52525C7.01856 7.30454 6.88376 7.07776 6.75884 6.84552C6.6346 7.12645 6.50251 7.40384 6.36272 7.67736V7.67815ZM8.30051 8.03465C8.41934 8.16299 8.53501 8.27232 8.64513 8.35947C8.83526 8.50999 8.96757 8.5599 9.03966 8.56228C9.05896 8.5648 9.07854 8.56061 9.09511 8.55039C9.12807 8.52437 9.15373 8.49025 9.16958 8.45137C9.19775 8.40311 9.21379 8.34874 9.21632 8.29292C9.21587 8.27431 9.20853 8.25653 9.19573 8.24301C9.15453 8.19389 9.03728 8.12259 8.78535 8.07743C8.6251 8.05065 8.46298 8.03661 8.30051 8.03545V8.03465ZM6.72398 5.25711C6.79065 5.04203 6.84358 4.82294 6.88242 4.60114C6.90698 4.4522 6.91649 4.32941 6.91253 4.23276C6.91275 4.17943 6.90418 4.12644 6.88718 4.0759C6.84755 4.0808 6.80885 4.09148 6.7723 4.10758C6.70338 4.13531 6.64713 4.19156 6.61703 4.33178C6.58534 4.48389 6.59326 4.70334 6.65347 4.983C6.67248 5.07093 6.69625 5.16283 6.72477 5.25711H6.72398Z" /> +</g> +<defs> +<clipPath id="clip0_2148_10595"> +<rect width="12.6756" height="12.6756" fill="white" transform="translate(0.324371 0.66217)"/> +</clipPath> +</defs> +</svg> diff --git a/frontend/app/svg/icons/folder-plus.svg b/frontend/app/svg/icons/folder-plus.svg new file mode 100644 index 000000000..9e6d99b36 --- /dev/null +++ b/frontend/app/svg/icons/folder-plus.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-folder-plus" viewBox="0 0 16 16"> + <path d="m.5 3 .04.87a1.99 1.99 0 0 0-.342 1.311l.637 7A2 2 0 0 0 2.826 14H9v-1H2.826a1 1 0 0 1-.995-.91l-.637-7A1 1 0 0 1 2.19 4h11.62a1 1 0 0 1 .996 1.09L14.54 8h1.005l.256-2.819A2 2 0 0 0 13.81 3H9.828a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 6.172 1H2.5a2 2 0 0 0-2 2zm5.672-1a1 1 0 0 1 .707.293L7.586 3H2.19c-.24 0-.47.042-.683.12L1.5 2.98a1 1 0 0 1 1-.98h3.672z"/> + <path d="M13.5 10a.5.5 0 0 1 .5.5V12h1.5a.5.5 0 1 1 0 1H14v1.5a.5.5 0 1 1-1 0V13h-1.5a.5.5 0 0 1 0-1H13v-1.5a.5.5 0 0 1 .5-.5z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/folder2.svg b/frontend/app/svg/icons/folder2.svg new file mode 100644 index 000000000..273f49c63 --- /dev/null +++ b/frontend/app/svg/icons/folder2.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-folder2" viewBox="0 0 16 16"> + <path d="M1 3.5A1.5 1.5 0 0 1 2.5 2h2.764c.958 0 1.76.56 2.311 1.184C7.985 3.648 8.48 4 9 4h4.5A1.5 1.5 0 0 1 15 5.5v7a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 1 12.5v-9zM2.5 3a.5.5 0 0 0-.5.5V6h12v-.5a.5.5 0 0 0-.5-.5H9c-.964 0-1.71-.629-2.174-1.154C6.374 3.334 5.82 3 5.264 3H2.5zM14 7H2v5.5a.5.5 0 0 0 .5.5h11a.5.5 0 0 0 .5-.5V7z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/gear-fill.svg b/frontend/app/svg/icons/gear-fill.svg new file mode 100644 index 000000000..ac2a31086 --- /dev/null +++ b/frontend/app/svg/icons/gear-fill.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-gear-fill" viewBox="0 0 16 16"> + <path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/gear.svg b/frontend/app/svg/icons/gear.svg new file mode 100644 index 000000000..0133c1c5f --- /dev/null +++ b/frontend/app/svg/icons/gear.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-gear" viewBox="0 0 16 16"> + <path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z"/> + <path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/info-circle.svg b/frontend/app/svg/icons/info-circle.svg index c5ddfebc6..42dc99c8f 100644 --- a/frontend/app/svg/icons/info-circle.svg +++ b/frontend/app/svg/icons/info-circle.svg @@ -1,11 +1,4 @@ -<svg viewBox="0 0 35 35" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g clip-path="url(#clip0_10_16)"> -<path d="M17.5 32.8125C13.4389 32.8125 9.54408 31.1992 6.67243 28.3276C3.80078 25.4559 2.1875 21.5611 2.1875 17.5C2.1875 13.4389 3.80078 9.54408 6.67243 6.67243C9.54408 3.80078 13.4389 2.1875 17.5 2.1875C21.5611 2.1875 25.4559 3.80078 28.3276 6.67243C31.1992 9.54408 32.8125 13.4389 32.8125 17.5C32.8125 21.5611 31.1992 25.4559 28.3276 28.3276C25.4559 31.1992 21.5611 32.8125 17.5 32.8125ZM17.5 35C22.1413 35 26.5925 33.1563 29.8744 29.8744C33.1563 26.5925 35 22.1413 35 17.5C35 12.8587 33.1563 8.40752 29.8744 5.12563C26.5925 1.84375 22.1413 0 17.5 0C12.8587 0 8.40752 1.84375 5.12563 5.12563C1.84375 8.40752 0 12.8587 0 17.5C0 22.1413 1.84375 26.5925 5.12563 29.8744C8.40752 33.1563 12.8587 35 17.5 35V35Z" /> -<path fill-rule="evenodd" clip-rule="evenodd" d="M17.5 13C18.3284 13 19 12.3284 19 11.5C19 10.6716 18.3284 10 17.5 10C16.6716 10 16 10.6716 16 11.5C16 12.3284 16.6716 13 17.5 13ZM19 15.877C19 15.0485 18.3284 14.377 17.5 14.377C16.6716 14.377 16 15.0485 16 15.877V24.5C16 25.3284 16.6716 26 17.5 26C18.3284 26 19 25.3284 19 24.5V15.877Z" /> -</g> -<defs> -<clipPath id="clip0_10_16"> -<rect width="35" height="35" fill="white"/> -</clipPath> -</defs> +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-info-circle" viewBox="0 0 16 16"> + <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/> + <path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/> </svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/list-arrow.svg b/frontend/app/svg/icons/list-arrow.svg new file mode 100644 index 000000000..5c5d0a2d8 --- /dev/null +++ b/frontend/app/svg/icons/list-arrow.svg @@ -0,0 +1,3 @@ +<svg preserveAspectRatio="none" viewBox="0 0 338 247" xmlns="http://www.w3.org/2000/svg"> +<path d="M260.695 120.004L259.405 119.24L259.405 119.24L260.695 120.004ZM337.938 0.0078125L322.574 8.00488L337.182 17.3118L337.938 0.0078125ZM147.764 210.533L146.708 211.599L147.764 210.533ZM1.1362 246.494C16.5808 245.086 34.261 245.487 52.2398 245.589C70.1658 245.69 88.3625 245.492 104.64 242.842C120.91 240.193 135.451 235.068 145.927 225.17C156.452 215.224 162.686 200.643 162.686 179.504H159.686C159.686 200.01 153.665 213.731 143.867 222.989C134.019 232.294 120.166 237.275 104.158 239.881C88.1578 242.485 70.1922 242.69 52.2568 242.589C34.3742 242.488 16.4939 242.081 0.863802 243.506L1.1362 246.494ZM146.708 211.599C153.027 217.859 160.884 219.773 169.653 217.974C178.333 216.193 187.9 210.784 197.935 202.47C218.02 185.829 240.436 157.164 261.986 120.768L259.405 119.24C237.932 155.504 215.724 183.835 196.021 200.16C186.161 208.329 177.042 213.395 169.049 215.035C161.145 216.657 154.343 214.94 148.82 209.468L146.708 211.599ZM261.986 120.768C316.752 28.2758 314.948 38.0283 331.937 12.2184L329.431 10.569C312.611 36.1221 314.199 26.6994 259.405 119.24L261.986 120.768ZM162.686 179.504C162.686 178.453 162.584 177.529 162.351 176.755C162.12 175.986 161.724 175.255 161.058 174.756C159.605 173.668 157.899 174.312 156.745 175.04C154.304 176.582 151.447 180.198 149.056 184.411C146.633 188.682 144.532 193.839 143.752 198.69C142.981 203.483 143.447 208.368 146.708 211.599L148.82 209.468C146.595 207.264 145.997 203.623 146.714 199.166C147.422 194.766 149.362 189.95 151.665 185.892C154.001 181.776 156.557 178.707 158.347 177.577C159.309 176.969 159.423 177.28 159.261 177.158C159.241 177.143 159.358 177.22 159.478 177.62C159.598 178.016 159.686 178.623 159.686 179.504H162.686Z" fill="black"/> +</svg> diff --git a/frontend/app/svg/icons/magic.svg b/frontend/app/svg/icons/magic.svg new file mode 100644 index 000000000..842901486 --- /dev/null +++ b/frontend/app/svg/icons/magic.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-magic" viewBox="0 0 16 16"> + <path d="M9.5 2.672a.5.5 0 1 0 1 0V.843a.5.5 0 0 0-1 0v1.829Zm4.5.035A.5.5 0 0 0 13.293 2L12 3.293a.5.5 0 1 0 .707.707L14 2.707ZM7.293 4A.5.5 0 1 0 8 3.293L6.707 2A.5.5 0 0 0 6 2.707L7.293 4Zm-.621 2.5a.5.5 0 1 0 0-1H4.843a.5.5 0 1 0 0 1h1.829Zm8.485 0a.5.5 0 1 0 0-1h-1.829a.5.5 0 0 0 0 1h1.829ZM13.293 10A.5.5 0 1 0 14 9.293L12.707 8a.5.5 0 1 0-.707.707L13.293 10ZM9.5 11.157a.5.5 0 0 0 1 0V9.328a.5.5 0 0 0-1 0v1.829Zm1.854-5.097a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L8.646 5.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0l1.293-1.293Zm-3 3a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L.646 13.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0L8.354 9.06Z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/network.svg b/frontend/app/svg/icons/network.svg new file mode 100644 index 000000000..690603691 --- /dev/null +++ b/frontend/app/svg/icons/network.svg @@ -0,0 +1,11 @@ +<svg viewBox="0 0 13 14" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_2199_12097)"> +<path d="M3.64902 4.87542C3.75408 4.87542 3.85483 4.83368 3.92912 4.7594C4.0034 4.68511 4.04514 4.58436 4.04514 4.4793C4.04514 4.37425 4.0034 4.2735 3.92912 4.19921C3.85483 4.12492 3.75408 4.08319 3.64902 4.08319C3.54397 4.08319 3.44322 4.12492 3.36893 4.19921C3.29464 4.2735 3.25291 4.37425 3.25291 4.4793C3.25291 4.58436 3.29464 4.68511 3.36893 4.7594C3.44322 4.83368 3.54397 4.87542 3.64902 4.87542ZM2.46068 4.4793C2.46068 4.58436 2.41895 4.68511 2.34467 4.7594C2.27038 4.83368 2.16963 4.87542 2.06457 4.87542C1.95951 4.87542 1.85876 4.83368 1.78448 4.7594C1.71019 4.68511 1.66846 4.58436 1.66846 4.4793C1.66846 4.37425 1.71019 4.2735 1.78448 4.19921C1.85876 4.12492 1.95951 4.08319 2.06457 4.08319C2.16963 4.08319 2.27038 4.12492 2.34467 4.19921C2.41895 4.2735 2.46068 4.37425 2.46068 4.4793Z" fill-opacity="0.6"/> +<path d="M0.0839844 4.08317C0.0839844 3.66295 0.250917 3.25994 0.54806 2.96279C0.845203 2.66565 1.24822 2.49872 1.66844 2.49872H11.1752C11.5954 2.49872 11.9984 2.66565 12.2955 2.96279C12.5927 3.25994 12.7596 3.66295 12.7596 4.08317V4.8754C12.7596 5.29562 12.5927 5.69864 12.2955 5.99578C11.9984 6.29292 11.5954 6.45985 11.1752 6.45985H6.81791V8.83653C7.13308 8.83653 7.43534 8.96173 7.6582 9.18459C7.88106 9.40745 8.00626 9.70971 8.00626 10.0249H12.3635C12.4686 10.0249 12.5693 10.0666 12.6436 10.1409C12.7179 10.2152 12.7596 10.3159 12.7596 10.421C12.7596 10.526 12.7179 10.6268 12.6436 10.7011C12.5693 10.7754 12.4686 10.8171 12.3635 10.8171H8.00626C8.00626 11.1323 7.88106 11.4345 7.6582 11.6574C7.43534 11.8802 7.13308 12.0054 6.81791 12.0054H6.02569C5.71052 12.0054 5.40826 11.8802 5.1854 11.6574C4.96255 11.4345 4.83735 11.1323 4.83735 10.8171H0.480098C0.375042 10.8171 0.274289 10.7754 0.200003 10.7011C0.125718 10.6268 0.0839844 10.526 0.0839844 10.421C0.0839844 10.3159 0.125718 10.2152 0.200003 10.1409C0.274289 10.0666 0.375042 10.0249 0.480098 10.0249H4.83735C4.83735 9.70971 4.96255 9.40745 5.1854 9.18459C5.40826 8.96173 5.71052 8.83653 6.02569 8.83653V6.45985H1.66844C1.24822 6.45985 0.845203 6.29292 0.54806 5.99578C0.250917 5.69864 0.0839844 5.29562 0.0839844 4.8754V4.08317ZM0.876211 4.08317V4.8754C0.876211 5.08551 0.959678 5.28702 1.10825 5.43559C1.25682 5.58416 1.45833 5.66763 1.66844 5.66763H11.1752C11.3853 5.66763 11.5868 5.58416 11.7354 5.43559C11.8839 5.28702 11.9674 5.08551 11.9674 4.8754V4.08317C11.9674 3.87306 11.8839 3.67155 11.7354 3.52298C11.5868 3.37441 11.3853 3.29095 11.1752 3.29095H1.66844C1.45833 3.29095 1.25682 3.37441 1.10825 3.52298C0.959678 3.67155 0.876211 3.87306 0.876211 4.08317ZM5.62957 10.0249V10.8171C5.62957 10.9222 5.67131 11.0229 5.74559 11.0972C5.81988 11.1715 5.92063 11.2132 6.02569 11.2132H6.81791C6.92297 11.2132 7.02372 11.1715 7.09801 11.0972C7.1723 11.0229 7.21403 10.9222 7.21403 10.8171V10.0249C7.21403 9.91982 7.1723 9.81907 7.09801 9.74478C7.02372 9.6705 6.92297 9.62876 6.81791 9.62876H6.02569C5.92063 9.62876 5.81988 9.6705 5.74559 9.74478C5.67131 9.81907 5.62957 9.91982 5.62957 10.0249Z" /> +</g> +<defs> +<clipPath id="clip0_2199_12097"> +<rect width="12.6756" height="12.6756" transform="translate(0.0839844 0.914276)"/> +</clipPath> +</defs> +</svg> diff --git a/frontend/app/svg/icons/puzzle.svg b/frontend/app/svg/icons/puzzle.svg new file mode 100644 index 000000000..928b53546 --- /dev/null +++ b/frontend/app/svg/icons/puzzle.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-puzzle" viewBox="0 0 16 16"> + <path d="M3.112 3.645A1.5 1.5 0 0 1 4.605 2H7a.5.5 0 0 1 .5.5v.382c0 .696-.497 1.182-.872 1.469a.459.459 0 0 0-.115.118.113.113 0 0 0-.012.025L6.5 4.5v.003l.003.01c.004.01.014.028.036.053a.86.86 0 0 0 .27.194C7.09 4.9 7.51 5 8 5c.492 0 .912-.1 1.19-.24a.86.86 0 0 0 .271-.194.213.213 0 0 0 .039-.063v-.009a.112.112 0 0 0-.012-.025.459.459 0 0 0-.115-.118c-.375-.287-.872-.773-.872-1.469V2.5A.5.5 0 0 1 9 2h2.395a1.5 1.5 0 0 1 1.493 1.645L12.645 6.5h.237c.195 0 .42-.147.675-.48.21-.274.528-.52.943-.52.568 0 .947.447 1.154.862C15.877 6.807 16 7.387 16 8s-.123 1.193-.346 1.638c-.207.415-.586.862-1.154.862-.415 0-.733-.246-.943-.52-.255-.333-.48-.48-.675-.48h-.237l.243 2.855A1.5 1.5 0 0 1 11.395 14H9a.5.5 0 0 1-.5-.5v-.382c0-.696.497-1.182.872-1.469a.459.459 0 0 0 .115-.118.113.113 0 0 0 .012-.025L9.5 11.5v-.003a.214.214 0 0 0-.039-.064.859.859 0 0 0-.27-.193C8.91 11.1 8.49 11 8 11c-.491 0-.912.1-1.19.24a.859.859 0 0 0-.271.194.214.214 0 0 0-.039.063v.003l.001.006a.113.113 0 0 0 .012.025c.016.027.05.068.115.118.375.287.872.773.872 1.469v.382a.5.5 0 0 1-.5.5H4.605a1.5 1.5 0 0 1-1.493-1.645L3.356 9.5h-.238c-.195 0-.42.147-.675.48-.21.274-.528.52-.943.52-.568 0-.947-.447-1.154-.862C.123 9.193 0 8.613 0 8s.123-1.193.346-1.638C.553 5.947.932 5.5 1.5 5.5c.415 0 .733.246.943.52.255.333.48.48.675.48h.238l-.244-2.855zM4.605 3a.5.5 0 0 0-.498.55l.001.007.29 3.4A.5.5 0 0 1 3.9 7.5h-.782c-.696 0-1.182-.497-1.469-.872a.459.459 0 0 0-.118-.115.112.112 0 0 0-.025-.012L1.5 6.5h-.003a.213.213 0 0 0-.064.039.86.86 0 0 0-.193.27C1.1 7.09 1 7.51 1 8c0 .491.1.912.24 1.19.07.14.14.225.194.271a.213.213 0 0 0 .063.039H1.5l.006-.001a.112.112 0 0 0 .025-.012.459.459 0 0 0 .118-.115c.287-.375.773-.872 1.469-.872H3.9a.5.5 0 0 1 .498.542l-.29 3.408a.5.5 0 0 0 .497.55h1.878c-.048-.166-.195-.352-.463-.557-.274-.21-.52-.528-.52-.943 0-.568.447-.947.862-1.154C6.807 10.123 7.387 10 8 10s1.193.123 1.638.346c.415.207.862.586.862 1.154 0 .415-.246.733-.52.943-.268.205-.415.39-.463.557h1.878a.5.5 0 0 0 .498-.55l-.001-.007-.29-3.4A.5.5 0 0 1 12.1 8.5h.782c.696 0 1.182.497 1.469.872.05.065.091.099.118.115.013.008.021.01.025.012a.02.02 0 0 0 .006.001h.003a.214.214 0 0 0 .064-.039.86.86 0 0 0 .193-.27c.14-.28.24-.7.24-1.191 0-.492-.1-.912-.24-1.19a.86.86 0 0 0-.194-.271.215.215 0 0 0-.063-.039H14.5l-.006.001a.113.113 0 0 0-.025.012.459.459 0 0 0-.118.115c-.287.375-.773.872-1.469.872H12.1a.5.5 0 0 1-.498-.543l.29-3.407a.5.5 0 0 0-.497-.55H9.517c.048.166.195.352.463.557.274.21.52.528.52.943 0 .568-.447.947-.862 1.154C9.193 5.877 8.613 6 8 6s-1.193-.123-1.638-.346C5.947 5.447 5.5 5.068 5.5 4.5c0-.415.246-.733.52-.943.268-.205.415-.39.463-.557H4.605z"/> +</svg> \ No newline at end of file diff --git a/frontend/app/svg/icons/quotes.svg b/frontend/app/svg/icons/quotes.svg new file mode 100644 index 000000000..252b3b50f --- /dev/null +++ b/frontend/app/svg/icons/quotes.svg @@ -0,0 +1,3 @@ +<svg viewBox="0 0 29 19" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path opacity="0.7" d="M11.6355 2.9045C10.8963 1.75328 9.80334 0.873101 8.521 0.396241C7.23867 -0.0806184 5.83621 -0.128393 4.5244 0.260101C3.21259 0.648595 2.06231 1.45237 1.24645 2.55061C0.430585 3.64885 -0.00678382 4.98223 7.95597e-05 6.35034C0.00076002 7.48328 0.305669 8.59524 0.882952 9.57006C1.46024 10.5449 2.28871 11.3468 3.28182 11.892C4.27493 12.4372 5.39624 12.7058 6.52859 12.6695C7.66095 12.6333 8.76279 12.2937 9.71903 11.6861C9.22188 13.1623 8.29591 14.7372 6.77033 16.316C6.47844 16.6179 6.31846 17.0234 6.32558 17.4433C6.3327 17.8632 6.50633 18.2631 6.80828 18.555C7.11022 18.8469 7.51575 19.0069 7.93566 18.9997C8.35556 18.9926 8.75543 18.819 9.04731 18.517C14.6867 12.6728 13.9542 6.31998 11.6355 2.91209V2.9045ZM26.8154 2.9045C26.0762 1.75328 24.9833 0.873101 23.7009 0.396241C22.4186 -0.0806184 21.0161 -0.128393 19.7043 0.260101C18.3925 0.648595 17.2422 1.45237 16.4264 2.55061C15.6105 3.64885 15.1731 4.98223 15.18 6.35034C15.1807 7.48328 15.4856 8.59524 16.0629 9.57006C16.6402 10.5449 17.4686 11.3468 18.4617 11.892C19.4549 12.4372 20.5762 12.7058 21.7085 12.6695C22.8409 12.6333 23.9427 12.2937 24.899 11.6861C24.4018 13.1623 23.4758 14.7372 21.9503 16.316C21.6584 16.6179 21.4984 17.0234 21.5055 17.4433C21.5126 17.8632 21.6863 18.2631 21.9882 18.555C22.2901 18.8469 22.6957 19.0069 23.1156 18.9997C23.5355 18.9926 23.9354 18.819 24.2272 18.517C29.8666 12.6728 29.1342 6.31998 26.8154 2.91209V2.9045Z" /> +</svg> diff --git a/frontend/app/theme/colors.js b/frontend/app/theme/colors.js index 297e044bd..3986cf3d5 100644 --- a/frontend/app/theme/colors.js +++ b/frontend/app/theme/colors.js @@ -44,6 +44,7 @@ module.exports = { 'primary': '#3490dc', 'transparent': 'transparent', }, + transparent: 'transparent', // actual theme colors - use this for new components figmaColors: { diff --git a/frontend/app/types/dashboard/helper.js b/frontend/app/types/dashboard/helper.js index 05e50d757..f6e819da8 100644 --- a/frontend/app/types/dashboard/helper.js +++ b/frontend/app/types/dashboard/helper.js @@ -27,7 +27,7 @@ const weekdays = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]; // const months = [ "January", "February" ]; export const getTimeString = (ts, period) => { const date = new Date(ts); - const diff = period.end - period.start; + const diff = period.endTimestamp - period.startTimestamp; if (diff <= DAY) { var isPM = date.getHours() >= 12; return `${ isPM ? date.getHours() - 12 : date.getHours() }:${ startWithZero(date.getMinutes()) } ${isPM? 'pm' : 'am'}`; diff --git a/frontend/app/types/errorInfo.js b/frontend/app/types/errorInfo.js index db4c2f3a0..b3bb48e1d 100644 --- a/frontend/app/types/errorInfo.js +++ b/frontend/app/types/errorInfo.js @@ -36,6 +36,7 @@ const ErrorInfo = Record({ chart24: [], chart30: [], tags: [], + customTags: [], lastHydratedSession: Session(), disabled: false, }, { diff --git a/frontend/app/types/filter/newFilter.js b/frontend/app/types/filter/newFilter.js index 2c49df433..8abd3f5fc 100644 --- a/frontend/app/types/filter/newFilter.js +++ b/frontend/app/types/filter/newFilter.js @@ -8,15 +8,15 @@ const containsFilters = [{ key: 'contains', label: 'contains', text: 'contains', export const filters = [ { key: FilterKey.CLICK, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Click', operator: 'on', operatorOptions: filterOptions.targetOperators, icon: 'filters/click', isEvent: true }, - { key: FilterKey.INPUT, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Input', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/input', isEvent: true }, - { key: FilterKey.LOCATION, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Path', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/location', isEvent: true }, - { key: FilterKey.CUSTOM, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Custom Events', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/custom', isEvent: true }, + { key: FilterKey.INPUT, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Text Input', placeholder: 'Enter input label name', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/input', isEvent: true }, + { key: FilterKey.LOCATION, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Visited URL', placeholder: 'Enter path', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/location', isEvent: true }, + { key: FilterKey.CUSTOM, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Custom Events', placeholder: 'Enter event key', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/custom', isEvent: true }, // { key: FilterKey.REQUEST, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Fetch', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', isEvent: true }, { key: FilterKey.FETCH, type: FilterType.SUB_FILTERS, category: FilterCategory.JAVASCRIPT, operator: 'is', label: 'Network Request', filters: [ - { key: FilterKey.FETCH_URL, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with URL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, - { key: FilterKey.FETCH_STATUS_CODE, type: FilterType.NUMBER_MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with status code', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, - { key: FilterKey.FETCH_METHOD, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.PERFORMANCE, label: 'with method', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', options: filterOptions.methodOptions }, - { key: FilterKey.FETCH_DURATION, type: FilterType.NUMBER, category: FilterCategory.PERFORMANCE, label: 'with duration (ms)', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_URL, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with URL', placeholder: 'Enter path or URL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_STATUS_CODE, type: FilterType.NUMBER_MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with status code', placeholder: 'Enter status code', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_METHOD, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.PERFORMANCE, label: 'with method', operator: 'is', placeholder: 'Select method type', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', options: filterOptions.methodOptions }, + { key: FilterKey.FETCH_DURATION, type: FilterType.NUMBER, category: FilterCategory.PERFORMANCE, label: 'with duration (ms)', placeholder: 'E.g. 12', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, { key: FilterKey.FETCH_REQUEST_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with request body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, { key: FilterKey.FETCH_RESPONSE_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with response body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, ], icon: 'filters/fetch', isEvent: true }, @@ -26,8 +26,8 @@ export const filters = [ { key: FilterKey.GRAPHQL_REQUEST_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with request body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, { key: FilterKey.GRAPHQL_RESPONSE_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with response body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, ]}, - { key: FilterKey.STATEACTION, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'StateAction', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/state-action', isEvent: true }, - { key: FilterKey.ERROR, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Error', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/error', isEvent: true }, + { key: FilterKey.STATEACTION, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'State Action', placeholder: 'E.g. 12', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/state-action', isEvent: true }, + { key: FilterKey.ERROR, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Error Message', placeholder: 'E.g. Uncaught SyntaxError', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/error', isEvent: true }, // { key: FilterKey.METADATA, type: FilterType.MULTIPLE, category: FilterCategory.METADATA, label: 'Metadata', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/metadata', isEvent: true }, // FILTERS @@ -35,22 +35,22 @@ export const filters = [ { key: FilterKey.USER_BROWSER, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'User Browser', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/browser' }, { key: FilterKey.USER_DEVICE, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'User Device', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/device' }, { key: FilterKey.PLATFORM, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.GEAR, label: 'Platform', operator: 'is', operatorOptions: filterOptions.baseOperators, icon: 'filters/platform', options: platformOptions }, - { key: FilterKey.REVID, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'Version ID', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'collection' }, + { key: FilterKey.REVID, type: FilterType.MULTIPLE, category: FilterCategory.GEAR, label: 'Version ID', placeholder: 'E.g. v1.0.8', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'collection' }, { key: FilterKey.REFERRER, type: FilterType.MULTIPLE, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'Referrer', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/arrow-return-right' }, { key: FilterKey.DURATION, type: FilterType.DURATION, category: FilterCategory.RECORDING_ATTRIBUTES, label: 'Duration', operator: 'is', operatorOptions: filterOptions.getOperatorsByKeys(['is']), icon: 'filters/duration' }, { key: FilterKey.USER_COUNTRY, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.USER, label: 'User Country', operator: 'is', operatorOptions: filterOptions.getOperatorsByKeys(['is', 'isAny', 'isNot']), icon: 'filters/country', options: countryOptions }, // { key: FilterKey.CONSOLE, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Console', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/console' }, - { key: FilterKey.USERID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'User Id', operator: 'is', operatorOptions: filterOptions.stringOperators.concat([{ label: 'is undefined', value: 'isUndefined'}]), icon: 'filters/userid' }, + { key: FilterKey.USERID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'User Id', placeholder: 'E.g. Alex, or alex@domain.com, or EMP123', operator: 'is', operatorOptions: filterOptions.stringOperators.concat([{ label: 'is undefined', value: 'isUndefined'}]), icon: 'filters/userid' }, { key: FilterKey.USERANONYMOUSID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'User AnonymousId', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/userid' }, // PERFORMANCE - { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/dom-complete', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.LARGEST_CONTENTFUL_PAINT_TIME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Largest Contentful Paint', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/lcpt', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.TTFB, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Time to First Byte', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/ttfb', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.AVG_CPU_LOAD, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg CPU Load', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/cpu-load', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: '%', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg Memory Usage', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/memory-load', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'mb', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.FETCH_FAILED, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Failed Request', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, icon: 'filters/fetch-failed', isEvent: true }, - { key: FilterKey.ISSUE, type: FilterType.ISSUE, category: FilterCategory.JAVASCRIPT, label: 'Issue', operator: 'is', operatorOptions: filterOptions.getOperatorsByKeys(['is', 'isAny', 'isNot']), icon: 'filters/click', options: filterOptions.issueOptions }, + { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', placeholder: 'Enter path', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/dom-complete', isEvent: true, hasSource: true, sourceOperator: '>=', sourcePlaceholder: 'E.g. 12', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.LARGEST_CONTENTFUL_PAINT_TIME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Largest Contentful Paint', placeholder: 'Enter path', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/lcpt', isEvent: true, hasSource: true, sourceOperator: '>=', sourcePlaceholder: 'E.g. 12', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.TTFB, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Time to First Byte', placeholder: 'Enter path', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/ttfb', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators, sourcePlaceholder: 'E.g. 12', }, + { key: FilterKey.AVG_CPU_LOAD, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg CPU Load', placeholder: 'Enter path', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/cpu-load', isEvent: true, hasSource: true, sourceOperator: '>=', sourcePlaceholder: 'E.g. 12', sourceUnit: '%', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg Memory Usage', placeholder: 'Enter path', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/memory-load', isEvent: true, hasSource: true, sourceOperator: '>=', sourcePlaceholder: 'E.g. 12', sourceUnit: 'mb', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.FETCH_FAILED, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Failed Request', placeholder: 'Enter path', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, icon: 'filters/fetch-failed', isEvent: true }, + { key: FilterKey.ISSUE, type: FilterType.ISSUE, category: FilterCategory.JAVASCRIPT, label: 'Issue', placeholder: 'Select an issue', operator: 'is', operatorOptions: filterOptions.getOperatorsByKeys(['is', 'isAny', 'isNot']), icon: 'filters/click', options: filterOptions.issueOptions }, ]; const mapFilters = (list) => { @@ -137,6 +137,7 @@ export default Record({ timestamp: 0, key: '', label: '', + placeholder: '', icon: '', type: '', value: [""], @@ -155,6 +156,7 @@ export default Record({ source: [""], sourceType: '', sourceOperator: '=', + sourcePlaceholder: '', sourceUnit: '', sourceOperatorOptions: [], diff --git a/frontend/app/types/member.js b/frontend/app/types/member.js index 03495784c..8e15397f6 100644 --- a/frontend/app/types/member.js +++ b/frontend/app/types/member.js @@ -31,5 +31,6 @@ export default Record({ fromJS: ({ createdAt, ...rest }) => ({ ...rest, createdAt: createdAt && DateTime.fromISO(createdAt || 0), + id: rest.userId, }), }); diff --git a/frontend/app/types/session/issue.js b/frontend/app/types/session/issue.js index d2afff190..308bf32be 100644 --- a/frontend/app/types/session/issue.js +++ b/frontend/app/types/session/issue.js @@ -1,13 +1,13 @@ import Record from 'Types/Record'; import { List } from 'immutable'; import Watchdog from 'Types/watchdog' - export const issues_types = List([ { 'type': 'all', 'visible': true, 'order': 0, 'name': 'All', 'icon': '' }, { 'type': 'js_exception', 'visible': true, 'order': 1, 'name': 'Errors', 'icon': 'funnel/exclamation-circle' }, - { 'type': 'click_rage', 'visible': true, 'order': 2, 'name': 'Click Rage', 'icon': 'funnel/emoji-angry' }, - { 'type': 'crash', 'visible': true, 'order': 3, 'name': 'Crashes', 'icon': 'funnel/file-earmark-break' }, - { 'type': 'memory', 'visible': true, 'order': 4, 'name': 'High Memory', 'icon': 'funnel/sd-card' }, + { 'type': 'bad_request', 'visible': true, 'order': 2, 'name': 'Bad Requests', 'icon': 'funnel/file-medical-alt' }, + { 'type': 'click_rage', 'visible': true, 'order': 3, 'name': 'Click Rage', 'icon': 'funnel/emoji-angry' }, + { 'type': 'crash', 'visible': true, 'order': 4, 'name': 'Crashes', 'icon': 'funnel/file-earmark-break' }, + // { 'type': 'memory', 'visible': true, 'order': 4, 'name': 'High Memory', 'icon': 'funnel/sd-card' }, // { 'type': 'vault', 'visible': true, 'order': 5, 'name': 'Vault', 'icon': 'safe' }, // { 'type': 'bookmark', 'visible': true, 'order': 5, 'name': 'Bookmarks', 'icon': 'safe' }, // { 'type': 'bad_request', 'visible': true, 'order': 1, 'name': 'Bad Requests', 'icon': 'funnel/file-medical-alt' }, diff --git a/frontend/app/types/session/log.js b/frontend/app/types/session/log.js index 4c24f9141..c1dbe0ef7 100644 --- a/frontend/app/types/session/log.js +++ b/frontend/app/types/session/log.js @@ -24,13 +24,14 @@ export default Record({ value: '', time: undefined, index: undefined, + errorId: undefined, }, { methods: { isRed() { return isRed(this); }, isYellow() { - return this.level === WARNING; + return this.level === WARNING || WARN; } } }); diff --git a/frontend/app/types/session/session.ts b/frontend/app/types/session/session.ts index 5eadadf4b..961b34864 100644 --- a/frontend/app/types/session/session.ts +++ b/frontend/app/types/session/session.ts @@ -1,16 +1,13 @@ import Record from 'Types/Record'; import { List, Map } from 'immutable'; -import { DateTime, Duration } from 'luxon'; +import { Duration } from 'luxon'; import SessionEvent, { TYPES } from './event'; import Log from './log'; import StackEvent from './stackEvent'; import Resource from './resource'; -import CustomField from './customField'; import SessionError from './error'; import Issue from './issue'; -const SOURCE_JS = 'js_exception'; - const HASH_MOD = 1610612741; const HASH_P = 53; function hashString(s: string): number { @@ -18,139 +15,177 @@ function hashString(s: string): number { let hash = 0; for (let i = 0; i < s.length; i++) { hash = (hash + s.charCodeAt(i) * mul) % HASH_MOD; - mul = (mul*HASH_P) % HASH_MOD; + mul = (mul * HASH_P) % HASH_MOD; } return hash; } -export default Record({ - sessionId: '', - pageTitle: '', - active: false, - siteId: '', - projectKey: '', - peerId: '', - live: false, - startedAt: 0, - duration: 0, - events: List(), - logs: List(), - stackEvents: List(), - resources: List(), - missedResources: List(), - metadata: Map(), - favorite: false, - filterId: '', - messagesUrl: '', - mobsUrl: [], - userBrowser: '', - userBrowserVersion: '?', - userCountry: '', - userDevice: '', - userDeviceType: '', - isMobile: false, - userOs: '', - userOsVersion: '', - userId: '', - userAnonymousId: '', - userUuid: undefined, - userDisplayName: "", - userNumericHash: 0, - viewed: false, - consoleLogCount: '?', - eventsCount: '?', - pagesCount: '?', - clickRage: undefined, - clickRageTime: undefined, - resourcesScore: 0, - consoleError: undefined, - resourceError: undefined, - returningLocation: undefined, - returningLocationTime: undefined, - errorsCount: 0, - watchdogs: [], - issueTypes: [], - issues: [], - userDeviceHeapSize: 0, - userDeviceMemorySize: 0, - errors: List(), - crashes: [], - socket: null, - isIOS: false, - revId: '', - userSessionsCount: 0, - agentIds: [], - isCallActive: false -}, { - fromJS:({ - startTs=0, - timestamp = 0, - backendErrors=0, - consoleErrors=0, - projectId, - errors, - stackEvents = [], - issues = [], - sessionId, sessionID, - mobsUrl = [], - ...session - }) => { - const duration = Duration.fromMillis(session.duration < 1000 ? 1000 : session.duration); - const durationSeconds = duration.valueOf(); - const startedAt = +startTs || +timestamp; - - const userDevice = session.userDevice || session.userDeviceType || 'Other'; - const userDeviceType = session.userDeviceType || 'other'; - const isMobile = [ 'console', 'mobile', 'tablet' ].includes(userDeviceType) - - const events = List(session.events) - .map(e => SessionEvent({ ...e, time: e.timestamp - startedAt })) - .filter(({ type, time }) => type !== TYPES.CONSOLE && time <= durationSeconds); - - let resources = List(session.resources) - .map(Resource); - // this code shoud die. - const firstResourceTime = resources.map(r => r.time).reduce((a,b)=>Math.min(a,b), Number.MAX_SAFE_INTEGER); - resources = resources - .map(r => r.set("time", r.time - firstResourceTime)) - .sort((r1, r2) => r1.time - r2.time); - const missedResources = resources.filter(({ success }) => !success); - const logs = List(session.logs).map(Log); - - const stackEventsList = List(stackEvents) - .concat(List(session.userEvents)) - .sortBy(se => se.timestamp) - .map(se => StackEvent({ ...se, time: se.timestamp - startedAt })); - const exceptions = List(errors) - .map(SessionError) - - const issuesList = List(issues) - .map(e => Issue({ ...e, time: e.timestamp - startedAt })) - - return { - ...session, - isIOS: session.platform === "ios", - watchdogs: session.watchdogs || [], - errors: exceptions, - siteId: projectId, - events, - logs, - stackEvents: stackEventsList, - resources, - missedResources, - userDevice, - userDeviceType, - isMobile, - startedAt, - duration, - userNumericHash: hashString(session.userId || session.userAnonymousId || session.userUuid || session.userID || session.userUUID || ""), - userDisplayName: session.userId || session.userAnonymousId || session.userID || 'Anonymous User', - firstResourceTime, - issues: issuesList, - sessionId: sessionId || sessionID, - userId: session.userId || session.userID, - mobsUrl: Array.isArray(mobsUrl) ? mobsUrl : [ mobsUrl ] - }; +export default Record( + { + sessionId: '', + pageTitle: '', + active: false, + siteId: '', + projectKey: '', + peerId: '', + live: false, + startedAt: 0, + duration: 0, + events: List(), + logs: List(), + stackEvents: List(), + resources: List(), + missedResources: List(), + metadata: Map(), + favorite: false, + filterId: '', + messagesUrl: '', + domURL: [], + devtoolsURL: [], + mobsUrl: [], // @depricated + userBrowser: '', + userBrowserVersion: '?', + userCountry: '', + userDevice: '', + userDeviceType: '', + isMobile: false, + userOs: '', + userOsVersion: '', + userId: '', + userAnonymousId: '', + userUuid: undefined, + userDisplayName: '', + userNumericHash: 0, + viewed: false, + consoleLogCount: '?', + eventsCount: '?', + pagesCount: '?', + clickRage: undefined, + clickRageTime: undefined, + resourcesScore: 0, + consoleError: undefined, + resourceError: undefined, + returningLocation: undefined, + returningLocationTime: undefined, + errorsCount: 0, + watchdogs: [], + issueTypes: [], + issues: [], + userDeviceHeapSize: 0, + userDeviceMemorySize: 0, + errors: List(), + crashes: [], + socket: null, + isIOS: false, + revId: '', + userSessionsCount: 0, + agentIds: [], + isCallActive: false, + agentToken: '', + notes: [], + notesWithEvents: [], + fileKey: '', }, - idKey: "sessionId", -}); + { + fromJS: ({ + startTs = 0, + timestamp = 0, + backendErrors = 0, + consoleErrors = 0, + projectId, + errors, + stackEvents = [], + issues = [], + sessionId, + sessionID, + domURL = [], + devtoolsURL = [], + mobsUrl = [], + notes = [], + ...session + }) => { + const duration = Duration.fromMillis(session.duration < 1000 ? 1000 : session.duration); + const durationSeconds = duration.valueOf(); + const startedAt = +startTs || +timestamp; + + const userDevice = session.userDevice || session.userDeviceType || 'Other'; + const userDeviceType = session.userDeviceType || 'other'; + const isMobile = ['console', 'mobile', 'tablet'].includes(userDeviceType); + + const events = List(session.events) + .map((e) => SessionEvent({ ...e, time: e.timestamp - startedAt })) + .filter(({ type, time }) => type !== TYPES.CONSOLE && time <= durationSeconds); + + let resources = List(session.resources).map(Resource); + // this code shoud die. + const firstResourceTime = resources + .map((r) => r.time) + .reduce((a, b) => Math.min(a, b), Number.MAX_SAFE_INTEGER); + resources = resources + .map((r) => r.set('time', r.time - firstResourceTime)) + .sort((r1, r2) => r1.time - r2.time); + const missedResources = resources.filter(({ success }) => !success); + const logs = List(session.logs).map(Log); + + const stackEventsList = List(stackEvents) + .concat(List(session.userEvents)) + .sortBy((se) => se.timestamp) + .map((se) => StackEvent({ ...se, time: se.timestamp - startedAt })); + const exceptions = List(errors).map(SessionError); + + const issuesList = List(issues).map((e) => Issue({ ...e, time: e.timestamp - startedAt })); + + const rawEvents = !session.events + ? [] + : // @ts-ignore + session.events + .map((evt) => ({ ...evt, time: evt.timestamp - startedAt })) + .filter(({ type, time }) => type !== TYPES.CONSOLE && time <= durationSeconds) || []; + const rawNotes = notes; + const notesWithEvents = [...rawEvents, ...rawNotes].sort((a, b) => { + const aTs = a.time || a.timestamp; + const bTs = b.time || b.timestamp; + + return aTs - bTs; + }); + + return { + ...session, + isIOS: session.platform === 'ios', + watchdogs: session.watchdogs || [], + errors: exceptions, + siteId: projectId, + events, + logs, + stackEvents: stackEventsList, + resources, + missedResources, + userDevice, + userDeviceType, + isMobile, + startedAt, + duration, + userNumericHash: hashString( + session.userId || + session.userAnonymousId || + session.userUuid || + session.userID || + session.userUUID || + '' + ), + userDisplayName: + session.userId || session.userAnonymousId || session.userID || 'Anonymous User', + firstResourceTime, + issues: issuesList, + sessionId: sessionId || sessionID, + userId: session.userId || session.userID, + mobsUrl: Array.isArray(mobsUrl) ? mobsUrl : [mobsUrl], + domURL, + devtoolsURL, + notes, + notesWithEvents: List(notesWithEvents), + }; + }, + idKey: 'sessionId', + } +); diff --git a/frontend/app/utils.ts b/frontend/app/utils.ts index 52bf7c6ad..e3cd50134 100644 --- a/frontend/app/utils.ts +++ b/frontend/app/utils.ts @@ -269,11 +269,11 @@ export const positionOfTheNumber = (min, max, value, length) => { return position; }; -export const convertElementToImage = async (el) => { - const fontEmbedCss = await htmlToImage.getFontEmbedCSS(el); +export const convertElementToImage = async (el: HTMLElement) => { + // const fontEmbedCss = await htmlToImage.getFontEmbedCSS(el); const image = await htmlToImage.toJpeg(el, { pixelRatio: 2, - fontEmbedCss, + // fontEmbedCss, filter: function (node) { return node.id !== 'no-print'; }, diff --git a/frontend/package.json b/frontend/package.json index 8fb7f651f..c4f0a68de 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,6 +17,7 @@ "postinstall": "yarn gen:icons && yarn gen:colors" }, "dependencies": { + "@floating-ui/react-dom-interactions": "^0.10.3", "@sentry/browser": "^5.21.1", "@svg-maps/world": "^1.0.1", "@svgr/webpack": "^6.2.1", @@ -25,39 +26,42 @@ "copy-to-clipboard": "^3.3.1", "deep-diff": "^1.0.2", "html-to-image": "^1.9.0", + "html2canvas": "^1.4.1", "immutable": "^4.0.0-rc.12", "jsbi": "^4.1.0", "jshint": "^2.11.1", "jspdf": "^2.5.1", + "jsx-runtime": "^1.2.0", "luxon": "^1.24.1", "mobx": "^6.3.8", "mobx-react-lite": "^3.1.6", - "moment": "^2.29.2", - "moment-range": "^3.0.3", + "moment": "^2.29.4", + "moment-range": "^4.0.2", "peerjs": "1.3.2", "rc-time-picker": "^3.7.3", - "react": "^16.14.0", + "react": "^18.2.0", "react-circular-progressbar": "^2.1.0", - "react-confirm": "^0.1.27", + "react-confirm": "^0.2.3", "react-date-range": "^1.4.0", "react-daterange-picker": "^2.0.1", - "react-dnd": "^15.1.1", + "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^15.1.2", - "react-dom": "^16.13.1", + "react-dom": "^18.2.0", "react-draggable": "^4.4.5", "react-google-recaptcha": "^1.1.0", "react-highlight": "^0.14.0", "react-json-view": "^1.21.3", "react-lazyload": "^3.2.0", + "react-merge-refs": "^2.0.1", "react-redux": "^5.1.2", "react-router": "^5.3.3", "react-router-dom": "^5.3.3", "react-select": "^5.3.2", "react-svg-map": "^2.2.0", "react-tippy": "^1.4.0", - "react-toastify": "^9.0.3", + "react-toastify": "^9.1.1", "react-virtualized": "^9.22.3", - "recharts": "^2.1.10", + "recharts": "^2.1.13", "redux": "^4.0.5", "redux-immutable": "^4.0.0", "redux-thunk": "^2.3.0", @@ -87,6 +91,7 @@ "@types/react-dom": "^18.0.4", "@types/react-redux": "^7.1.24", "@types/react-router-dom": "^5.3.3", + "@types/react-virtualized": "^9.21.21", "@typescript-eslint/eslint-plugin": "^5.24.0", "@typescript-eslint/parser": "^5.24.0", "autoprefixer": "^10.4.7", diff --git a/frontend/path-alias.js b/frontend/path-alias.js index 4dd1117e0..630e3868c 100644 --- a/frontend/path-alias.js +++ b/frontend/path-alias.js @@ -1,23 +1,25 @@ const path = require('path'); module.exports = { - "@": path.resolve(__dirname, "app"), - "App": path.resolve(__dirname, "app"), - "App/*": path.resolve(__dirname, "app/*"), - "SVG": path.resolve(__dirname, "app/svg"), - "SVG/*": path.resolve(__dirname, "app/svg/*"), - "Components": path.resolve(__dirname, "app/components"), - "Components/*": path.resolve(__dirname, "app/components/*"), - "Types": path.resolve(__dirname, "app/types" ), - "Types/*": path.resolve(__dirname, "app/types/*"), - "UI": path.resolve(__dirname, "app/components/ui"), - "UI/*": path.resolve(__dirname, "app/components/ui/*"), - "Duck": path.resolve(__dirname, "app/duck"), - "Duck/*": path.resolve(__dirname, "app/duck/*"), - "HOCs": path.resolve(__dirname, "app/components/hocs"), - "HOCs/*": path.resolve(__dirname, "app/components/hocs/*"), - "Shared": path.resolve(__dirname, "app/components/shared"), - "Shared/*": path.resolve(__dirname, "app/components/shared/*"), - "Player": path.resolve(__dirname, "app/player"), - "Player/*": path.resolve(__dirname, "app/player/*"), -}; + '@': path.resolve(__dirname, 'app'), + App: path.resolve(__dirname, 'app'), + 'App/*': path.resolve(__dirname, 'app/*'), + SVG: path.resolve(__dirname, 'app/svg'), + 'SVG/*': path.resolve(__dirname, 'app/svg/*'), + Components: path.resolve(__dirname, 'app/components'), + 'Components/*': path.resolve(__dirname, 'app/components/*'), + Types: path.resolve(__dirname, 'app/types'), + 'Types/*': path.resolve(__dirname, 'app/types/*'), + UI: path.resolve(__dirname, 'app/components/ui'), + 'UI/*': path.resolve(__dirname, 'app/components/ui/*'), + Duck: path.resolve(__dirname, 'app/duck'), + 'Duck/*': path.resolve(__dirname, 'app/duck/*'), + HOCs: path.resolve(__dirname, 'app/components/hocs'), + 'HOCs/*': path.resolve(__dirname, 'app/components/hocs/*'), + Shared: path.resolve(__dirname, 'app/components/shared'), + 'Shared/*': path.resolve(__dirname, 'app/components/shared/*'), + Player: path.resolve(__dirname, 'app/player'), + 'Player/*': path.resolve(__dirname, 'app/player/*'), + 'react/jsx-runtime.js': 'react/jsx-runtime', + 'react/jsx-dev-runtime.js': 'react/jsx-dev-runtime', +}; diff --git a/frontend/scripts/icons.ts b/frontend/scripts/icons.ts index 4ad35692d..c3b5aaf9e 100644 --- a/frontend/scripts/icons.ts +++ b/frontend/scripts/icons.ts @@ -25,7 +25,7 @@ const basePlugins = { 'removeStyleElement', ] } -const plugins = (removeFill = true) => { +const plugins = (removeFill = true) => { return { plugins: [ { @@ -51,7 +51,7 @@ const plugins = (removeFill = true) => { } }, { name: 'removeXMLNS' }, - // { name: 'replaceDashes', params: { + // { name: 'replaceDashes', params: { // type: 'perItem', // fn: (item) => { // item.eachAttr(attr => { @@ -59,7 +59,7 @@ const plugins = (removeFill = true) => { // }) // } // } }, - + ] } } @@ -90,8 +90,11 @@ ${icons.map(icon => { .replace(/xmlns\:xlink/g, 'xmlnsXlink') .replace(/clip-path/g, 'clipPath') .replace(/clip-rule/g, 'clipRule') - .replace(/xml:space="preserve"/g, '')};` -}).join('\n')} + .replace(/fill-opacity/g, 'fillOpacity') + .replace(/stop-color/g, 'stopColor') + .replace(/xml:space="preserve"/g, '')};`; + }) + .join('\n')} default: return <svg width={ width } height={ height } />; // if (window.ENV.PRODUCTION) return null; diff --git a/mobs/README.md b/mobs/README.md index 7c2cb17ac..773c658f0 100644 --- a/mobs/README.md +++ b/mobs/README.md @@ -4,11 +4,5 @@ To generate all necessary files for the project: ```sh -ruby run.rb +sh generate.sh ``` - -In order format generated files run: -```sh -sh format.sh -``` -(Otherwise there will be changes in stage) diff --git a/mobs/format.sh b/mobs/generate.sh similarity index 72% rename from mobs/format.sh rename to mobs/generate.sh index b91c013fa..075c511d8 100644 --- a/mobs/format.sh +++ b/mobs/generate.sh @@ -1 +1,2 @@ +ruby run.rb gofmt -w ../backend/pkg/messages \ No newline at end of file diff --git a/mobs/messages.rb b/mobs/messages.rb index 6d21c2e05..60bde0626 100644 --- a/mobs/messages.rb +++ b/mobs/messages.rb @@ -46,7 +46,7 @@ message 1, 'SessionStart', :tracker => false, :replayer => false do end ## message 2, 'CreateDocument', do # end -message 3, 'SessionEnd', :tracker => false, :replayer => false do +message 3, 'SessionEndDeprecated', :tracker => false, :replayer => false do uint 'Timestamp' end message 4, 'SetPageLocation' do @@ -125,13 +125,8 @@ message 20, 'MouseMove' do uint 'X' uint 'Y' end -# Depricated since OpenReplay 1.2.0 (tracker version?) -message 21, 'MouseClickDepricated', :tracker => false, :replayer => false do - uint 'ID' - uint 'HesitationTime' - string 'Label' -end -message 22, 'ConsoleLog' do +# 21 +message 22, 'ConsoleLog', :replayer => :devtools do string 'Level' string 'Value' end @@ -151,7 +146,8 @@ message 24, 'PageRenderTiming', :replayer => false do uint 'VisuallyComplete' uint 'TimeToInteractive' end -message 25, 'JSException', :replayer => false do +# deprecated since 4.1.6 / 1.8.2 in favor of #78 +message 25, 'JSExceptionDeprecated', :replayer => false do string 'Name' string 'Message' string 'Payload' @@ -210,14 +206,14 @@ message 33, 'ClickEvent', :tracker => false, :replayer => false do string 'Label' string 'Selector' end -message 34, 'ErrorEvent', :tracker => false, :replayer => false do - uint 'MessageID' - uint 'Timestamp' - string 'Source' - string 'Name' - string 'Message' - string 'Payload' -end +# message 34, 'ErrorEvent', :tracker => false, :replayer => false do +# uint 'MessageID' +# uint 'Timestamp' +# string 'Source' +# string 'Name' +# string 'Message' +# string 'Payload' +# end message 35, 'ResourceEvent', :tracker => false, :replayer => false do uint 'MessageID' uint 'Timestamp' @@ -238,19 +234,19 @@ message 36, 'CustomEvent', :tracker => false, :replayer => false do string 'Name' string 'Payload' end -# depricated since 4.0.2 in favor of AdoptedSSInsertRule + AdoptedSSAddOwner +# deprecated since 4.0.2 in favor of AdoptedSSInsertRule + AdoptedSSAddOwner message 37, 'CSSInsertRule' do uint 'ID' string 'Rule' uint 'Index' end -# depricated since 4.0.2 +# deprecated since 4.0.2 message 38, 'CSSDeleteRule' do uint 'ID' uint 'Index' end -message 39, 'Fetch' do +message 39, 'Fetch', :replayer => :devtools do string 'Method' string 'URL' string 'Request' @@ -259,16 +255,17 @@ message 39, 'Fetch' do uint 'Timestamp' uint 'Duration' end -message 40, 'Profiler' do +message 40, 'Profiler', :replayer => :devtools do string 'Name' uint 'Duration' string 'Args' string 'Result' end -message 41, 'OTable' do +message 41, 'OTable', :replayer => :devtools do string 'Key' string 'Value' end +# Do we use that? message 42, 'StateAction', :replayer => false do string 'Type' end @@ -277,36 +274,37 @@ message 43, 'StateActionEvent', :tracker => false, :replayer => false do uint 'Timestamp' string 'Type' end -message 44, 'Redux' do +message 44, 'Redux', :replayer => :devtools do string 'Action' string 'State' uint 'Duration' end -message 45, 'Vuex' do +message 45, 'Vuex', :replayer => :devtools do string 'Mutation' string 'State' end -message 46, 'MobX' do +message 46, 'MobX', :replayer => :devtools do string 'Type' string 'Payload' end -message 47, 'NgRx' do +message 47, 'NgRx', :replayer => :devtools do string 'Action' string 'State' uint 'Duration' end -message 48, 'GraphQL' do +message 48, 'GraphQL', :replayer => :devtools do string 'OperationKind' string 'OperationName' string 'Variables' string 'Response' end -message 49, 'PerformanceTrack' do +message 49, 'PerformanceTrack' do #, :replayer => :devtools --> requires player performance refactoring (now is tied with nodes counter) int 'Frames' int 'Ticks' uint 'TotalJSHeapSize' uint 'UsedJSHeapSize' end +# next 2 should be removed after refactoring backend/pkg/handlers/custom/eventMapper.go (move "wrapping" logic to pg connector insertion) message 50, 'GraphQLEvent', :tracker => false, :replayer => false do uint 'MessageID' uint 'Timestamp' @@ -361,7 +359,20 @@ message 56, 'PerformanceTrackAggr', :tracker => false, :replayer => false do uint 'AvgUsedJSHeapSize' uint 'MaxUsedJSHeapSize' end -## 57 58 + +# Since 4.1.7 / 1.9.0 +message 57, 'LoadFontFace' do + uint 'ParentID' + string 'Family' + string 'Source' + string 'Descriptors' +end +# Since 4.1.7 / 1.9.0 +message 58, 'SetNodeFocus' do + int 'ID' +end + +#Depricated (since 3.0.?) message 59, 'LongTask' do uint 'Timestamp' uint 'Duration' @@ -457,16 +468,26 @@ message 77, 'AdoptedSSRemoveOwner' do uint 'SheetID' uint 'ID' end -#Since 4.0.1 -# message 78, 'ReplaceVCSSURLBased' do -# uint 'SheetID' -# uint 'Index' -# string 'Styles' -# string 'BaseURL' -# end -message 79, 'Zustand' do +message 79, 'Zustand', :replayer => :devtools do string 'Mutation' string 'State' end +message 78, 'JSException', :replayer => false do + string 'Name' + string 'Message' + string 'Payload' + string 'Metadata' +end -# 80 -- 90 reserved \ No newline at end of file + +message 126, 'SessionEnd', :tracker => false, :replayer => false do + uint 'Timestamp' + string 'EncryptionKey' +end +message 127, 'SessionSearch', :tracker => false, :replayer => false do + uint 'Timestamp' + uint 'Partition' +end + + +# 80 -- 90 reserved diff --git a/mobs/run.rb b/mobs/run.rb index 67a9b4eea..31adfcba1 100644 --- a/mobs/run.rb +++ b/mobs/run.rb @@ -113,7 +113,7 @@ $ids = [] $messages = [] def message(id, name, opts = {}, &block) raise "id duplicated #{name}" if $ids.include? id - raise "id is too big #{name}" if id > 120 + raise "id is too big #{name}" if id > 127 $ids << id opts[:id] = id opts[:name] = name diff --git a/mobs/templates/backend~pkg~messages~filters.go.erb b/mobs/templates/backend~pkg~messages~filters.go.erb index ac4ba9cba..bb43037e8 100644 --- a/mobs/templates/backend~pkg~messages~filters.go.erb +++ b/mobs/templates/backend~pkg~messages~filters.go.erb @@ -2,9 +2,13 @@ package messages func IsReplayerType(id int) bool { - return <%= $messages.select { |msg| msg.replayer }.map{ |msg| "#{msg.id} == id" }.join(' || ') %> + return <%= $messages.select { |msg| msg.replayer == false }.map{ |msg| "#{msg.id} != id" }.join(' && ') %> } func IsIOSType(id int) bool { return <%= $messages.select { |msg| msg.context == :ios }.map{ |msg| "#{msg.id} == id"}.join(' || ') %> } + +func IsDOMType(id int) bool { + return <%= $messages.select { |msg| msg.replayer == true }.map{ |msg| "#{msg.id} == id" }.join(' || ') %> +} \ No newline at end of file diff --git a/mobs/templates/frontend~app~player~MessageDistributor~messages~RawMessageReader.ts.erb b/mobs/templates/frontend~app~player~MessageDistributor~messages~RawMessageReader.ts.erb index 11bd38e1a..336fd957e 100644 --- a/mobs/templates/frontend~app~player~MessageDistributor~messages~RawMessageReader.ts.erb +++ b/mobs/templates/frontend~app~player~MessageDistributor~messages~RawMessageReader.ts.erb @@ -17,7 +17,7 @@ export default class RawMessageReader extends PrimitiveReader { if (tp === null) { return resetPointer() } switch (tp) { - <% $messages.select { |msg| msg.replayer }.each do |msg| %> +<% $messages.select { |msg| msg.replayer != false }.each do |msg| %> case <%= msg.id %>: { <%= msg.attributes.map { |attr| " const #{attr.name.camel_case} = this.read#{attr.type.to_s.pascal_case}(); if (#{attr.name.camel_case} === null) { return resetPointer() }" }.join "\n" %> @@ -27,7 +27,7 @@ export default class RawMessageReader extends PrimitiveReader { " #{attr.name.camel_case}," }.join "\n" %> }; } - <% end %> +<% end %> default: throw new Error(`Unrecognizable message type: ${ tp }; Pointer at the position ${this.p} of ${this.buf.length}`) return null; diff --git a/mobs/templates/frontend~app~player~MessageDistributor~messages~message.ts.erb b/mobs/templates/frontend~app~player~MessageDistributor~messages~message.ts.erb index 178fa3e44..666b0f740 100644 --- a/mobs/templates/frontend~app~player~MessageDistributor~messages~message.ts.erb +++ b/mobs/templates/frontend~app~player~MessageDistributor~messages~message.ts.erb @@ -4,11 +4,11 @@ import type { Timed } from './timed' import type { RawMessage } from './raw' import type { -<%= $messages.select { |msg| msg.replayer }.map { |msg| " Raw#{msg.name.snake_case.pascal_case}," }.join "\n" %> +<%= $messages.select { |msg| msg.replayer != false }.map { |msg| " Raw#{msg.name.snake_case.pascal_case}," }.join "\n" %> } from './raw' export type Message = RawMessage & Timed -<% $messages.select { |msg| msg.replayer }.each do |msg| %> +<% $messages.select { |msg| msg.replayer != false }.each do |msg| %> export type <%= msg.name.snake_case.pascal_case %> = Raw<%= msg.name.snake_case.pascal_case %> & Timed <% end %> diff --git a/mobs/templates/frontend~app~player~MessageDistributor~messages~raw.ts.erb b/mobs/templates/frontend~app~player~MessageDistributor~messages~raw.ts.erb index 97dc34be6..3099f39ff 100644 --- a/mobs/templates/frontend~app~player~MessageDistributor~messages~raw.ts.erb +++ b/mobs/templates/frontend~app~player~MessageDistributor~messages~raw.ts.erb @@ -1,11 +1,11 @@ // Auto-generated, do not edit /* eslint-disable */ -<% $messages.select { |msg| msg.replayer }.each do |msg| %> +<% $messages.select { |msg| msg.replayer != false }.each do |msg| %> export interface Raw<%= msg.name.snake_case.pascal_case %> { tp: "<%= msg.name.snake_case %>", <%= msg.attributes.map { |attr| " #{attr.name.camel_case}: #{attr.type_js}," }.join "\n" %> } <% end %> -export type RawMessage = <%= $messages.select { |msg| msg.replayer }.map { |msg| "Raw#{msg.name.snake_case.pascal_case}" }.join " | " %>; +export type RawMessage = <%= $messages.select { |msg| msg.replayer != false }.map { |msg| "Raw#{msg.name.snake_case.pascal_case}" }.join " | " %>; diff --git a/mobs/templates/frontend~app~player~MessageDistributor~messages~tracker-legacy.ts.erb b/mobs/templates/frontend~app~player~MessageDistributor~messages~tracker-legacy.ts.erb index e0ba92069..28f1d64d7 100644 --- a/mobs/templates/frontend~app~player~MessageDistributor~messages~tracker-legacy.ts.erb +++ b/mobs/templates/frontend~app~player~MessageDistributor~messages~tracker-legacy.ts.erb @@ -3,5 +3,5 @@ // Auto-generated, do not edit export const TP_MAP = { -<%= $messages.select { |msg| msg.tracker || msg.replayer }.map { |msg| " #{msg.id}: \"#{msg.name.snake_case}\"," }.join "\n" %> +<%= $messages.select { |msg| msg.tracker || msg.replayer != false }.map { |msg| " #{msg.id}: \"#{msg.name.snake_case}\"," }.join "\n" %> } as const diff --git a/mobs/templates/frontend~app~player~MessageDistributor~messages~tracker.ts.erb b/mobs/templates/frontend~app~player~MessageDistributor~messages~tracker.ts.erb index f6e739c86..8c5874de6 100644 --- a/mobs/templates/frontend~app~player~MessageDistributor~messages~tracker.ts.erb +++ b/mobs/templates/frontend~app~player~MessageDistributor~messages~tracker.ts.erb @@ -14,7 +14,7 @@ export type TrackerMessage = <%= $messages.select { |msg| msg.tracker }.map { |m export default function translate(tMsg: TrackerMessage): RawMessage | null { switch(tMsg[0]) { - <% $messages.select { |msg| msg.replayer & msg.tracker }.each do |msg| %> + <% $messages.select { |msg| msg.replayer != false && msg.tracker }.each do |msg| %> case <%= msg.id %>: { return { tp: "<%= msg.name.snake_case %>", diff --git a/peers/Dockerfile b/peers/Dockerfile index c22e33f37..bfabf6bea 100644 --- a/peers/Dockerfile +++ b/peers/Dockerfile @@ -2,7 +2,8 @@ FROM node:18-alpine LABEL Maintainer="KRAIEM Taha Yassine<tahayk2@gmail.com>" RUN apk add --no-cache tini ARG envarg -ENV ENTERPRISE_BUILD=${envarg} +ENV PRIVATE_ENDPOINTS=false \ + ENTERPRISE_BUILD=${envarg} WORKDIR /work COPY package.json . diff --git a/peers/build.sh b/peers/build.sh index 381189927..e84b942ec 100644 --- a/peers/build.sh +++ b/peers/build.sh @@ -15,12 +15,20 @@ check_prereq() { } function build_api(){ + destination="_peers" + [[ $1 == "ee" ]] && { + destination="_peers_ee" + } + cp -R ../peers ../${destination} + cd ../${destination} cp -R ../utilities/utils . # Copy enterprise code [[ $1 == "ee" ]] && { cp -rf ../ee/peers/* ./ } docker build -f ./Dockerfile -t ${DOCKER_REPO:-'local'}/peers:${git_sha1} . + cd ../peers + rm -rf ../${destination} [[ $PUSH_IMAGE -eq 1 ]] && { docker push ${DOCKER_REPO:-'local'}/peers:${git_sha1} docker tag ${DOCKER_REPO:-'local'}/peers:${git_sha1} ${DOCKER_REPO:-'local'}/peers:latest diff --git a/peers/package-lock.json b/peers/package-lock.json index a903cfd08..ce7c3c1c4 100644 --- a/peers/package-lock.json +++ b/peers/package-lock.json @@ -10,87 +10,7 @@ "license": "Elastic License 2.0 (ELv2)", "dependencies": { "express": "^4.18.1", - "peer": "^0.6.1" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.30", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", - "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" - }, - "node_modules/@types/node": { - "version": "18.7.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.16.tgz", - "integrity": "sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg==" - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "node_modules/@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", - "dependencies": { - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "dependencies": { - "@types/node": "*" + "peer": "^v1.0.0-rc.4" } }, "node_modules/accepts": { @@ -655,17 +575,12 @@ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/peer": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/peer/-/peer-0.6.1.tgz", - "integrity": "sha512-zPJSPoZvo+83sPJNrW8o93QTktx7dKk67965RRDDNAIelWw1ZwE6ZmmhsvRrdNRlK0knQb3rR8GBdZlbWzCYJw==", + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/peer/-/peer-1.0.0-rc.4.tgz", + "integrity": "sha512-xaNIDm3yWR5m8cuijK7jEFAMOWqNJDGSVJ0+Y3qKW5XTNYsNWEdqtg/Btq9eznGxTTeqQZGNw/SxwyrCVdmmDg==", "dependencies": { - "@types/cors": "^2.8.6", - "@types/express": "^4.17.3", - "@types/ws": "^7.2.3", - "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1", - "uuid": "^3.4.0", "ws": "^7.2.3", "yargs": "^15.3.1" }, @@ -673,7 +588,7 @@ "peerjs": "bin/peerjs" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/proxy-addr": { @@ -894,15 +809,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -989,86 +895,6 @@ } }, "dependencies": { - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.30", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", - "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" - }, - "@types/node": { - "version": "18.7.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.16.tgz", - "integrity": "sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg==" - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", - "requires": { - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "requires": { - "@types/node": "*" - } - }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -1482,17 +1308,12 @@ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "peer": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/peer/-/peer-0.6.1.tgz", - "integrity": "sha512-zPJSPoZvo+83sPJNrW8o93QTktx7dKk67965RRDDNAIelWw1ZwE6ZmmhsvRrdNRlK0knQb3rR8GBdZlbWzCYJw==", + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/peer/-/peer-1.0.0-rc.4.tgz", + "integrity": "sha512-xaNIDm3yWR5m8cuijK7jEFAMOWqNJDGSVJ0+Y3qKW5XTNYsNWEdqtg/Btq9eznGxTTeqQZGNw/SxwyrCVdmmDg==", "requires": { - "@types/cors": "^2.8.6", - "@types/express": "^4.17.3", - "@types/ws": "^7.2.3", - "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1", - "uuid": "^3.4.0", "ws": "^7.2.3", "yargs": "^15.3.1" } @@ -1655,11 +1476,6 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/peers/package.json b/peers/package.json index 51f37b5fa..a38ad3343 100644 --- a/peers/package.json +++ b/peers/package.json @@ -19,6 +19,6 @@ "homepage": "https://github.com/openreplay/openreplay#readme", "dependencies": { "express": "^4.18.1", - "peer": "^0.6.1" + "peer": "^v1.0.0-rc.4" } } diff --git a/peers/server.js b/peers/server.js index c4416b58a..e553513ad 100644 --- a/peers/server.js +++ b/peers/server.js @@ -41,4 +41,12 @@ process.on('uncaughtException', err => { console.log(`Uncaught Exception: ${err.message}`); debug && console.log(err.stack); // process.exit(1); -}); \ No newline at end of file +}); + +app.get('/private/shutdown', (req, res) => { + console.log("Requested shutdown"); + res.statusCode = 200; + res.end("ok!"); + process.kill(1, "SIGTERM"); + } +); \ No newline at end of file diff --git a/scripts/helm/app/README.md b/scripts/helm/app/README.md deleted file mode 100644 index a5b73f915..000000000 --- a/scripts/helm/app/README.md +++ /dev/null @@ -1,37 +0,0 @@ -## Core OpenReplay application configuration folder - - This folder contains configuration for core OpenReplay apps. All applications share common helm chart named *openreplay* which can be overridden by `<application>.yaml` file. - - **Below is a sample template.** - - ```yaml - namespace: app # In which namespace alerts runs. - image: - repository: rg.fr-par.scw.cloud/foss # Which image to use - name: alerts - pullPolicy: IfNotPresent - tag: "latest" # Overrides the image tag whose default is the chart appVersion. - - imagePullSecrets: - # If needed credentials to pull the image. - # aws-registry is created using script docker_registry.sh. - - name: aws-registry - - service: - type: ClusterIP - port: 9000 - - resources: - limits: - cpu: 256m - memory: 512Mi - requests: - cpu: 100m - memory: 128Mi - - # env vars for the application - env: - ALERT_NOTIFICATION_STRING: http://chalice-openreplay.app.svc.cluster.local:8000/alerts/notifications - CLICKHOUSE_STRING: tcp://clickhouse.db.svc.cluster.local:9000/default - POSTGRES_STRING: postgres://postgresql.db.svc.cluster.local:5432 - ``` diff --git a/scripts/helm/app/alerts.yaml b/scripts/helm/app/alerts.yaml deleted file mode 100644 index 8998f3a1f..000000000 --- a/scripts/helm/app/alerts.yaml +++ /dev/null @@ -1,48 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: alerts - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 9000 - -resources: - limits: - cpu: 256m - memory: 512Mi - requests: - cpu: 1m - memory: 1Mi - -env: - pg_host: postgresql.db.svc.cluster.local - pg_port: 5432 - pg_dbname: postgres - pg_user: postgres - pg_password: asayerPostgres - ch_host: clickhouse.db.svc.cluster.local - ch_port: 9000 - EMAIL_HOST: '' - EMAIL_PORT: '587' - EMAIL_USER: '' - EMAIL_PASSWORD: '' - EMAIL_USE_TLS: 'true' - EMAIL_USE_SSL: 'false' - EMAIL_SSL_KEY: '' - EMAIL_SSL_CERT: '' - EMAIL_FROM: OpenReplay<do-not-reply@openreplay.com> - SITE_URL: '' - S3_HOST: 'http://minio.db.svc.cluster.local:9000' - S3_KEY: minios3AccessKeyS3cr3t - S3_SECRET: m1n10s3CretK3yPassw0rd - AWS_DEFAULT_REGION: us-east-1 - LICENSE_KEY: "" - PYTHONUNBUFFERED: '0' - version_number: '1.3.6' diff --git a/scripts/helm/app/assets.yaml b/scripts/helm/app/assets.yaml deleted file mode 100644 index cedc5f6aa..000000000 --- a/scripts/helm/app/assets.yaml +++ /dev/null @@ -1,35 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: assets - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 9000 - -resources: - limits: - cpu: 256m - memory: 512Mi - requests: - cpu: 1m - memory: 1Mi - -env: - ASSETS_ORIGIN: /sessions-assets # TODO: full path (with the minio prefix) - S3_BUCKET_ASSETS: sessions-assets - AWS_ENDPOINT: http://minio.db.svc.cluster.local:9000 - AWS_ACCESS_KEY_ID: "minios3AccessKeyS3cr3t" - AWS_SECRET_ACCESS_KEY: "m1n10s3CretK3yPassw0rd" - AWS_REGION: us-east-1 - # Can I use the kafka-headless? means will the client loadbalance b/w multiple ips? - REDIS_STRING: redis-master.db.svc.cluster.local:6379 - KAFKA_SERVERS: kafka.db.svc.cluster.local:9092 - KAFKA_USE_SSL: false - LICENSE_KEY: "" diff --git a/scripts/helm/app/chalice.yaml b/scripts/helm/app/chalice.yaml deleted file mode 100644 index 2d6b53ead..000000000 --- a/scripts/helm/app/chalice.yaml +++ /dev/null @@ -1,69 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: chalice - pullPolicy: IfNotPresent - tag: latest - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 8000 - -resources: - limits: - cpu: 1000m - memory: 1Gi - requests: - cpu: 1m - memory: 1Mi -env: - pg_host: postgresql.db.svc.cluster.local - pg_port: 5432 - pg_dbname: postgres - pg_user: postgres - pg_password: asayerPostgres - ch_host: clickhouse.db.svc.cluster.local - ch_port: 9000 - captcha_server: '' - captcha_key: '' - async_Token: '' - EMAIL_HOST: '' - EMAIL_PORT: '587' - EMAIL_USER: '' - EMAIL_PASSWORD: '' - EMAIL_USE_TLS: 'true' - EMAIL_USE_SSL: 'false' - EMAIL_SSL_KEY: '' - EMAIL_SSL_CERT: '' - EMAIL_FROM: OpenReplay<do-not-reply@openreplay.com> - SITE_URL: '' - announcement_url: '' - jwt_secret: "SetARandomStringHere" - jwt_algorithm: HS512 - jwt_exp_delta_seconds: '2592000' - # Override with your https://domain_name - # eg: https://openreplay.mycompany.com - S3_HOST: 'http://minio.db.svc.cluster.local:9000' - S3_KEY: minios3AccessKeyS3cr3t - S3_SECRET: m1n10s3CretK3yPassw0rd - AWS_DEFAULT_REGION: us-east-1 - sessions_region: us-east-1 - sessions_bucket: mobs - sourcemaps_bucket: sourcemaps - js_cache_bucket: sessions-assets - # Enable logging for python app - # Ref: https://stackoverflow.com/questions/43969743/logs-in-kubernetes-pod-not-showing-up - PYTHONUNBUFFERED: '0' - version_number: '1.3.6' - SAML2_MD_URL: '' - idp_entityId: '' - idp_sso_url: '' - idp_x509cert: '' - idp_sls_url: '' - idp_name: '' - idp_tenantKey: '' - assist_secret: '' - iceServers: '' diff --git a/scripts/helm/app/db.yaml b/scripts/helm/app/db.yaml deleted file mode 100644 index 98b96b855..000000000 --- a/scripts/helm/app/db.yaml +++ /dev/null @@ -1,31 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: db - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 9000 - -resources: - limits: - cpu: 256m - memory: 512Mi - requests: - cpu: 1m - memory: 1Mi - -env: - POSTGRES_STRING: postgres://postgres:asayerPostgres@postgresql.db.svc.cluster.local:5432 - # - CLICKHOUSE_STRING: tcp://clickhouse.db.svc.cluster.local:9000/default - REDIS_STRING: redis-master.db.svc.cluster.local:6379 - KAFKA_SERVERS: kafka.db.svc.cluster.local:9092 - KAFKA_USE_SSL: false - LICENSE_KEY: "" diff --git a/scripts/helm/app/docker_registry.sh b/scripts/helm/app/docker_registry.sh deleted file mode 100644 index 98e01eee2..000000000 --- a/scripts/helm/app/docker_registry.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -DOCKER_REGISTRY_SERVER=998611063711.dkr.ecr.eu-central-1.amazonaws.com -DOCKER_USER=AWS -AWS_REGION=eu-central-1 -DOCKER_PASSWORD=`aws ecr get-login-password --region eu-central-1` -kubectl delete -n app secret aws-registry -kubectl create secret -n app docker-registry aws-registry \ - --docker-server=$DOCKER_REGISTRY_SERVER \ - --docker-username=$DOCKER_USER \ - --docker-password=$DOCKER_PASSWORD \ - --docker-email=no@email.local diff --git a/scripts/helm/app/ender.yaml b/scripts/helm/app/ender.yaml deleted file mode 100644 index 9c88afa0f..000000000 --- a/scripts/helm/app/ender.yaml +++ /dev/null @@ -1,28 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: ender - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 9000 - -resources: - limits: - cpu: 256m - memory: 512Mi - requests: - cpu: 1m - memory: 1Mi - -env: - REDIS_STRING: redis-master.db.svc.cluster.local:6379 - KAFKA_SERVERS: kafka.db.svc.cluster.local:9092 - KAFKA_USE_SSL: false - LICENSE_KEY: "" diff --git a/scripts/helm/app/http.yaml b/scripts/helm/app/http.yaml deleted file mode 100644 index 7f2792018..000000000 --- a/scripts/helm/app/http.yaml +++ /dev/null @@ -1,37 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: http - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 80 - -resources: - limits: - cpu: 256m - memory: 512Mi - requests: - cpu: 1m - memory: 1Mi - -env: - ASSETS_ORIGIN: /sessions-assets # TODO: full path (with the minio prefix) - TOKEN_SECRET: secret_token_string # TODO: generate on buld - S3_BUCKET_IOS_IMAGES: sessions-mobile-assets - AWS_ACCESS_KEY_ID: "minios3AccessKeyS3cr3t" - AWS_SECRET_ACCESS_KEY: "m1n10s3CretK3yPassw0rd" - AWS_REGION: us-east-1 - POSTGRES_STRING: postgres://postgres:asayerPostgres@postgresql.db.svc.cluster.local:5432 - CACHE_ASSETS: true - # - REDIS_STRING: redis-master.db.svc.cluster.local:6379 - KAFKA_SERVERS: kafka.db.svc.cluster.local:9092 - KAFKA_USE_SSL: false - LICENSE_KEY: "" diff --git a/scripts/helm/app/install.sh b/scripts/helm/app/install.sh deleted file mode 100644 index 3ab12861c..000000000 --- a/scripts/helm/app/install.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -clear -cat << EOF -▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ -█░▄▄▀█░▄▄█░▄▄▀█░██░█░▄▄█░▄▄▀███░▄▄▀█▀▄▄▀█▀▄▄▀█░▄▄ -█░▀▀░█▄▄▀█░▀▀░█░▀▀░█░▄▄█░▀▀▄███░▀▀░█░▀▀░█░▀▀░█▄▄▀ -█░██░█▄▄▄█▄██▄█▀▀▀▄█▄▄▄█▄█▄▄███░██░█░████░████▄▄▄ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -EOF - -# Global vars -namespace=app -cwd=$PWD - -# Create namespaces -kubectl get ns app &> /dev/null || kubectl create ns app - -# Creating secrets -bash docker_registry.sh - -{ -# Installing all apps -echo $(date) >> helm.log -for app in $(ls *.yaml); do - application=$(echo $app | cut -d '.' -f1) - echo -e ${white}${bold}Installing ${application}${reset} - # helm uninstall -n ${namespace} ${application} - helm upgrade --install -n ${namespace} ${application} -f $app ./openreplay --create-namespace &>> ${cwd}/helm_apps.log - echo -e ${green}${bold}Done ✔${reset} -done -} || { - echo -e Application installation faled. Please check ${red}${cwd}/helm_apps.log${reset} for more details. -} - -# Setting kubernetes namespace -kubectl config set-context --current --namespace=$namespace diff --git a/scripts/helm/app/integrations.yaml b/scripts/helm/app/integrations.yaml deleted file mode 100644 index 0a8a2ee91..000000000 --- a/scripts/helm/app/integrations.yaml +++ /dev/null @@ -1,31 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: integrations - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 9000 - -resources: - limits: - cpu: 512m - memory: 1Gi - requests: - cpu: 1m - memory: 1Mi - -env: - POSTGRES_STRING: postgres://postgres:asayerPostgres@postgresql.db.svc.cluster.local:5432 - # - REDIS_STRING: redis-master.db.svc.cluster.local:6379 - KAFKA_SERVERS: kafka.db.svc.cluster.local:9092 - KAFKA_USE_SSL: false - TOKEN_SECRET: secret_token_string # TODO: generate on buld - LICENSE_KEY: "" diff --git a/scripts/helm/app/openreplay/.helmignore b/scripts/helm/app/openreplay/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/scripts/helm/app/openreplay/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/scripts/helm/app/openreplay/Chart.yaml b/scripts/helm/app/openreplay/Chart.yaml deleted file mode 100644 index cdccd307f..000000000 --- a/scripts/helm/app/openreplay/Chart.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v2 -name: openreplay -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 1.16.0 diff --git a/scripts/helm/app/openreplay/templates/deployment.yaml b/scripts/helm/app/openreplay/templates/deployment.yaml deleted file mode 100644 index e578b4bea..000000000 --- a/scripts/helm/app/openreplay/templates/deployment.yaml +++ /dev/null @@ -1,81 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "openreplay.fullname" . }} - namespace: {{ default .Values.namespace .Release.namespace }} - labels: - {{- include "openreplay.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "openreplay.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - openreplayRolloutID: {{ randAlphaNum 5 | quote }} # Restart nginx after every deployment - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "openreplay.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "openreplay.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ default .Chart.Name .Release.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}/{{ .Values.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - {{- range $key, $value := .Values.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- end }} - ports: - - name: http - containerPort: {{ .Values.service.port }} - protocol: TCP - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- if .Values.pvc }} - {{- if eq .Values.pvc.name "hostPath" }} - volumeMounts: - - mountPath: {{ .Values.pvc.mountPath }} - name: datadir - volumes: - - name: datadir - hostPath: - # Ensure the file directory is created. - path: {{ .Values.pvc.hostMountPath }} - type: DirectoryOrCreate - {{- else }} - volumeMounts: - - name: datadir - mountPath: {{ .Values.pvc.mountPath }} - volumes: - - name: {{ .Values.pvc.name }} - persistentVolumeClaim: - claimName: {{ .Values.pvc.volumeName }} - {{- end }} - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/scripts/helm/app/openreplay/templates/hpa.yaml b/scripts/helm/app/openreplay/templates/hpa.yaml deleted file mode 100644 index 240119d44..000000000 --- a/scripts/helm/app/openreplay/templates/hpa.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "openreplay.fullname" . }} - namespace: {{ default .Values.namespace .Release.namespace }} - labels: - {{- include "openreplay.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "openreplay.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/scripts/helm/app/openreplay/templates/ingress.yaml b/scripts/helm/app/openreplay/templates/ingress.yaml deleted file mode 100644 index 18ee9c1ee..000000000 --- a/scripts/helm/app/openreplay/templates/ingress.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "openreplay.fullname" . -}} -{{- $svcPort := .Values.service.port -}} -{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - namespace: {{ default .Values.namespace .Release.namespace }} - labels: - {{- include "openreplay.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ . }} - backend: - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} diff --git a/scripts/helm/app/openreplay/templates/pvc.yaml b/scripts/helm/app/openreplay/templates/pvc.yaml deleted file mode 100644 index fc02fa6c3..000000000 --- a/scripts/helm/app/openreplay/templates/pvc.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.pvc }} -{{- if and (.Values.pvc.create) (ne .Values.pvc.name "hostPath") }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ .Values.pvc.name }} - namespace: {{ default .Values.namespace .Release.namespace }} - labels: - {{- include "openreplay.labels" . | nindent 4 }} -spec: - storageClassName: {{ .Values.pvc.storageClassName }} - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.pvc.storageSize }} -{{- end}} -{{- end }} diff --git a/scripts/helm/app/openreplay/templates/service.yaml b/scripts/helm/app/openreplay/templates/service.yaml deleted file mode 100644 index e39eb5b7b..000000000 --- a/scripts/helm/app/openreplay/templates/service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "openreplay.fullname" . }} - namespace: {{ default .Values.namespace .Release.namespace }} - labels: - {{- include "openreplay.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "openreplay.selectorLabels" . | nindent 4 }} diff --git a/scripts/helm/app/openreplay/templates/serviceaccount.yaml b/scripts/helm/app/openreplay/templates/serviceaccount.yaml deleted file mode 100644 index 615b6b653..000000000 --- a/scripts/helm/app/openreplay/templates/serviceaccount.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "openreplay.serviceAccountName" . }} - namespace: {{ default .Values.namespace .Release.namespace }} - labels: - {{- include "openreplay.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/scripts/helm/app/openreplay/templates/tests/test-connection.yaml b/scripts/helm/app/openreplay/templates/tests/test-connection.yaml deleted file mode 100644 index 613af0b5a..000000000 --- a/scripts/helm/app/openreplay/templates/tests/test-connection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: "{{ include "openreplay.fullname" . }}-test-connection" - labels: - {{- include "openreplay.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test -spec: - containers: - - name: wget - image: busybox - command: ['wget'] - args: ['{{ include "openreplay.fullname" . }}:{{ .Values.service.port }}'] - restartPolicy: Never diff --git a/scripts/helm/app/sink.yaml b/scripts/helm/app/sink.yaml deleted file mode 100644 index 8d6239d3e..000000000 --- a/scripts/helm/app/sink.yaml +++ /dev/null @@ -1,37 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: sink - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 9000 - -resources: - limits: - cpu: 512m - memory: 512Mi - requests: - cpu: 1m - memory: 1Mi - -pvc: - create: true - name: hostPath - storageClassName: nfs - volumeName: nfs - mountPath: /mnt/efs - hostMountPath: /openreplay/storage/nfs - storageSize: 5Gi - -env: - REDIS_STRING: redis-master.db.svc.cluster.local:6379 - KAFKA_SERVERS: kafka.db.svc.cluster.local:9092 - KAFKA_USE_SSL: false - LICENSE_KEY: "" diff --git a/scripts/helm/app/storage.yaml b/scripts/helm/app/storage.yaml deleted file mode 100644 index ef839210e..000000000 --- a/scripts/helm/app/storage.yaml +++ /dev/null @@ -1,47 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: storage - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "latest" - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 9000 - -resources: - limits: - cpu: 512m - memory: 512Mi - requests: - cpu: 1m - memory: 1Mi - -pvc: - # PVC Created from filesink.yaml - create: false - name: hostPath - storageClassName: nfs - volumeName: nfs - mountPath: /mnt/efs - hostMountPath: /openreplay/storage/nfs - storageSize: 5Gi - -env: - AWS_ENDPOINT: http://minio.db.svc.cluster.local:9000 - AWS_ACCESS_KEY_ID: "minios3AccessKeyS3cr3t" - AWS_SECRET_ACCESS_KEY: "m1n10s3CretK3yPassw0rd" - AWS_REGION_WEB: us-east-1 - AWS_REGION_IOS: us-east-1 - S3_BUCKET_WEB: mobs - S3_BUCKET_IOS: mobs - # - REDIS_STRING: redis-master.db.svc.cluster.local:6379 - KAFKA_SERVERS: kafka.db.svc.cluster.local:9092 - KAFKA_USE_SSL: false - LICENSE_KEY: "" - FS_CLEAN_HRS: 24 diff --git a/scripts/helm/app/utilities.yaml b/scripts/helm/app/utilities.yaml deleted file mode 100644 index e229fae2c..000000000 --- a/scripts/helm/app/utilities.yaml +++ /dev/null @@ -1,28 +0,0 @@ -namespace: app -image: - repository: rg.fr-par.scw.cloud/foss - name: utilities - pullPolicy: IfNotPresent - tag: latest - -imagePullSecrets: - - name: aws-registry - -service: - type: ClusterIP - port: 9000 - -resources: - limits: - cpu: 1000m - memory: 1Gi - requests: - cpu: 1m - memory: 1Mi -env: - AWS_DEFAULT_REGION: us-east-1 - # Override with your https://domain_name - # eg: https://openreplay.mycompany.com - S3_HOST: 'http://minio.db.svc.cluster.local:9000' - S3_KEY: minios3AccessKeyS3cr3t - S3_SECRET: m1n10s3CretK3yPassw0rd \ No newline at end of file diff --git a/scripts/helm/build_deploy.sh b/scripts/helm/build_deploy.sh deleted file mode 100644 index 7a75fad8b..000000000 --- a/scripts/helm/build_deploy.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -set -e - -# This script will build and push docker image to registry - -# Usage: IMAGE_TAG=latest DOCKER_REPO=rg.fr-par.scw.cloud/foss bash build_deploy.sh - -echo $DOCKER_REPO -[[ -z DOCKER_REPO ]] && { - echo Set DOCKER_REPO="your docker registry" - exit 1 -} || { - docker login $DOCKER_REPO - cd ../../api - PUSH_IMAGE=1 bash build.sh $@ - cd ../backend - PUSH_IMAGE=1 bash build.sh $@ - cd ../utilities - PUSH_IMAGE=1 bash build.sh $@ - cd ../peers - PUSH_IMAGE=1 bash build.sh $@ -} diff --git a/scripts/helm/db/bucket_policy.sh b/scripts/helm/db/bucket_policy.sh deleted file mode 100644 index 65ea068e5..000000000 --- a/scripts/helm/db/bucket_policy.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -buckets=("mobs" "sessions-assets" "static" "sourcemaps" "sessions-mobile-assets") - -mc alias set minio http://localhost:9000 $1 $2 - -for bucket in ${buckets[*]}; do -mc mb minio/${bucket} -mc ilm import minio/${bucket} <<EOF -{ - "Rules": [ - { - "Expiration": { - "Days": 180 - }, - "ID": "${bucket}", - "Status": "Enabled" - } - ] -} -EOF -done - -# Creating frontend bucket -mc mb minio/frontend -mc policy set download minio/frontend -mc policy set download minio/sessions-assets -mc policy set download minio/static diff --git a/scripts/helm/db/install.sh b/scripts/helm/db/install.sh deleted file mode 100644 index 15ff75a3b..000000000 --- a/scripts/helm/db/install.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash - -cat <<EOF -▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ -█░▄▄▀█░▄▄█░▄▄▀█░██░█░▄▄█░▄▄▀████░▄▄▀██░▄▄▀█░▄▄ -█░▀▀░█▄▄▀█░▀▀░█░▀▀░█░▄▄█░▀▀▄████░██░██░▄▄▀█▄▄▀ -█░██░█▄▄▄█▄██▄█▀▀▀▄█▄▄▄█▄█▄▄████░▀▀░██░▀▀░█▄▄▄ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ -EOF - - -# Global vars -namespace=db -cwd=$PWD - -# Array of dbs -dbs=("clickhouse" "kafka" "minio" "nfs-server-provisioner" "postgresql" "redis" "sqs") - -echo in db $installation_type - -# Based on the above variable and `type` which is inherited from the main script, -# Installation resource usgage will change -# _cpu/_memory * installation_type = resource_limit -# -# Basic limits for db resource -postgres_cpu=256 -postgres_memory=512 -clickhouse_cpu=256 -clickhouse_memory=512 -redis_cpu=128 -redis_memory=512 -kafka_cpu=256 -kafka_memory=512 -minio_cpu=256 -minio_memory=512 -nfs-server-provisioner_cpu=256 -nfs-server-provisioner_memory=512 -sqs_cpu=256 -sqs_memory=512 - -# Installing all dbs -echo $(date) >> helm.log -for db in ${dbs[*]}; do - { - echo -e ${green}${bold}Installing $db${reset} - helm upgrade --install -n db $db ./$db --wait --create-namespace &>> helm.log - echo -e ${green}${bold}Done ✔${reset} - } || { - echo -e execution failed. Please check ${yello}$cwd/helm.log${reset} for more details. - exit 1 - } -done - -# Setting kubernetes namespace -kubectl config set-context --current --namespace=$namespace - -# Initializing dbs - -### Create topics: -echo -e ${green}${bold}Restoring kafka topics${reset} -kubectl exec kafka-0 -- /bin/bash -c "KAFKA_HEAP_OPTS=\"-Xms512m -Xmx1g\" /opt/bitnami/kafka/bin/kafka-topics.sh --create --zookeeper kafka-zookeeper.${namespace}.svc.cluster.local:2181 --replication-factor 2 --partitions 16 --topic messages || true" -kubectl exec kafka-0 -- /bin/bash -c "KAFKA_HEAP_OPTS=\"-Xms512m -Xmx1g\" /opt/bitnami/kafka/bin/kafka-topics.sh --create --zookeeper kafka-zookeeper.${namespace}.svc.cluster.local:2181 --replication-factor 2 --partitions 16 --topic events || true" -kubectl exec kafka-0 -- /bin/bash -c "KAFKA_HEAP_OPTS=\"-Xms512m -Xmx1g\" /opt/bitnami/kafka/bin/kafka-topics.sh --create --zookeeper kafka-zookeeper.${namespace}.svc.cluster.local:2181 --replication-factor 2 --partitions 16 --topic raw || true" -kubectl exec kafka-0 -- /bin/bash -c "KAFKA_HEAP_OPTS=\"-Xms512m -Xmx1g\" /opt/bitnami/kafka/bin/kafka-topics.sh --create --zookeeper kafka-zookeeper.${namespace}.svc.cluster.local:2181 --replication-factor 2 --partitions 16 --topic trigger || true" -### Set retention time: -kubectl exec kafka-0 -- /bin/bash -c "KAFKA_HEAP_OPTS=\"-Xms512m -Xmx1g\" /opt/bitnami/kafka/bin/kafka-configs.sh --zookeeper kafka-zookeeper.${namespace}.svc.cluster.local:2181 --entity-type topics --alter --add-config retention.ms=345600000 --entity-name messages" -kubectl exec kafka-0 -- /bin/bash -c "KAFKA_HEAP_OPTS=\"-Xms512m -Xmx1g\" /opt/bitnami/kafka/bin/kafka-configs.sh --zookeeper kafka-zookeeper.${namespace}.svc.cluster.local:2181 --entity-type topics --alter --add-config retention.ms=3456000000 --entity-name events" -kubectl exec kafka-0 -- /bin/bash -c "KAFKA_HEAP_OPTS=\"-Xms512m -Xmx1g\" /opt/bitnami/kafka/bin/kafka-configs.sh --zookeeper kafka-zookeeper.${namespace}.svc.cluster.local:2181 --entity-type topics --alter --add-config retention.ms=3456000000 --entity-name raw" -kubectl exec kafka-0 -- /bin/bash -c "KAFKA_HEAP_OPTS=\"-Xms512m -Xmx1g\" /opt/bitnami/kafka/bin/kafka-configs.sh --zookeeper kafka-zookeeper.${namespace}.svc.cluster.local:2181 --entity-type topics --alter --add-config retention.ms=3456000000 --entity-name trigger" -echo -e ${green}${bold}Done ✔${reset} - -## Postgresql - - -cd init_dbs/postgresql -echo -e ${green}${bold}Restoring postgresql data${reset} -{ -for file in $(ls *.sql); do - echo -e ${green}${bold}Restoring $file ${reset} - kubectl exec postgresql-postgresql-0 -- /bin/bash -c "rm -rf /tmp/$file" - kubectl cp $file postgresql-postgresql-0:/tmp/ - kubectl exec postgresql-postgresql-0 -- /bin/bash -c "PGPASSWORD=asayerPostgres psql -U postgres -f /tmp/$file" &> $cwd/postgresql_init.log - echo -e ${green}${bold}Done ✔${reset} -done -cd $cwd -} || { - echo -e Postgres db init failed. Please check ${red}$cwd/postgresql_init.log${reset} for more details. - exit 1 -} - -## clickhouse -cd init_dbs/clickhouse/create/ -echo -e ${green}${bold}Restoring clickhouse data${reset} -for file in $(ls *.sql); do -{ - echo -e ${green}${bold}Restoring $file ${reset} - kubectl exec clickhouse-0 -- /bin/bash -c "rm -rf /tmp/$file" - kubectl cp $file clickhouse-0:/tmp/ - kubectl exec clickhouse-0 -- /bin/bash -c "clickhouse-client < /tmp/$file" 2>&1 | tee -a $cwd/clickhouse_init.log - echo -e ${green}${bold}Done ✔${reset} -} || { - echo -e Clickhouse db init failed. Please check ${red}$cwd/clickhouse_init.log${reset} for more details. - exit 1 -} -done -cd $cwd - - -## Minio -MINIO_ACCESS_KEY=$(kubectl get secret --namespace $namespace minio -o jsonpath="{.data.access-key}" | base64 --decode) -MINIO_SECRET_KEY=$(kubectl get secret --namespace $namespace minio -o jsonpath="{.data.secret-key}" | base64 --decode) -# Set bucket retention for minio -minio_pod=$(kubectl get po -n db -l app.kubernetes.io/name=minio -n db --output custom-columns=name:.metadata.name | tail -n+2) - -kubectl cp -n db bucket_policy.sh $minio_pod:/tmp/bucket_policy.sh -kubectl exec -n db $minio_pod -- sh /tmp/bucket_policy.sh $MINIO_ACCESS_KEY $MINIO_SECRET_KEY - -echo $MINIO_ACCESS_KEY -echo $MINIO_SECRET_KEY diff --git a/scripts/helm/db/minio/.helmignore b/scripts/helm/db/minio/.helmignore deleted file mode 100755 index f0c131944..000000000 --- a/scripts/helm/db/minio/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/scripts/helm/db/minio/Chart.yaml b/scripts/helm/db/minio/Chart.yaml deleted file mode 100755 index 395e3ac91..000000000 --- a/scripts/helm/db/minio/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -annotations: - category: Infrastructure -apiVersion: v1 -appVersion: 2020.10.9 -description: MinIO is an object storage server, compatible with Amazon S3 cloud storage - service, mainly used for storing unstructured data (such as photos, videos, log - files, etc.) -engine: gotpl -home: https://github.com/bitnami/charts/tree/master/bitnami/minio -icon: https://bitnami.com/assets/stacks/minio/img/minio-stack-220x234.png -keywords: -- minio -- storage -- object-storage -- s3 -- cluster -maintainers: -- email: containers@bitnami.com - name: Bitnami -name: minio -sources: -- https://github.com/bitnami/bitnami-docker-minio -- https://min.io -version: 3.7.14 diff --git a/scripts/helm/db/minio/README.md b/scripts/helm/db/minio/README.md deleted file mode 100755 index 4a4c45c65..000000000 --- a/scripts/helm/db/minio/README.md +++ /dev/null @@ -1,259 +0,0 @@ -# MinIO - -[MinIO](https://min.io) is an object storage server, compatible with Amazon S3 cloud storage service, mainly used for storing unstructured data (such as photos, videos, log files, etc.) - -## TL;DR - -```console -$ helm repo add bitnami https://charts.bitnami.com/bitnami -$ helm install my-release bitnami/minio -``` - -## Introduction - -This chart bootstraps a [MinIO](https://github.com/bitnami/bitnami-docker-minio) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 2.12+ or Helm 3.0-beta3+ -- PV provisioner support in the underlying infrastructure -- ReadWriteMany volumes for deployment scaling - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -$ helm repo add bitnami https://charts.bitnami.com/bitnami -$ helm install my-release bitnami/minio -``` - -These commands deploy MinIO on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```console -$ helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Parameters - -The following table lists the configurable parameters of the MinIO chart and their default values. - -| Parameter | Description | Default | -|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------| -| `global.imageRegistry` | Global Docker image registry | `nil` | -| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | -| `global.minio.existingSecret` | Name of existing secret to use for MinIO credentials (overrides `existingSecret`) | `nil` | -| `global.minio.accessKey` | MinIO Access Key (overrides `accessKey.password`) | `nil` | -| `global.minio.secretKey` | MinIO Secret Key (overrides `secretKey.password`) | `nil` | -| `image.registry` | MinIO image registry | `docker.io` | -| `image.repository` | MinIO image name | `bitnami/minio` | -| `image.tag` | MinIO image tag | `{TAG_NAME}` | -| `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `image.debug` | Specify if debug logs should be enabled | `false` | -| `nameOverride` | String to partially override minio.fullname template with a string (will prepend the release name) | `nil` | -| `fullnameOverride` | String to fully override minio.fullname template with a string | `nil` | -| `schedulerName` | Specifies the schedulerName, if it's nil uses kube-scheduler | `nil` | -| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` | -| `serviceAccount.name` | If serviceAccount.create is enabled, what should the serviceAccount name be - otherwise defaults to the fullname | `nil` | -| `clusterDomain` | Kubernetes cluster domain | `cluster.local` | -| `clientImage.registry` | MinIO Client image registry | `docker.io` | -| `clientImage.repository` | MinIO Client image name | `bitnami/minio-client` | -| `clientImage.tag` | MinIO Client image tag | `{TAG_NAME}` | -| `volumePermissions.enabled` | Enable init container that changes volume permissions in the data directory (for cases where the default k8s `runAsUser` and `fsUser` values do not work) | `false` | -| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | -| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/minideb` | -| `volumePermissions.image.tag` | Init container volume-permissions image tag | `buster` | -| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | -| `volumePermissions.resources` | Init container resource requests/limit | `nil` | -| `mode` | MinIO server mode (`standalone` or `distributed`) | `standalone` | -| `statefulset.replicaCount` | Number of pods (only for Minio distributed mode). Should be 4 <= x <= 32 | `4` | -| `statefulset.updateStrategy` | Statefulset update strategy policy | `RollingUpdate` | -| `statefulset.podManagementpolicy` | Statefulset pods management policy | `Parallel` | -| `deployment.updateStrategy` | Deployment update strategy policy | `Recreate` | -| `existingSecret` | Existing secret with MinIO credentials | `nil` | -| `useCredentialsFile` | Have the secret mounted as a file instead of env vars | `false` | -| `forceNewKeys` | Force admin credentials (access and secret key) to be reconfigured every time they change in the secrets | `false` | -| `accessKey.password` | MinIO Access Key. Ignored if existing secret is provided. | _random 10 character alphanumeric string_ | -| `accessKey.forcePassword` | Force users to specify an Access Key | `false` | -| `secretKey.password` | MinIO Secret Key. Ignored if existing secret is provided. | _random 40 character alphanumeric string_ | -| `secretKey.forcePassword` | Force users to specify an Secret Key | `false` | -| `defaultBuckets` | Comma, semi-colon or space separated list of buckets to create (only in standalone mode) | `nil` | -| `disableWebUI` | Disable MinIO Web UI | `false` | -| `extraEnv` | Any extra environment variables you would like to pass to the pods | `{}` | -| `command` | Command for the minio container | `{}` | -| `resources` | Minio containers' resources | `{}` | -| `podAnnotations` | Pod annotations | `{}` | -| `affinity` | Map of node/pod affinities | `{}` (The value is evaluated as a template) | -| `nodeSelector` | Node labels for pod assignment | `{}` (The value is evaluated as a template) | -| `tolerations` | Tolerations for pod assignment | `[]` (The value is evaluated as a template) | -| `securityContext.enabled` | Enable security context | `true` | -| `securityContext.fsGroup` | Group ID for the container | `1001` | -| `securityContext.runAsUser` | User ID for the container | `1001` | -| `livenessProbe.enabled` | Enable/disable the Liveness probe | `true` | -| `livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | `60` | -| `livenessProbe.periodSeconds` | How often to perform the probe | `10` | -| `livenessProbe.timeoutSeconds` | When the probe times out | `5` | -| `livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed. | `1` | -| `livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | `6` | -| `readinessProbe.enabled` | Enable/disable the Readiness probe | `true` | -| `readinessProbe.initialDelaySeconds` | Delay before readiness probe is initiated | `5` | -| `readinessProbe.periodSeconds` | How often to perform the probe | `10` | -| `readinessProbe.timeoutSeconds` | When the probe times out | `5` | -| `readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | `6` | -| `readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed. | `1` | -| `persistence.enabled` | Use a PVC to persist data | `true` | -| `persistence.mountPath` | Path to mount the volume at | `/data` | -| `persistence.storageClass` | Storage class of backing PVC | `nil` (uses alpha storage class annotation) | -| `persistence.accessMode` | Use volume as ReadOnly or ReadWrite | `ReadWriteOnce` | -| `persistence.size` | Size of data volume | `8Gi` | -| `persistence.annotations` | Persistent Volume annotations | `{}` | -| `persistence.existingClaim` | Name of an existing PVC to use (only in "standalone" mode) | `nil` | -| `service.type` | Kubernetes Service type | `ClusterIP` | -| `service.port` | MinIO service port | `9000` | -| `service.nodePort` | Port to bind to for NodePort service type | `nil` | -| `service.loadBalancerIP` | Static IP Address to use for LoadBalancer service type | `nil` | -| `service.annotations` | Kubernetes service annotations | `{}` | -| `ingress.enabled` | Enable/disable ingress | `false` | -| `ingress.certManager` | Add annotations for cert-manager | `false` | -| `ingress.annotations` | Ingress annotations | `[]` | -| `ingress.labels` | Ingress additional labels | `{}` | -| `ingress.hosts[0].name` | Hostname to your MinIO installation | `minio.local` | -| `ingress.hosts[0].path` | Path within the url structure | `/` | -| `ingress.hosts[0].tls` | Utilize TLS backend in ingress | `false` | -| `ingress.hosts[0].tlsHosts` | Array of TLS hosts for ingress record (defaults to `ingress.hosts[0].name` if `nil`) | `nil` | -| `ingress.hosts[0].tlsSecret` | TLS Secret (certificates) | `minio.local-tls` | -| `ingress.secrets[0].name` | TLS Secret Name | `nil` | -| `ingress.secrets[0].certificate` | TLS Secret Certificate | `nil` | -| `ingress.secrets[0].key` | TLS Secret Key | `nil` | -| `networkPolicy.enabled` | Enable NetworkPolicy | `false` | -| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | -| `prometheusAuthType` | Authentication mode for Prometheus (`jwt` or `public`) | `public` | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, - -```console -$ helm install my-release \ - --set accessKey.password=minio-access-key \ - --set secretKey.password=minio-secret-key \ - bitnami/minio -``` - -The above command sets the MinIO Server access key and secret key to `minio-access-key` and `minio-secret-key`, respectively. - -Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, - -```console -$ helm install my-release -f values.yaml bitnami/minio -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -## Configuration and installation details - -### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) - -It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. - -Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. - -### Production configuration - -This chart includes a `values-production.yaml` file where you can find some parameters oriented to production configuration in comparison to the regular `values.yaml`. You can use this file instead of the default one. - -- MinIO server mode: -```diff -- mode: standalone -+ mode: distributed -``` - -- Disable MinIO Web UI: -```diff -- disableWebUI: false -+ disableWebUI: true -``` - -- Annotations to be added to pods: -```diff -- podAnnotations: {} -+ podAnnotations: -+ prometheus.io/scrape: "true" -+ prometheus.io/path: "/minio/prometheus/metrics" -+ prometheus.io/port: "9000" -``` - -- Pod resources: -```diff -- resources: {} -+ resources: -+ requests: -+ memory: 256Mi -+ cpu: 250m -``` - -- Enable NetworkPolicy: -```diff -- networkPolicy.enabled: false -+ networkPolicy.enabled: true -``` - -- Don't require client label for connections: -```diff -- networkPolicy.allowExternal: true -+ networkPolicy.allowExternal: false -``` - -- Change Prometheus authentication: -```diff -- prometheusAuthType: public -+ prometheusAuthType: jwt -``` - -### Distributed mode - -You can start the MinIO chart in distributed mode with the following parameter: `mode=distributed` - -This chart sets Minio server in distributed mode with 4 nodes by default. You can change the number of nodes setting the `statefulset.replicaCount` parameter, for example to `statefulset.replicaCount=8` - -> Note: that the number of replicas must even, greater than 4 and lower than 32 - -### Prometheus exporter - -MinIO exports Prometheus metrics at `/minio/prometheus/metrics`. To allow Prometheus collecting your MinIO metrics, modify the `values.yaml` adding the corresponding annotations: - -```diff -- podAnnotations: {} -+ podAnnotations: -+ prometheus.io/scrape: "true" -+ prometheus.io/path: "/minio/prometheus/metrics" -+ prometheus.io/port: "9000" -``` - -> Find more information about MinIO metrics at https://docs.min.io/docs/how-to-monitor-minio-using-prometheus.html - -## Persistence - -The [Bitnami MinIO](https://github.com/bitnami/bitnami-docker-minio) image stores data at the `/data` path of the container. - -The chart mounts a [Persistent Volume](http://kubernetes.io/docs/user-guide/persistent-volumes/) at this location. The volume is created using dynamic volume provisioning. - -### Adjust permissions of persistent volume mountpoint - -As the image run as non-root by default, it is necessary to adjust the ownership of the persistent volume so that the container can write data into it. - -By default, the chart is configured to use Kubernetes Security Context to automatically change the ownership of the volume. However, this feature does not work in all Kubernetes distributions. -As an alternative, this chart supports using an initContainer to change the ownership of the volume before mounting it in the final destination. - -You can enable this initContainer by setting `volumePermissions.enabled` to `true`. diff --git a/scripts/helm/db/minio/ci/values-production.yaml b/scripts/helm/db/minio/ci/values-production.yaml deleted file mode 100755 index d5e966334..000000000 --- a/scripts/helm/db/minio/ci/values-production.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# Test values file for generating all of the yaml and check that -# the rendering is correct - -volumePermissions: - enabled: true - -mode: distributed - -useCredentialsFile: true - -disableWebUI: false - -podAnnotations: - prometheus.io/scrape: "true" - prometheus.io/path: "/minio/prometheus/metric" - prometheus.io/port: "9000" - -resources: - requests: - cpu: 250m - memory: 256Mi - -ingress: - enabled: true - -networkPolicy: - enabled: true diff --git a/scripts/helm/db/minio/templates/NOTES.txt b/scripts/helm/db/minio/templates/NOTES.txt deleted file mode 100755 index e7492fbe7..000000000 --- a/scripts/helm/db/minio/templates/NOTES.txt +++ /dev/null @@ -1,71 +0,0 @@ -** Please be patient while the chart is being deployed ** - -MinIO can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: - - {{ include "minio.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} - -To get your credentials run: - - export MINIO_ACCESS_KEY=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "minio.fullname" . }} -o jsonpath="{.data.access-key}" | base64 --decode) - export MINIO_SECRET_KEY=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ include "minio.fullname" . }} -o jsonpath="{.data.secret-key}" | base64 --decode) - -To connect to your MinIO server using a client: - -- Run a MinIO Client pod and append the desired command (e.g. 'admin info server'): - - kubectl run --namespace {{ .Release.Namespace }} {{ include "minio.fullname" . }}-client \ - --rm --tty -i --restart='Never' \ - --env MINIO_SERVER_ACCESS_KEY=$MINIO_ACCESS_KEY \ - --env MINIO_SERVER_SECRET_KEY=$MINIO_SECRET_KEY \ - --env MINIO_SERVER_HOST={{ include "minio.fullname" . }} \ - {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} - --labels="{{ template "minio.name" . }}-client=true" \ - {{- end }} - --image {{ template "minio.clientImage" . }} -- admin info server minio - -{{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} - - NOTE: Since NetworkPolicy is enabled, only pods with label - "{{ template "minio.fullname" . }}-client=true" will be able to connect to MinIO. -{{- end }} -{{- if not .Values.disableWebUI }} - -To access the MinIO web UI: - -- Get the MinIO URL: - -{{- if .Values.ingress.enabled }} - - You should be able to access your new MinIO web UI through - - {{- range .Values.ingress.hosts }} - {{ if .tls }}https{{ else }}http{{ end }}://{{ .name }}/minio/ - {{- end }} -{{- else if contains "LoadBalancer" .Values.service.type }} - - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ include "minio.fullname" . }}' - - {{- $port:=.Values.service.port | toString }} - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "minio.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo "MinIO web URL: http://$SERVICE_IP{{- if ne $port "80" }}:{{ .Values.service.port }}{{ end }}/minio" - -{{- else if contains "ClusterIP" .Values.service.type }} - - echo "MinIO web URL: http://127.0.0.1:9000/minio" - kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "minio.fullname" . }} 9000:{{ .Values.service.port }} - -{{- else if contains "NodePort" .Values.service.type }} - - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "minio.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo "MinIO web URL: http://$NODE_IP:$NODE_PORT/minio" - -{{- end }} -{{- else }} - - WARN: MinIO Web UI is disabled. -{{- end }} - -{{ include "minio.validateValues" . }} -{{ include "minio.checkRollingTags" . }} diff --git a/scripts/helm/db/minio/templates/_helpers.tpl b/scripts/helm/db/minio/templates/_helpers.tpl deleted file mode 100755 index dd67e53e6..000000000 --- a/scripts/helm/db/minio/templates/_helpers.tpl +++ /dev/null @@ -1,265 +0,0 @@ -{{/* vim: set filetype=mustache: */}} - -{{/* -Expand the name of the chart. -*/}} -{{- define "minio.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "minio.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "minio.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "minio.labels" -}} -app.kubernetes.io/name: {{ include "minio.name" . }} -helm.sh/chart: {{ include "minio.chart" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector -*/}} -{{- define "minio.matchLabels" -}} -app.kubernetes.io/name: {{ include "minio.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Return the proper MinIO image name -*/}} -{{- define "minio.image" -}} -{{- $registryName := coalesce .Values.global.imageRegistry .Values.image.registry -}} -{{- $repositoryName := .Values.image.repository -}} -{{- $tag := .Values.image.tag | toString -}} -{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} - -{{/* -Return the proper MinIO Client image name -*/}} -{{- define "minio.clientImage" -}} -{{- $registryName := coalesce .Values.global.imageRegistry .Values.clientImage.registry -}} -{{- $repositoryName := .Values.clientImage.repository -}} -{{- $tag := .Values.clientImage.tag | toString -}} -{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names -*/}} -{{- define "minio.imagePullSecrets" -}} -{{- $imagePullSecrets := coalesce .Values.global.imagePullSecrets .Values.image.pullSecrets .Values.volumePermissions.image.pullSecrets -}} -{{- if $imagePullSecrets }} -imagePullSecrets: -{{- range $imagePullSecrets }} - - name: {{ . }} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Return MinIO accessKey -*/}} -{{- define "minio.accessKey" -}} -{{- $accessKey := coalesce .Values.global.minio.accessKey .Values.accessKey.password -}} -{{- if $accessKey }} - {{- $accessKey -}} -{{- else if (not .Values.accessKey.forcePassword) }} - {{- randAlphaNum 10 -}} -{{- else -}} - {{ required "An Access Key is required!" .Values.accessKey.password }} -{{- end -}} -{{- end -}} - -{{/* -Return MinIO secretKey -*/}} -{{- define "minio.secretKey" -}} -{{- $secretKey := coalesce .Values.global.minio.secretKey .Values.secretKey.password -}} -{{- if $secretKey }} - {{- $secretKey -}} -{{- else if (not .Values.secretKey.forcePassword) }} - {{- randAlphaNum 40 -}} -{{- else -}} - {{ required "A Secret Key is required!" .Values.secretKey.password }} -{{- end -}} -{{- end -}} - -{{/* -Get the credentials secret. -*/}} -{{- define "minio.secretName" -}} -{{- if .Values.global.minio.existingSecret }} - {{- printf "%s" .Values.global.minio.existingSecret -}} -{{- else if .Values.existingSecret -}} - {{- printf "%s" .Values.existingSecret -}} -{{- else -}} - {{- printf "%s" (include "minio.fullname" .) -}} -{{- end -}} -{{- end -}} - -{{/* -Return true if a secret object should be created -*/}} -{{- define "minio.createSecret" -}} -{{- if .Values.global.minio.existingSecret }} -{{- else if .Values.existingSecret -}} -{{- else -}} - {{- true -}} -{{- end -}} -{{- end -}} - -{{/* -Compile all warnings into a single message, and call fail. -*/}} -{{- define "minio.validateValues" -}} -{{- $messages := list -}} -{{- $messages := append $messages (include "minio.validateValues.mode" .) -}} -{{- $messages := append $messages (include "minio.validateValues.replicaCount" .) -}} -{{- $messages := without $messages "" -}} -{{- $message := join "\n" $messages -}} - -{{- if $message -}} -{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} -{{- end -}} -{{- end -}} - -{{/* Validate values of MinIO - must provide a valid mode ("distributed" or "standalone") */}} -{{- define "minio.validateValues.mode" -}} -{{- if and (ne .Values.mode "distributed") (ne .Values.mode "standalone") -}} -minio: mode - Invalid mode selected. Valid values are "distributed" and - "standalone". Please set a valid mode (--set mode="xxxx") -{{- end -}} -{{- end -}} - -{{/* Validate values of MinIO - number of replicas must be even, greater than 4 and lower than 32 */}} -{{- define "minio.validateValues.replicaCount" -}} -{{- $replicaCount := int .Values.statefulset.replicaCount }} -{{- if and (eq .Values.mode "distributed") (or (eq (mod $replicaCount 2) 1) (lt $replicaCount 4) (gt $replicaCount 32)) -}} -minio: replicaCount - Number of replicas must be even, greater than 4 and lower than 32!! - Please set a valid number of replicas (--set statefulset.replicaCount=X) -{{- end -}} -{{- end -}} - -{{/* Check if there are rolling tags in the images */}} -{{- define "minio.checkRollingTags" -}} -{{- if and (contains "bitnami/" .Values.image.repository) (not (.Values.image.tag | toString | regexFind "-r\\d+$|sha256:")) }} -WARNING: Rolling tag detected ({{ .Values.image.repository }}:{{ .Values.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. -+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ -{{- end }} -{{- if and (contains "bitnami/" .Values.clientImage.repository) (not (.Values.clientImage.tag | toString | regexFind "-r\\d+$|sha256:")) }} -WARNING: Rolling tag detected ({{ .Values.clientImage.repository }}:{{ .Values.clientImage.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. -+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ -{{- end }} -{{- end -}} - -{{/* -Return the proper image name (for the init container volume-permissions image) -*/}} -{{- define "minio.volumePermissions.image" -}} -{{- $registryName := .Values.volumePermissions.image.registry -}} -{{- $repositoryName := .Values.volumePermissions.image.repository -}} -{{- $tag := .Values.volumePermissions.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Storage Class -*/}} -{{- define "minio.storageClass" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -*/}} -{{- if .Values.global -}} - {{- if .Values.global.storageClass -}} - {{- if (eq "-" .Values.global.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.global.storageClass -}} - {{- end -}} - {{- else -}} - {{- if .Values.persistence.storageClass -}} - {{- if (eq "-" .Values.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} - {{- end -}} - {{- end -}} - {{- end -}} -{{- else -}} - {{- if .Values.persistence.storageClass -}} - {{- if (eq "-" .Values.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} - {{- end -}} - {{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Renders a value that contains template. -Usage: -{{ include "minio.tplValue" ( dict "value" .Values.path.to.the.Value "context" $) }} -*/}} -{{- define "minio.tplValue" -}} - {{- if typeIs "string" .value }} - {{- tpl .value .context }} - {{- else }} - {{- tpl (.value | toYaml) .context }} - {{- end }} -{{- end -}} - -{{/* -Returns the proper service account name depending if an explicit service account name is set -in the values file. If the name is not set it will default to either minio.fullname if serviceAccount.create -is true or default otherwise. -*/}} -{{- define "minio.serviceAccountName" -}} - {{- if .Values.serviceAccount.create -}} - {{ default (include "minio.fullname" .) .Values.serviceAccount.name }} - {{- else -}} - {{ default "default" .Values.serviceAccount.name }} - {{- end -}} -{{- end -}} \ No newline at end of file diff --git a/scripts/helm/db/minio/templates/deployment-standalone.yaml b/scripts/helm/db/minio/templates/deployment-standalone.yaml deleted file mode 100755 index 23a7232a8..000000000 --- a/scripts/helm/db/minio/templates/deployment-standalone.yaml +++ /dev/null @@ -1,160 +0,0 @@ -{{- if eq .Values.mode "standalone" }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "minio.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} -spec: - {{- if .Values.deployment.updateStrategy }} - strategy: {{ toYaml .Values.deployment.updateStrategy | nindent 4 }} - {{- end }} - selector: - matchLabels: {{- include "minio.matchLabels" . | nindent 6 }} - template: - metadata: - labels: {{- include "minio.labels" . | nindent 8 }} - {{- if or .Values.podAnnotations (include "minio.createSecret" .) }} - annotations: - {{- if (include "minio.createSecret" .) }} - checksum/credentials-secret: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} - {{- end }} - {{- if .Values.podAnnotations }} - {{- include "minio.tplValue" ( dict "value" .Values.podAnnotations "context" $) | nindent 8 }} - {{- end }} - {{- end }} - spec: - {{- if .Values.schedulerName }} - schedulerName: {{ .Values.schedulerName }} - {{- end }} - serviceAccountName: {{ template "minio.serviceAccountName" . }} -{{- include "minio.imagePullSecrets" . | nindent 6 }} - {{- if .Values.affinity }} - affinity: {{- include "minio.tplValue" (dict "value" .Values.affinity "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: {{- include "minio.tplValue" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.tolerations }} - tolerations: {{- include "minio.tplValue" (dict "value" .Values.tolerations "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.securityContext.enabled }} - securityContext: - fsGroup: {{ .Values.securityContext.fsGroup }} - {{- end }} - {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} - initContainers: - - name: volume-permissions - image: {{ template "minio.volumePermissions.image" . }} - imagePullPolicy: {{ default "" .Values.volumePermissions.image.pullPolicy | quote }} - command: - - /bin/bash - - -ec - - | - chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.persistence.mountPath }} - securityContext: - runAsUser: 0 - {{- if .Values.volumePermissions.resources }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: data - mountPath: {{ .Values.persistence.mountPath }} - {{- end }} - containers: - - name: minio - image: {{ include "minio.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - {{- if .Values.securityContext.enabled }} - securityContext: - runAsUser: {{ .Values.securityContext.runAsUser }} - {{- end }} - env: - - name: BITNAMI_DEBUG - value: {{ ternary "true" "false" .Values.image.debug | quote }} - - name: MINIO_FORCE_NEW_KEYS - value: {{ ternary "yes" "no" .Values.forceNewKeys | quote }} - {{- if .Values.useCredentialsFile }} - - name: MINIO_ACCESS_KEY_FILE - value: "/opt/bitnami/minio/secrets/access-key" - {{- else }} - - name: MINIO_ACCESS_KEY - valueFrom: - secretKeyRef: - name: {{ include "minio.secretName" . }} - key: access-key - {{- end }} - {{- if .Values.useCredentialsFile }} - - name: MINIO_SECRET_KEY_FILE - value: "/opt/bitnami/minio/secrets/secret-key" - {{- else }} - - name: MINIO_SECRET_KEY - valueFrom: - secretKeyRef: - name: {{ include "minio.secretName" . }} - key: secret-key - {{- end }} - {{- if .Values.defaultBuckets }} - - name: MINIO_DEFAULT_BUCKETS - value: {{ .Values.defaultBuckets }} - {{- end }} - - name: MINIO_BROWSER - value: {{ ternary "off" "on" .Values.disableWebUI | quote }} - {{- if .Values.prometheusAuthType }} - - name: MINIO_PROMETHEUS_AUTH_TYPE - value: {{ .Values.prometheusAuthType }} - {{- end }} - {{- if .Values.extraEnv }} - {{- toYaml .Values.extraEnv | nindent 12 }} - {{- end }} - {{ if .Values.command }} - command: {{- toYaml .Values.command | nindent 12 }} - {{- end }} - ports: - - name: minio - containerPort: 9000 - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - httpGet: - path: /minio/health/live - port: minio - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - tcpSocket: - port: minio - {{- end }} - {{- if .Values.resources }} - resources: {{ toYaml .Values.resources | nindent 12 }} - {{- end }} - volumeMounts: - {{- if .Values.useCredentialsFile }} - - name: minio-credentials - mountPath: /opt/bitnami/minio/secrets/ - {{- end }} - - name: "data" - mountPath: {{ .Values.persistence.mountPath }} - volumes: - {{- if .Values.useCredentialsFile }} - - name: minio-credentials - secret: - secretName: {{ include "minio.secretName" . }} - {{- end }} - - name: data - {{- if .Values.persistence.enabled }} - persistentVolumeClaim: - claimName: {{ if .Values.persistence.existingClaim }}{{ .Values.persistence.existingClaim }}{{- else }}{{ include "minio.fullname" . }}{{- end }} - {{- else }} - emptyDir: {} - {{- end }} - {{- end }} diff --git a/scripts/helm/db/minio/templates/ingress.yaml b/scripts/helm/db/minio/templates/ingress.yaml deleted file mode 100755 index 486feb5ac..000000000 --- a/scripts/helm/db/minio/templates/ingress.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if and .Values.ingress.enabled (not .Values.disableWebUI ) -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ include "minio.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} -{{- range $key, $value := .Values.ingress.labels }} - {{ $key }}: {{ $value }} -{{- end }} - annotations: - {{- if .Values.ingress.certManager }} - kubernetes.io/tls-acme: "true" - {{- end }} - {{- range $key, $value := .Values.ingress.annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .name }} - http: - paths: - - path: {{ default "/" .path }} - backend: - serviceName: {{ include "minio.fullname" $ }} - servicePort: minio - {{- end }} - tls: - {{- range .Values.ingress.hosts }} - {{- if .tls }} - - hosts: - {{- if .tlsHosts }} - {{- range $host := .tlsHosts }} - - {{ $host }} - {{- end }} - {{- else }} - - {{ .name }} - {{- end }} - secretName: {{ .tlsSecret }} - {{- end }} - {{- end }} -{{- end }} diff --git a/scripts/helm/db/minio/templates/networkpolicy.yaml b/scripts/helm/db/minio/templates/networkpolicy.yaml deleted file mode 100755 index cffc5be13..000000000 --- a/scripts/helm/db/minio/templates/networkpolicy.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -kind: NetworkPolicy -apiVersion: networking.k8s.io/v1 -metadata: - name: {{ include "minio.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: - app.kubernetes.io/name: {{ include "minio.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - ingress: - # Allow inbound connections - - ports: - - port: 9000 - {{- if not .Values.networkPolicy.allowExternal }} - from: - - podSelector: - matchLabels: - {{ include "minio.fullname" . }}-client: "true" - {{- end }} -{{- end }} diff --git a/scripts/helm/db/minio/templates/pvc-standalone.yaml b/scripts/helm/db/minio/templates/pvc-standalone.yaml deleted file mode 100755 index 8e4be7da4..000000000 --- a/scripts/helm/db/minio/templates/pvc-standalone.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.mode "standalone") }} -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: {{ include "minio.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} -spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{ include "minio.storageClass" . }} -{{- end }} diff --git a/scripts/helm/db/minio/templates/secrets.yaml b/scripts/helm/db/minio/templates/secrets.yaml deleted file mode 100755 index 1a813eeda..000000000 --- a/scripts/helm/db/minio/templates/secrets.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if (include "minio.createSecret" .) }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "minio.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} -type: Opaque -data: - access-key: {{ include "minio.accessKey" . | b64enc | quote }} - secret-key: {{ include "minio.secretKey" . | b64enc | quote }} -{{- end }} diff --git a/scripts/helm/db/minio/templates/service.yaml b/scripts/helm/db/minio/templates/service.yaml deleted file mode 100755 index 7a6c380de..000000000 --- a/scripts/helm/db/minio/templates/service.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "minio.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} - {{- if .Values.service.annotations }} - annotations: {{- include "minio.tplValue" ( dict "value" .Values.service.annotations "context" $) | nindent 4 }} - {{- end }} -spec: - type: {{ .Values.service.type }} - {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }} - loadBalancerIP: {{ .Values.service.loadBalancerIP }} - {{- end }} - ports: - - name: minio - port: {{ .Values.service.port }} - targetPort: minio - {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePort)) }} - nodePort: {{ .Values.service.nodePort }} - {{- else if eq .Values.service.type "ClusterIP" }} - nodePort: null - {{- end }} - selector: {{- include "minio.matchLabels" . | nindent 4 }} diff --git a/scripts/helm/db/minio/templates/serviceaccount.yaml b/scripts/helm/db/minio/templates/serviceaccount.yaml deleted file mode 100755 index 76efe62f0..000000000 --- a/scripts/helm/db/minio/templates/serviceaccount.yaml +++ /dev/null @@ -1,10 +0,0 @@ -{{- if .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "minio.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} -secrets: - - name: {{ include "minio.fullname" . }} -{{- end }} diff --git a/scripts/helm/db/minio/templates/statefulset.yaml b/scripts/helm/db/minio/templates/statefulset.yaml deleted file mode 100755 index 7add4501f..000000000 --- a/scripts/helm/db/minio/templates/statefulset.yaml +++ /dev/null @@ -1,181 +0,0 @@ -{{- if eq .Values.mode "distributed" }} -{{- $replicaCount := int .Values.statefulset.replicaCount }} -{{- if and (eq (mod $replicaCount 2) 0) (gt $replicaCount 3) (lt $replicaCount 33) }} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ include "minio.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} -spec: - selector: - matchLabels: {{- include "minio.matchLabels" . | nindent 6 }} - serviceName: {{ include "minio.fullname" . }}-headless - replicas: {{ .Values.statefulset.replicaCount }} - podManagementPolicy: {{ .Values.statefulset.podManagementPolicy }} - updateStrategy: - type: {{ .Values.statefulset.updateStrategy }} - {{- if (eq "Recreate" .Values.statefulset.updateStrategy) }} - rollingUpdate: null - {{- end }} - template: - metadata: - labels: {{- include "minio.labels" . | nindent 8 }} - {{- if or .Values.podAnnotations (include "minio.createSecret" .) }} - annotations: - {{- if (include "minio.createSecret" .) }} - checksum/credentials-secret: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} - {{- end }} - {{- if .Values.podAnnotations }} - {{- include "minio.tplValue" ( dict "value" .Values.podAnnotations "context" $) | nindent 8 }} - {{- end }} - {{- end }} - spec: - {{- if .Values.schedulerName }} - schedulerName: {{ .Values.schedulerName }} - {{- end }} - serviceAccountName: {{ template "minio.serviceAccountName" . }} -{{- include "minio.imagePullSecrets" . | nindent 6 }} - {{- if .Values.affinity }} - affinity: {{- include "minio.tplValue" (dict "value" .Values.affinity "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: {{- include "minio.tplValue" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.tolerations }} - tolerations: {{- include "minio.tplValue" (dict "value" .Values.tolerations "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.securityContext.enabled }} - securityContext: - fsGroup: {{ .Values.securityContext.fsGroup }} - {{- end }} - {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} - initContainers: - - name: volume-permissions - image: {{ template "minio.volumePermissions.image" . }} - imagePullPolicy: {{ default "" .Values.volumePermissions.image.pullPolicy | quote }} - command: - - /bin/bash - - -ec - - | - chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.persistence.mountPath }} - securityContext: - runAsUser: 0 - {{- if .Values.volumePermissions.resources }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} - {{- end }} - volumeMounts: - - name: data - mountPath: {{ .Values.persistence.mountPath }} - {{- end }} - containers: - - name: minio - image: {{ include "minio.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - {{- if .Values.securityContext.enabled }} - securityContext: - runAsUser: {{ .Values.securityContext.runAsUser }} - {{- end }} - env: - - name: BITNAMI_DEBUG - value: {{ ternary "true" "false" .Values.image.debug | quote }} - - name: MINIO_DISTRIBUTED_MODE_ENABLED - value: "yes" - - name: MINIO_SKIP_CLIENT - value: "yes" - - name: MINIO_DISTRIBUTED_NODES - {{- $minioFullname := include "minio.fullname" . }} - {{- $minioHeadlessServiceName := printf "%s-%s" $minioFullname "headless" | trunc 63 }} - {{- $releaseNamespace := .Release.Namespace }} - value: {{range $i, $e := until $replicaCount }}{{ $minioFullname }}-{{ $e }}.{{ $minioHeadlessServiceName }}.{{ $releaseNamespace }}.svc.{{ $.Values.clusterDomain }},{{ end }} - - name: MINIO_FORCE_NEW_KEYS - value: {{ ternary "yes" "no" .Values.forceNewKeys | quote }} - {{- if .Values.useCredentialsFile }} - - name: MINIO_ACCESS_KEY_FILE - value: "/opt/bitnami/minio/secrets/access-key" - {{- else }} - - name: MINIO_ACCESS_KEY - valueFrom: - secretKeyRef: - name: {{ include "minio.secretName" . }} - key: access-key - {{- end }} - {{- if .Values.useCredentialsFile }} - - name: MINIO_SECRET_KEY_FILE - value: "/opt/bitnami/minio/secrets/secret-key" - {{- else }} - - name: MINIO_SECRET_KEY - valueFrom: - secretKeyRef: - name: {{ include "minio.secretName" . }} - key: secret-key - {{- end }} - - name: MINIO_BROWSER - value: {{ ternary "off" "on" .Values.disableWebUI | quote }} - {{- if .Values.prometheusAuthType }} - - name: MINIO_PROMETHEUS_AUTH_TYPE - value: {{ .Values.prometheusAuthType }} - {{- end }} - {{- if .Values.extraEnv }} - {{- toYaml .Values.extraEnv | nindent 12 }} - {{- end }} - ports: - - name: minio - containerPort: 9000 - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - httpGet: - path: /minio/health/live - port: minio - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - tcpSocket: - port: minio - {{- end }} - {{- if .Values.resources }} - resources: {{ toYaml .Values.resources | nindent 12 }} - {{- end }} - volumeMounts: - {{- if .Values.useCredentialsFile }} - - name: minio-credentials - mountPath: /opt/bitnami/minio/secrets/ - {{- end }} - - name: data - mountPath: {{ .Values.persistence.mountPath }} - volumes: - {{- if .Values.useCredentialsFile }} - - name: minio-credentials - secret: - secretName: {{ include "minio.secretName" . }} - {{- end }} -{{- if not .Values.persistence.enabled }} - - name: data - emptyDir: {} -{{- else }} - volumeClaimTemplates: - - metadata: - name: data - labels: {{- include "minio.matchLabels" . | nindent 10 }} - {{- if .Values.persistence.annotations }} - annotations: {{- include "minio.tplValue" ( dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} - {{- end }} - spec: - accessModes: {{ toYaml .Values.persistence.accessModes | nindent 10 }} - {{ include "minio.storageClass" . }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} -{{- end }} -{{- end }} -{{- end }} diff --git a/scripts/helm/db/minio/templates/svc-headless.yaml b/scripts/helm/db/minio/templates/svc-headless.yaml deleted file mode 100755 index 41a4cf507..000000000 --- a/scripts/helm/db/minio/templates/svc-headless.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if eq .Values.mode "distributed" }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "minio.fullname" . }}-headless - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" . | nindent 4 }} -spec: - type: ClusterIP - clusterIP: None - ports: - - name: minio - port: {{ .Values.service.port }} - targetPort: minio - selector: {{- include "minio.matchLabels" . | nindent 4 }} -{{- end }} diff --git a/scripts/helm/db/minio/templates/tls-secrets.yaml b/scripts/helm/db/minio/templates/tls-secrets.yaml deleted file mode 100755 index 68b31d324..000000000 --- a/scripts/helm/db/minio/templates/tls-secrets.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.ingress.enabled }} -{{- range .Values.ingress.secrets }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ .name }} - namespace: {{ .Release.Namespace }} - labels: {{- include "minio.labels" $ | nindent 4 }} -type: kubernetes.io/tls -data: - tls.crt: {{ .certificate | b64enc }} - tls.key: {{ .key | b64enc }} -{{- end }} -{{- end }} diff --git a/scripts/helm/db/minio/values-production.yaml b/scripts/helm/db/minio/values-production.yaml deleted file mode 100755 index d4d639732..000000000 --- a/scripts/helm/db/minio/values-production.yaml +++ /dev/null @@ -1,389 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -global: - minio: {} -# minio: -# existingSecret: "" -# accessKey: "" -# secretKey: "" -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami MinIO image version -## ref: https://hub.docker.com/r/bitnami/minio/tags/ -## -image: - registry: docker.io - repository: bitnami/minio - tag: 2020.10.9-debian-10-r6 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - - ## Set to true if you would like to see extra information on logs - ## It turns BASH and NAMI debugging in minideb - ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging - debug: false - -## String to partially override minio.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override minio.fullname template -## -# fullnameOverride: - -## Scheduler name -## https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: stork - -serviceAccount: - # Specifies whether a ServiceAccount should be created - create: true - # The name of the ServiceAccount to use. - # If not set and create is true, a name is generated using the fullname template - name: - -## Cluster domain -## -clusterDomain: cluster.local - -## Bitnami MinIO Client image version -## ref: https://hub.docker.com/r/bitnami/minio-client/tags/ -## -clientImage: - registry: docker.io - repository: bitnami/minio-client - tag: 2020.10.3-debian-10-r9 - -## Init containers parameters: -## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Init container' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - -## MinIO server mode. Allowed values: standalone or distributed. -## Distributed Minio ref: https://docs.minio.io/docs/distributed-minio-quickstart-guide -## -mode: distributed - -## MinIO deployment parameters -## Only when mode is 'standalone' -## -deployment: - ## Set to Recreate if you use persistent volume that cannot be mounted by more than one pods to makesure the pods is destroyed first. - ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy - ## Example: - ## updateStrategy: - ## type: RollingUpdate - ## rollingUpdate: - ## maxSurge: 25% - ## maxUnavailable: 25% - ## - updateStrategy: - type: Recreate - -## MinIO statefulset parameters -## Only when mode is 'distributed' -## -statefulset: - ## Update strategy, can be set to RollingUpdate or OnDelete by default. - ## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets - ## - updateStrategy: RollingUpdate - - ## StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: OrderedReady and Parallel - ## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy - ## - podManagementPolicy: Parallel - - ## Number of replicas, it must even and greater than 4 - ## - replicaCount: 4 - -## Use existing secret (ignores accessKey, and secretKey passwords) -## -# existingSecret: - -## Mount MinIO secret as a file instead of passing environment variable -## -useCredentialsFile: false - -## Force reconfiguring new keys whenever the credentials change -## -forceNewKeys: false - -## MinIO credentials -## -accessKey: - ## MinIO Access Key - ## ref: https://github.com/bitnami/bitnami-docker-minio/#setting-up-minio-in-distributed-mode - ## - password: - ## Option to force users to specify a password. That is required for 'helm upgrade' to work properly. - ## If it is not force, a random password will be generated. - ## - forcePassword: false -secretKey: - ## MinIO Secret Key - ## ref: https://github.com/bitnami/bitnami-docker-minio/#setting-up-minio-in-distributed-mode - ## - password: - ## Option to force users to specify a password. That is required for 'helm upgrade' to work properly. - ## If it is not force, a random password will be generated. - ## - forcePassword: false - -## Comma, semi-colon or space separated list of buckets to create at initialization (only in standalone mode) -## -# defaultBuckets: "my-bucket, my-second-bucket" - -## Disable MinIO Web UI -## ref: https://github.com/minio/minio/tree/master/docs/config/#browser -## -disableWebUI: true - -## Define custom environment variables to pass to the image here -## -extraEnv: {} - -## Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -## -securityContext: - enabled: true - fsGroup: 1001 - runAsUser: 1001 - -## Pod annotations -## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -## -podAnnotations: - prometheus.io/scrape: "true" - prometheus.io/path: "/minio/prometheus/metric" - prometheus.io/port: "9000" - -## Affinity for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Node labels for pod assignment. Evaluated as a template. -## Ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## MinIO containers' resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 250m - # memory: 256Mi - requests: - cpu: 250m - memory: 256Mi - -## MinIO containers' liveness and readiness probes -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes -## -livenessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 -readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 5 - -## Enable persistence using Persistent Volume Claims -## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ -## -persistence: - ## If true, use a Persistent Volume Claim, If false, use emptyDir - ## - enabled: true - - ## Enable persistence using an existing PVC (only in standalone mode) - ## - # existingClaim: - - ## Data volume mount path - ## - mountPath: /data - - ## Persistent Volume Access Mode - ## - accessModes: - - ReadWriteOnce - - ## Persistent Volume size - ## - size: 8Gi - - ## Persistent Volume Storage Class - ## If defined, storageClassName: <storageClass> - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - - ## Persistent Volume Claim annotations - ## - annotations: {} - -## MinIO Service properties -## -service: - ## MinIO Service type - ## - type: ClusterIP - - ## MinIO Service port - ## - port: 9000 - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - annotations: {} - - ## loadBalancerIP for the PrestaShop Service (optional, cloud specific) - ## ref: http://kubernetes.io/docs/user-guide/services/#type-loadbalancer - ## - # loadBalancerIP: - -## Configure the ingress resource that allows you to access the -## MinIO web browser. Set up the URL -## ref: http://kubernetes.io/docs/user-guide/ingress/ -## -ingress: - ## Set to true to enable ingress record generation - enabled: false - - ## Set this to true in order to add the corresponding annotations for cert-manager - certManager: false - - ## Ingress annotations done as key:value pairs - ## For a full list of possible ingress annotations, please see - ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md - ## - ## If tls is set to true, annotation ingress.kubernetes.io/secure-backends: "true" will automatically be set - ## If certManager is set to true, annotation kubernetes.io/tls-acme: "true" will automatically be set - # annotations: - # kubernetes.io/ingress.class: nginx - - ## Ingress additional labels done as key:value pairs - labels: {} - - ## The list of hostnames to be covered with this ingress record. - ## Most likely this will be just one host, but in the event more hosts are needed, this is an array - hosts: - - name: minio.local - path: / - - ## Set this to true in order to enable TLS on the ingress record - tls: false - - ## Optionally specify the TLS hosts for the ingress record - ## Useful when the Ingress controller supports www-redirection - ## If not specified, the above host name will be used - # tlsHosts: - # - www.minio.local - # - minio.local - - ## If TLS is set to true, you must declare what secret will store the key/certificate for TLS - tlsSecret: minio.local-tls - - secrets: - ## If you're providing your own certificates, please use this to add the certificates as secrets - ## key and certificate should start with -----BEGIN CERTIFICATE----- or - ## -----BEGIN RSA PRIVATE KEY----- - ## - ## name should line up with a tlsSecret set further up - ## If you're using cert-manager, this is unneeded, as it will create the secret for you if it is not set - ## - ## It is also possible to create and manage the certificates outside of this helm chart - ## Please see README.md for more information - # - name: minio.local-tls - # key: - # certificate: - -## NetworkPolicy parameters -## -networkPolicy: - ## Specifies whether a NetworkPolicy should be created - ## - enabled: true - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port MinIO is listening - ## on. When true, MinIO will accept connections from any source - ## (with the correct destination port). - ## - allowExternal: false - -## MinIO supports two authentication modes for Prometheus either jwt or public, by default MinIO runs in jwt mode. -## To allow public access without authentication for prometheus metrics set environment as follows. -prometheusAuthType: jwt diff --git a/scripts/helm/db/minio/values.yaml b/scripts/helm/db/minio/values.yaml deleted file mode 100755 index 84124299d..000000000 --- a/scripts/helm/db/minio/values.yaml +++ /dev/null @@ -1,391 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -global: - minio: - accessKey: "minios3AccessKeyS3cr3t" - secretKey: "m1n10s3CretK3yPassw0rd" -# minio: {} -# existingSecret: "" -# accessKey: "" -# secretKey: "" -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami MinIO image version -## ref: https://hub.docker.com/r/bitnami/minio/tags/ -## -image: - registry: docker.io - repository: bitnami/minio - tag: 2020.10.9-debian-10-r6 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - - ## Set to true if you would like to see extra information on logs - ## It turns BASH and NAMI debugging in minideb - ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging - debug: false - -## String to partially override minio.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override minio.fullname template -## -# fullnameOverride: - -## Scheduler name -## https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: stork - -serviceAccount: - # Specifies whether a ServiceAccount should be created - create: true - # The name of the ServiceAccount to use. - # If not set and create is true, a name is generated using the fullname template - name: - -## Cluster domain -## -clusterDomain: cluster.local - -## Bitnami MinIO Client image version -## ref: https://hub.docker.com/r/bitnami/minio-client/tags/ -## -clientImage: - registry: docker.io - repository: bitnami/minio-client - tag: 2020.10.3-debian-10-r9 - -## Init containers parameters: -## volumePermissions: Change the owner and group of the persistent volume mountpoint to runAsUser:fsGroup values from the securityContext section. -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Init container' resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 100m - # memory: 128Mi - requests: {} - # cpu: 100m - # memory: 128Mi - -## MinIO server mode. Allowed values: standalone or distributed. -## Distributed Minio ref: https://docs.minio.io/docs/distributed-minio-quickstart-guide -## -mode: standalone - -## MinIO deployment parameters -## Only when mode is 'standalone' -## -deployment: - ## Set to Recreate if you use persistent volume that cannot be mounted by more than one pods to makesure the pods is destroyed first. - ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy - ## Example: - ## updateStrategy: - ## type: RollingUpdate - ## rollingUpdate: - ## maxSurge: 25% - ## maxUnavailable: 25% - ## - updateStrategy: - type: Recreate - -## MinIO statefulset parameters -## Only when mode is 'distributed' -## -statefulset: - ## Update strategy, can be set to RollingUpdate or OnDelete by default. - ## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets - ## - updateStrategy: RollingUpdate - - ## StatefulSet controller supports relax its ordering guarantees while preserving its uniqueness and identity guarantees. There are two valid pod management policies: OrderedReady and Parallel - ## ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy - ## - podManagementPolicy: Parallel - - ## Number of replicas, it must even and greater than 4 - ## - replicaCount: 4 - -## Use existing secret (ignores accessKey, and secretKey passwords) -## -# existingSecret: - -## Mount MinIO secret as a file instead of passing environment variable -## -useCredentialsFile: false - -## Force reconfiguring new keys whenever the credentials change -## -forceNewKeys: false - -## MinIO credentials -## -accessKey: - ## MinIO Access Key - ## ref: https://github.com/bitnami/bitnami-docker-minio/#setting-up-minio-in-distributed-mode - ## - password: - ## Option to force users to specify a password. That is required for 'helm upgrade' to work properly. - ## If it is not force, a random password will be generated. - ## - forcePassword: false -secretKey: - ## MinIO Secret Key - ## ref: https://github.com/bitnami/bitnami-docker-minio/#setting-up-minio-in-distributed-mode - ## - password: - ## Option to force users to specify a password. That is required for 'helm upgrade' to work properly. - ## If it is not force, a random password will be generated. - ## - forcePassword: false - -## Comma, semi-colon or space separated list of buckets to create at initialization (only in standalone mode) -## -# defaultBuckets: "my-bucket, my-second-bucket" - -## Disable MinIO Web UI -## ref: https://github.com/minio/minio/tree/master/docs/config/#browser -## -disableWebUI: false - -## Define custom environment variables to pass to the image here -## -extraEnv: {} - -## Define a custom command for the minio container -command: {} - -## Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -## -securityContext: - enabled: true - fsGroup: 1001 - runAsUser: 1001 - -## Pod annotations -## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -## -podAnnotations: {} - -## Affinity for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## Node labels for pod assignment. Evaluated as a template. -## Ref: https://kubernetes.io/docs/user-guide/node-selection/ -## -nodeSelector: {} - -## Tolerations for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## MinIO containers' resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - limits: {} - # cpu: 250m - # memory: 256Mi - requests: {} - # cpu: 250m - # memory: 256Mi - -## MinIO containers' liveness and readiness probes -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes -## -livenessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 -readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 5 - -## Enable persistence using Persistent Volume Claims -## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ -## -persistence: - ## If true, use a Persistent Volume Claim, If false, use emptyDir - ## - enabled: true - - ## Enable persistence using an existing PVC (only in standalone mode) - ## - # existingClaim: - - ## Data volume mount path - ## - mountPath: /data - - ## Persistent Volume Access Mode - ## - accessModes: - - ReadWriteOnce - - ## Persistent Volume size - ## - size: 50Gi - - ## Persistent Volume Storage Class - ## If defined, storageClassName: <storageClass> - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - - ## Persistent Volume Claim annotations - ## - annotations: {} - -## MinIO Service properties -## -service: - ## MinIO Service type - ## - type: ClusterIP - - ## MinIO Service port - ## - port: 9000 - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - annotations: {} - - ## loadBalancerIP for the PrestaShop Service (optional, cloud specific) - ## ref: http://kubernetes.io/docs/user-guide/services/#type-loadbalancer - ## - # loadBalancerIP: - -## Configure the ingress resource that allows you to access the -## MinIO web browser. Set up the URL -## ref: http://kubernetes.io/docs/user-guide/ingress/ -## -ingress: - ## Set to true to enable ingress record generation - enabled: false - - ## Set this to true in order to add the corresponding annotations for cert-manager - certManager: false - - ## Ingress annotations done as key:value pairs - ## For a full list of possible ingress annotations, please see - ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md - ## - ## If tls is set to true, annotation ingress.kubernetes.io/secure-backends: "true" will automatically be set - ## If certManager is set to true, annotation kubernetes.io/tls-acme: "true" will automatically be set - # annotations: - # kubernetes.io/ingress.class: nginx - - ## Ingress additional labels done as key:value pairs - labels: {} - - ## The list of hostnames to be covered with this ingress record. - ## Most likely this will be just one host, but in the event more hosts are needed, this is an array - hosts: - - name: minio.local - path: / - - ## Set this to true in order to enable TLS on the ingress record - tls: false - - ## Optionally specify the TLS hosts for the ingress record - ## Useful when the Ingress controller supports www-redirection - ## If not specified, the above host name will be used - # tlsHosts: - # - www.minio.local - # - minio.local - - ## If TLS is set to true, you must declare what secret will store the key/certificate for TLS - tlsSecret: minio.local-tls - - secrets: - ## If you're providing your own certificates, please use this to add the certificates as secrets - ## key and certificate should start with -----BEGIN CERTIFICATE----- or - ## -----BEGIN RSA PRIVATE KEY----- - ## - ## name should line up with a tlsSecret set further up - ## If you're using cert-manager, this is unneeded, as it will create the secret for you if it is not set - ## - ## It is also possible to create and manage the certificates outside of this helm chart - ## Please see README.md for more information - # - name: minio.local-tls - # key: - # certificate: - -## NetworkPolicy parameters -## -networkPolicy: - ## Specifies whether a NetworkPolicy should be created - ## - enabled: false - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port MinIO is listening - ## on. When true, MinIO will accept connections from any source - ## (with the correct destination port). - ## - allowExternal: true - -## MinIO supports two authentication modes for Prometheus either jwt or public, by default MinIO runs in jwt mode. -## To allow public access without authentication for prometheus metrics set environment as follows. -prometheusAuthType: public diff --git a/scripts/helm/db/nfs-server-provisioner/.helmignore b/scripts/helm/db/nfs-server-provisioner/.helmignore deleted file mode 100755 index f0c131944..000000000 --- a/scripts/helm/db/nfs-server-provisioner/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/scripts/helm/db/nfs-server-provisioner/Chart.yaml b/scripts/helm/db/nfs-server-provisioner/Chart.yaml deleted file mode 100755 index c08e0ce0b..000000000 --- a/scripts/helm/db/nfs-server-provisioner/Chart.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -appVersion: 2.3.0 -description: nfs-server-provisioner is an out-of-tree dynamic provisioner for Kubernetes. - You can use it to quickly & easily deploy shared storage that works almost anywhere. -home: https://github.com/kubernetes/charts/tree/master/stable/nfs-server-provisioner -keywords: -- nfs -- storage -maintainers: -- email: kiall@macinnes.ie - name: kiall -- email: kvapss@gmail.com - name: kvaps -- email: joaocc-dev@live.com - name: joaocc -- email: naseem@transit.app - name: naseemkullah -name: nfs-server-provisioner -sources: -- https://github.com/kubernetes-incubator/external-storage/tree/master/nfs -version: 1.1.1 diff --git a/scripts/helm/db/nfs-server-provisioner/OWNERS b/scripts/helm/db/nfs-server-provisioner/OWNERS deleted file mode 100755 index b65278579..000000000 --- a/scripts/helm/db/nfs-server-provisioner/OWNERS +++ /dev/null @@ -1,8 +0,0 @@ -approvers: -- kiall -- kvaps -- naseemkullah -reviewers: -- kiall -- kvaps -- naseemkullah diff --git a/scripts/helm/db/nfs-server-provisioner/README.md b/scripts/helm/db/nfs-server-provisioner/README.md deleted file mode 100755 index 56245e87e..000000000 --- a/scripts/helm/db/nfs-server-provisioner/README.md +++ /dev/null @@ -1,206 +0,0 @@ -# NFS Server Provisioner - -[NFS Server Provisioner](https://github.com/kubernetes-incubator/external-storage/tree/master/nfs) -is an out-of-tree dynamic provisioner for Kubernetes. You can use it to quickly -& easily deploy shared storage that works almost anywhere. - -This chart will deploy the Kubernetes [external-storage projects](https://github.com/kubernetes-incubator/external-storage) -`nfs` provisioner. This provisioner includes a built in NFS server, and is not intended for connecting to a pre-existing -NFS server. If you have a pre-existing NFS Server, please consider using the [NFS Client Provisioner](https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client) -instead. - -## TL;DR; - -```console -$ helm install stable/nfs-server-provisioner -``` - -> **Warning**: While installing in the default configuration will work, any data stored on -the dynamic volumes provisioned by this chart will not be persistent! - -## Introduction - -This chart bootstraps a [nfs-server-provisioner](https://github.com/kubernetes-incubator/external-storage/tree/master/nfs) -deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) -package manager. - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -$ helm install stable/nfs-server-provisioner --name my-release -``` - -The command deploys nfs-server-provisioner on the Kubernetes cluster in the default -configuration. The [configuration](#configuration) section lists the parameters -that can be configured during installation. - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```console -$ helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and -deletes the release. - -## Configuration - -The following table lists the configurable parameters of the kibana chart and -their default values. - -| Parameter | Description | Default | -|:-------------------------------|:----------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------| -| `extraArgs` | [Additional command line arguments](https://github.com/kubernetes-incubator/external-storage/blob/master/nfs/docs/deployment.md#arguments) | `{}` -| `imagePullSecrets` | Specify image pull secrets | `nil` (does not add image pull secrets to deployed pods) | -| `image.repository` | The image repository to pull from | `quay.io/kubernetes_incubator/nfs-provisioner` | -| `image.tag` | The image tag to pull from | `v2.2.2` | -| `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `service.type` | service type | `ClusterIP` | -| `service.nfsPort` | TCP port on which the nfs-server-provisioner NFS service is exposed | `2049` | -| `service.mountdPort` | TCP port on which the nfs-server-provisioner mountd service is exposed | `20048` | -| `service.rpcbindPort` | TCP port on which the nfs-server-provisioner RPC service is exposed | `111` | -| `service.nfsNodePort` | if `service.type` is `NodePort` and this is non-empty, sets the nfs-server-provisioner node port of the NFS service | `nil` | -| `service.mountdNodePort` | if `service.type` is `NodePort` and this is non-empty, sets the nfs-server-provisioner node port of the mountd service | `nil` | -| `service.rpcbindNodePort` | if `service.type` is `NodePort` and this is non-empty, sets the nfs-server-provisioner node port of the RPC service | `nil` | -| `persistence.enabled` | Enable config persistence using PVC | `false` | -| `persistence.storageClass` | PVC Storage Class for config volume | `nil` | -| `persistence.accessMode` | PVC Access Mode for config volume | `ReadWriteOnce` | -| `persistence.size` | PVC Storage Request for config volume | `1Gi` | -| `storageClass.create` | Enable creation of a StorageClass to consume this nfs-server-provisioner instance | `true` | -| `storageClass.provisionerName` | The provisioner name for the storageclass | `cluster.local/{release-name}-{chart-name}` | -| `storageClass.defaultClass` | Whether to set the created StorageClass as the clusters default StorageClass | `false` | -| `storageClass.name` | The name to assign the created StorageClass | `nfs` | -| `storageClass.allowVolumeExpansion` | Allow base storage PCV to be dynamically resizeable (set to null to disable ) | `true | -| `storageClass.parameters` | Parameters for StorageClass | `{}` | -| `storageClass.mountOptions` | Mount options for StorageClass | `[ "vers=3" ]` | -| `storageClass.reclaimPolicy` | ReclaimPolicy field of the class, which can be either Delete or Retain | `Delete` | -| `resources` | Resource limits for nfs-server-provisioner pod | `{}` | -| `nodeSelector` | Map of node labels for pod assignment | `{}` | -| `tolerations` | List of node taints to tolerate | `[]` | -| `affinity` | Map of node/pod affinities | `{}` | -| `podSecurityContext` | Security context settings for nfs-server-provisioner pod (see https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) | `{}` | - -```console -$ helm install stable/nfs-server-provisioner --name my-release \ - --set=image.tag=v1.0.8,resources.limits.cpu=200m -``` - -Alternatively, a YAML file that specifies the values for the above parameters -can be provided while installing the chart. For example, - -```console -$ helm install stable/nfs-server-provisioner --name my-release -f values.yaml -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) as an example - -## Persistence - -The nfs-server-provisioner image stores it's configuration data, and importantly, **the dynamic volumes it -manages** `/export` path of the container. - -The chart mounts a [Persistent Volume](http://kubernetes.io/docs/user-guide/persistent-volumes/) -volume at this location. The volume can be created using dynamic volume -provisioning. However, **it is highly recommended** to explicitly specify -a storageclass to use rather than accept the clusters default, or pre-create -a volume for each replica. - -If this chart is deployed with more than 1 replica, `storageClass.defaultClass=true` -and `persistence.storageClass`, then the 2nd+ replica will end up using the 1st -replica to provision storage - which is likely never a desired outcome. - -## Recommended Persistence Configuration Examples - -The following is a recommended configuration example when another storage class -exists to provide persistence: - - persistence: - enabled: true - storageClass: "standard" - size: 200Gi - - storageClass: - defaultClass: true - -On many clusters, the cloud provider integration will create a "standard" storage -class which will create a volume (e.g. a Google Compute Engine Persistent Disk or -Amazon EBS volume) to provide persistence. - ---- - -The following is a recommended configuration example when another storage class -does not exist to provide persistence: - - persistence: - enabled: true - storageClass: "-" - size: 200Gi - - storageClass: - defaultClass: true - -In this configuration, a `PersistentVolume` must be created for each replica -to use. Installing the Helm chart, and then inspecting the `PersistentVolumeClaim`'s -created will provide the necessary names for your `PersistentVolume`'s to bind to. - -An example of the necessary `PersistentVolume`: - - apiVersion: v1 - kind: PersistentVolume - metadata: - name: data-nfs-server-provisioner-0 - spec: - capacity: - storage: 200Gi - accessModes: - - ReadWriteOnce - gcePersistentDisk: - fsType: "ext4" - pdName: "data-nfs-server-provisioner-0" - claimRef: - namespace: kube-system - name: data-nfs-server-provisioner-0 - ---- - -The following is a recommended configuration example for running on bare metal with a hostPath volume: - - persistence: - enabled: true - storageClass: "-" - size: 200Gi - - storageClass: - defaultClass: true - - nodeSelector: - kubernetes.io/hostname: {node-name} - -In this configuration, a `PersistentVolume` must be created for each replica -to use. Installing the Helm chart, and then inspecting the `PersistentVolumeClaim`'s -created will provide the necessary names for your `PersistentVolume`'s to bind to. - -An example of the necessary `PersistentVolume`: - - apiVersion: v1 - kind: PersistentVolume - metadata: - name: data-nfs-server-provisioner-0 - spec: - capacity: - storage: 200Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /srv/volumes/data-nfs-server-provisioner-0 - claimRef: - namespace: kube-system - name: data-nfs-server-provisioner-0 - -> **Warning**: `hostPath` volumes cannot be migrated between machines by Kubernetes, as such, -in this example, we have restricted the `nfs-server-provisioner` pod to run on a single node. This -is unsuitable for production deployments. diff --git a/scripts/helm/db/nfs-server-provisioner/templates/NOTES.txt b/scripts/helm/db/nfs-server-provisioner/templates/NOTES.txt deleted file mode 100755 index 09376d296..000000000 --- a/scripts/helm/db/nfs-server-provisioner/templates/NOTES.txt +++ /dev/null @@ -1,26 +0,0 @@ -The NFS Provisioner service has now been installed. - -{{ if .Values.storageClass.create -}} -A storage class named '{{ .Values.storageClass.name }}' has now been created -and is available to provision dynamic volumes. - -You can use this storageclass by creating a `PersistentVolumeClaim` with the -correct storageClassName attribute. For example: - - --- - kind: PersistentVolumeClaim - apiVersion: v1 - metadata: - name: test-dynamic-volume-claim - spec: - storageClassName: "{{ .Values.storageClass.name }}" - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 100Mi - -{{ else -}} -A storage class has NOT been created. You may create a custom `StorageClass` -resource with a `provisioner` attribute of `{{ template "nfs-provisioner.provisionerName" . }}`. -{{ end -}} diff --git a/scripts/helm/db/nfs-server-provisioner/templates/_helpers.tpl b/scripts/helm/db/nfs-server-provisioner/templates/_helpers.tpl deleted file mode 100755 index cdc13bfa4..000000000 --- a/scripts/helm/db/nfs-server-provisioner/templates/_helpers.tpl +++ /dev/null @@ -1,43 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "nfs-provisioner.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "nfs-provisioner.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "nfs-provisioner.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "nfs-provisioner.provisionerName" -}} -{{- if .Values.storageClass.provisionerName -}} -{{- printf .Values.storageClass.provisionerName -}} -{{- else -}} -cluster.local/{{ template "nfs-provisioner.fullname" . -}} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/nfs-server-provisioner/templates/clusterrole.yaml b/scripts/helm/db/nfs-server-provisioner/templates/clusterrole.yaml deleted file mode 100755 index 5affc4bab..000000000 --- a/scripts/helm/db/nfs-server-provisioner/templates/clusterrole.yaml +++ /dev/null @@ -1,34 +0,0 @@ -{{ if .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "nfs-provisioner.fullname" . }} - labels: - app: {{ template "nfs-provisioner.name" . }} - chart: {{ template "nfs-provisioner.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -rules: - - apiGroups: [""] - resources: ["persistentvolumes"] - verbs: ["get", "list", "watch", "create", "delete"] - - apiGroups: [""] - resources: ["persistentvolumeclaims"] - verbs: ["get", "list", "watch", "update"] - - apiGroups: ["storage.k8s.io"] - resources: ["storageclasses"] - verbs: ["get", "list", "watch"] - - apiGroups: [""] - resources: ["events"] - verbs: ["list", "watch", "create", "update", "patch"] - - apiGroups: [""] - resources: ["services", "endpoints"] - verbs: ["get"] - - apiGroups: ["extensions"] - resources: ["podsecuritypolicies"] - resourceNames: ["nfs-provisioner"] - verbs: ["use"] - - apiGroups: [""] - resources: ["endpoints"] - verbs: ["get", "list", "watch", "create", "delete", "update", "patch"] -{{- end -}} diff --git a/scripts/helm/db/nfs-server-provisioner/templates/rolebinding.yaml b/scripts/helm/db/nfs-server-provisioner/templates/rolebinding.yaml deleted file mode 100755 index fc88425f9..000000000 --- a/scripts/helm/db/nfs-server-provisioner/templates/rolebinding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app: {{ template "nfs-provisioner.name" . }} - chart: {{ template "nfs-provisioner.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "nfs-provisioner.fullname" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "nfs-provisioner.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "nfs-provisioner.fullname" . }} - namespace: {{ .Release.Namespace }} -{{- end -}} diff --git a/scripts/helm/db/nfs-server-provisioner/templates/service.yaml b/scripts/helm/db/nfs-server-provisioner/templates/service.yaml deleted file mode 100755 index 1de216836..000000000 --- a/scripts/helm/db/nfs-server-provisioner/templates/service.yaml +++ /dev/null @@ -1,103 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "nfs-provisioner.fullname" . }} - labels: - app: {{ template "nfs-provisioner.name" . }} - chart: {{ template "nfs-provisioner.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.nfsPort }} - targetPort: nfs - protocol: TCP - name: nfs - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nfsNodePort))) }} - nodePort: {{ .Values.service.nfsNodePort }} - {{- end }} - - port: {{ .Values.service.nfsPort }} - targetPort: nfs-udp - protocol: UDP - name: nfs-udp - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nfsNodePort))) }} - nodePort: {{ .Values.service.nfsNodePort }} - {{- end }} - - port: {{ .Values.service.nlockmgrPort }} - targetPort: nlockmgr - protocol: TCP - name: nlockmgr - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nlockmgrNodePort))) }} - nodePort: {{ .Values.service.nlockmgrNodePort }} - {{- end }} - - port: {{ .Values.service.nlockmgrPort }} - targetPort: nlockmgr-udp - protocol: UDP - name: nlockmgr-udp - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nlockmgrPort))) }} - nodePort: {{ .Values.service.nlockmgrNodePort }} - {{- end }} - - port: {{ .Values.service.mountdPort }} - targetPort: mountd - protocol: TCP - name: mountd - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.mountdNodePort))) }} - nodePort: {{ .Values.service.mountdNodePort }} - {{- end }} - - port: {{ .Values.service.mountdPort }} - targetPort: mountd-udp - protocol: UDP - name: mountd-udp - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.mountdNodePort))) }} - nodePort: {{ .Values.service.mountdNodePort }} - {{- end }} - - port: {{ .Values.service.rquotadPort }} - targetPort: rquotad - protocol: TCP - name: rquotad - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.rquotadNodePort))) }} - nodePort: {{ .Values.service.rquotadNodePort }} - {{- end }} - - port: {{ .Values.service.rquotadPort }} - targetPort: rquotad-udp - protocol: UDP - name: rquotad-udp - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.rquotadNodePort))) }} - nodePort: {{ .Values.service.rquotadNodePort }} - {{- end }} - - port: {{ .Values.service.rpcbindPort }} - targetPort: rpcbind - protocol: TCP - name: rpcbind - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.rpcbindNodePort))) }} - nodePort: {{ .Values.service.rpcbindNodePort }} - {{- end }} - - port: {{ .Values.service.rpcbindPort }} - targetPort: rpcbind-udp - protocol: UDP - name: rpcbind-udp - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.rpcbindNodePort))) }} - nodePort: {{ .Values.service.rpcbindNodePort }} - {{- end }} - - port: {{ .Values.service.statdPort }} - targetPort: statd - protocol: TCP - name: statd - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.statdPort))) }} - nodePort: {{ .Values.service.statdNodePort }} - {{- end }} - - port: {{ .Values.service.statdPort }} - targetPort: statd-udp - protocol: UDP - name: statd-udp - {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.statdPort))) }} - nodePort: {{ .Values.service.statdNodePort }} - {{- end }} - {{- if .Values.service.externalIPs }} - externalIPs: - {{- toYaml .Values.service.externalIPs | nindent 4 }} - {{- end }} - selector: - app: {{ template "nfs-provisioner.name" . }} - release: {{ .Release.Name }} diff --git a/scripts/helm/db/nfs-server-provisioner/templates/serviceaccount.yaml b/scripts/helm/db/nfs-server-provisioner/templates/serviceaccount.yaml deleted file mode 100755 index 79fd0ae0e..000000000 --- a/scripts/helm/db/nfs-server-provisioner/templates/serviceaccount.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app: {{ template "nfs-provisioner.name" . }} - chart: {{ template "nfs-provisioner.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "nfs-provisioner.fullname" . }} -{{- end -}} diff --git a/scripts/helm/db/nfs-server-provisioner/templates/statefulset.yaml b/scripts/helm/db/nfs-server-provisioner/templates/statefulset.yaml deleted file mode 100755 index a405163c6..000000000 --- a/scripts/helm/db/nfs-server-provisioner/templates/statefulset.yaml +++ /dev/null @@ -1,141 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "nfs-provisioner.fullname" . }} - labels: - app: {{ template "nfs-provisioner.name" . }} - chart: {{ template "nfs-provisioner.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - # TODO: Investigate how/if nfs-provisioner can be scaled out beyond 1 replica - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "nfs-provisioner.name" . }} - release: {{ .Release.Name }} - serviceName: {{ template "nfs-provisioner.fullname" . }} - template: - metadata: - labels: - app: {{ template "nfs-provisioner.name" . }} - chart: {{ template "nfs-provisioner.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - spec: - # NOTE: This is 10 seconds longer than the default nfs-provisioner --grace-period value of 90sec - terminationGracePeriodSeconds: 100 - serviceAccountName: {{ if .Values.rbac.create }}{{ template "nfs-provisioner.fullname" . }}{{ else }}{{ .Values.rbac.serviceAccountName | quote }}{{ end }} - {{- if .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml .Values.imagePullSecrets | nindent 8 }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: nfs - containerPort: 2049 - protocol: TCP - - name: nfs-udp - containerPort: 2049 - protocol: UDP - - name: nlockmgr - containerPort: 32803 - protocol: TCP - - name: nlockmgr-udp - containerPort: 32803 - protocol: UDP - - name: mountd - containerPort: 20048 - protocol: TCP - - name: mountd-udp - containerPort: 20048 - protocol: UDP - - name: rquotad - containerPort: 875 - protocol: TCP - - name: rquotad-udp - containerPort: 875 - protocol: UDP - - name: rpcbind - containerPort: 111 - protocol: TCP - - name: rpcbind-udp - containerPort: 111 - protocol: UDP - - name: statd - containerPort: 662 - protocol: TCP - - name: statd-udp - containerPort: 662 - protocol: UDP - securityContext: - capabilities: - add: - - DAC_READ_SEARCH - - SYS_RESOURCE - args: - - "-provisioner={{ template "nfs-provisioner.provisionerName" . }}" - {{- range $key, $value := .Values.extraArgs }} - - "-{{ $key }}={{ $value }}" - {{- end }} - env: - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: SERVICE_NAME - value: {{ template "nfs-provisioner.fullname" . }} - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - volumeMounts: - - name: data - mountPath: /export - {{- with .Values.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.podSecurityContext }} - securityContext: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - - {{- if not .Values.persistence.enabled }} - volumes: - - name: data - emptyDir: {} - {{- end }} - - {{- if .Values.persistence.enabled }} - volumeClaimTemplates: - - metadata: - name: data - spec: - accessModes: [ {{ .Values.persistence.accessMode | quote }} ] - {{- if .Values.persistence.storageClass }} - {{- if (eq "-" .Values.persistence.storageClass) }} - storageClassName: "" - {{- else }} - storageClassName: {{ .Values.persistence.storageClass | quote }} - {{- end }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{- end }} diff --git a/scripts/helm/db/nfs-server-provisioner/templates/storageclass.yaml b/scripts/helm/db/nfs-server-provisioner/templates/storageclass.yaml deleted file mode 100755 index be1787aed..000000000 --- a/scripts/helm/db/nfs-server-provisioner/templates/storageclass.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{ if .Values.storageClass.create -}} -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: {{ .Values.storageClass.name }} - labels: - app: {{ template "nfs-provisioner.name" . }} - chart: {{ template "nfs-provisioner.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - {{- if .Values.storageClass.defaultClass }} - annotations: - storageclass.kubernetes.io/is-default-class: "true" - {{- end }} -provisioner: {{ template "nfs-provisioner.provisionerName" . }} -reclaimPolicy: {{ .Values.storageClass.reclaimPolicy }} -{{ if .Values.storageClass.allowVolumeExpansion }} -allowVolumeExpansion: {{ .Values.storageClass.allowVolumeExpansion }} -{{ end }} -{{- with .Values.storageClass.parameters }} -parameters: -{{- toYaml . | nindent 2 }} -{{- end }} -{{- with .Values.storageClass.mountOptions }} -mountOptions: -{{- toYaml . | nindent 2 }} -{{- end }} -{{ end -}} diff --git a/scripts/helm/db/nfs-server-provisioner/values.yaml b/scripts/helm/db/nfs-server-provisioner/values.yaml deleted file mode 100755 index 6f97ad27c..000000000 --- a/scripts/helm/db/nfs-server-provisioner/values.yaml +++ /dev/null @@ -1,98 +0,0 @@ -# Default values for nfs-provisioner. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -# imagePullSecrets: - -image: - repository: quay.io/kubernetes_incubator/nfs-provisioner - tag: v2.3.0 - pullPolicy: IfNotPresent - -# For a list of available arguments -# Please see https://github.com/kubernetes-incubator/external-storage/blob/master/nfs/docs/deployment.md#arguments -extraArgs: {} - # device-based-fsids: false - -service: - type: ClusterIP - - nfsPort: 2049 - nlockmgrPort: 32803 - mountdPort: 20048 - rquotadPort: 875 - rpcbindPort: 111 - statdPort: 662 - # nfsNodePort: - # nlockmgrNodePort: - # mountdNodePort: - # rquotadNodePort: - # rpcbindNodePort: - # statdNodePort: - - externalIPs: [] - -persistence: - enabled: true - - ## Persistent Volume Storage Class - ## If defined, storageClassName: <storageClass> - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - - accessMode: ReadWriteOnce - size: 10Gi - -## For creating the StorageClass automatically: -storageClass: - create: true - - ## Set a provisioner name. If unset, a name will be generated. - # provisionerName: - - ## Set StorageClass as the default StorageClass - ## Ignored if storageClass.create is false - defaultClass: false - - ## Set a StorageClass name - ## Ignored if storageClass.create is false - name: nfs - - # set to null to prevent expansion - allowVolumeExpansion: true - ## StorageClass parameters - parameters: {} - - mountOptions: - - vers=3 - - ## ReclaimPolicy field of the class, which can be either Delete or Retain - reclaimPolicy: Delete - -## For RBAC support: -rbac: - create: true - - ## Ignored if rbac.create is true - ## - serviceAccountName: default - -resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/scripts/helm/db/postgresql/.helmignore b/scripts/helm/db/postgresql/.helmignore deleted file mode 100755 index f0c131944..000000000 --- a/scripts/helm/db/postgresql/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/scripts/helm/db/postgresql/Chart.yaml b/scripts/helm/db/postgresql/Chart.yaml deleted file mode 100755 index 3ac2d3605..000000000 --- a/scripts/helm/db/postgresql/Chart.yaml +++ /dev/null @@ -1,26 +0,0 @@ -annotations: - category: Database -apiVersion: v1 -appVersion: 11.9.0 -description: Chart for PostgreSQL, an object-relational database management system - (ORDBMS) with an emphasis on extensibility and on standards-compliance. -engine: gotpl -home: https://github.com/bitnami/charts/tree/master/bitnami/postgresql -icon: https://bitnami.com/assets/stacks/postgresql/img/postgresql-stack-110x117.png -keywords: -- postgresql -- postgres -- database -- sql -- replication -- cluster -maintainers: -- email: containers@bitnami.com - name: Bitnami -- email: cedric@desaintmartin.fr - name: desaintmartin -name: postgresql -sources: -- https://github.com/bitnami/bitnami-docker-postgresql -- https://www.postgresql.org/ -version: 9.8.2 diff --git a/scripts/helm/db/postgresql/README.md b/scripts/helm/db/postgresql/README.md deleted file mode 100755 index 8cdb2ca13..000000000 --- a/scripts/helm/db/postgresql/README.md +++ /dev/null @@ -1,707 +0,0 @@ -# PostgreSQL - -[PostgreSQL](https://www.postgresql.org/) is an object-relational database management system (ORDBMS) with an emphasis on extensibility and on standards-compliance. - -For HA, please see [this repo](https://github.com/bitnami/charts/tree/master/bitnami/postgresql-ha) - -## TL;DR - -```console -$ helm repo add bitnami https://charts.bitnami.com/bitnami -$ helm install my-release bitnami/postgresql -``` - -## Introduction - -This chart bootstraps a [PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This chart has been tested to work with NGINX Ingress, cert-manager, fluentd and Prometheus on top of the [BKPR](https://kubeprod.io/). - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 2.12+ or Helm 3.0-beta3+ -- PV provisioner support in the underlying infrastructure - -## Installing the Chart -To install the chart with the release name `my-release`: - -```console -$ helm install my-release bitnami/postgresql -``` - -The command deploys PostgreSQL on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```console -$ helm delete my-release -``` - -The command removes all the Kubernetes components but PVC's associated with the chart and deletes the release. - -To delete the PVC's associated with `my-release`: - -```console -$ kubectl delete pvc -l release=my-release -``` - -> **Note**: Deleting the PVC's will delete postgresql data as well. Please be cautious before doing it. - -## Parameters - -The following tables lists the configurable parameters of the PostgreSQL chart and their default values. - -| Parameter | Description | Default | -|-----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------| -| `global.imageRegistry` | Global Docker Image registry | `nil` | -| `global.postgresql.postgresqlDatabase` | PostgreSQL database (overrides `postgresqlDatabase`) | `nil` | -| `global.postgresql.postgresqlUsername` | PostgreSQL username (overrides `postgresqlUsername`) | `nil` | -| `global.postgresql.existingSecret` | Name of existing secret to use for PostgreSQL passwords (overrides `existingSecret`) | `nil` | -| `global.postgresql.postgresqlPassword` | PostgreSQL admin password (overrides `postgresqlPassword`) | `nil` | -| `global.postgresql.servicePort` | PostgreSQL port (overrides `service.port`) | `nil` | -| `global.postgresql.replicationPassword` | Replication user password (overrides `replication.password`) | `nil` | -| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | -| `image.registry` | PostgreSQL Image registry | `docker.io` | -| `image.repository` | PostgreSQL Image name | `bitnami/postgresql` | -| `image.tag` | PostgreSQL Image tag | `{TAG_NAME}` | -| `image.pullPolicy` | PostgreSQL Image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Specify Image pull secrets | `nil` (does not add image pull secrets to deployed pods) | -| `image.debug` | Specify if debug values should be set | `false` | -| `nameOverride` | String to partially override postgresql.fullname template with a string (will prepend the release name) | `nil` | -| `fullnameOverride` | String to fully override postgresql.fullname template with a string | `nil` | -| `volumePermissions.enabled` | Enable init container that changes volume permissions in the data directory (for cases where the default k8s `runAsUser` and `fsUser` values do not work) | `false` | -| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | -| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/minideb` | -| `volumePermissions.image.tag` | Init container volume-permissions image tag | `buster` | -| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | -| `volumePermissions.securityContext.*` | Other container security context to be included as-is in the container spec | `{}` | -| `volumePermissions.securityContext.runAsUser` | User ID for the init container (when facing issues in OpenShift or uid unknown, try value "auto") | `0` | -| `usePasswordFile` | Have the secrets mounted as a file instead of env vars | `false` | -| `ldap.enabled` | Enable LDAP support | `false` | -| `ldap.existingSecret` | Name of existing secret to use for LDAP passwords | `nil` | -| `ldap.url` | LDAP URL beginning in the form `ldap[s]://host[:port]/basedn[?[attribute][?[scope][?[filter]]]]` | `nil` | -| `ldap.server` | IP address or name of the LDAP server. | `nil` | -| `ldap.port` | Port number on the LDAP server to connect to | `nil` | -| `ldap.scheme` | Set to `ldaps` to use LDAPS. | `nil` | -| `ldap.tls` | Set to `1` to use TLS encryption | `nil` | -| `ldap.prefix` | String to prepend to the user name when forming the DN to bind | `nil` | -| `ldap.suffix` | String to append to the user name when forming the DN to bind | `nil` | -| `ldap.search_attr` | Attribute to match agains the user name in the search | `nil` | -| `ldap.search_filter` | The search filter to use when doing search+bind authentication | `nil` | -| `ldap.baseDN` | Root DN to begin the search for the user in | `nil` | -| `ldap.bindDN` | DN of user to bind to LDAP | `nil` | -| `ldap.bind_password` | Password for the user to bind to LDAP | `nil` | -| `replication.enabled` | Enable replication | `false` | -| `replication.user` | Replication user | `repl_user` | -| `replication.password` | Replication user password | `repl_password` | -| `replication.slaveReplicas` | Number of slaves replicas | `1` | -| `replication.synchronousCommit` | Set synchronous commit mode. Allowed values: `on`, `remote_apply`, `remote_write`, `local` and `off` | `off` | -| `replication.numSynchronousReplicas` | Number of replicas that will have synchronous replication. Note: Cannot be greater than `replication.slaveReplicas`. | `0` | -| `replication.applicationName` | Cluster application name. Useful for advanced replication settings | `my_application` | -| `existingSecret` | Name of existing secret to use for PostgreSQL passwords. The secret has to contain the keys `postgresql-password` which is the password for `postgresqlUsername` when it is different of `postgres`, `postgresql-postgres-password` which will override `postgresqlPassword`, `postgresql-replication-password` which will override `replication.password` and `postgresql-ldap-password` which will be sed to authenticate on LDAP. The value is evaluated as a template. | `nil` | -| `postgresqlPostgresPassword` | PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`, in which case`postgres` is the admin username). | _random 10 character alphanumeric string_ | -| `postgresqlUsername` | PostgreSQL user (creates a non-admin user when `postgresqlUsername` is not `postgres`) | `postgres` | -| `postgresqlPassword` | PostgreSQL user password | _random 10 character alphanumeric string_ | -| `postgresqlDatabase` | PostgreSQL database | `nil` | -| `postgresqlDataDir` | PostgreSQL data dir folder | `/bitnami/postgresql` (same value as persistence.mountPath) | -| `extraEnv` | Any extra environment variables you would like to pass on to the pod. The value is evaluated as a template. | `[]` | -| `extraEnvVarsCM` | Name of a Config Map containing extra environment variables you would like to pass on to the pod. The value is evaluated as a template. | `nil` | -| `postgresqlInitdbArgs` | PostgreSQL initdb extra arguments | `nil` | -| `postgresqlInitdbWalDir` | PostgreSQL location for transaction log | `nil` | -| `postgresqlConfiguration` | Runtime Config Parameters | `nil` | -| `postgresqlExtendedConf` | Extended Runtime Config Parameters (appended to main or default configuration) | `nil` | -| `pgHbaConfiguration` | Content of pg_hba.conf | `nil (do not create pg_hba.conf)` | -| `postgresqlSharedPreloadLibraries` | Shared preload libraries (comma-separated list) | `pgaudit` | -| `postgresqlMaxConnections` | Maximum total connections | `nil` | -| `postgresqlPostgresConnectionLimit` | Maximum total connections for the postgres user | `nil` | -| `postgresqlDbUserConnectionLimit` | Maximum total connections for the non-admin user | `nil` | -| `postgresqlTcpKeepalivesInterval` | TCP keepalives interval | `nil` | -| `postgresqlTcpKeepalivesIdle` | TCP keepalives idle | `nil` | -| `postgresqlTcpKeepalivesCount` | TCP keepalives count | `nil` | -| `postgresqlStatementTimeout` | Statement timeout | `nil` | -| `postgresqlPghbaRemoveFilters` | Comma-separated list of patterns to remove from the pg_hba.conf file | `nil` | -| `customLivenessProbe` | Override default liveness probe | `nil` | -| `customReadinessProbe` | Override default readiness probe | `nil` | -| `audit.logHostname` | Add client hostnames to the log file | `false` | -| `audit.logConnections` | Add client log-in operations to the log file | `false` | -| `audit.logDisconnections` | Add client log-outs operations to the log file | `false` | -| `audit.pgAuditLog` | Add operations to log using the pgAudit extension | `nil` | -| `audit.clientMinMessages` | Message log level to share with the user | `nil` | -| `audit.logLinePrefix` | Template string for the log line prefix | `nil` | -| `audit.logTimezone` | Timezone for the log timestamps | `nil` | -| `configurationConfigMap` | ConfigMap with the PostgreSQL configuration files (Note: Overrides `postgresqlConfiguration` and `pgHbaConfiguration`). The value is evaluated as a template. | `nil` | -| `extendedConfConfigMap` | ConfigMap with the extended PostgreSQL configuration files. The value is evaluated as a template. | `nil` | -| `initdbScripts` | Dictionary of initdb scripts | `nil` | -| `initdbUser` | PostgreSQL user to execute the .sql and sql.gz scripts | `nil` | -| `initdbPassword` | Password for the user specified in `initdbUser` | `nil` | -| `initdbScriptsConfigMap` | ConfigMap with the initdb scripts (Note: Overrides `initdbScripts`). The value is evaluated as a template. | `nil` | -| `initdbScriptsSecret` | Secret with initdb scripts that contain sensitive information (Note: can be used with `initdbScriptsConfigMap` or `initdbScripts`). The value is evaluated as a template. | `nil` | -| `service.type` | Kubernetes Service type | `ClusterIP` | -| `service.port` | PostgreSQL port | `5432` | -| `service.nodePort` | Kubernetes Service nodePort | `nil` | -| `service.annotations` | Annotations for PostgreSQL service | `{}` (evaluated as a template) | -| `service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` | -| `service.loadBalancerSourceRanges` | Address that are allowed when svc is LoadBalancer | `[]` (evaluated as a template) | -| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | -| `shmVolume.enabled` | Enable emptyDir volume for /dev/shm for master and slave(s) Pod(s) | `true` | -| `shmVolume.chmod.enabled` | Run at init chmod 777 of the /dev/shm (ignored if `volumePermissions.enabled` is `false`) | `true` | -| `persistence.enabled` | Enable persistence using PVC | `true` | -| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim`, the value is evaluated as a template. | `nil` | -| `persistence.mountPath` | Path to mount the volume at | `/bitnami/postgresql` | -| `persistence.subPath` | Subdirectory of the volume to mount at | `""` | -| `persistence.storageClass` | PVC Storage Class for PostgreSQL volume | `nil` | -| `persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `[ReadWriteOnce]` | -| `persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` | -| `persistence.annotations` | Annotations for the PVC | `{}` | -| `commonAnnotations` | Annotations to be added to all deployed resources (rendered as a template) | `{}` | -| `master.nodeSelector` | Node labels for pod assignment (postgresql master) | `{}` | -| `master.affinity` | Affinity labels for pod assignment (postgresql master) | `{}` | -| `master.tolerations` | Toleration labels for pod assignment (postgresql master) | `[]` | -| `master.anotations` | Map of annotations to add to the statefulset (postgresql master) | `{}` | -| `master.labels` | Map of labels to add to the statefulset (postgresql master) | `{}` | -| `master.podAnnotations` | Map of annotations to add to the pods (postgresql master) | `{}` | -| `master.podLabels` | Map of labels to add to the pods (postgresql master) | `{}` | -| `master.priorityClassName` | Priority Class to use for each pod (postgresql master) | `nil` | -| `master.extraInitContainers` | Additional init containers to add to the pods (postgresql master) | `[]` | -| `master.extraVolumeMounts` | Additional volume mounts to add to the pods (postgresql master) | `[]` | -| `master.extraVolumes` | Additional volumes to add to the pods (postgresql master) | `[]` | -| `master.sidecars` | Add additional containers to the pod | `[]` | -| `master.service.type` | Allows using a different service type for Master | `nil` | -| `master.service.nodePort` | Allows using a different nodePort for Master | `nil` | -| `master.service.clusterIP` | Allows using a different clusterIP for Master | `nil` | -| `masterAsStandBy.enabled` | Whether to enable current cluster's Master as standby server of another cluster or not. | `false` | -| `masterAsStandBy.masterHost` | The Host of replication Master in the other cluster. | `nil` | -| `masterAsStandBy.masterPort ` | The Port of replication Master in the other cluster. | `nil` | -| `slave.nodeSelector` | Node labels for pod assignment (postgresql slave) | `{}` | -| `slave.affinity` | Affinity labels for pod assignment (postgresql slave) | `{}` | -| `slave.tolerations` | Toleration labels for pod assignment (postgresql slave) | `[]` | -| `slave.anotations` | Map of annotations to add to the statefulsets (postgresql slave) | `{}` | -| `slave.resources` | CPU/Memory resource requests/limits override for slaves. Will fallback to `values.resources` if not defined. | `{}` | -| `slave.labels` | Map of labels to add to the statefulsets (postgresql slave) | `{}` | -| `slave.podAnnotations` | Map of annotations to add to the pods (postgresql slave) | `{}` | -| `slave.podLabels` | Map of labels to add to the pods (postgresql slave) | `{}` | -| `slave.priorityClassName` | Priority Class to use for each pod (postgresql slave) | `nil` | -| `slave.extraInitContainers` | Additional init containers to add to the pods (postgresql slave) | `[]` | -| `slave.extraVolumeMounts` | Additional volume mounts to add to the pods (postgresql slave) | `[]` | -| `slave.extraVolumes` | Additional volumes to add to the pods (postgresql slave) | `[]` | -| `slave.sidecars` | Add additional containers to the pod | `[]` | -| `slave.service.type` | Allows using a different service type for Slave | `nil` | -| `slave.service.nodePort` | Allows using a different nodePort for Slave | `nil` | -| `slave.service.clusterIP` | Allows using a different clusterIP for Slave | `nil` | -| `slave.persistence.enabled` | Whether to enable slave replicas persistence | `true` | -| `terminationGracePeriodSeconds` | Seconds the pod needs to terminate gracefully | `nil` | -| `resources` | CPU/Memory resource requests/limits | Memory: `256Mi`, CPU: `250m` | -| `securityContext.*` | Other pod security context to be included as-is in the pod spec | `{}` | -| `securityContext.enabled` | Enable security context | `true` | -| `securityContext.fsGroup` | Group ID for the pod | `1001` | -| `containerSecurityContext.*` | Other container security context to be included as-is in the container spec | `{}` | -| `containerSecurityContext.enabled` | Enable container security context | `true` | -| `containerSecurityContext.runAsUser` | User ID for the container | `1001` | -| `serviceAccount.enabled` | Enable service account (Note: Service Account will only be automatically created if `serviceAccount.name` is not set) | `false` | -| `serviceAccount.name` | Name of existing service account | `nil` | -| `livenessProbe.enabled` | Would you like a livenessProbe to be enabled | `true` | -| `networkPolicy.enabled` | Enable NetworkPolicy | `false` | -| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | -| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed | `{}` | -| `livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 30 | -| `livenessProbe.periodSeconds` | How often to perform the probe | 10 | -| `livenessProbe.timeoutSeconds` | When the probe times out | 5 | -| `livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | -| `livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | -| `readinessProbe.enabled` | would you like a readinessProbe to be enabled | `true` | -| `readinessProbe.initialDelaySeconds` | Delay before readiness probe is initiated | 5 | -| `readinessProbe.periodSeconds` | How often to perform the probe | 10 | -| `readinessProbe.timeoutSeconds` | When the probe times out | 5 | -| `readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | -| `readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | -| `tls.enabled` | Enable TLS traffic support | `false` | -| `tls.preferServerCiphers` | Whether to use the server's TLS cipher preferences rather than the client's | `true` | -| `tls.certificatesSecret` | Name of an existing secret that contains the certificates | `nil` | -| `tls.certFilename` | Certificate filename | `""` | -| `tls.certKeyFilename` | Certificate key filename | `""` | -| `tls.certCAFilename` | CA Certificate filename. If provided, PostgreSQL will authenticate TLS/SSL clients by requesting them a certificate. | `nil` | -| `tls.crlFilename` | File containing a Certificate Revocation List | `nil` | -| `metrics.enabled` | Start a prometheus exporter | `false` | -| `metrics.service.type` | Kubernetes Service type | `ClusterIP` | -| `service.clusterIP` | Static clusterIP or None for headless services | `nil` | -| `metrics.service.annotations` | Additional annotations for metrics exporter pod | `{ prometheus.io/scrape: "true", prometheus.io/port: "9187"}` | -| `metrics.service.loadBalancerIP` | loadBalancerIP if redis metrics service type is `LoadBalancer` | `nil` | -| `metrics.serviceMonitor.enabled` | Set this to `true` to create ServiceMonitor for Prometheus operator | `false` | -| `metrics.serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` | -| `metrics.serviceMonitor.namespace` | Optional namespace in which to create ServiceMonitor | `nil` | -| `metrics.serviceMonitor.interval` | Scrape interval. If not set, the Prometheus default scrape interval is used | `nil` | -| `metrics.serviceMonitor.scrapeTimeout` | Scrape timeout. If not set, the Prometheus default scrape timeout is used | `nil` | -| `metrics.prometheusRule.enabled` | Set this to true to create prometheusRules for Prometheus operator | `false` | -| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so prometheusRules will be discovered by Prometheus | `{}` | -| `metrics.prometheusRule.namespace` | namespace where prometheusRules resource should be created | the same namespace as postgresql | -| `metrics.prometheusRule.rules` | [rules](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/) to be created, check values for an example. | `[]` | -| `metrics.image.registry` | PostgreSQL Exporter Image registry | `docker.io` | -| `metrics.image.repository` | PostgreSQL Exporter Image name | `bitnami/postgres-exporter` | -| `metrics.image.tag` | PostgreSQL Exporter Image tag | `{TAG_NAME}` | -| `metrics.image.pullPolicy` | PostgreSQL Exporter Image pull policy | `IfNotPresent` | -| `metrics.image.pullSecrets` | Specify Image pull secrets | `nil` (does not add image pull secrets to deployed pods) | -| `metrics.customMetrics` | Additional custom metrics | `nil` | -| `metrics.extraEnvVars` | Extra environment variables to add to exporter | `{}` (evaluated as a template) | -| `metrics.securityContext.*` | Other container security context to be included as-is in the container spec | `{}` | -| `metrics.securityContext.enabled` | Enable security context for metrics | `false` | -| `metrics.securityContext.runAsUser` | User ID for the container for metrics | `1001` | -| `metrics.livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 30 | -| `metrics.livenessProbe.periodSeconds` | How often to perform the probe | 10 | -| `metrics.livenessProbe.timeoutSeconds` | When the probe times out | 5 | -| `metrics.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | -| `metrics.livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | -| `metrics.readinessProbe.enabled` | would you like a readinessProbe to be enabled | `true` | -| `metrics.readinessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 5 | -| `metrics.readinessProbe.periodSeconds` | How often to perform the probe | 10 | -| `metrics.readinessProbe.timeoutSeconds` | When the probe times out | 5 | -| `metrics.readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | -| `metrics.readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | -| `updateStrategy` | Update strategy policy | `{type: "RollingUpdate"}` | -| `psp.create` | Create Pod Security Policy | `false` | -| `rbac.create` | Create Role and RoleBinding (required for PSP to work) | `false` | -| `extraDeploy` | Array of extra objects to deploy with the release (evaluated as a template). | `nil` | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, - -```console -$ helm install my-release \ - --set postgresqlPassword=secretpassword,postgresqlDatabase=my-database \ - bitnami/postgresql -``` - -The above command sets the PostgreSQL `postgres` account password to `secretpassword`. Additionally it creates a database named `my-database`. - -Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, - -```console -$ helm install my-release -f values.yaml bitnami/postgresql -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -## Configuration and installation details - -### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) - -It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. - -Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. - -### Production configuration and horizontal scaling - -This chart includes a `values-production.yaml` file where you can find some parameters oriented to production configuration in comparison to the regular `values.yaml`. You can use this file instead of the default one. - -- Enable replication: -```diff -- replication.enabled: false -+ replication.enabled: true -``` - -- Number of slaves replicas: -```diff -- replication.slaveReplicas: 1 -+ replication.slaveReplicas: 2 -``` - -- Set synchronous commit mode: -```diff -- replication.synchronousCommit: "off" -+ replication.synchronousCommit: "on" -``` - -- Number of replicas that will have synchronous replication: -```diff -- replication.numSynchronousReplicas: 0 -+ replication.numSynchronousReplicas: 1 -``` - -- Start a prometheus exporter: -```diff -- metrics.enabled: false -+ metrics.enabled: true -``` - -To horizontally scale this chart, you can use the `--replicas` flag to modify the number of nodes in your PostgreSQL deployment. Also you can use the `values-production.yaml` file or modify the parameters shown above. - -### Customizing Master and Slave services in a replicated configuration - -At the top level, there is a service object which defines the services for both master and slave. For deeper customization, there are service objects for both the master and slave types individually. This allows you to override the values in the top level service object so that the master and slave can be of different service types and with different clusterIPs / nodePorts. Also in the case you want the master and slave to be of type nodePort, you will need to set the nodePorts to different values to prevent a collision. The values that are deeper in the master.service or slave.service objects will take precedence over the top level service object. - -### Change PostgreSQL version - -To modify the PostgreSQL version used in this chart you can specify a [valid image tag](https://hub.docker.com/r/bitnami/postgresql/tags/) using the `image.tag` parameter. For example, `image.tag=X.Y.Z`. This approach is also applicable to other images like exporters. - -### postgresql.conf / pg_hba.conf files as configMap - -This helm chart also supports to customize the whole configuration file. - -Add your custom file to "files/postgresql.conf" in your working directory. This file will be mounted as configMap to the containers and it will be used for configuring the PostgreSQL server. - -Alternatively, you can specify PostgreSQL configuration parameters using the `postgresqlConfiguration` parameter as a dict, using camelCase, e.g. {"sharedBuffers": "500MB"}. - -In addition to these options, you can also set an external ConfigMap with all the configuration files. This is done by setting the `configurationConfigMap` parameter. Note that this will override the two previous options. - -### Allow settings to be loaded from files other than the default `postgresql.conf` - -If you don't want to provide the whole PostgreSQL configuration file and only specify certain parameters, you can add your extended `.conf` files to "files/conf.d/" in your working directory. -Those files will be mounted as configMap to the containers adding/overwriting the default configuration using the `include_dir` directive that allows settings to be loaded from files other than the default `postgresql.conf`. - -Alternatively, you can also set an external ConfigMap with all the extra configuration files. This is done by setting the `extendedConfConfigMap` parameter. Note that this will override the previous option. - -### Initialize a fresh instance - -The [Bitnami PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) image allows you to use your custom scripts to initialize a fresh instance. In order to execute the scripts, they must be located inside the chart folder `files/docker-entrypoint-initdb.d` so they can be consumed as a ConfigMap. - -Alternatively, you can specify custom scripts using the `initdbScripts` parameter as dict. - -In addition to these options, you can also set an external ConfigMap with all the initialization scripts. This is done by setting the `initdbScriptsConfigMap` parameter. Note that this will override the two previous options. If your initialization scripts contain sensitive information such as credentials or passwords, you can use the `initdbScriptsSecret` parameter. - -The allowed extensions are `.sh`, `.sql` and `.sql.gz`. - -### Securing traffic using TLS - -TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the chart: - -- `tls.enabled`: Enable TLS support. Defaults to `false` -- `tls.certificatesSecret`: Name of an existing secret that contains the certificates. No defaults. -- `tls.certFilename`: Certificate filename. No defaults. -- `tls.certKeyFilename`: Certificate key filename. No defaults. - -For example: - -* First, create the secret with the cetificates files: - - ```console - kubectl create secret generic certificates-tls-secret --from-file=./cert.crt --from-file=./cert.key --from-file=./ca.crt - ``` - -* Then, use the following parameters: - - ```console - volumePermissions.enabled=true - tls.enabled=true - tls.certificatesSecret="certificates-tls-secret" - tls.certFilename="cert.crt" - tls.certKeyFilename="cert.key" - ``` - - > Note TLS and VolumePermissions: PostgreSQL requires certain permissions on sensitive files (such as certificate keys) to start up. Due to an on-going [issue](https://github.com/kubernetes/kubernetes/issues/57923) regarding kubernetes permissions and the use of `containerSecurityContext.runAsUser`, you must enable `volumePermissions` to ensure everything works as expected. - -### Sidecars - -If you need additional containers to run within the same pod as PostgreSQL (e.g. an additional metrics or logging exporter), you can do so via the `sidecars` config parameter. Simply define your container according to the Kubernetes container spec. - -```yaml -# For the PostgreSQL master -master: - sidecars: - - name: your-image-name - image: your-image - imagePullPolicy: Always - ports: - - name: portname - containerPort: 1234 -# For the PostgreSQL replicas -slave: - sidecars: - - name: your-image-name - image: your-image - imagePullPolicy: Always - ports: - - name: portname - containerPort: 1234 -``` - -### Metrics - -The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9187) is not exposed and it is expected that the metrics are collected from inside the k8s cluster using something similar as the described in the [example Prometheus scrape configuration](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml). - -The exporter allows to create custom metrics from additional SQL queries. See the Chart's `values.yaml` for an example and consult the [exporters documentation](https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file) for more details. - -### Use of global variables - -In more complex scenarios, we may have the following tree of dependencies - -``` - +--------------+ - | | - +------------+ Chart 1 +-----------+ - | | | | - | --------+------+ | - | | | - | | | - | | | - | | | - v v v -+-------+------+ +--------+------+ +--------+------+ -| | | | | | -| PostgreSQL | | Sub-chart 1 | | Sub-chart 2 | -| | | | | | -+--------------+ +---------------+ +---------------+ -``` - -The three charts below depend on the parent chart Chart 1. However, subcharts 1 and 2 may need to connect to PostgreSQL as well. In order to do so, subcharts 1 and 2 need to know the PostgreSQL credentials, so one option for deploying could be deploy Chart 1 with the following parameters: - -``` -postgresql.postgresqlPassword=testtest -subchart1.postgresql.postgresqlPassword=testtest -subchart2.postgresql.postgresqlPassword=testtest -postgresql.postgresqlDatabase=db1 -subchart1.postgresql.postgresqlDatabase=db1 -subchart2.postgresql.postgresqlDatabase=db1 -``` - -If the number of dependent sub-charts increases, installing the chart with parameters can become increasingly difficult. An alternative would be to set the credentials using global variables as follows: - -``` -global.postgresql.postgresqlPassword=testtest -global.postgresql.postgresqlDatabase=db1 -``` - -This way, the credentials will be available in all of the subcharts. - -## Persistence - -The [Bitnami PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) image stores the PostgreSQL data and configurations at the `/bitnami/postgresql` path of the container. - -Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. -See the [Parameters](#parameters) section to configure the PVC or to disable persistence. - -If you already have data in it, you will fail to sync to standby nodes for all commits, details can refer to [code](https://github.com/bitnami/bitnami-docker-postgresql/blob/8725fe1d7d30ebe8d9a16e9175d05f7ad9260c93/9.6/debian-9/rootfs/libpostgresql.sh#L518-L556). If you need to use those data, please covert them to sql and import after `helm install` finished. - -## NetworkPolicy - -To enable network policy for PostgreSQL, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), and set `networkPolicy.enabled` to `true`. - -For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting the DefaultDeny namespace annotation. Note: this will enforce policy for _all_ pods in the namespace: - -```console -$ kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" -``` - -With NetworkPolicy enabled, traffic will be limited to just port 5432. - -For more precise policy, set `networkPolicy.allowExternal=false`. This will only allow pods with the generated client label to connect to PostgreSQL. -This label will be displayed in the output of a successful install. - -## Differences between Bitnami PostgreSQL image and [Docker Official](https://hub.docker.com/_/postgres) image - -- The Docker Official PostgreSQL image does not support replication. If you pass any replication environment variable, this would be ignored. The only environment variables supported by the Docker Official image are POSTGRES_USER, POSTGRES_DB, POSTGRES_PASSWORD, POSTGRES_INITDB_ARGS, POSTGRES_INITDB_WALDIR and PGDATA. All the remaining environment variables are specific to the Bitnami PostgreSQL image. -- The Bitnami PostgreSQL image is non-root by default. This requires that you run the pod with `securityContext` and updates the permissions of the volume with an `initContainer`. A key benefit of this configuration is that the pod follows security best practices and is prepared to run on Kubernetes distributions with hard security constraints like OpenShift. -- For OpenShift, one may either define the runAsUser and fsGroup accordingly, or try this more dynamic option: volumePermissions.securityContext.runAsUser="auto",securityContext.enabled=false,containerSecurityContext.enabled=false,shmVolume.chmod.enabled=false - -### Deploy chart using Docker Official PostgreSQL Image - -From chart version 4.0.0, it is possible to use this chart with the Docker Official PostgreSQL image. -Besides specifying the new Docker repository and tag, it is important to modify the PostgreSQL data directory and volume mount point. Basically, the PostgreSQL data dir cannot be the mount point directly, it has to be a subdirectory. - -``` -image.repository=postgres -image.tag=10.6 -postgresqlDataDir=/data/pgdata -persistence.mountPath=/data/ -``` - -## Upgrade - -It's necessary to specify the existing passwords while performing an upgrade to ensure the secrets are not updated with invalid randomly generated passwords. Remember to specify the existing values of the `postgresqlPassword` and `replication.password` parameters when upgrading the chart: - -```bash -$ helm upgrade my-release stable/postgresql \ - --set postgresqlPassword=[POSTGRESQL_PASSWORD] \ - --set replication.password=[REPLICATION_PASSWORD] -``` - -> Note: you need to substitute the placeholders _[POSTGRESQL_PASSWORD]_, and _[REPLICATION_PASSWORD]_ with the values obtained from instructions in the installation notes. - -## 9.0.0 - -In this version the chart was adapted to follow the Helm label best practices, see [PR 3021](https://github.com/bitnami/charts/pull/3021). That means the backward compatibility is not guarantee when upgrading the chart to this major version. - -As a workaround, you can delete the existing statefulset (using the `--cascade=false` flag pods are not deleted) before upgrade the chart. For example, this can be a valid workflow: - -- Deploy an old version (8.X.X) -```console -$ helm install postgresql bitnami/postgresql --version 8.10.14 -``` - -- Old version is up and running -```console -$ helm ls -NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION -postgresql default 1 2020-08-04 13:39:54.783480286 +0000 UTC deployed postgresql-8.10.14 11.8.0 - -$ kubectl get pods -NAME READY STATUS RESTARTS AGE -postgresql-postgresql-0 1/1 Running 0 76s -``` - -- The upgrade to the latest one (9.X.X) is going to fail -```console -$ helm upgrade postgresql bitnami/postgresql -Error: UPGRADE FAILED: cannot patch "postgresql-postgresql" with kind StatefulSet: StatefulSet.apps "postgresql-postgresql" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden -``` - -- Delete the statefulset -```console -$ kubectl delete statefulsets.apps --cascade=false postgresql-postgresql -statefulset.apps "postgresql-postgresql" deleted -``` - -- Now the upgrade works -```cosnole -$ helm upgrade postgresql bitnami/postgresql -$ helm ls -NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION -postgresql default 3 2020-08-04 13:42:08.020385884 +0000 UTC deployed postgresql-9.1.2 11.8.0 -``` - -- We can kill the existing pod and the new statefulset is going to create a new one: -```console -$ kubectl delete pod postgresql-postgresql-0 -pod "postgresql-postgresql-0" deleted - -$ kubectl get pods -NAME READY STATUS RESTARTS AGE -postgresql-postgresql-0 1/1 Running 0 19s -``` - -Please, note that without the `--cascade=false` both objects (statefulset and pod) are going to be removed and both objects will be deployed again with the `helm upgrade` command - -## 8.0.0 - -Prefixes the port names with their protocols to comply with Istio conventions. - -If you depend on the port names in your setup, make sure to update them to reflect this change. - -## 7.1.0 - -Adds support for LDAP configuration. - -## 7.0.0 - -Helm performs a lookup for the object based on its group (apps), version (v1), and kind (Deployment). Also known as its GroupVersionKind, or GVK. Changing the GVK is considered a compatibility breaker from Kubernetes' point of view, so you cannot "upgrade" those objects to the new GVK in-place. Earlier versions of Helm 3 did not perform the lookup correctly which has since been fixed to match the spec. - -In https://github.com/helm/charts/pull/17281 the `apiVersion` of the statefulset resources was updated to `apps/v1` in tune with the api's deprecated, resulting in compatibility breakage. - -This major version bump signifies this change. - -## 6.5.7 - -In this version, the chart will use PostgreSQL with the Postgis extension included. The version used with Postgresql version 10, 11 and 12 is Postgis 2.5. It has been compiled with the following dependencies: - -- protobuf -- protobuf-c -- json-c -- geos -- proj - -## 5.0.0 - -In this version, the **chart is using PostgreSQL 11 instead of PostgreSQL 10**. You can find the main difference and notable changes in the following links: [https://www.postgresql.org/about/news/1894/](https://www.postgresql.org/about/news/1894/) and [https://www.postgresql.org/about/featurematrix/](https://www.postgresql.org/about/featurematrix/). - -For major releases of PostgreSQL, the internal data storage format is subject to change, thus complicating upgrades, you can see some errors like the following one in the logs: - -```console -Welcome to the Bitnami postgresql container -Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-postgresql -Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-postgresql/issues -Send us your feedback at containers@bitnami.com - -INFO ==> ** Starting PostgreSQL setup ** -NFO ==> Validating settings in POSTGRESQL_* env vars.. -INFO ==> Initializing PostgreSQL database... -INFO ==> postgresql.conf file not detected. Generating it... -INFO ==> pg_hba.conf file not detected. Generating it... -INFO ==> Deploying PostgreSQL with persisted data... -INFO ==> Configuring replication parameters -INFO ==> Loading custom scripts... -INFO ==> Enabling remote connections -INFO ==> Stopping PostgreSQL... -INFO ==> ** PostgreSQL setup finished! ** - -INFO ==> ** Starting PostgreSQL ** - [1] FATAL: database files are incompatible with server - [1] DETAIL: The data directory was initialized by PostgreSQL version 10, which is not compatible with this version 11.3. -``` - -In this case, you should migrate the data from the old chart to the new one following an approach similar to that described in [this section](https://www.postgresql.org/docs/current/upgrading.html#UPGRADING-VIA-PGDUMPALL) from the official documentation. Basically, create a database dump in the old chart, move and restore it in the new one. - -### 4.0.0 - -This chart will use by default the Bitnami PostgreSQL container starting from version `10.7.0-r68`. This version moves the initialization logic from node.js to bash. This new version of the chart requires setting the `POSTGRES_PASSWORD` in the slaves as well, in order to properly configure the `pg_hba.conf` file. Users from previous versions of the chart are advised to upgrade immediately. - -IMPORTANT: If you do not want to upgrade the chart version then make sure you use the `10.7.0-r68` version of the container. Otherwise, you will get this error - -``` -The POSTGRESQL_PASSWORD environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development -``` - -### 3.0.0 - -This releases make it possible to specify different nodeSelector, affinity and tolerations for master and slave pods. -It also fixes an issue with `postgresql.master.fullname` helper template not obeying fullnameOverride. - -#### Breaking changes - -- `affinty` has been renamed to `master.affinity` and `slave.affinity`. -- `tolerations` has been renamed to `master.tolerations` and `slave.tolerations`. -- `nodeSelector` has been renamed to `master.nodeSelector` and `slave.nodeSelector`. - -### 2.0.0 - -In order to upgrade from the `0.X.X` branch to `1.X.X`, you should follow the below steps: - - - Obtain the service name (`SERVICE_NAME`) and password (`OLD_PASSWORD`) of the existing postgresql chart. You can find the instructions to obtain the password in the NOTES.txt, the service name can be obtained by running - -```console -$ kubectl get svc -``` - -- Install (not upgrade) the new version - -```console -$ helm repo update -$ helm install my-release bitnami/postgresql -``` - -- Connect to the new pod (you can obtain the name by running `kubectl get pods`): - -```console -$ kubectl exec -it NAME bash -``` - -- Once logged in, create a dump file from the previous database using `pg_dump`, for that we should connect to the previous postgresql chart: - -```console -$ pg_dump -h SERVICE_NAME -U postgres DATABASE_NAME > /tmp/backup.sql -``` - -After run above command you should be prompted for a password, this password is the previous chart password (`OLD_PASSWORD`). -This operation could take some time depending on the database size. - -- Once you have the backup file, you can restore it with a command like the one below: - -```console -$ psql -U postgres DATABASE_NAME < /tmp/backup.sql -``` - -In this case, you are accessing to the local postgresql, so the password should be the new one (you can find it in NOTES.txt). - -If you want to restore the database and the database schema does not exist, it is necessary to first follow the steps described below. - -```console -$ psql -U postgres -postgres=# drop database DATABASE_NAME; -postgres=# create database DATABASE_NAME; -postgres=# create user USER_NAME; -postgres=# alter role USER_NAME with password 'BITNAMI_USER_PASSWORD'; -postgres=# grant all privileges on database DATABASE_NAME to USER_NAME; -postgres=# alter database DATABASE_NAME owner to USER_NAME; -``` diff --git a/scripts/helm/db/postgresql/charts/common/.helmignore b/scripts/helm/db/postgresql/charts/common/.helmignore deleted file mode 100755 index 50af03172..000000000 --- a/scripts/helm/db/postgresql/charts/common/.helmignore +++ /dev/null @@ -1,22 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/scripts/helm/db/postgresql/charts/common/Chart.yaml b/scripts/helm/db/postgresql/charts/common/Chart.yaml deleted file mode 100755 index 5566cdc21..000000000 --- a/scripts/helm/db/postgresql/charts/common/Chart.yaml +++ /dev/null @@ -1,22 +0,0 @@ -annotations: - category: Infrastructure -apiVersion: v1 -appVersion: 0.8.1 -description: A Library Helm Chart for grouping common logic between bitnami charts. - This chart is not deployable by itself. -home: https://github.com/bitnami/charts/tree/master/bitnami/common -icon: https://bitnami.com/downloads/logos/bitnami-mark.png -keywords: -- common -- helper -- template -- function -- bitnami -maintainers: -- email: containers@bitnami.com - name: Bitnami -name: common -sources: -- https://github.com/bitnami/charts -- http://www.bitnami.com/ -version: 0.8.1 diff --git a/scripts/helm/db/postgresql/charts/common/README.md b/scripts/helm/db/postgresql/charts/common/README.md deleted file mode 100755 index acdbe7bfa..000000000 --- a/scripts/helm/db/postgresql/charts/common/README.md +++ /dev/null @@ -1,286 +0,0 @@ -# Bitnami Common Library Chart - -A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between bitnami charts. - -## TL;DR - -```yaml -dependencies: - - name: common - version: 0.x.x - repository: https://charts.bitnami.com/bitnami -``` - -```bash -$ helm dependency update -``` - -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "common.names.fullname" . }} -data: - myvalue: "Hello World" -``` - -## Introduction - -This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 2.12+ or Helm 3.0-beta3+ - -## Parameters - -The following table lists the helpers available in the library which are scoped in different sections. - -### Affinities - -| Helper identifier | Description | Expected Input | -|-------------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------| -| `common.affinities.node.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | -| `common.affinities.node.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | -| `common.affinities.pod.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | -| `common.affinities.pod.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | - -### Capabilities - -| Helper identifier | Description | Expected Input | -|------------------------------------------------|-----------------------------------------------------------------|----------------------------| -| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | -| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | -| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | - -### Errors - -| Helper identifier | Description | Expected Input | -|------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| -| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | - -### Images - -| Helper identifier | Description | Expected Input | -|--------------------------------|-----------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| -| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | -| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | - -### Labels - -| Helper identifier | Description | Expected Input | -|--------------------------------|-----------------------------------------------------------------|-----------------------------| -| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | -| `common.labels.matchLabels` | Return the proper Docker Image Registry Secret Names | `.` Chart context | - -### Names - -| Helper identifier | Description | Expected Input | -|--------------------------------|-----------------------------------------------------------------|-----------------------------| -| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | -| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | -| `common.names.chart` | Chart name plus version | `.` Chart context | - -### Secrets - -| Helper identifier | Description | Expected Input | -|--------------------------------|-----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | -| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | - -### Storage - -| Helper identifier | Description | Expected Input | -|--------------------------------|-----------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------| -| `common.affinities.node.soft` | Return a soft nodeAffinity definition | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | - -### TplValues - -| Helper identifier | Description | Expected Input | -|--------------------------------|-----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| -| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frecuently is the chart context `$` or `.` | - -### Utils - -| Helper identifier | Description | Expected Input | -|--------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------------| -| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | -| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | -| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | - -### Validations - -| Helper identifier | Description | Expected Input | -|--------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "context" $` secret and field are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | -| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | -| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use postgresql chart and the helper. | -| `common.validations.values.postgresql.passwords` | This helper will ensure required password for PostgreSQL are not empty. It returns a shared error for all the values. | `dict "secret" "postgresql-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use postgresql chart and the helper. | - -### Warnings - -| Helper identifier | Description | Expected Input | -|--------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------| -| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | - -## Special input schemas - -### ImageRoot - -```yaml -registry: - type: string - description: Docker registry where the image is located - example: docker.io - -repository: - type: string - description: Repository and image name - example: bitnami/nginx - -tag: - type: string - description: image tag - example: 1.16.1-debian-10-r63 - -pullPolicy: - type: string - description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - -pullSecrets: - type: array - items: - type: string - description: Optionally specify an array of imagePullSecrets. - -debug: - type: boolean - description: Set to true if you would like to see extra information on logs - example: false - -## An instance would be: -# registry: docker.io -# repository: bitnami/nginx -# tag: 1.16.1-debian-10-r63 -# pullPolicy: IfNotPresent -# debug: false -``` - -### Persistence - -```yaml -enabled: - type: boolean - description: Whether enable persistence. - example: true - -storageClass: - type: string - description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. - example: "-" - -accessMode: - type: string - description: Access mode for the Persistent Volume Storage. - example: ReadWriteOnce - -size: - type: string - description: Size the Persistent Volume Storage. - example: 8Gi - -path: - type: string - description: Path to be persisted. - example: /bitnami - -## An instance would be: -# enabled: true -# storageClass: "-" -# accessMode: ReadWriteOnce -# size: 8Gi -# path: /bitnami -``` - -### ExistingSecret - -```yaml -name: - type: string - description: Name of the existing secret. - example: mySecret -keyMapping: - description: Mapping between the expected key name and the name of the key in the existing secret. - type: object - -## An instance would be: -# name: mySecret -# keyMapping: -# password: myPasswordKey -``` - -#### Example of use - -When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. - -```yaml -# templates/secret.yaml ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "common.names.fullname" . }} - labels: - app: {{ include "common.names.fullname" . }} -type: Opaque -data: - password: {{ .Values.password | b64enc | quote }} - -# templates/dpl.yaml ---- -... - env: - - name: PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} - key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} -... - -# values.yaml ---- -name: mySecret -keyMapping: - password: myPasswordKey -``` - -### ValidateValue - -#### NOTES.txt - -```console -{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} -{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} - -{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} -``` - -If we force those values to be empty we will see some alerts - -```console -$ helm install test mychart --set path.to.value00="",path.to.value01="" - 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: - - export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 --decode) - - 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: - - export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 --decode) -``` - -## Notable changes - -N/A diff --git a/scripts/helm/db/postgresql/charts/common/templates/_affinities.tpl b/scripts/helm/db/postgresql/charts/common/templates/_affinities.tpl deleted file mode 100755 index 40f575cb6..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_affinities.tpl +++ /dev/null @@ -1,94 +0,0 @@ -{{/* vim: set filetype=mustache: */}} - -{{/* -Return a soft nodeAffinity definition -{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} -*/}} -{{- define "common.affinities.nodes.soft" -}} -preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - key: {{ .key }} - operator: In - values: - {{- range .values }} - - {{ . }} - {{- end }} - weight: 1 -{{- end -}} - -{{/* -Return a hard nodeAffinity definition -{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} -*/}} -{{- define "common.affinities.nodes.hard" -}} -requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - key: {{ .key }} - operator: In - values: - {{- range .values }} - - {{ . }} - {{- end }} -{{- end -}} - -{{/* -Return a nodeAffinity definition -{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} -*/}} -{{- define "common.affinities.nodes" -}} - {{- if eq .type "soft" }} - {{- include "common.affinities.nodes.soft" . -}} - {{- else if eq .type "hard" }} - {{- include "common.affinities.nodes.hard" . -}} - {{- end -}} -{{- end -}} - -{{/* -Return a soft podAffinity/podAntiAffinity definition -{{ include "common.affinities.pods.soft" (dict "component" "FOO" "context" $) -}} -*/}} -{{- define "common.affinities.pods.soft" -}} -{{- $component := default "" .component -}} -preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 10 }} - {{- if not (empty $component) }} - {{ printf "app.kubernetes.io/component: %s" $component }} - {{- end }} - namespaces: - - {{ .context.Release.Namespace }} - topologyKey: kubernetes.io/hostname - weight: 1 -{{- end -}} - -{{/* -Return a hard podAffinity/podAntiAffinity definition -{{ include "common.affinities.pods.hard" (dict "component" "FOO" "context" $) -}} -*/}} -{{- define "common.affinities.pods.hard" -}} -{{- $component := default "" .component -}} -requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 8 }} - {{- if not (empty $component) }} - {{ printf "app.kubernetes.io/component: %s" $component }} - {{- end }} - namespaces: - - {{ .context.Release.Namespace }} - topologyKey: kubernetes.io/hostname -{{- end -}} - -{{/* -Return a podAffinity/podAntiAffinity definition -{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} -*/}} -{{- define "common.affinities.pods" -}} - {{- if eq .type "soft" }} - {{- include "common.affinities.pods.soft" . -}} - {{- else if eq .type "hard" }} - {{- include "common.affinities.pods.hard" . -}} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_capabilities.tpl b/scripts/helm/db/postgresql/charts/common/templates/_capabilities.tpl deleted file mode 100755 index 143bef2a4..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_capabilities.tpl +++ /dev/null @@ -1,33 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Return the appropriate apiVersion for deployment. -*/}} -{{- define "common.capabilities.deployment.apiVersion" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "extensions/v1beta1" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for statefulset. -*/}} -{{- define "common.capabilities.statefulset.apiVersion" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "apps/v1beta1" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for ingress. -*/}} -{{- define "common.capabilities.ingress.apiVersion" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "extensions/v1beta1" -}} -{{- else -}} -{{- print "networking.k8s.io/v1beta1" -}} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_errors.tpl b/scripts/helm/db/postgresql/charts/common/templates/_errors.tpl deleted file mode 100755 index d6d3ec65a..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_errors.tpl +++ /dev/null @@ -1,20 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Through error when upgrading using empty passwords values that must not be empty. - -Usage: -{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} -{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} -{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} - -Required password params: - - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. - - context - Context - Required. Parent context. -*/}} -{{- define "common.errors.upgrade.passwords.empty" -}} - {{- $validationErrors := join "" .validationErrors -}} - {{- if and $validationErrors .context.Release.IsUpgrade -}} - {{- $errorString := "\nPASSWORDS ERROR: you must provide your current passwords when upgrade the release%s" -}} - {{- printf $errorString $validationErrors | fail -}} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_images.tpl b/scripts/helm/db/postgresql/charts/common/templates/_images.tpl deleted file mode 100755 index aafde9f3b..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_images.tpl +++ /dev/null @@ -1,43 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Return the proper image name -{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" $) }} -*/}} -{{- define "common.images.image" -}} -{{- $registryName := .imageRoot.registry -}} -{{- $repositoryName := .imageRoot.repository -}} -{{- $tag := .imageRoot.tag | toString -}} -{{- if .global }} - {{- if .global.imageRegistry }} - {{- $registryName = .global.imageRegistry -}} - {{- end -}} -{{- end -}} -{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names -{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} -*/}} -{{- define "common.images.pullSecrets" -}} - {{- $pullSecrets := list }} - - {{- if .global }} - {{- range .global.imagePullSecrets -}} - {{- $pullSecrets = append $pullSecrets . -}} - {{- end -}} - {{- end -}} - - {{- range .images -}} - {{- range .pullSecrets -}} - {{- $pullSecrets = append $pullSecrets . -}} - {{- end -}} - {{- end -}} - - {{- if (not (empty $pullSecrets)) }} -imagePullSecrets: - {{- range $pullSecrets }} - - name: {{ . }} - {{- end }} - {{- end }} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_labels.tpl b/scripts/helm/db/postgresql/charts/common/templates/_labels.tpl deleted file mode 100755 index 252066c7e..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_labels.tpl +++ /dev/null @@ -1,18 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Kubernetes standard labels -*/}} -{{- define "common.labels.standard" -}} -app.kubernetes.io/name: {{ include "common.names.name" . }} -helm.sh/chart: {{ include "common.names.chart" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector -*/}} -{{- define "common.labels.matchLabels" -}} -app.kubernetes.io/name: {{ include "common.names.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_names.tpl b/scripts/helm/db/postgresql/charts/common/templates/_names.tpl deleted file mode 100755 index adf2a74f4..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_names.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "common.names.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "common.names.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "common.names.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_secrets.tpl b/scripts/helm/db/postgresql/charts/common/templates/_secrets.tpl deleted file mode 100755 index 8eee91d21..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_secrets.tpl +++ /dev/null @@ -1,49 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Generate secret name. - -Usage: -{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} - -Params: - - existingSecret - ExistingSecret - Optional. The path to the existing secrets in the values.yaml given by the user - to be used istead of the default one. +info: https://github.com/bitnami/charts/tree/master/bitnami/common#existingsecret - - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. - - context - Dict - Required. The context for the template evaluation. -*/}} -{{- define "common.secrets.name" -}} -{{- $name := (include "common.names.fullname" .context) -}} - -{{- if .defaultNameSuffix -}} -{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{- with .existingSecret -}} -{{- $name = .name -}} -{{- end -}} - -{{- printf "%s" $name -}} -{{- end -}} - -{{/* -Generate secret key. - -Usage: -{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} - -Params: - - existingSecret - ExistingSecret - Optional. The path to the existing secrets in the values.yaml given by the user - to be used istead of the default one. +info: https://github.com/bitnami/charts/tree/master/bitnami/common#existingsecret - - key - String - Required. Name of the key in the secret. -*/}} -{{- define "common.secrets.key" -}} -{{- $key := .key -}} - -{{- if .existingSecret -}} - {{- if .existingSecret.keyMapping -}} - {{- $key = index .existingSecret.keyMapping $.key -}} - {{- end -}} -{{- end -}} - -{{- printf "%s" $key -}} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_storage.tpl b/scripts/helm/db/postgresql/charts/common/templates/_storage.tpl deleted file mode 100755 index 60e2a844f..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_storage.tpl +++ /dev/null @@ -1,23 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Return the proper Storage Class -{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} -*/}} -{{- define "common.storage.class" -}} - -{{- $storageClass := .persistence.storageClass -}} -{{- if .global -}} - {{- if .global.storageClass -}} - {{- $storageClass = .global.storageClass -}} - {{- end -}} -{{- end -}} - -{{- if $storageClass -}} - {{- if (eq "-" $storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" $storageClass -}} - {{- end -}} -{{- end -}} - -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_tplvalues.tpl b/scripts/helm/db/postgresql/charts/common/templates/_tplvalues.tpl deleted file mode 100755 index 2db166851..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_tplvalues.tpl +++ /dev/null @@ -1,13 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Renders a value that contains template. -Usage: -{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} -*/}} -{{- define "common.tplvalues.render" -}} - {{- if typeIs "string" .value }} - {{- tpl .value .context }} - {{- else }} - {{- tpl (.value | toYaml) .context }} - {{- end }} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_utils.tpl b/scripts/helm/db/postgresql/charts/common/templates/_utils.tpl deleted file mode 100755 index 74774a3ca..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_utils.tpl +++ /dev/null @@ -1,45 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Print instructions to get a secret value. -Usage: -{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} -*/}} -{{- define "common.utils.secret.getvalue" -}} -{{- $varname := include "common.utils.fieldToEnvVar" . -}} -export {{ $varname }}=$(kubectl get secret --namespace {{ .context.Release.Namespace }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 --decode) -{{- end -}} - -{{/* -Build env var name given a field -Usage: -{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} -*/}} -{{- define "common.utils.fieldToEnvVar" -}} - {{- $fieldNameSplit := splitList "-" .field -}} - {{- $upperCaseFieldNameSplit := list -}} - - {{- range $fieldNameSplit -}} - {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} - {{- end -}} - - {{ join "_" $upperCaseFieldNameSplit }} -{{- end -}} - -{{/* -Gets a value from .Values given -Usage: -{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} -*/}} -{{- define "common.utils.getValueFromKey" -}} -{{- $splitKey := splitList "." .key -}} -{{- $value := "" -}} -{{- $latestObj := $.context.Values -}} -{{- range $splitKey -}} - {{- if not $latestObj -}} - {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} - {{- end -}} - {{- $value = ( index $latestObj . ) -}} - {{- $latestObj = $value -}} -{{- end -}} -{{- printf "%v" (default "" $value) -}} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_validations.tpl b/scripts/helm/db/postgresql/charts/common/templates/_validations.tpl deleted file mode 100755 index 05d1edbaf..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_validations.tpl +++ /dev/null @@ -1,278 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Validate values must not be empty. - -Usage: -{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} -{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} -{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} - -Validate value params: - - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" - - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" - - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" -*/}} -{{- define "common.validations.values.multiple.empty" -}} - {{- range .required -}} - {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} - {{- end -}} -{{- end -}} - -{{/* -Validate a value must not be empty. - -Usage: -{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "context" $) }} - -Validate value params: - - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" - - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" - - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" -*/}} -{{- define "common.validations.values.single.empty" -}} - {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} - - {{- if not $value -}} - {{- $varname := "my-value" -}} - {{- $getCurrentValue := "" -}} - {{- if and .secret .field -}} - {{- $varname = include "common.utils.fieldToEnvVar" . -}} - {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} - {{- end -}} - {{- printf "\n '%s' must not be empty, please add '--set %s=$%s' to the command.%s" .valueKey .valueKey $varname $getCurrentValue -}} - {{- end -}} -{{- end -}} - -{{/* -Validate MariaDB required passwords are not empty. - -Usage: -{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} -Params: - - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.validations.values.mariadb.passwords" -}} - {{- $existingSecret := include "common.mariadb.values.existingSecret" . -}} - {{- $enabled := include "common.mariadb.values.enabled" . -}} - {{- $architecture := include "common.mariadb.values.architecture" . -}} - {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} - {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} - {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} - {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} - {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} - - {{- if and (not $existingSecret) (eq $enabled "true") -}} - {{- $requiredPasswords := list -}} - - {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} - - {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} - {{- if not (empty $valueUsername) -}} - {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} - {{- end -}} - - {{- if (eq $architecture "replication") -}} - {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} - {{- end -}} - - {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} - - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for existingSecret. - -Usage: -{{ include "common.mariadb.values.existingSecret" (dict "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.mariadb.values.existingSecret" -}} - {{- if .subchart -}} - {{- .context.Values.mariadb.existingSecret | quote -}} - {{- else -}} - {{- .context.Values.existingSecret | quote -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for enabled mariadb. - -Usage: -{{ include "common.mariadb.values.enabled" (dict "context" $) }} -*/}} -{{- define "common.mariadb.values.enabled" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.mariadb.enabled -}} - {{- else -}} - {{- printf "%v" (not .context.Values.enabled) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for architecture - -Usage: -{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.mariadb.values.architecture" -}} - {{- if .subchart -}} - {{- .context.Values.mariadb.architecture -}} - {{- else -}} - {{- .context.Values.architecture -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for the key auth - -Usage: -{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.mariadb.values.key.auth" -}} - {{- if .subchart -}} - mariadb.auth - {{- else -}} - auth - {{- end -}} -{{- end -}} - -{{/* -Validate PostgreSQL required passwords are not empty. - -Usage: -{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} -Params: - - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "mysql-passwords-secret" - - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false -*/}} -{{- define "common.validations.values.postgresql.passwords" -}} - {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} - {{- $enabled := include "common.postgresql.values.enabled" . -}} - {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} - {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} - {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} - - {{- if and (not $existingSecret) (eq $enabled "true") -}} - {{- $requiredPasswords := list -}} - - {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} - - {{- if (eq $enabledReplication "true") -}} - {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} - {{- end -}} - - {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to decide whether evaluate global values. - -Usage: -{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} -Params: - - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" -*/}} -{{- define "common.postgresql.values.use.global" -}} - {{- if .context.Values.global -}} - {{- if .context.Values.global.postgresql -}} - {{- index .context.Values.global.postgresql .key | quote -}} - {{- end -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for existingSecret. - -Usage: -{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} -*/}} -{{- define "common.postgresql.values.existingSecret" -}} - {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} - - {{- if .subchart -}} - {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} - {{- else -}} - {{- default (.context.Values.existingSecret | quote) $globalValue -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for enabled postgresql. - -Usage: -{{ include "common.postgresql.values.enabled" (dict "context" $) }} -*/}} -{{- define "common.postgresql.values.enabled" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.postgresql.enabled -}} - {{- else -}} - {{- printf "%v" (not .context.Values.enabled) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for the key postgressPassword. - -Usage: -{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false -*/}} -{{- define "common.postgresql.values.key.postgressPassword" -}} - {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} - - {{- if not $globalValue -}} - {{- if .subchart -}} - postgresql.postgresqlPassword - {{- else -}} - postgresqlPassword - {{- end -}} - {{- else -}} - global.postgresql.postgresqlPassword - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for enabled.replication. - -Usage: -{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false -*/}} -{{- define "common.postgresql.values.enabled.replication" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.postgresql.replication.enabled -}} - {{- else -}} - {{- printf "%v" .context.Values.replication.enabled -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliar function to get the right value for the key replication.password. - -Usage: -{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false -*/}} -{{- define "common.postgresql.values.key.replicationPassword" -}} - {{- if .subchart -}} - postgresql.replication.password - {{- else -}} - replication.password - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/templates/_warnings.tpl b/scripts/helm/db/postgresql/charts/common/templates/_warnings.tpl deleted file mode 100755 index ae10fa41e..000000000 --- a/scripts/helm/db/postgresql/charts/common/templates/_warnings.tpl +++ /dev/null @@ -1,14 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Warning about using rolling tag. -Usage: -{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} -*/}} -{{- define "common.warnings.rollingTag" -}} - -{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} -WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. -+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ -{{- end }} - -{{- end -}} diff --git a/scripts/helm/db/postgresql/charts/common/values.yaml b/scripts/helm/db/postgresql/charts/common/values.yaml deleted file mode 100755 index 9ecdc93f5..000000000 --- a/scripts/helm/db/postgresql/charts/common/values.yaml +++ /dev/null @@ -1,3 +0,0 @@ -## bitnami/common -## It is required by CI/CD tools and processes. -exampleValue: common-chart diff --git a/scripts/helm/db/postgresql/ci/commonAnnotations.yaml b/scripts/helm/db/postgresql/ci/commonAnnotations.yaml deleted file mode 100755 index f6977823c..000000000 --- a/scripts/helm/db/postgresql/ci/commonAnnotations.yaml +++ /dev/null @@ -1,3 +0,0 @@ -commonAnnotations: - helm.sh/hook: 'pre-install, pre-upgrade' - helm.sh/hook-weight: '-1' diff --git a/scripts/helm/db/postgresql/ci/default-values.yaml b/scripts/helm/db/postgresql/ci/default-values.yaml deleted file mode 100755 index fc2ba605a..000000000 --- a/scripts/helm/db/postgresql/ci/default-values.yaml +++ /dev/null @@ -1 +0,0 @@ -# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml. diff --git a/scripts/helm/db/postgresql/ci/shmvolume-disabled-values.yaml b/scripts/helm/db/postgresql/ci/shmvolume-disabled-values.yaml deleted file mode 100755 index 347d3b40a..000000000 --- a/scripts/helm/db/postgresql/ci/shmvolume-disabled-values.yaml +++ /dev/null @@ -1,2 +0,0 @@ -shmVolume: - enabled: false diff --git a/scripts/helm/db/postgresql/files/README.md b/scripts/helm/db/postgresql/files/README.md deleted file mode 100755 index 1813a2fea..000000000 --- a/scripts/helm/db/postgresql/files/README.md +++ /dev/null @@ -1 +0,0 @@ -Copy here your postgresql.conf and/or pg_hba.conf files to use it as a config map. diff --git a/scripts/helm/db/postgresql/files/conf.d/README.md b/scripts/helm/db/postgresql/files/conf.d/README.md deleted file mode 100755 index 184c1875d..000000000 --- a/scripts/helm/db/postgresql/files/conf.d/README.md +++ /dev/null @@ -1,4 +0,0 @@ -If you don't want to provide the whole configuration file and only specify certain parameters, you can copy here your extended `.conf` files. -These files will be injected as a config maps and add/overwrite the default configuration using the `include_dir` directive that allows settings to be loaded from files other than the default `postgresql.conf`. - -More info in the [bitnami-docker-postgresql README](https://github.com/bitnami/bitnami-docker-postgresql#configuration-file). diff --git a/scripts/helm/db/postgresql/files/docker-entrypoint-initdb.d/README.md b/scripts/helm/db/postgresql/files/docker-entrypoint-initdb.d/README.md deleted file mode 100755 index cba38091e..000000000 --- a/scripts/helm/db/postgresql/files/docker-entrypoint-initdb.d/README.md +++ /dev/null @@ -1,3 +0,0 @@ -You can copy here your custom `.sh`, `.sql` or `.sql.gz` file so they are executed during the first boot of the image. - -More info in the [bitnami-docker-postgresql](https://github.com/bitnami/bitnami-docker-postgresql#initializing-a-new-instance) repository. \ No newline at end of file diff --git a/scripts/helm/db/postgresql/postgresql.yaml b/scripts/helm/db/postgresql/postgresql.yaml deleted file mode 100644 index 4e5e192d7..000000000 --- a/scripts/helm/db/postgresql/postgresql.yaml +++ /dev/null @@ -1,185 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: db ---- -# Source: postgresql/templates/secrets.yaml -apiVersion: v1 -kind: Secret -metadata: - name: postgres-postgresql - labels: - app.kubernetes.io/name: postgresql - helm.sh/chart: postgresql-9.8.2 - app.kubernetes.io/instance: postgres - app.kubernetes.io/managed-by: Helm -type: Opaque -data: - postgresql-password: "YXNheWVyUG9zdGdyZXM=" ---- -# Source: postgresql/templates/svc-headless.yaml -apiVersion: v1 -kind: Service -metadata: - name: postgres-postgresql-headless - labels: - app.kubernetes.io/name: postgresql - helm.sh/chart: postgresql-9.8.2 - app.kubernetes.io/instance: postgres - app.kubernetes.io/managed-by: Helm -spec: - type: ClusterIP - clusterIP: None - ports: - - name: tcp-postgresql - port: 5432 - targetPort: tcp-postgresql - selector: - app.kubernetes.io/name: postgresql - app.kubernetes.io/instance: postgres ---- -# Source: postgresql/templates/svc.yaml -apiVersion: v1 -kind: Service -metadata: - name: postgres-postgresql - labels: - app.kubernetes.io/name: postgresql - helm.sh/chart: postgresql-9.8.2 - app.kubernetes.io/instance: postgres - app.kubernetes.io/managed-by: Helm - annotations: -spec: - type: ClusterIP - ports: - - name: tcp-postgresql - port: 5432 - targetPort: tcp-postgresql - selector: - app.kubernetes.io/name: postgresql - app.kubernetes.io/instance: postgres - role: master ---- -# Source: postgresql/templates/statefulset.yaml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: postgres-postgresql - labels: - app.kubernetes.io/name: postgresql - helm.sh/chart: postgresql-9.8.2 - app.kubernetes.io/instance: postgres - app.kubernetes.io/managed-by: Helm - annotations: -spec: - serviceName: postgres-postgresql-headless - replicas: 1 - updateStrategy: - type: RollingUpdate - selector: - matchLabels: - app.kubernetes.io/name: postgresql - app.kubernetes.io/instance: postgres - role: master - template: - metadata: - name: postgres-postgresql - labels: - app.kubernetes.io/name: postgresql - helm.sh/chart: postgresql-9.8.2 - app.kubernetes.io/instance: postgres - app.kubernetes.io/managed-by: Helm - role: master - spec: - securityContext: - fsGroup: 1001 - containers: - - name: postgres-postgresql - image: docker.io/bitnami/postgresql:11.9.0-debian-10-r48 - imagePullPolicy: "IfNotPresent" - resources: - requests: - cpu: 250m - memory: 256Mi - securityContext: - runAsUser: 1001 - env: - - name: BITNAMI_DEBUG - value: "false" - - name: POSTGRESQL_PORT_NUMBER - value: "5432" - - name: POSTGRESQL_VOLUME_DIR - value: "/bitnami/postgresql" - - name: PGDATA - value: "/bitnami/postgresql/data" - - name: POSTGRES_USER - value: "postgres" - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: postgres-postgresql - key: postgresql-password - - name: POSTGRESQL_ENABLE_LDAP - value: "no" - - name: POSTGRESQL_ENABLE_TLS - value: "no" - - name: POSTGRESQL_LOG_HOSTNAME - value: "false" - - name: POSTGRESQL_LOG_CONNECTIONS - value: "false" - - name: POSTGRESQL_LOG_DISCONNECTIONS - value: "false" - - name: POSTGRESQL_PGAUDIT_LOG_CATALOG - value: "off" - - name: POSTGRESQL_CLIENT_MIN_MESSAGES - value: "error" - - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES - value: "pgaudit" - ports: - - name: tcp-postgresql - containerPort: 5432 - livenessProbe: - exec: - command: - - /bin/sh - - -c - - exec pg_isready -U "postgres" -h 127.0.0.1 -p 5432 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 6 - readinessProbe: - exec: - command: - - /bin/sh - - -c - - -e - - | - exec pg_isready -U "postgres" -h 127.0.0.1 -p 5432 - [ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ] - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 6 - volumeMounts: - - name: dshm - mountPath: /dev/shm - - name: data - mountPath: /bitnami/postgresql - subPath: - volumes: - - name: dshm - emptyDir: - medium: Memory - sizeLimit: 1Gi - volumeClaimTemplates: - - metadata: - name: data - spec: - accessModes: - - "ReadWriteOnce" - resources: - requests: - storage: "8Gi" diff --git a/scripts/helm/db/postgresql/requirements.lock b/scripts/helm/db/postgresql/requirements.lock deleted file mode 100755 index b0b7b0673..000000000 --- a/scripts/helm/db/postgresql/requirements.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: common - repository: https://charts.bitnami.com/bitnami - version: 0.8.1 -digest: sha256:740783295d301fdd168fafdbaa760de27ab54b0ff36b513589a5a2515072b885 -generated: "2020-10-06T07:04:23.948475694Z" diff --git a/scripts/helm/db/postgresql/requirements.yaml b/scripts/helm/db/postgresql/requirements.yaml deleted file mode 100755 index 2c28bfe14..000000000 --- a/scripts/helm/db/postgresql/requirements.yaml +++ /dev/null @@ -1,4 +0,0 @@ -dependencies: - - name: common - version: 0.x.x - repository: https://charts.bitnami.com/bitnami diff --git a/scripts/helm/db/postgresql/templates/NOTES.txt b/scripts/helm/db/postgresql/templates/NOTES.txt deleted file mode 100755 index 596e969ce..000000000 --- a/scripts/helm/db/postgresql/templates/NOTES.txt +++ /dev/null @@ -1,59 +0,0 @@ -** Please be patient while the chart is being deployed ** - -PostgreSQL can be accessed via port {{ template "postgresql.port" . }} on the following DNS name from within your cluster: - - {{ template "postgresql.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - Read/Write connection -{{- if .Values.replication.enabled }} - {{ template "postgresql.fullname" . }}-read.{{ .Release.Namespace }}.svc.cluster.local - Read only connection -{{- end }} - -{{- if and (not (eq .Values.postgresqlUsername "postgres")) (or .Values.postgresqlPostgresPassword (include "postgresql.useExistingSecret" .)) }} - -To get the password for "postgres" run: - - export POSTGRES_ADMIN_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "postgresql.secretName" . }} -o jsonpath="{.data.postgresql-postgres-password}" | base64 --decode) -{{- end }} - -To get the password for "{{ template "postgresql.username" . }}" run: - - export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "postgresql.secretName" . }} -o jsonpath="{.data.postgresql-password}" | base64 --decode) - -To connect to your database run the following command: - - kubectl run {{ template "postgresql.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ .Release.Namespace }} --image {{ template "postgresql.image" . }} --env="PGPASSWORD=$POSTGRES_PASSWORD" {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} - --labels="{{ template "postgresql.fullname" . }}-client=true" {{- end }} --command -- psql --host {{ template "postgresql.fullname" . }} -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} -p {{ template "postgresql.port" . }} - -{{ if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} -Note: Since NetworkPolicy is enabled, only pods with label {{ template "postgresql.fullname" . }}-client=true" will be able to connect to this PostgreSQL cluster. -{{- end }} - -To connect to your database from outside the cluster execute the following commands: - -{{- if contains "NodePort" .Values.service.type }} - - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "postgresql.fullname" . }}) - {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host $NODE_IP --port $NODE_PORT -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} - -{{- else if contains "LoadBalancer" .Values.service.type }} - - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "postgresql.fullname" . }}' - - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "postgresql.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host $SERVICE_IP --port {{ template "postgresql.port" . }} -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} - -{{- else if contains "ClusterIP" .Values.service.type }} - - kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "postgresql.fullname" . }} {{ template "postgresql.port" . }}:{{ template "postgresql.port" . }} & - {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host 127.0.0.1 -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} -p {{ template "postgresql.port" . }} - -{{- end }} - -{{- include "postgresql.validateValues" . -}} - -{{- include "common.warnings.rollingTag" .Values.image -}} - -{{- $passwordValidationErrors := include "common.validations.values.postgresql.passwords" (dict "secret" (include "postgresql.fullname" .) "context" $) -}} - -{{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $passwordValidationErrors) "context" $) -}} diff --git a/scripts/helm/db/postgresql/templates/_helpers.tpl b/scripts/helm/db/postgresql/templates/_helpers.tpl deleted file mode 100755 index b6a683ae9..000000000 --- a/scripts/helm/db/postgresql/templates/_helpers.tpl +++ /dev/null @@ -1,488 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "postgresql.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "postgresql.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "postgresql.master.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- $fullname := default (printf "%s-%s" .Release.Name $name) .Values.fullnameOverride -}} -{{- if .Values.replication.enabled -}} -{{- printf "%s-%s" $fullname "master" | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s" $fullname | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for networkpolicy. -*/}} -{{- define "postgresql.networkPolicy.apiVersion" -}} -{{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.GitVersion -}} -"extensions/v1beta1" -{{- else if semverCompare "^1.7-0" .Capabilities.KubeVersion.GitVersion -}} -"networking.k8s.io/v1" -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "postgresql.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Return the proper PostgreSQL image name -*/}} -{{- define "postgresql.image" -}} -{{- $registryName := .Values.image.registry -}} -{{- $repositoryName := .Values.image.repository -}} -{{- $tag := .Values.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return PostgreSQL postgres user password -*/}} -{{- define "postgresql.postgres.password" -}} -{{- if .Values.global.postgresql.postgresqlPostgresPassword }} - {{- .Values.global.postgresql.postgresqlPostgresPassword -}} -{{- else if .Values.postgresqlPostgresPassword -}} - {{- .Values.postgresqlPostgresPassword -}} -{{- else -}} - {{- randAlphaNum 10 -}} -{{- end -}} -{{- end -}} - -{{/* -Return PostgreSQL password -*/}} -{{- define "postgresql.password" -}} -{{- if .Values.global.postgresql.postgresqlPassword }} - {{- .Values.global.postgresql.postgresqlPassword -}} -{{- else if .Values.postgresqlPassword -}} - {{- .Values.postgresqlPassword -}} -{{- else -}} - {{- randAlphaNum 10 -}} -{{- end -}} -{{- end -}} - -{{/* -Return PostgreSQL replication password -*/}} -{{- define "postgresql.replication.password" -}} -{{- if .Values.global.postgresql.replicationPassword }} - {{- .Values.global.postgresql.replicationPassword -}} -{{- else if .Values.replication.password -}} - {{- .Values.replication.password -}} -{{- else -}} - {{- randAlphaNum 10 -}} -{{- end -}} -{{- end -}} - -{{/* -Return PostgreSQL username -*/}} -{{- define "postgresql.username" -}} -{{- if .Values.global.postgresql.postgresqlUsername }} - {{- .Values.global.postgresql.postgresqlUsername -}} -{{- else -}} - {{- .Values.postgresqlUsername -}} -{{- end -}} -{{- end -}} - - -{{/* -Return PostgreSQL replication username -*/}} -{{- define "postgresql.replication.username" -}} -{{- if .Values.global.postgresql.replicationUser }} - {{- .Values.global.postgresql.replicationUser -}} -{{- else -}} - {{- .Values.replication.user -}} -{{- end -}} -{{- end -}} - -{{/* -Return PostgreSQL port -*/}} -{{- define "postgresql.port" -}} -{{- if .Values.global.postgresql.servicePort }} - {{- .Values.global.postgresql.servicePort -}} -{{- else -}} - {{- .Values.service.port -}} -{{- end -}} -{{- end -}} - -{{/* -Return PostgreSQL created database -*/}} -{{- define "postgresql.database" -}} -{{- if .Values.global.postgresql.postgresqlDatabase }} - {{- .Values.global.postgresql.postgresqlDatabase -}} -{{- else if .Values.postgresqlDatabase -}} - {{- .Values.postgresqlDatabase -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper image name to change the volume permissions -*/}} -{{- define "postgresql.volumePermissions.image" -}} -{{- $registryName := .Values.volumePermissions.image.registry -}} -{{- $repositoryName := .Values.volumePermissions.image.repository -}} -{{- $tag := .Values.volumePermissions.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper PostgreSQL metrics image name -*/}} -{{- define "postgresql.metrics.image" -}} -{{- $registryName := default "docker.io" .Values.metrics.image.registry -}} -{{- $repositoryName := .Values.metrics.image.repository -}} -{{- $tag := default "latest" .Values.metrics.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Get the password secret. -*/}} -{{- define "postgresql.secretName" -}} -{{- if .Values.global.postgresql.existingSecret }} - {{- printf "%s" (tpl .Values.global.postgresql.existingSecret $) -}} -{{- else if .Values.existingSecret -}} - {{- printf "%s" (tpl .Values.existingSecret $) -}} -{{- else -}} - {{- printf "%s" (include "postgresql.fullname" .) -}} -{{- end -}} -{{- end -}} - -{{/* -Return true if we should use an existingSecret. -*/}} -{{- define "postgresql.useExistingSecret" -}} -{{- if or .Values.global.postgresql.existingSecret .Values.existingSecret -}} - {{- true -}} -{{- end -}} -{{- end -}} - -{{/* -Return true if a secret object should be created -*/}} -{{- define "postgresql.createSecret" -}} -{{- if not (include "postgresql.useExistingSecret" .) -}} - {{- true -}} -{{- end -}} -{{- end -}} - -{{/* -Get the configuration ConfigMap name. -*/}} -{{- define "postgresql.configurationCM" -}} -{{- if .Values.configurationConfigMap -}} -{{- printf "%s" (tpl .Values.configurationConfigMap $) -}} -{{- else -}} -{{- printf "%s-configuration" (include "postgresql.fullname" .) -}} -{{- end -}} -{{- end -}} - -{{/* -Get the extended configuration ConfigMap name. -*/}} -{{- define "postgresql.extendedConfigurationCM" -}} -{{- if .Values.extendedConfConfigMap -}} -{{- printf "%s" (tpl .Values.extendedConfConfigMap $) -}} -{{- else -}} -{{- printf "%s-extended-configuration" (include "postgresql.fullname" .) -}} -{{- end -}} -{{- end -}} - -{{/* -Return true if a configmap should be mounted with PostgreSQL configuration -*/}} -{{- define "postgresql.mountConfigurationCM" -}} -{{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap }} - {{- true -}} -{{- end -}} -{{- end -}} - -{{/* -Get the initialization scripts ConfigMap name. -*/}} -{{- define "postgresql.initdbScriptsCM" -}} -{{- if .Values.initdbScriptsConfigMap -}} -{{- printf "%s" (tpl .Values.initdbScriptsConfigMap $) -}} -{{- else -}} -{{- printf "%s-init-scripts" (include "postgresql.fullname" .) -}} -{{- end -}} -{{- end -}} - -{{/* -Get the initialization scripts Secret name. -*/}} -{{- define "postgresql.initdbScriptsSecret" -}} -{{- printf "%s" (tpl .Values.initdbScriptsSecret $) -}} -{{- end -}} - -{{/* -Get the metrics ConfigMap name. -*/}} -{{- define "postgresql.metricsCM" -}} -{{- printf "%s-metrics" (include "postgresql.fullname" .) -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names -*/}} -{{- define "postgresql.imagePullSecrets" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -Also, we can not use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} -{{- if .Values.global.imagePullSecrets }} -imagePullSecrets: -{{- range .Values.global.imagePullSecrets }} - - name: {{ . }} -{{- end }} -{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets .Values.volumePermissions.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.metrics.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.volumePermissions.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- end -}} -{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets .Values.volumePermissions.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.metrics.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.volumePermissions.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- end -}} -{{- end -}} - -{{/* -Get the readiness probe command -*/}} -{{- define "postgresql.readinessProbeCommand" -}} -- | -{{- if (include "postgresql.database" .) }} - exec pg_isready -U {{ include "postgresql.username" . | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ template "postgresql.port" . }} -{{- else }} - exec pg_isready -U {{ include "postgresql.username" . | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} -{{- end }} -{{- if contains "bitnami/" .Values.image.repository }} - [ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ] -{{- end -}} -{{- end -}} - -{{/* -Return the proper Storage Class -*/}} -{{- define "postgresql.storageClass" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -*/}} -{{- if .Values.global -}} - {{- if .Values.global.storageClass -}} - {{- if (eq "-" .Values.global.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.global.storageClass -}} - {{- end -}} - {{- else -}} - {{- if .Values.persistence.storageClass -}} - {{- if (eq "-" .Values.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} - {{- end -}} - {{- end -}} - {{- end -}} -{{- else -}} - {{- if .Values.persistence.storageClass -}} - {{- if (eq "-" .Values.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} - {{- end -}} - {{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for statefulset. -*/}} -{{- define "postgresql.statefulset.apiVersion" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "apps/v1beta2" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Compile all warnings into a single message, and call fail. -*/}} -{{- define "postgresql.validateValues" -}} -{{- $messages := list -}} -{{- $messages := append $messages (include "postgresql.validateValues.ldapConfigurationMethod" .) -}} -{{- $messages := append $messages (include "postgresql.validateValues.psp" .) -}} -{{- $messages := append $messages (include "postgresql.validateValues.tls" .) -}} -{{- $messages := without $messages "" -}} -{{- $message := join "\n" $messages -}} - -{{- if $message -}} -{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} -{{- end -}} -{{- end -}} - -{{/* -Validate values of Postgresql - If ldap.url is used then you don't need the other settings for ldap -*/}} -{{- define "postgresql.validateValues.ldapConfigurationMethod" -}} -{{- if and .Values.ldap.enabled (and (not (empty .Values.ldap.url)) (not (empty .Values.ldap.server))) }} -postgresql: ldap.url, ldap.server - You cannot set both `ldap.url` and `ldap.server` at the same time. - Please provide a unique way to configure LDAP. - More info at https://www.postgresql.org/docs/current/auth-ldap.html -{{- end -}} -{{- end -}} - -{{/* -Validate values of Postgresql - If PSP is enabled RBAC should be enabled too -*/}} -{{- define "postgresql.validateValues.psp" -}} -{{- if and .Values.psp.create (not .Values.rbac.create) }} -postgresql: psp.create, rbac.create - RBAC should be enabled if PSP is enabled in order for PSP to work. - More info at https://kubernetes.io/docs/concepts/policy/pod-security-policy/#authorizing-policies -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for podsecuritypolicy. -*/}} -{{- define "podsecuritypolicy.apiVersion" -}} -{{- if semverCompare "<1.10-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "extensions/v1beta1" -}} -{{- else -}} -{{- print "policy/v1beta1" -}} -{{- end -}} -{{- end -}} - -{{/* -Validate values of Postgresql TLS - When TLS is enabled, so must be VolumePermissions -*/}} -{{- define "postgresql.validateValues.tls" -}} -{{- if and .Values.tls.enabled (not .Values.volumePermissions.enabled) }} -postgresql: tls.enabled, volumePermissions.enabled - When TLS is enabled you must enable volumePermissions as well to ensure certificates files have - the right permissions. -{{- end -}} -{{- end -}} - -{{/* -Return the path to the cert file. -*/}} -{{- define "postgresql.tlsCert" -}} -{{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} -{{- end -}} - -{{/* -Return the path to the cert key file. -*/}} -{{- define "postgresql.tlsCertKey" -}} -{{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} -{{- end -}} - -{{/* -Return the path to the CA cert file. -*/}} -{{- define "postgresql.tlsCACert" -}} -{{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.certCAFilename -}} -{{- end -}} - -{{/* -Return the path to the CRL file. -*/}} -{{- define "postgresql.tlsCRL" -}} -{{- if .Values.tls.crlFilename -}} -{{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.crlFilename -}} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/postgresql/templates/configmap.yaml b/scripts/helm/db/postgresql/templates/configmap.yaml deleted file mode 100755 index bc78771d4..000000000 --- a/scripts/helm/db/postgresql/templates/configmap.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{ if and (or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration) (not .Values.configurationConfigMap) }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "postgresql.fullname" . }}-configuration - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: -{{- if (.Files.Glob "files/postgresql.conf") }} -{{ (.Files.Glob "files/postgresql.conf").AsConfig | indent 2 }} -{{- else if .Values.postgresqlConfiguration }} - postgresql.conf: | -{{- range $key, $value := default dict .Values.postgresqlConfiguration }} - {{ $key | snakecase }}={{ $value }} -{{- end }} -{{- end }} -{{- if (.Files.Glob "files/pg_hba.conf") }} -{{ (.Files.Glob "files/pg_hba.conf").AsConfig | indent 2 }} -{{- else if .Values.pgHbaConfiguration }} - pg_hba.conf: | -{{ .Values.pgHbaConfiguration | indent 4 }} -{{- end }} -{{ end }} diff --git a/scripts/helm/db/postgresql/templates/extended-config-configmap.yaml b/scripts/helm/db/postgresql/templates/extended-config-configmap.yaml deleted file mode 100755 index c6793802f..000000000 --- a/scripts/helm/db/postgresql/templates/extended-config-configmap.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and (or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf) (not .Values.extendedConfConfigMap)}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "postgresql.fullname" . }}-extended-configuration - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: -{{- with .Files.Glob "files/conf.d/*.conf" }} -{{ .AsConfig | indent 2 }} -{{- end }} -{{ with .Values.postgresqlExtendedConf }} - override.conf: | -{{- range $key, $value := . }} - {{ $key | snakecase }}={{ $value }} -{{- end }} -{{- end }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/extra-list.yaml b/scripts/helm/db/postgresql/templates/extra-list.yaml deleted file mode 100755 index b28a03c1c..000000000 --- a/scripts/helm/db/postgresql/templates/extra-list.yaml +++ /dev/null @@ -1,5 +0,0 @@ -{{- if .Values.extraDeploy }} -apiVersion: v1 -kind: List -items: {{- include "postgresql.tplValue" (dict "value" .Values.extraDeploy "context" $) | nindent 2 }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/initialization-configmap.yaml b/scripts/helm/db/postgresql/templates/initialization-configmap.yaml deleted file mode 100755 index 2652ce732..000000000 --- a/scripts/helm/db/postgresql/templates/initialization-configmap.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if and (or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScripts) (not .Values.initdbScriptsConfigMap) }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "postgresql.fullname" . }}-init-scripts - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -{{- with .Files.Glob "files/docker-entrypoint-initdb.d/*.sql.gz" }} -binaryData: -{{- range $path, $bytes := . }} - {{ base $path }}: {{ $.Files.Get $path | b64enc | quote }} -{{- end }} -{{- end }} -data: -{{- with .Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql}" }} -{{ .AsConfig | indent 2 }} -{{- end }} -{{- with .Values.initdbScripts }} -{{ toYaml . | indent 2 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/metrics-configmap.yaml b/scripts/helm/db/postgresql/templates/metrics-configmap.yaml deleted file mode 100755 index 6216eca84..000000000 --- a/scripts/helm/db/postgresql/templates/metrics-configmap.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "postgresql.metricsCM" . }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -data: - custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/metrics-svc.yaml b/scripts/helm/db/postgresql/templates/metrics-svc.yaml deleted file mode 100755 index 9181ac89a..000000000 --- a/scripts/helm/db/postgresql/templates/metrics-svc.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.metrics.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "postgresql.fullname" . }}-metrics - labels: - {{- include "common.labels.standard" . | nindent 4 }} - annotations: - {{- if .Values.commonAnnotations }} - {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- toYaml .Values.metrics.service.annotations | nindent 4 }} -spec: - type: {{ .Values.metrics.service.type }} - {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} - {{- end }} - ports: - - name: http-metrics - port: 9187 - targetPort: http-metrics - selector: - {{- include "common.labels.matchLabels" . | nindent 4 }} - role: master -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/networkpolicy.yaml b/scripts/helm/db/postgresql/templates/networkpolicy.yaml deleted file mode 100755 index f2752af77..000000000 --- a/scripts/helm/db/postgresql/templates/networkpolicy.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -kind: NetworkPolicy -apiVersion: {{ template "postgresql.networkPolicy.apiVersion" . }} -metadata: - name: {{ template "postgresql.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - podSelector: - matchLabels: - {{- include "common.labels.matchLabels" . | nindent 6 }} - ingress: - # Allow inbound connections - - ports: - - port: {{ template "postgresql.port" . }} - {{- if not .Values.networkPolicy.allowExternal }} - from: - - podSelector: - matchLabels: - {{ template "postgresql.fullname" . }}-client: "true" - {{- if .Values.networkPolicy.explicitNamespacesSelector }} - namespaceSelector: -{{ toYaml .Values.networkPolicy.explicitNamespacesSelector | indent 12 }} - {{- end }} - - podSelector: - matchLabels: - {{- include "common.labels.matchLabels" . | nindent 14 }} - role: slave - {{- end }} - # Allow prometheus scrapes - - ports: - - port: 9187 -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/podsecuritypolicy.yaml b/scripts/helm/db/postgresql/templates/podsecuritypolicy.yaml deleted file mode 100755 index fb4c52f20..000000000 --- a/scripts/helm/db/postgresql/templates/podsecuritypolicy.yaml +++ /dev/null @@ -1,37 +0,0 @@ -{{- if .Values.psp.create }} -apiVersion: {{ include "podsecuritypolicy.apiVersion" . }} -kind: PodSecurityPolicy -metadata: - name: {{ template "postgresql.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - privileged: false - volumes: - - 'configMap' - - 'secret' - - 'persistentVolumeClaim' - - 'emptyDir' - - 'projected' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - rule: 'MustRunAsNonRoot' - seLinux: - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - - min: 1 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - - min: 1 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/prometheusrule.yaml b/scripts/helm/db/postgresql/templates/prometheusrule.yaml deleted file mode 100755 index 0afd8f41f..000000000 --- a/scripts/helm/db/postgresql/templates/prometheusrule.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ template "postgresql.fullname" . }} -{{- with .Values.metrics.prometheusRule.namespace }} - namespace: {{ . }} -{{- end }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- with .Values.metrics.prometheusRule.additionalLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: -{{- with .Values.metrics.prometheusRule.rules }} - groups: - - name: {{ template "postgresql.name" $ }} - rules: {{ tpl (toYaml .) $ | nindent 8 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/role.yaml b/scripts/helm/db/postgresql/templates/role.yaml deleted file mode 100755 index 24148aa6b..000000000 --- a/scripts/helm/db/postgresql/templates/role.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.rbac.create }} -kind: Role -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "postgresql.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -rules: - {{- if .Values.psp.create }} - - apiGroups: ["extensions"] - resources: ["podsecuritypolicies"] - verbs: ["use"] - resourceNames: - - {{ template "postgresql.fullname" . }} - {{- end }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/rolebinding.yaml b/scripts/helm/db/postgresql/templates/rolebinding.yaml deleted file mode 100755 index a105fb41b..000000000 --- a/scripts/helm/db/postgresql/templates/rolebinding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.rbac.create }} -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "postgresql.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -roleRef: - kind: Role - name: {{ template "postgresql.fullname" . }} - apiGroup: rbac.authorization.k8s.io -subjects: - - kind: ServiceAccount - name: {{ default (include "postgresql.fullname" . ) .Values.serviceAccount.name }} - namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/secrets.yaml b/scripts/helm/db/postgresql/templates/secrets.yaml deleted file mode 100755 index 8d968864c..000000000 --- a/scripts/helm/db/postgresql/templates/secrets.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if (include "postgresql.createSecret" .) }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "postgresql.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -type: Opaque -data: - {{- if and .Values.postgresqlPostgresPassword (not (eq .Values.postgresqlUsername "postgres")) }} - postgresql-postgres-password: {{ include "postgresql.postgres.password" . | b64enc | quote }} - {{- end }} - postgresql-password: {{ include "postgresql.password" . | b64enc | quote }} - {{- if .Values.replication.enabled }} - postgresql-replication-password: {{ include "postgresql.replication.password" . | b64enc | quote }} - {{- end }} - {{- if (and .Values.ldap.enabled .Values.ldap.bind_password)}} - postgresql-ldap-password: {{ .Values.ldap.bind_password | b64enc | quote }} - {{- end }} -{{- end -}} diff --git a/scripts/helm/db/postgresql/templates/serviceaccount.yaml b/scripts/helm/db/postgresql/templates/serviceaccount.yaml deleted file mode 100755 index 1e2a1f2a7..000000000 --- a/scripts/helm/db/postgresql/templates/serviceaccount.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{- if and (.Values.serviceAccount.enabled) (not .Values.serviceAccount.name) }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - {{- include "common.labels.standard" . | nindent 4 }} - name: {{ template "postgresql.fullname" . }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/servicemonitor.yaml b/scripts/helm/db/postgresql/templates/servicemonitor.yaml deleted file mode 100755 index e118002a3..000000000 --- a/scripts/helm/db/postgresql/templates/servicemonitor.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "postgresql.fullname" . }} - {{- if .Values.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.metrics.serviceMonitor.namespace }} - {{- end }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.metrics.serviceMonitor.additionalLabels }} - {{- toYaml .Values.metrics.serviceMonitor.additionalLabels | nindent 4 }} - {{- end }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - -spec: - endpoints: - - port: http-metrics - {{- if .Values.metrics.serviceMonitor.interval }} - interval: {{ .Values.metrics.serviceMonitor.interval }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} - {{- end }} - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} - selector: - matchLabels: - {{- include "common.labels.matchLabels" . | nindent 6 }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/statefulset-slaves.yaml b/scripts/helm/db/postgresql/templates/statefulset-slaves.yaml deleted file mode 100755 index d77142fa3..000000000 --- a/scripts/helm/db/postgresql/templates/statefulset-slaves.yaml +++ /dev/null @@ -1,403 +0,0 @@ -{{- if .Values.replication.enabled }} -{{- $slaveResources := coalesce .Values.slave.resources .Values.resources -}} -apiVersion: {{ template "postgresql.statefulset.apiVersion" . }} -kind: StatefulSet -metadata: - name: "{{ template "postgresql.fullname" . }}-slave" - labels: - {{- include "common.labels.standard" . | nindent 4 }} -{{- with .Values.slave.labels }} -{{ toYaml . | indent 4 }} -{{- end }} - annotations: - {{- if .Values.commonAnnotations }} - {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- with .Values.slave.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - serviceName: {{ template "postgresql.fullname" . }}-headless - replicas: {{ .Values.replication.slaveReplicas }} - selector: - matchLabels: - {{- include "common.labels.matchLabels" . | nindent 6 }} - role: slave - template: - metadata: - name: {{ template "postgresql.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 8 }} - role: slave -{{- with .Values.slave.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} -{{- with .Values.slave.podAnnotations }} - annotations: -{{ toYaml . | indent 8 }} -{{- end }} - spec: - {{- if .Values.schedulerName }} - schedulerName: "{{ .Values.schedulerName }}" - {{- end }} -{{- include "postgresql.imagePullSecrets" . | indent 6 }} - {{- if .Values.slave.nodeSelector }} - nodeSelector: -{{ toYaml .Values.slave.nodeSelector | indent 8 }} - {{- end }} - {{- if .Values.slave.affinity }} - affinity: -{{ toYaml .Values.slave.affinity | indent 8 }} - {{- end }} - {{- if .Values.slave.tolerations }} - tolerations: -{{ toYaml .Values.slave.tolerations | indent 8 }} - {{- end }} - {{- if .Values.terminationGracePeriodSeconds }} - terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} - {{- end }} - {{- if .Values.securityContext.enabled }} - securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} - {{- end }} - {{- if .Values.serviceAccount.enabled }} - serviceAccountName: {{ default (include "postgresql.fullname" . ) .Values.serviceAccount.name}} - {{- end }} - {{- if or .Values.slave.extraInitContainers (and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled))) }} - initContainers: - {{- if and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled) .Values.tls.enabled) }} - - name: init-chmod-data - image: {{ template "postgresql.volumePermissions.image" . }} - imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} - {{- if .Values.resources }} - resources: {{- toYaml .Values.resources | nindent 12 }} - {{- end }} - command: - - /bin/sh - - -cx - - | - {{- if .Values.persistence.enabled }} - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.persistence.mountPath }} - {{- else }} - chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.persistence.mountPath }} - {{- end }} - mkdir -p {{ .Values.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.persistence.mountPath }}/conf {{- end }} - chmod 700 {{ .Values.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.persistence.mountPath }}/conf {{- end }} - find {{ .Values.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \ - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - xargs chown -R `id -u`:`id -G | cut -d " " -f2` - {{- else }} - xargs chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} - {{- end }} - {{- end }} - {{- if and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled }} - chmod -R 777 /dev/shm - {{- end }} - {{- if .Values.tls.enabled }} - cp /tmp/certs/* /opt/bitnami/postgresql/certs/ - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ - {{- else }} - chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} /opt/bitnami/postgresql/certs/ - {{- end }} - chmod 600 {{ template "postgresql.tlsCertKey" . }} - {{- end }} - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} - {{- else }} - securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} - {{- end }} - volumeMounts: - {{ if .Values.persistence.enabled }} - - name: data - mountPath: {{ .Values.persistence.mountPath }} - subPath: {{ .Values.persistence.subPath }} - {{- end }} - {{- if .Values.shmVolume.enabled }} - - name: dshm - mountPath: /dev/shm - {{- end }} - {{- if .Values.tls.enabled }} - - name: raw-certificates - mountPath: /tmp/certs - - name: postgresql-certificates - mountPath: /opt/bitnami/postgresql/certs - {{- end }} - {{- end }} - {{- if .Values.slave.extraInitContainers }} -{{ tpl .Values.slave.extraInitContainers . | indent 8 }} - {{- end }} - {{- end }} - {{- if .Values.slave.priorityClassName }} - priorityClassName: {{ .Values.slave.priorityClassName }} - {{- end }} - containers: - - name: {{ template "postgresql.fullname" . }} - image: {{ template "postgresql.image" . }} - imagePullPolicy: "{{ .Values.image.pullPolicy }}" - {{- if $slaveResources }} - resources: {{- toYaml $slaveResources | nindent 12 }} - {{- end }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - env: - - name: BITNAMI_DEBUG - value: {{ ternary "true" "false" .Values.image.debug | quote }} - - name: POSTGRESQL_VOLUME_DIR - value: "{{ .Values.persistence.mountPath }}" - - name: POSTGRESQL_PORT_NUMBER - value: "{{ template "postgresql.port" . }}" - {{- if .Values.persistence.mountPath }} - - name: PGDATA - value: {{ .Values.postgresqlDataDir | quote }} - {{- end }} - - name: POSTGRES_REPLICATION_MODE - value: "slave" - - name: POSTGRES_REPLICATION_USER - value: {{ include "postgresql.replication.username" . | quote }} - {{- if .Values.usePasswordFile }} - - name: POSTGRES_REPLICATION_PASSWORD_FILE - value: "/opt/bitnami/postgresql/secrets/postgresql-replication-password" - {{- else }} - - name: POSTGRES_REPLICATION_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "postgresql.secretName" . }} - key: postgresql-replication-password - {{- end }} - - name: POSTGRES_CLUSTER_APP_NAME - value: {{ .Values.replication.applicationName }} - - name: POSTGRES_MASTER_HOST - value: {{ template "postgresql.fullname" . }} - - name: POSTGRES_MASTER_PORT_NUMBER - value: {{ include "postgresql.port" . | quote }} - {{- if and (not (eq .Values.postgresqlUsername "postgres")) (or .Values.postgresqlPostgresPassword (include "postgresql.useExistingSecret" .)) }} - {{- if .Values.usePasswordFile }} - - name: POSTGRES_POSTGRES_PASSWORD_FILE - value: "/opt/bitnami/postgresql/secrets/postgresql-postgres-password" - {{- else }} - - name: POSTGRES_POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "postgresql.secretName" . }} - key: postgresql-postgres-password - {{- end }} - {{- end }} - {{- if .Values.usePasswordFile }} - - name: POSTGRES_PASSWORD_FILE - value: "/opt/bitnami/postgresql/secrets/postgresql-password" - {{- else }} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "postgresql.secretName" . }} - key: postgresql-password - {{- end }} - - name: POSTGRESQL_ENABLE_TLS - value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} - {{- if .Values.tls.enabled }} - - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS - value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }} - - name: POSTGRESQL_TLS_CERT_FILE - value: {{ template "postgresql.tlsCert" . }} - - name: POSTGRESQL_TLS_KEY_FILE - value: {{ template "postgresql.tlsCertKey" . }} - {{- if .Values.tls.certCAFilename }} - - name: POSTGRESQL_TLS_CA_FILE - value: {{ template "postgresql.tlsCACert" . }} - {{- end }} - {{- if .Values.tls.crlFilename }} - - name: POSTGRESQL_TLS_CRL_FILE - value: {{ template "postgresql.tlsCRL" . }} - {{- end }} - {{- end }} - - name: POSTGRESQL_LOG_HOSTNAME - value: {{ .Values.audit.logHostname | quote }} - - name: POSTGRESQL_LOG_CONNECTIONS - value: {{ .Values.audit.logConnections | quote }} - - name: POSTGRESQL_LOG_DISCONNECTIONS - value: {{ .Values.audit.logDisconnections | quote }} - {{- if .Values.audit.logLinePrefix }} - - name: POSTGRESQL_LOG_LINE_PREFIX - value: {{ .Values.audit.logLinePrefix | quote }} - {{- end }} - {{- if .Values.audit.logTimezone }} - - name: POSTGRESQL_LOG_TIMEZONE - value: {{ .Values.audit.logTimezone | quote }} - {{- end }} - {{- if .Values.audit.pgAuditLog }} - - name: POSTGRESQL_PGAUDIT_LOG - value: {{ .Values.audit.pgAuditLog | quote }} - {{- end }} - - name: POSTGRESQL_PGAUDIT_LOG_CATALOG - value: {{ .Values.audit.pgAuditLogCatalog | quote }} - - name: POSTGRESQL_CLIENT_MIN_MESSAGES - value: {{ .Values.audit.clientMinMessages | quote }} - - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES - value: {{ .Values.postgresqlSharedPreloadLibraries | quote }} - {{- if .Values.postgresqlMaxConnections }} - - name: POSTGRESQL_MAX_CONNECTIONS - value: {{ .Values.postgresqlMaxConnections | quote }} - {{- end }} - {{- if .Values.postgresqlPostgresConnectionLimit }} - - name: POSTGRESQL_POSTGRES_CONNECTION_LIMIT - value: {{ .Values.postgresqlPostgresConnectionLimit | quote }} - {{- end }} - {{- if .Values.postgresqlDbUserConnectionLimit }} - - name: POSTGRESQL_USERNAME_CONNECTION_LIMIT - value: {{ .Values.postgresqlDbUserConnectionLimit | quote }} - {{- end }} - {{- if .Values.postgresqlTcpKeepalivesInterval }} - - name: POSTGRESQL_TCP_KEEPALIVES_INTERVAL - value: {{ .Values.postgresqlTcpKeepalivesInterval | quote }} - {{- end }} - {{- if .Values.postgresqlTcpKeepalivesIdle }} - - name: POSTGRESQL_TCP_KEEPALIVES_IDLE - value: {{ .Values.postgresqlTcpKeepalivesIdle | quote }} - {{- end }} - {{- if .Values.postgresqlStatementTimeout }} - - name: POSTGRESQL_STATEMENT_TIMEOUT - value: {{ .Values.postgresqlStatementTimeout | quote }} - {{- end }} - {{- if .Values.postgresqlTcpKeealivesCount }} - - name: POSTGRESQL_TCP_KEEPALIVES_COUNT - value: {{ .Values.postgresqlTcpKeealivesCount | quote }} - {{- end }} - {{- if .Values.postgresqlPghbaRemoveFilters }} - - name: POSTGRESQL_PGHBA_REMOVE_FILTERS - value: {{ .Values.postgresqlPghbaRemoveFilters | quote }} - {{- end }} - ports: - - name: tcp-postgresql - containerPort: {{ template "postgresql.port" . }} - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - exec: - command: - - /bin/sh - - -c - {{- if (include "postgresql.database" .) }} - - exec pg_isready -U {{ include "postgresql.username" . | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ template "postgresql.port" . }} - {{- else }} - - exec pg_isready -U {{ include "postgresql.username" . | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} - {{- end }} - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - {{- else if .Values.customLivenessProbe }} - livenessProbe: {{- include "postgresql.tplValue" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - exec: - command: - - /bin/sh - - -c - - -e - {{- include "postgresql.readinessProbeCommand" . | nindent 16 }} - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - {{- else if .Values.customReadinessProbe }} - readinessProbe: {{- include "postgresql.tplValue" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} - {{- end }} - volumeMounts: - {{- if .Values.usePasswordFile }} - - name: postgresql-password - mountPath: /opt/bitnami/postgresql/secrets/ - {{- end }} - {{- if .Values.shmVolume.enabled }} - - name: dshm - mountPath: /dev/shm - {{- end }} - {{- if .Values.persistence.enabled }} - - name: data - mountPath: {{ .Values.persistence.mountPath }} - subPath: {{ .Values.persistence.subPath }} - {{ end }} - {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} - - name: postgresql-extended-config - mountPath: /bitnami/postgresql/conf/conf.d/ - {{- end }} - {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap }} - - name: postgresql-config - mountPath: /bitnami/postgresql/conf - {{- end }} - {{- if .Values.tls.enabled }} - - name: postgresql-certificates - mountPath: /opt/bitnami/postgresql/certs - readOnly: true - {{- end }} - {{- if .Values.slave.extraVolumeMounts }} - {{- toYaml .Values.slave.extraVolumeMounts | nindent 12 }} - {{- end }} -{{- if .Values.slave.sidecars }} -{{- include "common.tplvalues.render" ( dict "value" .Values.slave.sidecars "context" $ ) | nindent 8 }} -{{- end }} - volumes: - {{- if .Values.usePasswordFile }} - - name: postgresql-password - secret: - secretName: {{ template "postgresql.secretName" . }} - {{- end }} - {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap}} - - name: postgresql-config - configMap: - name: {{ template "postgresql.configurationCM" . }} - {{- end }} - {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} - - name: postgresql-extended-config - configMap: - name: {{ template "postgresql.extendedConfigurationCM" . }} - {{- end }} - {{- if .Values.tls.enabled }} - - name: raw-certificates - secret: - secretName: {{ required "A secret containing TLS certificates is required when TLS is enabled" .Values.tls.certificatesSecret }} - - name: postgresql-certificates - emptyDir: {} - {{- end }} - {{- if .Values.shmVolume.enabled }} - - name: dshm - emptyDir: - medium: Memory - sizeLimit: 1Gi - {{- end }} - {{- if or (not .Values.persistence.enabled) (not .Values.slave.persistence.enabled) }} - - name: data - emptyDir: {} - {{- end }} - {{- if .Values.slave.extraVolumes }} - {{- toYaml .Values.slave.extraVolumes | nindent 8 }} - {{- end }} - updateStrategy: - type: {{ .Values.updateStrategy.type }} - {{- if (eq "Recreate" .Values.updateStrategy.type) }} - rollingUpdate: null - {{- end }} -{{- if and .Values.persistence.enabled .Values.slave.persistence.enabled }} - volumeClaimTemplates: - - metadata: - name: data - {{- with .Values.persistence.annotations }} - annotations: - {{- range $key, $value := . }} - {{ $key }}: {{ $value }} - {{- end }} - {{- end }} - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{ include "postgresql.storageClass" . }} -{{- end }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/statefulset.yaml b/scripts/helm/db/postgresql/templates/statefulset.yaml deleted file mode 100755 index 10c1af166..000000000 --- a/scripts/helm/db/postgresql/templates/statefulset.yaml +++ /dev/null @@ -1,580 +0,0 @@ -apiVersion: {{ template "postgresql.statefulset.apiVersion" . }} -kind: StatefulSet -metadata: - name: {{ template "postgresql.master.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- with .Values.master.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - annotations: - {{- if .Values.commonAnnotations }} - {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- with .Values.master.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - serviceName: {{ template "postgresql.fullname" . }}-headless - replicas: 1 - updateStrategy: - type: {{ .Values.updateStrategy.type }} - {{- if (eq "Recreate" .Values.updateStrategy.type) }} - rollingUpdate: null - {{- end }} - selector: - matchLabels: - {{- include "common.labels.matchLabels" . | nindent 6 }} - role: master - template: - metadata: - name: {{ template "postgresql.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 8 }} - role: master - {{- with .Values.master.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.master.podAnnotations }} - annotations: {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- if .Values.schedulerName }} - schedulerName: "{{ .Values.schedulerName }}" - {{- end }} -{{- include "postgresql.imagePullSecrets" . | indent 6 }} - {{- if .Values.master.nodeSelector }} - nodeSelector: {{- toYaml .Values.master.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.master.affinity }} - affinity: {{- toYaml .Values.master.affinity | nindent 8 }} - {{- end }} - {{- if .Values.master.tolerations }} - tolerations: {{- toYaml .Values.master.tolerations | nindent 8 }} - {{- end }} - {{- if .Values.terminationGracePeriodSeconds }} - terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} - {{- end }} - {{- if .Values.securityContext.enabled }} - securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} - {{- end }} - {{- if .Values.serviceAccount.enabled }} - serviceAccountName: {{ default (include "postgresql.fullname" . ) .Values.serviceAccount.name }} - {{- end }} - {{- if or .Values.master.extraInitContainers (and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled))) }} - initContainers: - {{- if and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled) .Values.tls.enabled) }} - - name: init-chmod-data - image: {{ template "postgresql.volumePermissions.image" . }} - imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} - {{- if .Values.resources }} - resources: {{- toYaml .Values.resources | nindent 12 }} - {{- end }} - command: - - /bin/sh - - -cx - - | - {{- if .Values.persistence.enabled }} - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.persistence.mountPath }} - {{- else }} - chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.persistence.mountPath }} - {{- end }} - mkdir -p {{ .Values.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.persistence.mountPath }}/conf {{- end }} - chmod 700 {{ .Values.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.persistence.mountPath }}/conf {{- end }} - find {{ .Values.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \ - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - xargs chown -R `id -u`:`id -G | cut -d " " -f2` - {{- else }} - xargs chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} - {{- end }} - {{- end }} - {{- if and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled }} - chmod -R 777 /dev/shm - {{- end }} - {{- if .Values.tls.enabled }} - cp /tmp/certs/* /opt/bitnami/postgresql/certs/ - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ - {{- else }} - chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} /opt/bitnami/postgresql/certs/ - {{- end }} - chmod 600 {{ template "postgresql.tlsCertKey" . }} - {{- end }} - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} - {{- else }} - securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} - {{- end }} - volumeMounts: - {{- if .Values.persistence.enabled }} - - name: data - mountPath: {{ .Values.persistence.mountPath }} - subPath: {{ .Values.persistence.subPath }} - {{- end }} - {{- if .Values.shmVolume.enabled }} - - name: dshm - mountPath: /dev/shm - {{- end }} - {{- if .Values.tls.enabled }} - - name: raw-certificates - mountPath: /tmp/certs - - name: postgresql-certificates - mountPath: /opt/bitnami/postgresql/certs - {{- end }} - {{- end }} - {{- if .Values.master.extraInitContainers }} - {{- include "common.tplvalues.render" ( dict "value" .Values.master.extraInitContainers "context" $ ) | nindent 8 }} - {{- end }} - {{- end }} - {{- if .Values.master.priorityClassName }} - priorityClassName: {{ .Values.master.priorityClassName }} - {{- end }} - containers: - - name: {{ template "postgresql.fullname" . }} - image: {{ template "postgresql.image" . }} - imagePullPolicy: "{{ .Values.image.pullPolicy }}" - {{- if .Values.resources }} - resources: {{- toYaml .Values.resources | nindent 12 }} - {{- end }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - env: - - name: BITNAMI_DEBUG - value: {{ ternary "true" "false" .Values.image.debug | quote }} - - name: POSTGRESQL_PORT_NUMBER - value: "{{ template "postgresql.port" . }}" - - name: POSTGRESQL_VOLUME_DIR - value: "{{ .Values.persistence.mountPath }}" - {{- if .Values.postgresqlInitdbArgs }} - - name: POSTGRES_INITDB_ARGS - value: {{ .Values.postgresqlInitdbArgs | quote }} - {{- end }} - {{- if .Values.postgresqlInitdbWalDir }} - - name: POSTGRES_INITDB_WALDIR - value: {{ .Values.postgresqlInitdbWalDir | quote }} - {{- end }} - {{- if .Values.initdbUser }} - - name: POSTGRESQL_INITSCRIPTS_USERNAME - value: {{ .Values.initdbUser }} - {{- end }} - {{- if .Values.initdbPassword }} - - name: POSTGRESQL_INITSCRIPTS_PASSWORD - value: {{ .Values.initdbPassword }} - {{- end }} - {{- if .Values.persistence.mountPath }} - - name: PGDATA - value: {{ .Values.postgresqlDataDir | quote }} - {{- end }} - {{- if .Values.masterAsStandBy.enabled }} - - name: POSTGRES_MASTER_HOST - value: {{ .Values.masterAsStandBy.masterHost }} - - name: POSTGRES_MASTER_PORT_NUMBER - value: {{ .Values.masterAsStandBy.masterPort | quote }} - {{- end }} - {{- if or .Values.replication.enabled .Values.masterAsStandBy.enabled }} - - name: POSTGRES_REPLICATION_MODE - {{- if .Values.masterAsStandBy.enabled }} - value: "slave" - {{- else }} - value: "master" - {{- end }} - - name: POSTGRES_REPLICATION_USER - value: {{ include "postgresql.replication.username" . | quote }} - {{- if .Values.usePasswordFile }} - - name: POSTGRES_REPLICATION_PASSWORD_FILE - value: "/opt/bitnami/postgresql/secrets/postgresql-replication-password" - {{- else }} - - name: POSTGRES_REPLICATION_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "postgresql.secretName" . }} - key: postgresql-replication-password - {{- end }} - {{- if not (eq .Values.replication.synchronousCommit "off")}} - - name: POSTGRES_SYNCHRONOUS_COMMIT_MODE - value: {{ .Values.replication.synchronousCommit | quote }} - - name: POSTGRES_NUM_SYNCHRONOUS_REPLICAS - value: {{ .Values.replication.numSynchronousReplicas | quote }} - {{- end }} - - name: POSTGRES_CLUSTER_APP_NAME - value: {{ .Values.replication.applicationName }} - {{- end }} - {{- if and (not (eq .Values.postgresqlUsername "postgres")) (or .Values.postgresqlPostgresPassword (include "postgresql.useExistingSecret" .)) }} - {{- if .Values.usePasswordFile }} - - name: POSTGRES_POSTGRES_PASSWORD_FILE - value: "/opt/bitnami/postgresql/secrets/postgresql-postgres-password" - {{- else }} - - name: POSTGRES_POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "postgresql.secretName" . }} - key: postgresql-postgres-password - {{- end }} - {{- end }} - - name: POSTGRES_USER - value: {{ include "postgresql.username" . | quote }} - {{- if .Values.usePasswordFile }} - - name: POSTGRES_PASSWORD_FILE - value: "/opt/bitnami/postgresql/secrets/postgresql-password" - {{- else }} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "postgresql.secretName" . }} - key: postgresql-password - {{- end }} - {{- if (include "postgresql.database" .) }} - - name: POSTGRES_DB - value: {{ (include "postgresql.database" .) | quote }} - {{- end }} - {{- if .Values.extraEnv }} - {{- include "common.tplvalues.render" (dict "value" .Values.extraEnv "context" $) | nindent 12 }} - {{- end }} - - name: POSTGRESQL_ENABLE_LDAP - value: {{ ternary "yes" "no" .Values.ldap.enabled | quote }} - {{- if .Values.ldap.enabled }} - - name: POSTGRESQL_LDAP_SERVER - value: {{ .Values.ldap.server }} - - name: POSTGRESQL_LDAP_PORT - value: {{ .Values.ldap.port | quote }} - - name: POSTGRESQL_LDAP_SCHEME - value: {{ .Values.ldap.scheme }} - {{- if .Values.ldap.tls }} - - name: POSTGRESQL_LDAP_TLS - value: "1" - {{- end }} - - name: POSTGRESQL_LDAP_PREFIX - value: {{ .Values.ldap.prefix | quote }} - - name: POSTGRESQL_LDAP_SUFFIX - value: {{ .Values.ldap.suffix | quote }} - - name: POSTGRESQL_LDAP_BASE_DN - value: {{ .Values.ldap.baseDN }} - - name: POSTGRESQL_LDAP_BIND_DN - value: {{ .Values.ldap.bindDN }} - {{- if (not (empty .Values.ldap.bind_password)) }} - - name: POSTGRESQL_LDAP_BIND_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "postgresql.secretName" . }} - key: postgresql-ldap-password - {{- end}} - - name: POSTGRESQL_LDAP_SEARCH_ATTR - value: {{ .Values.ldap.search_attr }} - - name: POSTGRESQL_LDAP_SEARCH_FILTER - value: {{ .Values.ldap.search_filter }} - - name: POSTGRESQL_LDAP_URL - value: {{ .Values.ldap.url }} - {{- end}} - - name: POSTGRESQL_ENABLE_TLS - value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} - {{- if .Values.tls.enabled }} - - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS - value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }} - - name: POSTGRESQL_TLS_CERT_FILE - value: {{ template "postgresql.tlsCert" . }} - - name: POSTGRESQL_TLS_KEY_FILE - value: {{ template "postgresql.tlsCertKey" . }} - {{- if .Values.tls.certCAFilename }} - - name: POSTGRESQL_TLS_CA_FILE - value: {{ template "postgresql.tlsCACert" . }} - {{- end }} - {{- if .Values.tls.crlFilename }} - - name: POSTGRESQL_TLS_CRL_FILE - value: {{ template "postgresql.tlsCRL" . }} - {{- end }} - {{- end }} - - name: POSTGRESQL_LOG_HOSTNAME - value: {{ .Values.audit.logHostname | quote }} - - name: POSTGRESQL_LOG_CONNECTIONS - value: {{ .Values.audit.logConnections | quote }} - - name: POSTGRESQL_LOG_DISCONNECTIONS - value: {{ .Values.audit.logDisconnections | quote }} - {{- if .Values.audit.logLinePrefix }} - - name: POSTGRESQL_LOG_LINE_PREFIX - value: {{ .Values.audit.logLinePrefix | quote }} - {{- end }} - {{- if .Values.audit.logTimezone }} - - name: POSTGRESQL_LOG_TIMEZONE - value: {{ .Values.audit.logTimezone | quote }} - {{- end }} - {{- if .Values.audit.pgAuditLog }} - - name: POSTGRESQL_PGAUDIT_LOG - value: {{ .Values.audit.pgAuditLog | quote }} - {{- end }} - - name: POSTGRESQL_PGAUDIT_LOG_CATALOG - value: {{ .Values.audit.pgAuditLogCatalog | quote }} - - name: POSTGRESQL_CLIENT_MIN_MESSAGES - value: {{ .Values.audit.clientMinMessages | quote }} - - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES - value: {{ .Values.postgresqlSharedPreloadLibraries | quote }} - {{- if .Values.postgresqlMaxConnections }} - - name: POSTGRESQL_MAX_CONNECTIONS - value: {{ .Values.postgresqlMaxConnections | quote }} - {{- end }} - {{- if .Values.postgresqlPostgresConnectionLimit }} - - name: POSTGRESQL_POSTGRES_CONNECTION_LIMIT - value: {{ .Values.postgresqlPostgresConnectionLimit | quote }} - {{- end }} - {{- if .Values.postgresqlDbUserConnectionLimit }} - - name: POSTGRESQL_USERNAME_CONNECTION_LIMIT - value: {{ .Values.postgresqlDbUserConnectionLimit | quote }} - {{- end }} - {{- if .Values.postgresqlTcpKeepalivesInterval }} - - name: POSTGRESQL_TCP_KEEPALIVES_INTERVAL - value: {{ .Values.postgresqlTcpKeepalivesInterval | quote }} - {{- end }} - {{- if .Values.postgresqlTcpKeepalivesIdle }} - - name: POSTGRESQL_TCP_KEEPALIVES_IDLE - value: {{ .Values.postgresqlTcpKeepalivesIdle | quote }} - {{- end }} - {{- if .Values.postgresqlStatementTimeout }} - - name: POSTGRESQL_STATEMENT_TIMEOUT - value: {{ .Values.postgresqlStatementTimeout | quote }} - {{- end }} - {{- if .Values.postgresqlTcpKeealivesCount }} - - name: POSTGRESQL_TCP_KEEPALIVES_COUNT - value: {{ .Values.postgresqlTcpKeealivesCount | quote }} - {{- end }} - {{- if .Values.postgresqlPghbaRemoveFilters }} - - name: POSTGRESQL_PGHBA_REMOVE_FILTERS - value: {{ .Values.postgresqlPghbaRemoveFilters | quote }} - {{- end }} - {{- if .Values.extraEnvVarsCM }} - envFrom: - - configMapRef: - name: {{ tpl .Values.extraEnvVarsCM . }} - {{- end }} - ports: - - name: tcp-postgresql - containerPort: {{ template "postgresql.port" . }} - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - exec: - command: - - /bin/sh - - -c - {{- if (include "postgresql.database" .) }} - - exec pg_isready -U {{ include "postgresql.username" . | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ template "postgresql.port" . }} - {{- else }} - - exec pg_isready -U {{ include "postgresql.username" . | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} - {{- end }} - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - {{- else if .Values.customLivenessProbe }} - livenessProbe: {{- include "postgresql.tplValue" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - exec: - command: - - /bin/sh - - -c - - -e - {{- include "postgresql.readinessProbeCommand" . | nindent 16 }} - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - {{- else if .Values.customReadinessProbe }} - readinessProbe: {{- include "postgresql.tplValue" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} - {{- end }} - volumeMounts: - {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} - - name: custom-init-scripts - mountPath: /docker-entrypoint-initdb.d/ - {{- end }} - {{- if .Values.initdbScriptsSecret }} - - name: custom-init-scripts-secret - mountPath: /docker-entrypoint-initdb.d/secret - {{- end }} - {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} - - name: postgresql-extended-config - mountPath: /bitnami/postgresql/conf/conf.d/ - {{- end }} - {{- if .Values.usePasswordFile }} - - name: postgresql-password - mountPath: /opt/bitnami/postgresql/secrets/ - {{- end }} - {{- if .Values.tls.enabled }} - - name: postgresql-certificates - mountPath: /opt/bitnami/postgresql/certs - readOnly: true - {{- end }} - {{- if .Values.shmVolume.enabled }} - - name: dshm - mountPath: /dev/shm - {{- end }} - {{- if .Values.persistence.enabled }} - - name: data - mountPath: {{ .Values.persistence.mountPath }} - subPath: {{ .Values.persistence.subPath }} - {{- end }} - {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap }} - - name: postgresql-config - mountPath: /bitnami/postgresql/conf - {{- end }} - {{- if .Values.master.extraVolumeMounts }} - {{- toYaml .Values.master.extraVolumeMounts | nindent 12 }} - {{- end }} -{{- if .Values.master.sidecars }} -{{- include "common.tplvalues.render" ( dict "value" .Values.master.sidecars "context" $ ) | nindent 8 }} -{{- end }} -{{- if .Values.metrics.enabled }} - - name: metrics - image: {{ template "postgresql.metrics.image" . }} - imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} - {{- if .Values.metrics.securityContext.enabled }} - securityContext: {{- omit .Values.metrics.securityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - env: - {{- $database := required "In order to enable metrics you need to specify a database (.Values.postgresqlDatabase or .Values.global.postgresql.postgresqlDatabase)" (include "postgresql.database" .) }} - {{- $sslmode := ternary "require" "disable" .Values.tls.enabled }} - {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} - - name: DATA_SOURCE_NAME - value: {{ printf "host=127.0.0.1 port=%d user=%s sslmode=%s sslcert=%s sslkey=%s" (int (include "postgresql.port" .)) (include "postgresql.username" .) $sslmode (include "postgresql.tlsCert" .) (include "postgresql.tlsCertKey" .) }} - {{- else }} - - name: DATA_SOURCE_URI - value: {{ printf "127.0.0.1:%d/%s?sslmode=%s" (int (include "postgresql.port" .)) $database $sslmode }} - {{- end }} - {{- if .Values.usePasswordFile }} - - name: DATA_SOURCE_PASS_FILE - value: "/opt/bitnami/postgresql/secrets/postgresql-password" - {{- else }} - - name: DATA_SOURCE_PASS - valueFrom: - secretKeyRef: - name: {{ template "postgresql.secretName" . }} - key: postgresql-password - {{- end }} - - name: DATA_SOURCE_USER - value: {{ template "postgresql.username" . }} - {{- if .Values.metrics.extraEnvVars }} - {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} - {{- end }} - {{- if .Values.livenessProbe.enabled }} - livenessProbe: - httpGet: - path: / - port: http-metrics - initialDelaySeconds: {{ .Values.metrics.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.metrics.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.metrics.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.metrics.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.metrics.livenessProbe.failureThreshold }} - {{- end }} - {{- if .Values.readinessProbe.enabled }} - readinessProbe: - httpGet: - path: / - port: http-metrics - initialDelaySeconds: {{ .Values.metrics.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.metrics.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.metrics.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.metrics.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.metrics.readinessProbe.failureThreshold }} - {{- end }} - volumeMounts: - {{- if .Values.usePasswordFile }} - - name: postgresql-password - mountPath: /opt/bitnami/postgresql/secrets/ - {{- end }} - {{- if .Values.tls.enabled }} - - name: postgresql-certificates - mountPath: /opt/bitnami/postgresql/certs - readOnly: true - {{- end }} - {{- if .Values.metrics.customMetrics }} - - name: custom-metrics - mountPath: /conf - readOnly: true - args: ["--extend.query-path", "/conf/custom-metrics.yaml"] - {{- end }} - ports: - - name: http-metrics - containerPort: 9187 - {{- if .Values.metrics.resources }} - resources: {{- toYaml .Values.metrics.resources | nindent 12 }} - {{- end }} -{{- end }} - volumes: - {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap}} - - name: postgresql-config - configMap: - name: {{ template "postgresql.configurationCM" . }} - {{- end }} - {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} - - name: postgresql-extended-config - configMap: - name: {{ template "postgresql.extendedConfigurationCM" . }} - {{- end }} - {{- if .Values.usePasswordFile }} - - name: postgresql-password - secret: - secretName: {{ template "postgresql.secretName" . }} - {{- end }} - {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} - - name: custom-init-scripts - configMap: - name: {{ template "postgresql.initdbScriptsCM" . }} - {{- end }} - {{- if .Values.initdbScriptsSecret }} - - name: custom-init-scripts-secret - secret: - secretName: {{ template "postgresql.initdbScriptsSecret" . }} - {{- end }} - {{- if .Values.tls.enabled }} - - name: raw-certificates - secret: - secretName: {{ required "A secret containing TLS certificates is required when TLS is enabled" .Values.tls.certificatesSecret }} - - name: postgresql-certificates - emptyDir: {} - {{- end }} - {{- if .Values.master.extraVolumes }} - {{- toYaml .Values.master.extraVolumes | nindent 8 }} - {{- end }} - {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} - - name: custom-metrics - configMap: - name: {{ template "postgresql.metricsCM" . }} - {{- end }} - {{- if .Values.shmVolume.enabled }} - - name: dshm - emptyDir: - medium: Memory - sizeLimit: 1Gi - {{- end }} -{{- if and .Values.persistence.enabled .Values.persistence.existingClaim }} - - name: data - persistentVolumeClaim: -{{- with .Values.persistence.existingClaim }} - claimName: {{ tpl . $ }} -{{- end }} -{{- else if not .Values.persistence.enabled }} - - name: data - emptyDir: {} -{{- else if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} - volumeClaimTemplates: - - metadata: - name: data - {{- with .Values.persistence.annotations }} - annotations: - {{- range $key, $value := . }} - {{ $key }}: {{ $value }} - {{- end }} - {{- end }} - spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{ include "postgresql.storageClass" . }} -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/svc-headless.yaml b/scripts/helm/db/postgresql/templates/svc-headless.yaml deleted file mode 100755 index fb8c838d2..000000000 --- a/scripts/helm/db/postgresql/templates/svc-headless.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "postgresql.fullname" . }}-headless - labels: - {{- include "common.labels.standard" . | nindent 4 }} - {{- if .Values.commonAnnotations }} - annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} -spec: - type: ClusterIP - clusterIP: None - ports: - - name: tcp-postgresql - port: {{ template "postgresql.port" . }} - targetPort: tcp-postgresql - selector: - {{- include "common.labels.matchLabels" . | nindent 4 }} diff --git a/scripts/helm/db/postgresql/templates/svc-read.yaml b/scripts/helm/db/postgresql/templates/svc-read.yaml deleted file mode 100755 index 5ee051c45..000000000 --- a/scripts/helm/db/postgresql/templates/svc-read.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- if .Values.replication.enabled }} -{{- $serviceAnnotations := coalesce .Values.slave.service.annotations .Values.service.annotations -}} -{{- $serviceType := coalesce .Values.slave.service.type .Values.service.type -}} -{{- $serviceLoadBalancerIP := coalesce .Values.slave.service.loadBalancerIP .Values.service.loadBalancerIP -}} -{{- $serviceLoadBalancerSourceRanges := coalesce .Values.slave.service.loadBalancerSourceRanges .Values.service.loadBalancerSourceRanges -}} -{{- $serviceClusterIP := coalesce .Values.slave.service.clusterIP .Values.service.clusterIP -}} -{{- $serviceNodePort := coalesce .Values.slave.service.nodePort .Values.service.nodePort -}} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "postgresql.fullname" . }}-read - labels: - {{- include "common.labels.standard" . | nindent 4 }} - annotations: - {{- if .Values.commonAnnotations }} - {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- if $serviceAnnotations }} - {{- include "common.tplvalues.render" (dict "value" $serviceAnnotations "context" $) | nindent 4 }} - {{- end }} -spec: - type: {{ $serviceType }} - {{- if and $serviceLoadBalancerIP (eq $serviceType "LoadBalancer") }} - loadBalancerIP: {{ $serviceLoadBalancerIP }} - {{- end }} - {{- if and (eq $serviceType "LoadBalancer") $serviceLoadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- include "common.tplvalues.render" (dict "value" $serviceLoadBalancerSourceRanges "context" $) | nindent 4 }} - {{- end }} - {{- if and (eq $serviceType "ClusterIP") $serviceClusterIP }} - clusterIP: {{ $serviceClusterIP }} - {{- end }} - ports: - - name: tcp-postgresql - port: {{ template "postgresql.port" . }} - targetPort: tcp-postgresql - {{- if $serviceNodePort }} - nodePort: {{ $serviceNodePort }} - {{- end }} - selector: - {{- include "common.labels.matchLabels" . | nindent 4 }} - role: slave -{{- end }} diff --git a/scripts/helm/db/postgresql/templates/svc.yaml b/scripts/helm/db/postgresql/templates/svc.yaml deleted file mode 100755 index 3dbfaa12d..000000000 --- a/scripts/helm/db/postgresql/templates/svc.yaml +++ /dev/null @@ -1,40 +0,0 @@ -{{- $serviceAnnotations := coalesce .Values.master.service.annotations .Values.service.annotations -}} -{{- $serviceType := coalesce .Values.master.service.type .Values.service.type -}} -{{- $serviceLoadBalancerIP := coalesce .Values.master.service.loadBalancerIP .Values.service.loadBalancerIP -}} -{{- $serviceLoadBalancerSourceRanges := coalesce .Values.master.service.loadBalancerSourceRanges .Values.service.loadBalancerSourceRanges -}} -{{- $serviceClusterIP := coalesce .Values.master.service.clusterIP .Values.service.clusterIP -}} -{{- $serviceNodePort := coalesce .Values.master.service.nodePort .Values.service.nodePort -}} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "postgresql.fullname" . }} - labels: - {{- include "common.labels.standard" . | nindent 4 }} - annotations: - {{- if .Values.commonAnnotations }} - {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} - {{- end }} - {{- if $serviceAnnotations }} - {{- include "common.tplvalues.render" (dict "value" $serviceAnnotations "context" $) | nindent 4 }} - {{- end }} -spec: - type: {{ $serviceType }} - {{- if and $serviceLoadBalancerIP (eq $serviceType "LoadBalancer") }} - loadBalancerIP: {{ $serviceLoadBalancerIP }} - {{- end }} - {{- if and (eq $serviceType "LoadBalancer") $serviceLoadBalancerSourceRanges }} - loadBalancerSourceRanges: {{- include "common.tplvalues.render" (dict "value" $serviceLoadBalancerSourceRanges "context" $) | nindent 4 }} - {{- end }} - {{- if and (eq $serviceType "ClusterIP") $serviceClusterIP }} - clusterIP: {{ $serviceClusterIP }} - {{- end }} - ports: - - name: tcp-postgresql - port: {{ template "postgresql.port" . }} - targetPort: tcp-postgresql - {{- if $serviceNodePort }} - nodePort: {{ $serviceNodePort }} - {{- end }} - selector: - {{- include "common.labels.matchLabels" . | nindent 4 }} - role: master diff --git a/scripts/helm/db/postgresql/values-production.yaml b/scripts/helm/db/postgresql/values-production.yaml deleted file mode 100755 index 3e144c131..000000000 --- a/scripts/helm/db/postgresql/values-production.yaml +++ /dev/null @@ -1,711 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -global: - postgresql: {} -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami PostgreSQL image version -## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ -## -image: - registry: docker.io - repository: bitnami/postgresql - tag: 11.9.0-debian-10-r48 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - - ## Set to true if you would like to see extra information on logs - ## It turns BASH and NAMI debugging in minideb - ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging - ## - debug: false - -## String to partially override postgresql.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override postgresql.fullname template -## -# fullnameOverride: - -## -## Init containers parameters: -## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Init container Security Context - ## Note: the chown of the data folder is done to securityContext.runAsUser - ## and not the below volumePermissions.securityContext.runAsUser - ## When runAsUser is set to special value "auto", init container will try to chwon the - ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` - ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). - ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with - ## pod securityContext.enabled=false and shmVolume.chmod.enabled=false - ## - securityContext: - runAsUser: 0 - -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: - -## Pod Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -## -securityContext: - enabled: true - fsGroup: 1001 - -## Container Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -## -containerSecurityContext: - enabled: true - runAsUser: 1001 - -## Pod Service Account -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - enabled: false - ## Name of an already existing service account. Setting this value disables the automatic service account creation. - # name: - -## Pod Security Policy -## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ -## -psp: - create: false - -## Creates role for ServiceAccount -## Required for PSP -## -rbac: - create: false - -replication: - enabled: true - user: repl_user - password: repl_password - slaveReplicas: 2 - ## Set synchronous commit mode: on, off, remote_apply, remote_write and local - ## ref: https://www.postgresql.org/docs/9.6/runtime-config-wal.html#GUC-WAL-LEVEL - ## - synchronousCommit: "on" - ## From the number of `slaveReplicas` defined above, set the number of those that will have synchronous replication - ## NOTE: It cannot be > slaveReplicas - ## - numSynchronousReplicas: 1 - ## Replication Cluster application name. Useful for defining multiple replication policies - ## - applicationName: my_application - -## PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`) -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-user-on-first-run (see note!) -# postgresqlPostgresPassword: - -## PostgreSQL user (has superuser privileges if username is `postgres`) -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run -## -postgresqlUsername: postgres - -## PostgreSQL password -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run -## -# postgresqlPassword: - -## PostgreSQL password using existing secret -## existingSecret: secret -## - -## Mount PostgreSQL secret as a file instead of passing environment variable -# usePasswordFile: false - -## Create a database -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run -## -# postgresqlDatabase: - -## PostgreSQL data dir -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md -## -postgresqlDataDir: /bitnami/postgresql/data - -## An array to add extra environment variables -## For example: -## extraEnv: -## - name: FOO -## value: "bar" -## -# extraEnv: -extraEnv: [] - -## Name of a ConfigMap containing extra env vars -## -# extraEnvVarsCM: - -## Specify extra initdb args -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md -## -# postgresqlInitdbArgs: - -## Specify a custom location for the PostgreSQL transaction log -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md -## -# postgresqlInitdbWalDir: - -## PostgreSQL configuration -## Specify runtime configuration parameters as a dict, using camelCase, e.g. -## {"sharedBuffers": "500MB"} -## Alternatively, you can put your postgresql.conf under the files/ directory -## ref: https://www.postgresql.org/docs/current/static/runtime-config.html -## -# postgresqlConfiguration: - -## PostgreSQL extended configuration -## As above, but _appended_ to the main configuration -## Alternatively, you can put your *.conf under the files/conf.d/ directory -## https://github.com/bitnami/bitnami-docker-postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf -## -# postgresqlExtendedConf: - -## Configure current cluster's master server to be the standby server in other cluster. -## This will allow cross cluster replication and provide cross cluster high availability. -## You will need to configure pgHbaConfiguration if you want to enable this feature with local cluster replication enabled. -## -masterAsStandBy: - enabled: false - # masterHost: - # masterPort: - -## PostgreSQL client authentication configuration -## Specify content for pg_hba.conf -## Default: do not create pg_hba.conf -## Alternatively, you can put your pg_hba.conf under the files/ directory -# pgHbaConfiguration: |- -# local all all trust -# host all all localhost trust -# host mydatabase mysuser 192.168.0.0/24 md5 - -## ConfigMap with PostgreSQL configuration -## NOTE: This will override postgresqlConfiguration and pgHbaConfiguration -# configurationConfigMap: - -## ConfigMap with PostgreSQL extended configuration -# extendedConfConfigMap: - -## initdb scripts -## Specify dictionary of scripts to be run at first boot -## Alternatively, you can put your scripts under the files/docker-entrypoint-initdb.d directory -## -# initdbScripts: -# my_init_script.sh: | -# #!/bin/sh -# echo "Do something." - -## Specify the PostgreSQL username and password to execute the initdb scripts -# initdbUser: -# initdbPassword: - -## ConfigMap with scripts to be run at first boot -## NOTE: This will override initdbScripts -# initdbScriptsConfigMap: - -## Secret with scripts to be run at first boot (in case it contains sensitive information) -## NOTE: This can work along initdbScripts or initdbScriptsConfigMap -# initdbScriptsSecret: - -## Optional duration in seconds the pod needs to terminate gracefully. -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods -## -# terminationGracePeriodSeconds: 30 - -## LDAP configuration -## -ldap: - enabled: false - url: "" - server: "" - port: "" - prefix: "" - suffix: "" - baseDN: "" - bindDN: "" - bind_password: - search_attr: "" - search_filter: "" - scheme: "" - tls: false - -## Audit settings -## https://github.com/bitnami/bitnami-docker-postgresql#auditing -## -audit: - ## Log client hostnames - ## - logHostname: false - ## Log connections to the server - ## - logConnections: false - ## Log disconnections - ## - logDisconnections: false - ## Operation to audit using pgAudit (default if not set) - ## - pgAuditLog: "" - ## Log catalog using pgAudit - ## - pgAuditLogCatalog: "off" - ## Log level for clients - ## - clientMinMessages: error - ## Template for log line prefix (default if not set) - ## - logLinePrefix: "" - ## Log timezone - ## - logTimezone: "" - -## Shared preload libraries -## -postgresqlSharedPreloadLibraries: "pgaudit" - -## Maximum total connections -## -postgresqlMaxConnections: - -## Maximum connections for the postgres user -## -postgresqlPostgresConnectionLimit: - -## Maximum connections for the created user -## -postgresqlDbUserConnectionLimit: - -## TCP keepalives interval -## -postgresqlTcpKeepalivesInterval: - -## TCP keepalives idle -## -postgresqlTcpKeepalivesIdle: - -## TCP keepalives count -## -postgresqlTcpKeepalivesCount: - -## Statement timeout -## -postgresqlStatementTimeout: - -## Remove pg_hba.conf lines with the following comma-separated patterns -## (cannot be used with custom pg_hba.conf) -## -postgresqlPghbaRemoveFilters: - -## PostgreSQL service configuration -## -service: - ## PosgresSQL service type - ## - type: ClusterIP - # clusterIP: None - port: 5432 - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - - ## Provide any additional annotations which may be required. Evaluated as a template. - ## - annotations: {} - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources. Evaluated as a template. - ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## - # loadBalancerSourceRanges: - # - 10.10.10.0/24 - -## Start master and slave(s) pod(s) without limitations on shm memory. -## By default docker and containerd (and possibly other container runtimes) -## limit `/dev/shm` to `64M` (see e.g. the -## [docker issue](https://github.com/docker-library/postgres/issues/416) and the -## [containerd issue](https://github.com/containerd/containerd/issues/3654), -## which could be not enough if PostgreSQL uses parallel workers heavily. -## -shmVolume: - ## Set `shmVolume.enabled` to `true` to mount a new tmpfs volume to remove - ## this limitation. - ## - enabled: true - ## Set to `true` to `chmod 777 /dev/shm` on a initContainer. - ## This option is ingored if `volumePermissions.enabled` is `false` - ## - chmod: - enabled: true - -## PostgreSQL data Persistent Volume Storage Class -## If defined, storageClassName: <storageClass> -## If set to "-", storageClassName: "", which disables dynamic provisioning -## If undefined (the default) or set to null, no storageClassName spec is -## set, choosing the default provisioner. (gp2 on AWS, standard on -## GKE, AWS & OpenStack) -## -persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template, so, for example, the name can depend on .Release or .Chart - ## - # existingClaim: - - ## The path the volume will be mounted at, useful when using different - ## PostgreSQL images. - ## - mountPath: /bitnami/postgresql - - ## The subdirectory of the volume to mount to, useful in dev environments - ## and one PV for multiple services. - ## - subPath: "" - - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - annotations: {} - -## updateStrategy for PostgreSQL StatefulSet and its slaves StatefulSets -## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies -## -updateStrategy: - type: RollingUpdate - -## -## PostgreSQL Master parameters -## -master: - ## Node, affinity, tolerations, and priorityclass settings for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature - ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption - ## - nodeSelector: {} - affinity: {} - tolerations: [] - labels: {} - annotations: {} - podLabels: {} - podAnnotations: {} - priorityClassName: "" - ## Additional PostgreSQL Master Volume mounts - ## - extraVolumeMounts: [] - ## Additional PostgreSQL Master Volumes - ## - extraVolumes: [] - ## Add sidecars to the pod - ## - ## For example: - ## sidecars: - ## - name: your-image-name - ## image: your-image - ## imagePullPolicy: Always - ## ports: - ## - name: portname - ## containerPort: 1234 - ## - sidecars: [] - - ## Override the service configuration for master - ## - service: {} - # type: - # nodePort: - # clusterIP: - -## -## PostgreSQL Slave parameters -## -slave: - ## Node, affinity, tolerations, and priorityclass settings for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature - ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption - ## - nodeSelector: {} - affinity: {} - tolerations: [] - labels: {} - annotations: {} - podLabels: {} - podAnnotations: {} - priorityClassName: "" - ## Extra init containers - ## Example - ## - ## extraInitContainers: - ## - name: do-something - ## image: busybox - ## command: ['do', 'something'] - ## - extraInitContainers: [] - ## Additional PostgreSQL Slave Volume mounts - ## - extraVolumeMounts: [] - ## Additional PostgreSQL Slave Volumes - ## - extraVolumes: [] - ## Add sidecars to the pod - ## - ## For example: - ## sidecars: - ## - name: your-image-name - ## image: your-image - ## imagePullPolicy: Always - ## ports: - ## - name: portname - ## containerPort: 1234 - ## - sidecars: [] - - ## Override the service configuration for slave - ## - service: {} - # type: - # nodePort: - # clusterIP: - ## Whether to enable PostgreSQL slave replicas data Persistent - ## - persistence: - enabled: true - - # Override the resource configuration for slave - resources: {} - # requests: - # memory: 256Mi - # cpu: 250m - -## Configure resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - requests: - memory: 256Mi - cpu: 250m - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -networkPolicy: - ## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. - ## - enabled: false - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port PostgreSQL is listening - ## on. When true, PostgreSQL will accept connections from any source - ## (with the correct destination port). - ## - allowExternal: true - - ## if explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace - ## and that match other criteria, the ones that have the good label, can reach the DB. - ## But sometimes, we want the DB to be accessible to clients from other namespaces, in this case, we can use this - ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. - ## - ## Example: - ## explicitNamespacesSelector: - ## matchLabels: - ## role: frontend - ## matchExpressions: - ## - {key: role, operator: In, values: [frontend]} - ## - explicitNamespacesSelector: {} - -## Configure extra options for liveness and readiness probes -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) -## -livenessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - -readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - -## Custom Liveness probe -## -customLivenessProbe: {} - -## Custom Rediness probe -## -customReadinessProbe: {} - -## -## TLS configuration -## -tls: - # Enable TLS traffic - enabled: false - # - # Whether to use the server's TLS cipher preferences rather than the client's. - preferServerCiphers: true - # - # Name of the Secret that contains the certificates - certificatesSecret: "" - # - # Certificate filename - certFilename: "" - # - # Certificate Key filename - certKeyFilename: "" - # - # CA Certificate filename - # If provided, PostgreSQL will authenticate TLS/SSL clients by requesting them a certificate - # ref: https://www.postgresql.org/docs/9.6/auth-methods.html - certCAFilename: - # - # File containing a Certificate Revocation List - crlFilename: - -## Configure metrics exporter -## -metrics: - enabled: true - # resources: {} - service: - type: ClusterIP - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "9187" - loadBalancerIP: - serviceMonitor: - enabled: false - additionalLabels: {} - # namespace: monitoring - # interval: 30s - # scrapeTimeout: 10s - ## Custom PrometheusRule to be defined - ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart - ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions - ## - prometheusRule: - enabled: false - additionalLabels: {} - namespace: "" - ## These are just examples rules, please adapt them to your needs. - ## Make sure to constraint the rules to the current postgresql service. - ## rules: - ## - alert: HugeReplicationLag - ## expr: pg_replication_lag{service="{{ template "postgresql.fullname" . }}-metrics"} / 3600 > 1 - ## for: 1m - ## labels: - ## severity: critical - ## annotations: - ## description: replication for {{ template "postgresql.fullname" . }} PostgreSQL is lagging by {{ "{{ $value }}" }} hour(s). - ## summary: PostgreSQL replication is lagging by {{ "{{ $value }}" }} hour(s). - ## - rules: [] - - image: - registry: docker.io - repository: bitnami/postgres-exporter - tag: 0.8.0-debian-10-r242 - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Define additional custom metrics - ## ref: https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file - # customMetrics: - # pg_database: - # query: "SELECT d.datname AS name, CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT') THEN pg_catalog.pg_database_size(d.datname) ELSE 0 END AS size FROM pg_catalog.pg_database d where datname not in ('template0', 'template1', 'postgres')" - # metrics: - # - name: - # usage: "LABEL" - # description: "Name of the database" - # - size_bytes: - # usage: "GAUGE" - # description: "Size of the database in bytes" - ## An array to add extra env vars to configure postgres-exporter - ## see: https://github.com/wrouesnel/postgres_exporter#environment-variables - ## For example: - # extraEnvVars: - # - name: PG_EXPORTER_DISABLE_DEFAULT_METRICS - # value: "true" - extraEnvVars: {} - - ## Pod Security Context - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - ## - securityContext: - enabled: false - runAsUser: 1001 - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) - ## Configure extra options for liveness and readiness probes - ## - livenessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - - readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 diff --git a/scripts/helm/db/postgresql/values.schema.json b/scripts/helm/db/postgresql/values.schema.json deleted file mode 100755 index 7b5e2efc3..000000000 --- a/scripts/helm/db/postgresql/values.schema.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "$schema": "http://json-schema.org/schema#", - "type": "object", - "properties": { - "postgresqlUsername": { - "type": "string", - "title": "Admin user", - "form": true - }, - "postgresqlPassword": { - "type": "string", - "title": "Password", - "form": true - }, - "persistence": { - "type": "object", - "properties": { - "size": { - "type": "string", - "title": "Persistent Volume Size", - "form": true, - "render": "slider", - "sliderMin": 1, - "sliderMax": 100, - "sliderUnit": "Gi" - } - } - }, - "resources": { - "type": "object", - "title": "Required Resources", - "description": "Configure resource requests", - "form": true, - "properties": { - "requests": { - "type": "object", - "properties": { - "memory": { - "type": "string", - "form": true, - "render": "slider", - "title": "Memory Request", - "sliderMin": 10, - "sliderMax": 2048, - "sliderUnit": "Mi" - }, - "cpu": { - "type": "string", - "form": true, - "render": "slider", - "title": "CPU Request", - "sliderMin": 10, - "sliderMax": 2000, - "sliderUnit": "m" - } - } - } - } - }, - "replication": { - "type": "object", - "form": true, - "title": "Replication Details", - "properties": { - "enabled": { - "type": "boolean", - "title": "Enable Replication", - "form": true - }, - "slaveReplicas": { - "type": "integer", - "title": "Slave Replicas", - "form": true, - "hidden": { - "value": false, - "path": "replication/enabled" - } - } - } - }, - "volumePermissions": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "form": true, - "title": "Enable Init Containers", - "description": "Change the owner of the persist volume mountpoint to RunAsUser:fsGroup" - } - } - }, - "metrics": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "title": "Configure metrics exporter", - "form": true - } - } - } - } -} diff --git a/scripts/helm/db/postgresql/values.yaml b/scripts/helm/db/postgresql/values.yaml deleted file mode 100755 index 0686f6532..000000000 --- a/scripts/helm/db/postgresql/values.yaml +++ /dev/null @@ -1,722 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -global: - postgresql: {} -# imageRegistry: myRegistryName -# imagePullSecrets: -# - myRegistryKeySecretName -# storageClass: myStorageClass - -## Bitnami PostgreSQL image version -## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ -## -image: - registry: docker.io - repository: bitnami/postgresql - tag: 11.9.0-debian-10-r48 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - - ## Set to true if you would like to see extra information on logs - ## It turns BASH and NAMI debugging in minideb - ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging - ## - debug: false - -## String to partially override postgresql.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override postgresql.fullname template -## -# fullnameOverride: - -## -## Init containers parameters: -## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/minideb - tag: buster - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Init container Security Context - ## Note: the chown of the data folder is done to securityContext.runAsUser - ## and not the below volumePermissions.securityContext.runAsUser - ## When runAsUser is set to special value "auto", init container will try to chwon the - ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` - ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). - ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with - ## pod securityContext.enabled=false and shmVolume.chmod.enabled=false - ## - securityContext: - runAsUser: 0 - -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: - -## Pod Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -## -securityContext: - enabled: true - fsGroup: 1001 - -## Container Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -## -containerSecurityContext: - enabled: true - runAsUser: 1001 - -## Pod Service Account -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ -## -serviceAccount: - enabled: false - ## Name of an already existing service account. Setting this value disables the automatic service account creation. - # name: - -## Pod Security Policy -## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ -## -psp: - create: false - -## Creates role for ServiceAccount -## Required for PSP -## -rbac: - create: false - -replication: - enabled: false - user: repl_user - password: repl_password - slaveReplicas: 1 - ## Set synchronous commit mode: on, off, remote_apply, remote_write and local - ## ref: https://www.postgresql.org/docs/9.6/runtime-config-wal.html#GUC-WAL-LEVEL - ## - synchronousCommit: 'off' - ## From the number of `slaveReplicas` defined above, set the number of those that will have synchronous replication - ## NOTE: It cannot be > slaveReplicas - ## - numSynchronousReplicas: 0 - ## Replication Cluster application name. Useful for defining multiple replication policies - ## - applicationName: my_application - -## PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`) -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-user-on-first-run (see note!) -# postgresqlPostgresPassword: - -## PostgreSQL user (has superuser privileges if username is `postgres`) -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run -## -postgresqlUsername: postgres - -## PostgreSQL password -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run -## -postgresqlPassword: asayerPostgres - -## PostgreSQL password using existing secret -## existingSecret: secret -## - -## Mount PostgreSQL secret as a file instead of passing environment variable -# usePasswordFile: false - -## Create a database -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run -## -# postgresqlDatabase: - -## PostgreSQL data dir -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md -## -postgresqlDataDir: /bitnami/postgresql/data - -## An array to add extra environment variables -## For example: -## extraEnv: -## - name: FOO -## value: "bar" -## -# extraEnv: -extraEnv: [] - -## Name of a ConfigMap containing extra env vars -## -# extraEnvVarsCM: - -## Specify extra initdb args -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md -## -# postgresqlInitdbArgs: - -## Specify a custom location for the PostgreSQL transaction log -## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md -## -# postgresqlInitdbWalDir: - -## PostgreSQL configuration -## Specify runtime configuration parameters as a dict, using camelCase, e.g. -## {"sharedBuffers": "500MB"} -## Alternatively, you can put your postgresql.conf under the files/ directory -## ref: https://www.postgresql.org/docs/current/static/runtime-config.html -## -# postgresqlConfiguration: - -## PostgreSQL extended configuration -## As above, but _appended_ to the main configuration -## Alternatively, you can put your *.conf under the files/conf.d/ directory -## https://github.com/bitnami/bitnami-docker-postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf -## -# postgresqlExtendedConf: - -## Configure current cluster's master server to be the standby server in other cluster. -## This will allow cross cluster replication and provide cross cluster high availability. -## You will need to configure pgHbaConfiguration if you want to enable this feature with local cluster replication enabled. -## -masterAsStandBy: - enabled: false - # masterHost: - # masterPort: - -## PostgreSQL client authentication configuration -## Specify content for pg_hba.conf -## Default: do not create pg_hba.conf -## Alternatively, you can put your pg_hba.conf under the files/ directory -# pgHbaConfiguration: |- -# local all all trust -# host all all localhost trust -# host mydatabase mysuser 192.168.0.0/24 md5 - -## ConfigMap with PostgreSQL configuration -## NOTE: This will override postgresqlConfiguration and pgHbaConfiguration -# configurationConfigMap: - -## ConfigMap with PostgreSQL extended configuration -# extendedConfConfigMap: - -## initdb scripts -## Specify dictionary of scripts to be run at first boot -## Alternatively, you can put your scripts under the files/docker-entrypoint-initdb.d directory -## -# initdbScripts: -# my_init_script.sh: | -# #!/bin/sh -# echo "Do something." - -## ConfigMap with scripts to be run at first boot -## NOTE: This will override initdbScripts -# initdbScriptsConfigMap: - -## Secret with scripts to be run at first boot (in case it contains sensitive information) -## NOTE: This can work along initdbScripts or initdbScriptsConfigMap -# initdbScriptsSecret: - -## Specify the PostgreSQL username and password to execute the initdb scripts -# initdbUser: -# initdbPassword: - -## Audit settings -## https://github.com/bitnami/bitnami-docker-postgresql#auditing -## -audit: - ## Log client hostnames - ## - logHostname: false - ## Log connections to the server - ## - logConnections: false - ## Log disconnections - ## - logDisconnections: false - ## Operation to audit using pgAudit (default if not set) - ## - pgAuditLog: "" - ## Log catalog using pgAudit - ## - pgAuditLogCatalog: "off" - ## Log level for clients - ## - clientMinMessages: error - ## Template for log line prefix (default if not set) - ## - logLinePrefix: "" - ## Log timezone - ## - logTimezone: "" - -## Shared preload libraries -## -postgresqlSharedPreloadLibraries: "pgaudit" - -## Maximum total connections -## -postgresqlMaxConnections: - -## Maximum connections for the postgres user -## -postgresqlPostgresConnectionLimit: - -## Maximum connections for the created user -## -postgresqlDbUserConnectionLimit: - -## TCP keepalives interval -## -postgresqlTcpKeepalivesInterval: - -## TCP keepalives idle -## -postgresqlTcpKeepalivesIdle: - -## TCP keepalives count -## -postgresqlTcpKeepalivesCount: - -## Statement timeout -## -postgresqlStatementTimeout: - -## Remove pg_hba.conf lines with the following comma-separated patterns -## (cannot be used with custom pg_hba.conf) -## -postgresqlPghbaRemoveFilters: - -## Optional duration in seconds the pod needs to terminate gracefully. -## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods -## -# terminationGracePeriodSeconds: 30 - -## LDAP configuration -## -ldap: - enabled: false - url: '' - server: '' - port: '' - prefix: '' - suffix: '' - baseDN: '' - bindDN: '' - bind_password: - search_attr: '' - search_filter: '' - scheme: '' - tls: false - -## PostgreSQL service configuration -## -service: - ## PosgresSQL service type - ## - type: ClusterIP - # clusterIP: None - port: 5432 - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - - ## Provide any additional annotations which may be required. Evaluated as a template. - ## - annotations: {} - ## Set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - # loadBalancerIP: - ## Load Balancer sources. Evaluated as a template. - ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service - ## - # loadBalancerSourceRanges: - # - 10.10.10.0/24 - -## Start master and slave(s) pod(s) without limitations on shm memory. -## By default docker and containerd (and possibly other container runtimes) -## limit `/dev/shm` to `64M` (see e.g. the -## [docker issue](https://github.com/docker-library/postgres/issues/416) and the -## [containerd issue](https://github.com/containerd/containerd/issues/3654), -## which could be not enough if PostgreSQL uses parallel workers heavily. -## -shmVolume: - ## Set `shmVolume.enabled` to `true` to mount a new tmpfs volume to remove - ## this limitation. - ## - enabled: true - ## Set to `true` to `chmod 777 /dev/shm` on a initContainer. - ## This option is ingored if `volumePermissions.enabled` is `false` - ## - chmod: - enabled: true - -## PostgreSQL data Persistent Volume Storage Class -## If defined, storageClassName: <storageClass> -## If set to "-", storageClassName: "", which disables dynamic provisioning -## If undefined (the default) or set to null, no storageClassName spec is -## set, choosing the default provisioner. (gp2 on AWS, standard on -## GKE, AWS & OpenStack) -## -persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## If defined, PVC must be created manually before volume will be bound - ## The value is evaluated as a template, so, for example, the name can depend on .Release or .Chart - ## - # existingClaim: - - ## The path the volume will be mounted at, useful when using different - ## PostgreSQL images. - ## - mountPath: /bitnami/postgresql - - ## The subdirectory of the volume to mount to, useful in dev environments - ## and one PV for multiple services. - ## - subPath: '' - - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - annotations: {} - -## updateStrategy for PostgreSQL StatefulSet and its slaves StatefulSets -## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies -## -updateStrategy: - type: RollingUpdate - -## -## PostgreSQL Master parameters -## -master: - ## Node, affinity, tolerations, and priorityclass settings for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature - ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption - ## - nodeSelector: {} - affinity: {} - tolerations: [] - labels: {} - annotations: {} - podLabels: {} - podAnnotations: {} - priorityClassName: '' - ## Extra init containers - ## Example - ## - ## extraInitContainers: - ## - name: do-something - ## image: busybox - ## command: ['do', 'something'] - ## - extraInitContainers: [] - - ## Additional PostgreSQL Master Volume mounts - ## - extraVolumeMounts: [] - ## Additional PostgreSQL Master Volumes - ## - extraVolumes: [] - ## Add sidecars to the pod - ## - ## For example: - ## sidecars: - ## - name: your-image-name - ## image: your-image - ## imagePullPolicy: Always - ## ports: - ## - name: portname - ## containerPort: 1234 - ## - sidecars: [] - - ## Override the service configuration for master - ## - service: {} - # type: - # nodePort: - # clusterIP: - -## -## PostgreSQL Slave parameters -## -slave: - ## Node, affinity, tolerations, and priorityclass settings for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature - ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption - ## - nodeSelector: {} - affinity: {} - tolerations: [] - labels: {} - annotations: {} - podLabels: {} - podAnnotations: {} - priorityClassName: '' - extraInitContainers: | - # - name: do-something - # image: busybox - # command: ['do', 'something'] - ## Additional PostgreSQL Slave Volume mounts - ## - extraVolumeMounts: [] - ## Additional PostgreSQL Slave Volumes - ## - extraVolumes: [] - ## Add sidecars to the pod - ## - ## For example: - ## sidecars: - ## - name: your-image-name - ## image: your-image - ## imagePullPolicy: Always - ## ports: - ## - name: portname - ## containerPort: 1234 - ## - sidecars: [] - - ## Override the service configuration for slave - ## - service: {} - # type: - # nodePort: - # clusterIP: - - ## Whether to enable PostgreSQL slave replicas data Persistent - ## - persistence: - enabled: true - - # Override the resource configuration for slave - resources: {} - # requests: - # memory: 256Mi - # cpu: 250m - -## Configure resource requests and limits -## ref: http://kubernetes.io/docs/user-guide/compute-resources/ -## -resources: - requests: - memory: 256Mi - cpu: 250m - -## Add annotations to all the deployed resources -## -commonAnnotations: {} - -networkPolicy: - ## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. - ## - enabled: false - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port PostgreSQL is listening - ## on. When true, PostgreSQL will accept connections from any source - ## (with the correct destination port). - ## - allowExternal: true - - ## if explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace - ## and that match other criteria, the ones that have the good label, can reach the DB. - ## But sometimes, we want the DB to be accessible to clients from other namespaces, in this case, we can use this - ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. - ## - ## Example: - ## explicitNamespacesSelector: - ## matchLabels: - ## role: frontend - ## matchExpressions: - ## - {key: role, operator: In, values: [frontend]} - ## - explicitNamespacesSelector: {} - -## Configure extra options for liveness and readiness probes -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) -## -livenessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - -readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - -## Custom Liveness probe -## -customLivenessProbe: {} - -## Custom Rediness probe -## -customReadinessProbe: {} - -## -## TLS configuration -## -tls: - # Enable TLS traffic - enabled: false - # - # Whether to use the server's TLS cipher preferences rather than the client's. - preferServerCiphers: true - # - # Name of the Secret that contains the certificates - certificatesSecret: '' - # - # Certificate filename - certFilename: '' - # - # Certificate Key filename - certKeyFilename: '' - # - # CA Certificate filename - # If provided, PostgreSQL will authenticate TLS/SSL clients by requesting them a certificate - # ref: https://www.postgresql.org/docs/9.6/auth-methods.html - certCAFilename: - # - # File containing a Certificate Revocation List - crlFilename: - -## Configure metrics exporter -## -metrics: - enabled: false - # resources: {} - service: - type: ClusterIP - annotations: - prometheus.io/scrape: 'true' - prometheus.io/port: '9187' - loadBalancerIP: - serviceMonitor: - enabled: false - additionalLabels: {} - # namespace: monitoring - # interval: 30s - # scrapeTimeout: 10s - ## Custom PrometheusRule to be defined - ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart - ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions - ## - prometheusRule: - enabled: false - additionalLabels: {} - namespace: '' - ## These are just examples rules, please adapt them to your needs. - ## Make sure to constraint the rules to the current postgresql service. - ## rules: - ## - alert: HugeReplicationLag - ## expr: pg_replication_lag{service="{{ template "postgresql.fullname" . }}-metrics"} / 3600 > 1 - ## for: 1m - ## labels: - ## severity: critical - ## annotations: - ## description: replication for {{ template "postgresql.fullname" . }} PostgreSQL is lagging by {{ "{{ $value }}" }} hour(s). - ## summary: PostgreSQL replication is lagging by {{ "{{ $value }}" }} hour(s). - ## - rules: [] - - image: - registry: docker.io - repository: bitnami/postgres-exporter - tag: 0.8.0-debian-10-r242 - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - ## Define additional custom metrics - ## ref: https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file - # customMetrics: - # pg_database: - # query: "SELECT d.datname AS name, CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT') THEN pg_catalog.pg_database_size(d.datname) ELSE 0 END AS size_bytes FROM pg_catalog.pg_database d where datname not in ('template0', 'template1', 'postgres')" - # metrics: - # - name: - # usage: "LABEL" - # description: "Name of the database" - # - size_bytes: - # usage: "GAUGE" - # description: "Size of the database in bytes" - # - ## An array to add extra env vars to configure postgres-exporter - ## see: https://github.com/wrouesnel/postgres_exporter#environment-variables - ## For example: - # extraEnvVars: - # - name: PG_EXPORTER_DISABLE_DEFAULT_METRICS - # value: "true" - extraEnvVars: {} - - ## Pod Security Context - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - ## - securityContext: - enabled: false - runAsUser: 1001 - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) - ## Configure extra options for liveness and readiness probes - ## - livenessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - - readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 6 - successThreshold: 1 - -## Array with extra yaml to deploy with the chart. Evaluated as a template -## -extraDeploy: [] diff --git a/scripts/helm/db/redis/.helmignore b/scripts/helm/db/redis/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/scripts/helm/db/redis/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/scripts/helm/db/redis/Chart.lock b/scripts/helm/db/redis/Chart.lock deleted file mode 100644 index 69cc5b92f..000000000 --- a/scripts/helm/db/redis/Chart.lock +++ /dev/null @@ -1,6 +0,0 @@ -dependencies: -- name: common - repository: https://charts.bitnami.com/bitnami - version: 1.4.2 -digest: sha256:4e3ec38e0e27e9fc1defb2a13f67a0aa12374bf0b15f06a6c13b1b46df6bffeb -generated: "2021-04-05T11:40:59.141264592Z" diff --git a/scripts/helm/db/redis/Chart.yaml b/scripts/helm/db/redis/Chart.yaml deleted file mode 100644 index dd36c43e0..000000000 --- a/scripts/helm/db/redis/Chart.yaml +++ /dev/null @@ -1,29 +0,0 @@ -annotations: - category: Database -apiVersion: v2 -appVersion: 6.0.12 -dependencies: -- name: common - repository: https://charts.bitnami.com/bitnami - tags: - - bitnami-common - version: 1.x.x -description: Open source, advanced key-value store. It is often referred to as a data - structure server since keys can contain strings, hashes, lists, sets and sorted - sets. -home: https://github.com/bitnami/charts/tree/master/bitnami/redis -icon: https://bitnami.com/assets/stacks/redis/img/redis-stack-220x234.png -keywords: -- redis -- keyvalue -- database -maintainers: -- email: containers@bitnami.com - name: Bitnami -- email: cedric@desaintmartin.fr - name: desaintmartin -name: redis -sources: -- https://github.com/bitnami/bitnami-docker-redis -- http://redis.io/ -version: 12.10.1 diff --git a/scripts/helm/db/redis/README.md b/scripts/helm/db/redis/README.md deleted file mode 100644 index de0a04e18..000000000 --- a/scripts/helm/db/redis/README.md +++ /dev/null @@ -1,738 +0,0 @@ -# Redis<sup>TM</sup> Chart packaged by Bitnami - -[Redis<sup>TM</sup>](http://redis.io/) is an advanced key-value cache and store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets, sorted sets, bitmaps and hyperloglogs. - -Disclaimer: REDIS® is a registered trademark of Redis Labs Ltd.Any rights therein are reserved to Redis Labs Ltd. Any use by Bitnami is for referential purposes only and does not indicate any sponsorship, endorsement, or affiliation between Redis Labs Ltd. - -## TL;DR - -```bash -$ helm repo add bitnami https://charts.bitnami.com/bitnami -$ helm install my-release bitnami/redis -``` - -## Introduction - -This chart bootstraps a [Redis<sup>TM</sup>](https://github.com/bitnami/bitnami-docker-redis) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This chart has been tested to work with NGINX Ingress, cert-manager, fluentd and Prometheus on top of the [BKPR](https://kubeprod.io/). - -### Choose between Redis<sup>TM</sup> Helm Chart and Redis<sup>TM</sup> Cluster Helm Chart - -You can choose any of the two Redis<sup>TM</sup> Helm charts for deploying a Redis<sup>TM</sup> cluster. -While [Redis<sup>TM</sup> Helm Chart](https://github.com/bitnami/charts/tree/master/bitnami/redis) will deploy a master-slave cluster using Redis<sup>TM</sup> Sentinel, the [Redis<sup>TM</sup> Cluster Helm Chart](https://github.com/bitnami/charts/tree/master/bitnami/redis-cluster) will deploy a Redis<sup>TM</sup> Cluster topology with sharding. -The main features of each chart are the following: - -| Redis<sup>TM</sup> | Redis<sup>TM</sup> Cluster | -|--------------------------------------------------------|------------------------------------------------------------------------| -| Supports multiple databases | Supports only one database. Better if you have a big dataset | -| Single write point (single master) | Multiple write points (multiple masters) | -| ![Redis<sup>TM</sup> Topology](img/redis-topology.png) | ![Redis<sup>TM</sup> Cluster Topology](img/redis-cluster-topology.png) | - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 3.1.0 -- PV provisioner support in the underlying infrastructure - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```bash -$ helm install my-release bitnami/redis -``` - -The command deploys Redis<sup>TM</sup> on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```bash -$ helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Parameters - -The following table lists the configurable parameters of the Redis<sup>TM</sup> chart and their default values. - -| Parameter | Description | Default | -|:------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------| -| `global.imageRegistry` | Global Docker image registry | `nil` | -| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | -| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | -| `global.redis.password` | Redis<sup>TM</sup> password (overrides `password`) | `nil` | -| `image.registry` | Redis<sup>TM</sup> Image registry | `docker.io` | -| `image.repository` | Redis<sup>TM</sup> Image name | `bitnami/redis` | -| `image.tag` | Redis<sup>TM</sup> Image tag | `{TAG_NAME}` | -| `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Specify docker-registry secret names as an array | `nil` | -| `nameOverride` | String to partially override redis.fullname template with a string (will prepend the release name) | `nil` | -| `fullnameOverride` | String to fully override redis.fullname template with a string | `nil` | -| `cluster.enabled` | Use master-slave topology | `true` | -| `cluster.slaveCount` | Number of slaves | `2` | -| `existingSecret` | Name of existing secret object (for password authentication) | `nil` | -| `existingSecretPasswordKey` | Name of key containing password to be retrieved from the existing secret | `nil` | -| `usePassword` | Use password | `true` | -| `usePasswordFile` | Mount passwords as files instead of environment variables | `false` | -| `password` | Redis<sup>TM</sup> password (ignored if existingSecret set) | Randomly generated | -| `configmap` | Additional common Redis<sup>TM</sup> node configuration (this value is evaluated as a template) | See values.yaml | -| `clusterDomain` | Kubernetes DNS Domain name to use | `cluster.local` | -| `extraVolumes` | Array of extra volumes to be added to master & slave nodes (evaluated as a template) | `[]` | -| `extraVolumeMounts` | Array of extra volume mounts to be added to master & slave nodes (evaluated as a template) | `[]` | -| `networkPolicy.enabled` | Enable NetworkPolicy | `false` | -| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | -| `networkPolicy.ingressNSMatchLabels` | Allow connections from other namespaces | `{}` | -| `networkPolicy.ingressNSPodMatchLabels` | For other namespaces match by pod labels and namespace labels | `{}` | -| `securityContext.*` | Other pod security context to be included as-is in the pod spec | `{}` | -| `securityContext.enabled` | Enable security context (both redis master and slave pods) | `true` | -| `securityContext.fsGroup` | Group ID for the container (both redis master and slave pods) | `1001` | -| `containerSecurityContext.*` | Other container security context to be included as-is in the container spec | `{}` | -| `containerSecurityContext.enabled` | Enable security context (both redis master and slave containers) | `true` | -| `containerSecurityContext.runAsUser` | User ID for the container (both redis master and slave containers) | `1001` | -| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `false` | -| `serviceAccount.name` | The name of the ServiceAccount to create | Generated using the fullname template | -| `serviceAccount.annotations` | Specifies annotations to add to ServiceAccount. | `nil` | -| `rbac.create` | Specifies whether RBAC resources should be created | `false` | -| `rbac.role.rules` | Rules to create | `[]` | -| `metrics.enabled` | Start a side-car prometheus exporter | `false` | -| `metrics.image.registry` | Redis<sup>TM</sup> exporter image registry | `docker.io` | -| `metrics.image.repository` | Redis<sup>TM</sup> exporter image name | `bitnami/redis-exporter` | -| `metrics.image.tag` | Redis<sup>TM</sup> exporter image tag | `{TAG_NAME}` | -| `metrics.image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `nil` | -| `metrics.extraArgs` | Extra arguments for the binary; possible values [here](https://github.com/oliver006/redis_exporter#flags) | {} | -| `metrics.podLabels` | Additional labels for Metrics exporter pod | {} | -| `metrics.podAnnotations` | Additional annotations for Metrics exporter pod | {} | -| `metrics.resources` | Exporter resource requests/limit | Memory: `256Mi`, CPU: `100m` | -| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | -| `metrics.serviceMonitor.namespace` | Optional namespace which Prometheus is running in | `nil` | -| `metrics.serviceMonitor.interval` | How frequently to scrape metrics (use by default, falling back to Prometheus' default) | `nil` | -| `metrics.serviceMonitor.selector` | Default to kube-prometheus install (CoreOS recommended), but should be set according to Prometheus install | `{ prometheus: kube-prometheus }` | -| `metrics.serviceMonitor.relabelings` | ServiceMonitor relabelings. Value is evaluated as a template | `[]` | -| `metrics.serviceMonitor.metricRelabelings` | ServiceMonitor metricRelabelings. Value is evaluated as a template | `[]` | -| `metrics.service.type` | Kubernetes Service type (redis metrics) | `ClusterIP` | -| `metrics.service.externalTrafficPolicy` | External traffic policy (when service type is LoadBalancer) | `Cluster` | -| `metrics.service.annotations` | Annotations for the services to monitor (redis master and redis slave service) | {} | -| `metrics.service.labels` | Additional labels for the metrics service | {} | -| `metrics.service.loadBalancerIP` | loadBalancerIP if redis metrics service type is `LoadBalancer` | `nil` | -| `metrics.priorityClassName` | Metrics exporter pod priorityClassName | `nil` | -| `metrics.prometheusRule.enabled` | Set this to true to create prometheusRules for Prometheus operator | `false` | -| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so prometheusRules will be discovered by Prometheus | `{}` | -| `metrics.prometheusRule.namespace` | namespace where prometheusRules resource should be created | Same namespace as redis | -| `metrics.prometheusRule.rules` | [rules](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/) to be created, check values for an example. | `[]` | -| `metrics.redisTargetHost` | way to specify an alternative redis hostname, if you set a local endpoint in hostAliases to match specific redis server certificate CN/SAN for example. - | `localhost` | -| `persistence.existingClaim` | Provide an existing PersistentVolumeClaim | `nil` | -| `master.persistence.enabled` | Use a PVC to persist data (master node) | `true` | -| `master.hostAliases` | Add deployment host aliases | `[]` | -| `master.persistence.path` | Path to mount the volume at, to use other images | `/data` | -| `master.persistence.subPath` | Subdirectory of the volume to mount at | `""` | -| `master.persistence.storageClass` | Storage class of backing PVC | `generic` | -| `master.persistence.accessModes` | Persistent Volume Access Modes | `[ReadWriteOnce]` | -| `master.persistence.size` | Size of data volume | `8Gi` | -| `master.persistence.matchLabels` | matchLabels persistent volume selector | `{}` | -| `master.persistence.matchExpressions` | matchExpressions persistent volume selector | `{}` | -| `master.persistence.volumes` | Additional volumes without creating PVC | `{}` | -| `master.statefulset.labels` | Additional labels for redis master StatefulSet | `{}` | -| `master.statefulset.annotations` | Additional annotations for redis master StatefulSet | `{}` | -| `master.statefulset.updateStrategy` | Update strategy for StatefulSet | onDelete | -| `master.statefulset.rollingUpdatePartition` | Partition update strategy | `nil` | -| `master.statefulset.volumeClaimTemplates.labels` | Additional labels for redis master StatefulSet volumeClaimTemplates | `{}` | -| `master.statefulset.volumeClaimTemplates.annotations` | Additional annotations for redis master StatefulSet volumeClaimTemplates | `{}` | -| `master.podLabels` | Additional labels for Redis<sup>TM</sup> master pod | {} | -| `master.podAnnotations` | Additional annotations for Redis<sup>TM</sup> master pod | {} | -| `master.extraEnvVars` | Additional Environment Variables passed to the pod of the master's stateful set set | `[]` | -| `master.extraEnvVarCMs` | Additional Environment Variables ConfigMappassed to the pod of the master's stateful set set | `[]` | -| `master.extraEnvVarsSecret` | Additional Environment Variables Secret passed to the master's stateful set | `[]` | -| `master.extraVolumes` | Array of extra volumes to be added to master pod (evaluated as a template) | `[]` | -| `master.extraVolumeMounts` | Array of extra volume mounts to be added to master pod (evaluated as a template) | `[]` | -| `podDisruptionBudget.enabled` | Pod Disruption Budget toggle | `false` | -| `podDisruptionBudget.minAvailable` | Minimum available pods | `1` | -| `podDisruptionBudget.maxUnavailable` | Maximum unavailable | `nil` | -| `redisPort` | Redis<sup>TM</sup> port (in both master and slaves) | `6379` | -| `tls.enabled` | Enable TLS support for replication traffic | `false` | -| `tls.authClients` | Require clients to authenticate or not | `true` | -| `tls.certificatesSecret` | Name of the secret that contains the certificates | `nil` | -| `tls.certFilename` | Certificate filename | `nil` | -| `tls.certKeyFilename` | Certificate key filename | `nil` | -| `tls.certCAFilename` | CA Certificate filename | `nil` | -| `tls.dhParamsFilename` | DH params (in order to support DH based ciphers) | `nil` | -| `master.command` | Redis<sup>TM</sup> master entrypoint string. The command `redis-server` is executed if this is not provided. Note this is prepended with `exec` | `/run.sh` | -| `master.preExecCmds` | Text to inset into the startup script immediately prior to `master.command`. Use this if you need to run other ad-hoc commands as part of startup | `nil` | -| `master.configmap` | Additional Redis<sup>TM</sup> configuration for the master nodes (this value is evaluated as a template) | `nil` | -| `master.disableCommands` | Array of Redis<sup>TM</sup> commands to disable (master) | `["FLUSHDB", "FLUSHALL"]` | -| `master.extraFlags` | Redis<sup>TM</sup> master additional command line flags | [] | -| `master.nodeSelector` | Redis<sup>TM</sup> master Node labels for pod assignment | {"beta.kubernetes.io/arch": "amd64"} | -| `master.tolerations` | Toleration labels for Redis<sup>TM</sup> master pod assignment | [] | -| `master.affinity` | Affinity settings for Redis<sup>TM</sup> master pod assignment | {} | -| `master.schedulerName` | Name of an alternate scheduler | `nil` | -| `master.service.type` | Kubernetes Service type (redis master) | `ClusterIP` | -| `master.service.externalTrafficPolicy` | External traffic policy (when service type is LoadBalancer) | `Cluster` | -| `master.service.port` | Kubernetes Service port (redis master) | `6379` | -| `master.service.nodePort` | Kubernetes Service nodePort (redis master) | `nil` | -| `master.service.annotations` | annotations for redis master service | {} | -| `master.service.labels` | Additional labels for redis master service | {} | -| `master.service.loadBalancerIP` | loadBalancerIP if redis master service type is `LoadBalancer` | `nil` | -| `master.service.loadBalancerSourceRanges` | loadBalancerSourceRanges if redis master service type is `LoadBalancer` | `nil` | -| `master.resources` | Redis<sup>TM</sup> master CPU/Memory resource requests/limits | Memory: `256Mi`, CPU: `100m` | -| `master.livenessProbe.enabled` | Turn on and off liveness probe (redis master pod) | `true` | -| `master.livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated (redis master pod) | `5` | -| `master.livenessProbe.periodSeconds` | How often to perform the probe (redis master pod) | `5` | -| `master.livenessProbe.timeoutSeconds` | When the probe times out (redis master pod) | `5` | -| `master.livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed (redis master pod) | `1` | -| `master.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | `5` | -| `master.readinessProbe.enabled` | Turn on and off readiness probe (redis master pod) | `true` | -| `master.readinessProbe.initialDelaySeconds` | Delay before readiness probe is initiated (redis master pod) | `5` | -| `master.readinessProbe.periodSeconds` | How often to perform the probe (redis master pod) | `5` | -| `master.readinessProbe.timeoutSeconds` | When the probe times out (redis master pod) | `1` | -| `master.readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed (redis master pod) | `1` | -| `master.readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | `5` | -| `master.shareProcessNamespace` | Redis<sup>TM</sup> Master pod `shareProcessNamespace` option. Enables /pause reap zombie PIDs. | `false` | -| `master.priorityClassName` | Redis<sup>TM</sup> Master pod priorityClassName | `nil` | -| `volumePermissions.enabled` | Enable init container that changes volume permissions in the registry (for cases where the default k8s `runAsUser` and `fsUser` values do not work) | `false` | -| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | -| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/bitnami-shell` | -| `volumePermissions.image.tag` | Init container volume-permissions image tag | `"10"` | -| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | -| `volumePermissions.resources ` | Init container volume-permissions CPU/Memory resource requests/limits | {} | -| `volumePermissions.securityContext.*` | Security context of the init container | `{}` | -| `volumePermissions.securityContext.runAsUser` | UserID for the init container (when facing issues in OpenShift or uid unknown, try value "auto") | 0 | -| `slave.hostAliases` | Add deployment host aliases | `[]` | -| `slave.service.type` | Kubernetes Service type (redis slave) | `ClusterIP` | -| `slave.service.externalTrafficPolicy` | External traffic policy (when service type is LoadBalancer) | `Cluster` | -| `slave.service.nodePort` | Kubernetes Service nodePort (redis slave) | `nil` | -| `slave.service.annotations` | annotations for redis slave service | {} | -| `slave.service.labels` | Additional labels for redis slave service | {} | -| `slave.service.port` | Kubernetes Service port (redis slave) | `6379` | -| `slave.service.loadBalancerIP` | LoadBalancerIP if Redis<sup>TM</sup> slave service type is `LoadBalancer` | `nil` | -| `slave.service.loadBalancerSourceRanges` | loadBalancerSourceRanges if Redis<sup>TM</sup> slave service type is `LoadBalancer` | `nil` | -| `slave.command` | Redis<sup>TM</sup> slave entrypoint string. The command `redis-server` is executed if this is not provided. Note this is prepended with `exec` | `/run.sh` | -| `slave.preExecCmds` | Text to inset into the startup script immediately prior to `slave.command`. Use this if you need to run other ad-hoc commands as part of startup | `nil` | -| `slave.configmap` | Additional Redis<sup>TM</sup> configuration for the slave nodes (this value is evaluated as a template) | `nil` | -| `slave.disableCommands` | Array of Redis<sup>TM</sup> commands to disable (slave) | `[FLUSHDB, FLUSHALL]` | -| `slave.extraFlags` | Redis<sup>TM</sup> slave additional command line flags | `[]` | -| `slave.livenessProbe.enabled` | Turn on and off liveness probe (redis slave pod) | `true` | -| `slave.livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated (redis slave pod) | `5` | -| `slave.livenessProbe.periodSeconds` | How often to perform the probe (redis slave pod) | `5` | -| `slave.livenessProbe.timeoutSeconds` | When the probe times out (redis slave pod) | `5` | -| `slave.livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed (redis slave pod) | `1` | -| `slave.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | `5` | -| `slave.readinessProbe.enabled` | Turn on and off slave.readiness probe (redis slave pod) | `true` | -| `slave.readinessProbe.initialDelaySeconds` | Delay before slave.readiness probe is initiated (redis slave pod) | `5` | -| `slave.readinessProbe.periodSeconds` | How often to perform the probe (redis slave pod) | `5` | -| `slave.readinessProbe.timeoutSeconds` | When the probe times out (redis slave pod) | `1` | -| `slave.readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed (redis slave pod) | `1` | -| `slave.readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. (redis slave pod) | `5` | -| `slave.shareProcessNamespace` | Redis<sup>TM</sup> slave pod `shareProcessNamespace` option. Enables /pause reap zombie PIDs. | `false` | -| `slave.persistence.enabled` | Use a PVC to persist data (slave node) | `true` | -| `slave.persistence.path` | Path to mount the volume at, to use other images | `/data` | -| `slave.persistence.subPath` | Subdirectory of the volume to mount at | `""` | -| `slave.persistence.storageClass` | Storage class of backing PVC | `generic` | -| `slave.persistence.accessModes` | Persistent Volume Access Modes | `[ReadWriteOnce]` | -| `slave.persistence.size` | Size of data volume | `8Gi` | -| `slave.persistence.matchLabels` | matchLabels persistent volume selector | `{}` | -| `slave.persistence.matchExpressions` | matchExpressions persistent volume selector | `{}` | -| `slave.statefulset.labels` | Additional labels for redis slave StatefulSet | `{}` | -| `slave.statefulset.annotations` | Additional annotations for redis slave StatefulSet | `{}` | -| `slave.statefulset.updateStrategy` | Update strategy for StatefulSet | onDelete | -| `slave.statefulset.rollingUpdatePartition` | Partition update strategy | `nil` | -| `slave.statefulset.volumeClaimTemplates.labels` | Additional labels for redis slave StatefulSet volumeClaimTemplates | `{}` | -| `slave.statefulset.volumeClaimTemplates.annotations` | Additional annotations for redis slave StatefulSet volumeClaimTemplates | `{}` | -| `slave.extraEnvVars` | Additional Environment Variables passed to the pod of the slave's stateful set set | `[]` | -| `slave.extraEnvVarCMs` | Additional Environment Variables ConfigMappassed to the pod of the slave's stateful set set | `[]` | -| `masslaveter.extraEnvVarsSecret` | Additional Environment Variables Secret passed to the slave's stateful set | `[]` | -| `slave.extraVolumes` | Array of extra volumes to be added to slave pod (evaluated as a template) | `[]` | -| `slave.extraVolumeMounts` | Array of extra volume mounts to be added to slave pod (evaluated as a template) | `[]` | -| `slave.podLabels` | Additional labels for Redis<sup>TM</sup> slave pod | `master.podLabels` | -| `slave.podAnnotations` | Additional annotations for Redis<sup>TM</sup> slave pod | `master.podAnnotations` | -| `slave.schedulerName` | Name of an alternate scheduler | `nil` | -| `slave.resources` | Redis<sup>TM</sup> slave CPU/Memory resource requests/limits | `{}` | -| `slave.affinity` | Enable node/pod affinity for slaves | {} | -| `slave.tolerations` | Toleration labels for Redis<sup>TM</sup> slave pod assignment | [] | -| `slave.spreadConstraints` | [Topology Spread Constraints](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) for Redis<sup>TM</sup> slave pod | {} | -| `slave.priorityClassName` | Redis<sup>TM</sup> Slave pod priorityClassName | `nil` | -| `sentinel.enabled` | Enable sentinel containers | `false` | -| `sentinel.usePassword` | Use password for sentinel containers | `true` | -| `sentinel.masterSet` | Name of the sentinel master set | `mymaster` | -| `sentinel.initialCheckTimeout` | Timeout for querying the redis sentinel service for the active sentinel list | `5` | -| `sentinel.quorum` | Quorum for electing a new master | `2` | -| `sentinel.downAfterMilliseconds` | Timeout for detecting a Redis<sup>TM</sup> node is down | `60000` | -| `sentinel.failoverTimeout` | Timeout for performing a election failover | `18000` | -| `sentinel.parallelSyncs` | Number of parallel syncs in the cluster | `1` | -| `sentinel.port` | Redis<sup>TM</sup> Sentinel port | `26379` | -| `sentinel.cleanDelaySeconds` | Delay seconds before issuing the the cleaning in the next node | `5` | -| `sentinel.configmap` | Additional Redis<sup>TM</sup> configuration for the sentinel nodes (this value is evaluated as a template) | `nil` | -| `sentinel.staticID` | Enable static IDs for sentinel replicas (If disabled IDs will be randomly generated on startup) | `false` | -| `sentinel.service.type` | Kubernetes Service type (redis sentinel) | `ClusterIP` | -| `sentinel.service.externalTrafficPolicy` | External traffic policy (when service type is LoadBalancer) | `Cluster` | -| `sentinel.service.nodePort` | Kubernetes Service nodePort (redis sentinel) | `nil` | -| `sentinel.service.annotations` | annotations for redis sentinel service | {} | -| `sentinel.service.labels` | Additional labels for redis sentinel service | {} | -| `sentinel.service.redisPort` | Kubernetes Service port for Redis<sup>TM</sup> read only operations | `6379` | -| `sentinel.service.sentinelPort` | Kubernetes Service port for Redis<sup>TM</sup> sentinel | `26379` | -| `sentinel.service.redisNodePort` | Kubernetes Service node port for Redis<sup>TM</sup> read only operations | `` | -| `sentinel.service.sentinelNodePort` | Kubernetes Service node port for Redis<sup>TM</sup> sentinel | `` | -| `sentinel.service.loadBalancerIP` | LoadBalancerIP if Redis<sup>TM</sup> sentinel service type is `LoadBalancer` | `nil` | -| `sentinel.livenessProbe.enabled` | Turn on and off liveness probe (redis sentinel pod) | `true` | -| `sentinel.livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated (redis sentinel pod) | `5` | -| `sentinel.livenessProbe.periodSeconds` | How often to perform the probe (redis sentinel container) | `5` | -| `sentinel.livenessProbe.timeoutSeconds` | When the probe times out (redis sentinel container) | `5` | -| `sentinel.livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed (redis sentinel container) | `1` | -| `sentinel.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | `5` | -| `sentinel.readinessProbe.enabled` | Turn on and off sentinel.readiness probe (redis sentinel pod) | `true` | -| `sentinel.readinessProbe.initialDelaySeconds` | Delay before sentinel.readiness probe is initiated (redis sentinel pod) | `5` | -| `sentinel.readinessProbe.periodSeconds` | How often to perform the probe (redis sentinel pod) | `5` | -| `sentinel.readinessProbe.timeoutSeconds` | When the probe times out (redis sentinel container) | `1` | -| `sentinel.readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed (redis sentinel container) | `1` | -| `sentinel.readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. (redis sentinel container) | `5` | -| `sentinel.resources` | Redis<sup>TM</sup> sentinel CPU/Memory resource requests/limits | `{}` | -| `sentinel.image.registry` | Redis<sup>TM</sup> Sentinel Image registry | `docker.io` | -| `sentinel.image.repository` | Redis<sup>TM</sup> Sentinel Image name | `bitnami/redis-sentinel` | -| `sentinel.image.tag` | Redis<sup>TM</sup> Sentinel Image tag | `{TAG_NAME}` | -| `sentinel.image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `sentinel.image.pullSecrets` | Specify docker-registry secret names as an array | `nil` | -| `sentinel.extraEnvVars` | Additional Environment Variables passed to the pod of the sentinel node stateful set set | `[]` | -| `sentinel.extraEnvVarCMs` | Additional Environment Variables ConfigMappassed to the pod of the sentinel node stateful set set | `[]` | -| `sentinel.extraEnvVarsSecret` | Additional Environment Variables Secret passed to the sentinel node statefulset | `[]` | -| `sentinel.extraVolumes` | Array of extra volumes to be added to sentinel node (evaluated as a template) | `[]` | -| `sentinel.extraVolumeMounts` | Array of extra volume mounts to be added to sentinel node (evaluated as a template) | `[]` | -| `sentinel.preExecCmds` | Text to inset into the startup script immediately prior to `sentinel.command`. Use this if you need to run other ad-hoc commands as part of startup | `nil` | -| `sentinel.metrics.enabled` | Start a side-car prometheus sentinel exporter | `false` | -| `sentinel.metrics.image.registry` | Redis Sentinel exporter image registry | `docker.io` | -| `sentinel.metrics.image.repository` | Redis Sentinel exporter image name | `bitnami/redis-sentinel-exporter` | -| `sentinel.metrics.image.tag` | Redis Sentinel exporter image tag | `{TAG_NAME}` | -| `sentinel.metrics.image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `sentinel.metrics.image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | -| `sentinel.metrics.extraArgs` | Extra arguments for the binary; possible values [here](https://github.com/leominov/redis_sentinel_exporter#configuration) | `{}` | -| `sentinel.metrics.resources` | Exporter resource requests/limit | `{}` | -| `sentinel.metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `sentinel.metrics.enabled` to be `true`) | `false` | -| `sentinel.metrics.serviceMonitor.namespace` | Optional namespace which Prometheus is running in | `nil` | -| `sentinel.metrics.serviceMonitor.interval` | How frequently to scrape metrics (use by default, falling back to Prometheus' default) | `nil` | -| `sentinel.metrics.serviceMonitor.selector` | Default to kube-prometheus install (CoreOS recommended), but should be set according to Prometheus install | `{ prometheus: kube-prometheus }` | -| `sentinel.metrics.service.type` | Kubernetes Service type (redis sentinel metrics) | `ClusterIP` | -| `sentinel.metrics.service.port` | Kubernetes service port (redis sentinel metrics) | `9355` | -| `sentinel.metrics.service.externalTrafficPolicy` | External traffic policy (when service type is LoadBalancer) | `Cluster` | -| `sentinel.metrics.service.annotations` | Annotations for the services to monitor (redis sentinel metrics service) | {} | -| `sentinel.metrics.service.labels` | Additional labels for the Sentinel metrics service | {} | -| `sentinel.metrics.service.loadBalancerIP` | loadBalancerIP if redis metrics service type is `LoadBalancer` | `nil` | -| `sentinel.metrics.priorityClassName` | Sentinel metrics exporter pod priorityClassName | `nil` | -| `sysctlImage.enabled` | Enable an init container to modify Kernel settings | `false` | -| `sysctlImage.command` | sysctlImage command to execute | [] | -| `sysctlImage.registry` | sysctlImage Init container registry | `docker.io` | -| `sysctlImage.repository` | sysctlImage Init container name | `bitnami/bitnami-shell` | -| `sysctlImage.tag` | sysctlImage Init container tag | `"10"` | -| `sysctlImage.pullPolicy` | sysctlImage Init container pull policy | `Always` | -| `sysctlImage.mountHostSys` | Mount the host `/sys` folder to `/host-sys` | `false` | -| `sysctlImage.resources` | sysctlImage Init container CPU/Memory resource requests/limits | {} | -| `podSecurityPolicy.create` | Specifies whether a PodSecurityPolicy should be created | `false` | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, - -```bash -$ helm install my-release \ - --set password=secretpassword \ - bitnami/redis -``` - -The above command sets the Redis<sup>TM</sup> server password to `secretpassword`. - -> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. - -Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, - -```bash -$ helm install my-release -f values.yaml bitnami/redis -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -> **Note for minikube users**: Current versions of minikube (v0.24.1 at the time of writing) provision `hostPath` persistent volumes that are only writable by root. Using chart defaults cause pod failure for the Redis<sup>TM</sup> pod as it attempts to write to the `/bitnami` directory. Consider installing Redis<sup>TM</sup> with `--set persistence.enabled=false`. See minikube issue [1990](https://github.com/kubernetes/minikube/issues/1990) for more information. - -## Configuration and installation details - -### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) - -It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. - -Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. - -### Change Redis<sup>TM</sup> version - -To modify the Redis<sup>TM</sup> version used in this chart you can specify a [valid image tag](https://hub.docker.com/r/bitnami/redis/tags/) using the `image.tag` parameter. For example, `image.tag=X.Y.Z`. This approach is also applicable to other images like exporters. - -### Cluster topologies - -#### Default: Master-Slave - -When installing the chart with `cluster.enabled=true`, it will deploy a Redis<sup>TM</sup> master StatefulSet (only one master node allowed) and a Redis<sup>TM</sup> slave StatefulSet. The slaves will be read-replicas of the master. Two services will be exposed: - - - Redis<sup>TM</sup> Master service: Points to the master, where read-write operations can be performed - - Redis<sup>TM</sup> Slave service: Points to the slaves, where only read operations are allowed. - -In case the master crashes, the slaves will wait until the master node is respawned again by the Kubernetes Controller Manager. - -#### Master-Slave with Sentinel - -When installing the chart with `cluster.enabled=true` and `sentinel.enabled=true`, it will deploy a Redis<sup>TM</sup> master StatefulSet (only one master allowed) and a Redis<sup>TM</sup> slave StatefulSet. In this case, the pods will contain an extra container with Redis<sup>TM</sup> Sentinel. This container will form a cluster of Redis<sup>TM</sup> Sentinel nodes, which will promote a new master in case the actual one fails. In addition to this, only one service is exposed: - - - Redis<sup>TM</sup> service: Exposes port 6379 for Redis<sup>TM</sup> read-only operations and port 26379 for accessing Redis<sup>TM</sup> Sentinel. - -For read-only operations, access the service using port 6379. For write operations, it's necessary to access the Redis<sup>TM</sup> Sentinel cluster and query the current master using the command below (using redis-cli or similar: - -``` -SENTINEL get-master-addr-by-name <name of your MasterSet. Example: mymaster> -``` -This command will return the address of the current master, which can be accessed from inside the cluster. - -In case the current master crashes, the Sentinel containers will elect a new master node. - -### Using password file -To use a password file for Redis<sup>TM</sup> you need to create a secret containing the password. - -> *NOTE*: It is important that the file with the password must be called `redis-password` - -And then deploy the Helm Chart using the secret name as parameter: - -```console -usePassword=true -usePasswordFile=true -existingSecret=redis-password-file -sentinels.enabled=true -metrics.enabled=true -``` - -### Securing traffic using TLS - -TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the chart: - -- `tls.enabled`: Enable TLS support. Defaults to `false` -- `tls.certificatesSecret`: Name of the secret that contains the certificates. No defaults. -- `tls.certFilename`: Certificate filename. No defaults. -- `tls.certKeyFilename`: Certificate key filename. No defaults. -- `tls.certCAFilename`: CA Certificate filename. No defaults. - -For example: - -First, create the secret with the certificates files: - -```console -kubectl create secret generic certificates-tls-secret --from-file=./cert.pem --from-file=./cert.key --from-file=./ca.pem -``` - -Then, use the following parameters: - -```console -tls.enabled="true" -tls.certificatesSecret="certificates-tls-secret" -tls.certFilename="cert.pem" -tls.certKeyFilename="cert.key" -tls.certCAFilename="ca.pem" -``` - -### Metrics - -The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9121) is exposed in the service. Metrics can be scraped from within the cluster using something similar as the described in the [example Prometheus scrape configuration](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml). If metrics are to be scraped from outside the cluster, the Kubernetes API proxy can be utilized to access the endpoint. - -If you have enabled TLS by specifying `tls.enabled=true` you also need to specify TLS option to the metrics exporter. You can do that via `metrics.extraArgs`. You can find the metrics exporter CLI flags for TLS [here](https://github.com/oliver006/redis_exporter#command-line-flags). For example: - -You can either specify `metrics.extraArgs.skip-tls-verification=true` to skip TLS verification or providing the following values under `metrics.extraArgs` for TLS client authentication: - -```console -tls-client-key-file -tls-client-cert-file -tls-ca-cert-file -``` - -### Host Kernel Settings - -Redis<sup>TM</sup> may require some changes in the kernel of the host machine to work as expected, in particular increasing the `somaxconn` value and disabling transparent huge pages. -To do so, you can set up a privileged initContainer with the `sysctlImage` config values, for example: - -``` -sysctlImage: - enabled: true - mountHostSys: true - command: - - /bin/sh - - -c - - |- - sysctl -w net.core.somaxconn=10000 - echo never > /host-sys/kernel/mm/transparent_hugepage/enabled -``` - -Alternatively, for Kubernetes 1.12+ you can set `securityContext.sysctls` which will configure sysctls for master and slave pods. Example: - -```yaml -securityContext: - sysctls: - - name: net.core.somaxconn - value: "10000" -``` - -Note that this will not disable transparent huge tables. - -## Persistence - -By default, the chart mounts a [Persistent Volume](http://kubernetes.io/docs/user-guide/persistent-volumes/) at the `/data` path. The volume is created using dynamic volume provisioning. If a Persistent Volume Claim already exists, specify it during installation. - -### Existing PersistentVolumeClaim - -1. Create the PersistentVolume -2. Create the PersistentVolumeClaim -3. Install the chart - -```bash -$ helm install my-release --set persistence.existingClaim=PVC_NAME bitnami/redis -``` - -## Backup and restore - -### Backup - -To perform a backup you will need to connect to one of the nodes and execute: - -```bash -$ kubectl exec -it my-redis-master-0 bash - -$ redis-cli -127.0.0.1:6379> auth your_current_redis_password -OK -127.0.0.1:6379> save -OK -``` - -Then you will need to get the created dump file form the redis node: - -```bash -$ kubectl cp my-redis-master-0:/data/dump.rdb dump.rdb -c redis -``` - -### Restore - -To restore in a new cluster, you will need to change a parameter in the redis.conf file and then upload the `dump.rdb` to the volume. - -Follow the following steps: - -- First you will need to set in the `values.yaml` the parameter `appendonly` to `no`, if it is already `no` you can skip this step. - -```yaml -configmap: |- - # Enable AOF https://redis.io/topics/persistence#append-only-file - appendonly no - # Disable RDB persistence, AOF persistence already enabled. - save "" -``` - -- Start the new cluster to create the PVCs. - -For example, : - -```bash -helm install new-redis -f values.yaml . --set cluster.enabled=true --set cluster.slaveCount=3 -``` - -- Now that the PVC were created, stop it and copy the `dump.rdp` on the persisted data by using a helping pod. - -``` -$ helm delete new-redis - -$ kubectl run --generator=run-pod/v1 -i --rm --tty volpod --overrides=' -{ - "apiVersion": "v1", - "kind": "Pod", - "metadata": { - "name": "redisvolpod" - }, - "spec": { - "containers": [{ - "command": [ - "tail", - "-f", - "/dev/null" - ], - "image": "bitnami/minideb", - "name": "mycontainer", - "volumeMounts": [{ - "mountPath": "/mnt", - "name": "redisdata" - }] - }], - "restartPolicy": "Never", - "volumes": [{ - "name": "redisdata", - "persistentVolumeClaim": { - "claimName": "redis-data-new-redis-master-0" - } - }] - } -}' --image="bitnami/minideb" - -$ kubectl cp dump.rdb redisvolpod:/mnt/dump.rdb -$ kubectl delete pod volpod -``` - -- Start again the cluster: - -``` -helm install new-redis -f values.yaml . --set cluster.enabled=true --set cluster.slaveCount=3 -``` - -## NetworkPolicy - -To enable network policy for Redis<sup>TM</sup>, install -[a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), -and set `networkPolicy.enabled` to `true`. - -For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting -the DefaultDeny namespace annotation. Note: this will enforce policy for _all_ pods in the namespace: - - kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" - -With NetworkPolicy enabled, only pods with the generated client label will be -able to connect to Redis<sup>TM</sup>. This label will be displayed in the output -after a successful install. - -With `networkPolicy.ingressNSMatchLabels` pods from other namespaces can connect to redis. Set `networkPolicy.ingressNSPodMatchLabels` to match pod labels in matched namespace. For example, for a namespace labeled `redis=external` and pods in that namespace labeled `redis-client=true` the fields should be set: - -``` -networkPolicy: - enabled: true - ingressNSMatchLabels: - redis: external - ingressNSPodMatchLabels: - redis-client: true -``` - -## Troubleshooting - -Find more information about how to deal with common errors related to Bitnami’s Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). - -## Upgrading an existing Release to a new major version - -A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an -incompatible breaking change needing manual actions. - -### To 11.0.0 - -When using sentinel, a new statefulset called `-node` was introduced. This will break upgrading from a previous version where the statefulsets are called master and slave. Hence the PVC will not match the new naming and won't be reused. If you want to keep your data, you will need to perform a backup and then a restore the data in this new version. - -### To 10.0.0 - -For releases with `usePassword: true`, the value `sentinel.usePassword` controls whether the password authentication also applies to the sentinel port. This defaults to `true` for a secure configuration, however it is possible to disable to account for the following cases: - -- Using a version of redis-sentinel prior to `5.0.1` where the authentication feature was introduced. -- Where redis clients need to be updated to support sentinel authentication. - -If using a master/slave topology, or with `usePassword: false`, no action is required. - -### To 8.0.18 - -For releases with `metrics.enabled: true` the default tag for the exporter image is now `v1.x.x`. This introduces many changes including metrics names. You'll want to use [this dashboard](https://github.com/oliver006/redis_exporter/blob/master/contrib/grafana_prometheus_redis_dashboard.json) now. Please see the [redis_exporter github page](https://github.com/oliver006/redis_exporter#upgrading-from-0x-to-1x) for more details. - -### To 7.0.0 - -This version causes a change in the Redis<sup>TM</sup> Master StatefulSet definition, so the command helm upgrade would not work out of the box. As an alternative, one of the following could be done: - -- Recommended: Create a clone of the Redis<sup>TM</sup> Master PVC (for example, using projects like [this one](https://github.com/edseymour/pvc-transfer)). Then launch a fresh release reusing this cloned PVC. - - ``` - helm install my-release bitnami/redis --set persistence.existingClaim=<NEW PVC> - ``` - -- Alternative (not recommended, do at your own risk): `helm delete --purge` does not remove the PVC assigned to the Redis<sup>TM</sup> Master StatefulSet. As a consequence, the following commands can be done to upgrade the release - - ``` - helm delete --purge <RELEASE> - helm install <RELEASE> bitnami/redis - ``` - -Previous versions of the chart were not using persistence in the slaves, so this upgrade would add it to them. Another important change is that no values are inherited from master to slaves. For example, in 6.0.0 `slaves.readinessProbe.periodSeconds`, if empty, would be set to `master.readinessProbe.periodSeconds`. This approach lacked transparency and was difficult to maintain. From now on, all the slave parameters must be configured just as it is done with the masters. - -Some values have changed as well: - -- `master.port` and `slave.port` have been changed to `redisPort` (same value for both master and slaves) -- `master.securityContext` and `slave.securityContext` have been changed to `securityContext`(same values for both master and slaves) - -By default, the upgrade will not change the cluster topology. In case you want to use Redis<sup>TM</sup> Sentinel, you must explicitly set `sentinel.enabled` to `true`. - -### To 6.0.0 - -Previous versions of the chart were using an init-container to change the permissions of the volumes. This was done in case the `securityContext` directive in the template was not enough for that (for example, with cephFS). In this new version of the chart, this container is disabled by default (which should not affect most of the deployments). If your installation still requires that init container, execute `helm upgrade` with the `--set volumePermissions.enabled=true`. - -### To 5.0.0 - -The default image in this release may be switched out for any image containing the `redis-server` -and `redis-cli` binaries. If `redis-server` is not the default image ENTRYPOINT, `master.command` -must be specified. - -#### Breaking changes - -- `master.args` and `slave.args` are removed. Use `master.command` or `slave.command` instead in order to override the image entrypoint, or `master.extraFlags` to pass additional flags to `redis-server`. -- `disableCommands` is now interpreted as an array of strings instead of a string of comma separated values. -- `master.persistence.path` now defaults to `/data`. - -### 4.0.0 - -This version removes the `chart` label from the `spec.selector.matchLabels` -which is immutable since `StatefulSet apps/v1beta2`. It has been inadvertently -added, causing any subsequent upgrade to fail. See https://github.com/helm/charts/issues/7726. - -It also fixes https://github.com/helm/charts/issues/7726 where a deployment `extensions/v1beta1` can not be upgraded if `spec.selector` is not explicitly set. - -Finally, it fixes https://github.com/helm/charts/issues/7803 by removing mutable labels in `spec.VolumeClaimTemplate.metadata.labels` so that it is upgradable. - -In order to upgrade, delete the Redis<sup>TM</sup> StatefulSet before upgrading: - -```bash -kubectl delete statefulsets.apps --cascade=false my-release-redis-master -``` - -And edit the Redis<sup>TM</sup> slave (and metrics if enabled) deployment: - -```bash -kubectl patch deployments my-release-redis-slave --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' -kubectl patch deployments my-release-redis-metrics --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]' -``` - -## Upgrading - -### To 12.0.0 - -[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. - -**What changes were introduced in this major version?** - -- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. -- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts - -**Considerations when upgrading to this version** - -- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues -- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore -- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 - -**Useful links** - -- https://docs.bitnami.com/tutorials/resolve-helm2-helm3-post-migration-issues/ -- https://helm.sh/docs/topics/v2_v3_migration/ -- https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/ - -### To 11.0.0 - -When deployed with sentinel enabled, only a group of nodes is deployed and the master/slave role is handled in the group. To avoid breaking the compatibility, the settings for this nodes are given through the `slave.xxxx` parameters in `values.yaml` - -### To 9.0.0 - -The metrics exporter has been changed from a separate deployment to a sidecar container, due to the latest changes in the Redis<sup>TM</sup> exporter code. Check the [official page](https://github.com/oliver006/redis_exporter/) for more information. The metrics container image was changed from oliver006/redis_exporter to bitnami/redis-exporter (Bitnami's maintained package of oliver006/redis_exporter). - -### To 7.0.0 - -In order to improve the performance in case of slave failure, we added persistence to the read-only slaves. That means that we moved from Deployment to StatefulSets. This should not affect upgrades from previous versions of the chart, as the deployments did not contain any persistence at all. - -This version also allows enabling Redis<sup>TM</sup> Sentinel containers inside of the Redis<sup>TM</sup> Pods (feature disabled by default). In case the master crashes, a new Redis<sup>TM</sup> node will be elected as master. In order to query the current master (no redis master service is exposed), you need to query first the Sentinel cluster. Find more information [in this section](#master-slave-with-sentinel). diff --git a/scripts/helm/db/redis/charts/common/.helmignore b/scripts/helm/db/redis/charts/common/.helmignore deleted file mode 100644 index 50af03172..000000000 --- a/scripts/helm/db/redis/charts/common/.helmignore +++ /dev/null @@ -1,22 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/scripts/helm/db/redis/charts/common/Chart.yaml b/scripts/helm/db/redis/charts/common/Chart.yaml deleted file mode 100644 index bcc3808d0..000000000 --- a/scripts/helm/db/redis/charts/common/Chart.yaml +++ /dev/null @@ -1,23 +0,0 @@ -annotations: - category: Infrastructure -apiVersion: v2 -appVersion: 1.4.2 -description: A Library Helm Chart for grouping common logic between bitnami charts. - This chart is not deployable by itself. -home: https://github.com/bitnami/charts/tree/master/bitnami/common -icon: https://bitnami.com/downloads/logos/bitnami-mark.png -keywords: -- common -- helper -- template -- function -- bitnami -maintainers: -- email: containers@bitnami.com - name: Bitnami -name: common -sources: -- https://github.com/bitnami/charts -- http://www.bitnami.com/ -type: library -version: 1.4.2 diff --git a/scripts/helm/db/redis/charts/common/README.md b/scripts/helm/db/redis/charts/common/README.md deleted file mode 100644 index 559788e39..000000000 --- a/scripts/helm/db/redis/charts/common/README.md +++ /dev/null @@ -1,322 +0,0 @@ -# Bitnami Common Library Chart - -A [Helm Library Chart](https://helm.sh/docs/topics/library_charts/#helm) for grouping common logic between bitnami charts. - -## TL;DR - -```yaml -dependencies: - - name: common - version: 0.x.x - repository: https://charts.bitnami.com/bitnami -``` - -```bash -$ helm dependency update -``` - -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "common.names.fullname" . }} -data: - myvalue: "Hello World" -``` - -## Introduction - -This chart provides a common template helpers which can be used to develop new charts using [Helm](https://helm.sh) package manager. - -Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This Helm chart has been tested on top of [Bitnami Kubernetes Production Runtime](https://kubeprod.io/) (BKPR). Deploy BKPR to get automated TLS certificates, logging and monitoring for your applications. - -## Prerequisites - -- Kubernetes 1.12+ -- Helm 3.1.0 - -## Parameters - -The following table lists the helpers available in the library which are scoped in different sections. - -### Affinities - -| Helper identifier | Description | Expected Input | -|-------------------------------|------------------------------------------------------|------------------------------------------------| -| `common.affinities.node.soft` | Return a soft nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | -| `common.affinities.node.hard` | Return a hard nodeAffinity definition | `dict "key" "FOO" "values" (list "BAR" "BAZ")` | -| `common.affinities.pod.soft` | Return a soft podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | -| `common.affinities.pod.hard` | Return a hard podAffinity/podAntiAffinity definition | `dict "component" "FOO" "context" $` | - -### Capabilities - -| Helper identifier | Description | Expected Input | -|----------------------------------------------|------------------------------------------------------------------------------------------------|-------------------| -| `common.capabilities.kubeVersion` | Return the target Kubernetes version (using client default if .Values.kubeVersion is not set). | `.` Chart context | -| `common.capabilities.deployment.apiVersion` | Return the appropriate apiVersion for deployment. | `.` Chart context | -| `common.capabilities.statefulset.apiVersion` | Return the appropriate apiVersion for statefulset. | `.` Chart context | -| `common.capabilities.ingress.apiVersion` | Return the appropriate apiVersion for ingress. | `.` Chart context | -| `common.capabilities.rbac.apiVersion` | Return the appropriate apiVersion for RBAC resources. | `.` Chart context | -| `common.capabilities.crd.apiVersion` | Return the appropriate apiVersion for CRDs. | `.` Chart context | -| `common.capabilities.supportsHelmVersion` | Returns true if the used Helm version is 3.3+ | `.` Chart context | - -### Errors - -| Helper identifier | Description | Expected Input | -|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| -| `common.errors.upgrade.passwords.empty` | It will ensure required passwords are given when we are upgrading a chart. If `validationErrors` is not empty it will throw an error and will stop the upgrade action. | `dict "validationErrors" (list $validationError00 $validationError01) "context" $` | - -### Images - -| Helper identifier | Description | Expected Input | -|-----------------------------|------------------------------------------------------|---------------------------------------------------------------------------------------------------------| -| `common.images.image` | Return the proper and full image name | `dict "imageRoot" .Values.path.to.the.image "global" $`, see [ImageRoot](#imageroot) for the structure. | -| `common.images.pullSecrets` | Return the proper Docker Image Registry Secret Names | `dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global` | - -### Ingress - -| Helper identifier | Description | Expected Input | -|--------------------------|----------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `common.ingress.backend` | Generate a proper Ingress backend entry depending on the API version | `dict "serviceName" "foo" "servicePort" "bar"`, see the [Ingress deprecation notice](https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/) for the syntax differences | - -### Labels - -| Helper identifier | Description | Expected Input | -|-----------------------------|------------------------------------------------------|-------------------| -| `common.labels.standard` | Return Kubernetes standard labels | `.` Chart context | -| `common.labels.matchLabels` | Return the proper Docker Image Registry Secret Names | `.` Chart context | - -### Names - -| Helper identifier | Description | Expected Input | -|-------------------------|------------------------------------------------------------|-------------------| -| `common.names.name` | Expand the name of the chart or use `.Values.nameOverride` | `.` Chart context | -| `common.names.fullname` | Create a default fully qualified app name. | `.` Chart context | -| `common.names.chart` | Chart name plus version | `.` Chart context | - -### Secrets - -| Helper identifier | Description | Expected Input | -|---------------------------|--------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `common.secrets.name` | Generate the name of the secret. | `dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $` see [ExistingSecret](#existingsecret) for the structure. | -| `common.secrets.key` | Generate secret key. | `dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName"` see [ExistingSecret](#existingsecret) for the structure. | -| `common.passwords.manage` | Generate secret password or retrieve one if already created. | `dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $`, length, strong and chartNAme fields are optional. | -| `common.secrets.exists` | Returns whether a previous generated secret already exists. | `dict "secret" "secret-name" "context" $` | - -### Storage - -| Helper identifier | Description | Expected Input | -|-------------------------------|---------------------------------------|---------------------------------------------------------------------------------------------------------------------| -| `common.affinities.node.soft` | Return a soft nodeAffinity definition | `dict "persistence" .Values.path.to.the.persistence "global" $`, see [Persistence](#persistence) for the structure. | - -### TplValues - -| Helper identifier | Description | Expected Input | -|---------------------------|----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| -| `common.tplvalues.render` | Renders a value that contains template | `dict "value" .Values.path.to.the.Value "context" $`, value is the value should rendered as template, context frequently is the chart context `$` or `.` | - -### Utils - -| Helper identifier | Description | Expected Input | -|--------------------------------|------------------------------------------------------------------------------------------|------------------------------------------------------------------------| -| `common.utils.fieldToEnvVar` | Build environment variable name given a field. | `dict "field" "my-password"` | -| `common.utils.secret.getvalue` | Print instructions to get a secret value. | `dict "secret" "secret-name" "field" "secret-value-field" "context" $` | -| `common.utils.getValueFromKey` | Gets a value from `.Values` object given its key path | `dict "key" "path.to.key" "context" $` | -| `common.utils.getKeyFromList` | Returns first `.Values` key with a defined value or first of the list if all non-defined | `dict "keys" (list "path.to.key1" "path.to.key2") "context" $` | - -### Validations - -| Helper identifier | Description | Expected Input | -|--------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `common.validations.values.single.empty` | Validate a value must not be empty. | `dict "valueKey" "path.to.value" "secret" "secret.name" "field" "my-password" "subchart" "subchart" "context" $` secret, field and subchart are optional. In case they are given, the helper will generate a how to get instruction. See [ValidateValue](#validatevalue) | -| `common.validations.values.multiple.empty` | Validate a multiple values must not be empty. It returns a shared error for all the values. | `dict "required" (list $validateValueConf00 $validateValueConf01) "context" $`. See [ValidateValue](#validatevalue) | -| `common.validations.values.mariadb.passwords` | This helper will ensure required password for MariaDB are not empty. It returns a shared error for all the values. | `dict "secret" "mariadb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mariadb chart and the helper. | -| `common.validations.values.postgresql.passwords` | This helper will ensure required password for PostgreSQL are not empty. It returns a shared error for all the values. | `dict "secret" "postgresql-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use postgresql chart and the helper. | -| `common.validations.values.redis.passwords` | This helper will ensure required password for Redis<sup>TM</sup> are not empty. It returns a shared error for all the values. | `dict "secret" "redis-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use redis chart and the helper. | -| `common.validations.values.cassandra.passwords` | This helper will ensure required password for Cassandra are not empty. It returns a shared error for all the values. | `dict "secret" "cassandra-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use cassandra chart and the helper. | -| `common.validations.values.mongodb.passwords` | This helper will ensure required password for MongoDB® are not empty. It returns a shared error for all the values. | `dict "secret" "mongodb-secret" "subchart" "true" "context" $` subchart field is optional and could be true or false it depends on where you will use mongodb chart and the helper. | - -### Warnings - -| Helper identifier | Description | Expected Input | -|------------------------------|----------------------------------|------------------------------------------------------------| -| `common.warnings.rollingTag` | Warning about using rolling tag. | `ImageRoot` see [ImageRoot](#imageroot) for the structure. | - -## Special input schemas - -### ImageRoot - -```yaml -registry: - type: string - description: Docker registry where the image is located - example: docker.io - -repository: - type: string - description: Repository and image name - example: bitnami/nginx - -tag: - type: string - description: image tag - example: 1.16.1-debian-10-r63 - -pullPolicy: - type: string - description: Specify a imagePullPolicy. Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - -pullSecrets: - type: array - items: - type: string - description: Optionally specify an array of imagePullSecrets. - -debug: - type: boolean - description: Set to true if you would like to see extra information on logs - example: false - -## An instance would be: -# registry: docker.io -# repository: bitnami/nginx -# tag: 1.16.1-debian-10-r63 -# pullPolicy: IfNotPresent -# debug: false -``` - -### Persistence - -```yaml -enabled: - type: boolean - description: Whether enable persistence. - example: true - -storageClass: - type: string - description: Ghost data Persistent Volume Storage Class, If set to "-", storageClassName: "" which disables dynamic provisioning. - example: "-" - -accessMode: - type: string - description: Access mode for the Persistent Volume Storage. - example: ReadWriteOnce - -size: - type: string - description: Size the Persistent Volume Storage. - example: 8Gi - -path: - type: string - description: Path to be persisted. - example: /bitnami - -## An instance would be: -# enabled: true -# storageClass: "-" -# accessMode: ReadWriteOnce -# size: 8Gi -# path: /bitnami -``` - -### ExistingSecret - -```yaml -name: - type: string - description: Name of the existing secret. - example: mySecret -keyMapping: - description: Mapping between the expected key name and the name of the key in the existing secret. - type: object - -## An instance would be: -# name: mySecret -# keyMapping: -# password: myPasswordKey -``` - -#### Example of use - -When we store sensitive data for a deployment in a secret, some times we want to give to users the possibility of using theirs existing secrets. - -```yaml -# templates/secret.yaml ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "common.names.fullname" . }} - labels: - app: {{ include "common.names.fullname" . }} -type: Opaque -data: - password: {{ .Values.password | b64enc | quote }} - -# templates/dpl.yaml ---- -... - env: - - name: PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "common.secrets.name" (dict "existingSecret" .Values.existingSecret "context" $) }} - key: {{ include "common.secrets.key" (dict "existingSecret" .Values.existingSecret "key" "password") }} -... - -# values.yaml ---- -name: mySecret -keyMapping: - password: myPasswordKey -``` - -### ValidateValue - -#### NOTES.txt - -```console -{{- $validateValueConf00 := (dict "valueKey" "path.to.value00" "secret" "secretName" "field" "password-00") -}} -{{- $validateValueConf01 := (dict "valueKey" "path.to.value01" "secret" "secretName" "field" "password-01") -}} - -{{ include "common.validations.values.multiple.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} -``` - -If we force those values to be empty we will see some alerts - -```console -$ helm install test mychart --set path.to.value00="",path.to.value01="" - 'path.to.value00' must not be empty, please add '--set path.to.value00=$PASSWORD_00' to the command. To get the current value: - - export PASSWORD_00=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-00}" | base64 --decode) - - 'path.to.value01' must not be empty, please add '--set path.to.value01=$PASSWORD_01' to the command. To get the current value: - - export PASSWORD_01=$(kubectl get secret --namespace default secretName -o jsonpath="{.data.password-01}" | base64 --decode) -``` - -## Upgrading - -### To 1.0.0 - -[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. - -**What changes were introduced in this major version?** - -- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. -- Use `type: library`. [Here](https://v3.helm.sh/docs/faq/#library-chart-support) you can find more information. -- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Charts - -**Considerations when upgrading to this version** - -- If you want to upgrade to this version from a previous one installed with Helm v3, you shouldn't face any issues -- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore -- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 - -**Useful links** - -- https://docs.bitnami.com/tutorials/resolve-helm2-helm3-post-migration-issues/ -- https://helm.sh/docs/topics/v2_v3_migration/ -- https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/ diff --git a/scripts/helm/db/redis/charts/common/templates/_affinities.tpl b/scripts/helm/db/redis/charts/common/templates/_affinities.tpl deleted file mode 100644 index 493a6dc7e..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_affinities.tpl +++ /dev/null @@ -1,94 +0,0 @@ -{{/* vim: set filetype=mustache: */}} - -{{/* -Return a soft nodeAffinity definition -{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} -*/}} -{{- define "common.affinities.nodes.soft" -}} -preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: {{ .key }} - operator: In - values: - {{- range .values }} - - {{ . }} - {{- end }} - weight: 1 -{{- end -}} - -{{/* -Return a hard nodeAffinity definition -{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} -*/}} -{{- define "common.affinities.nodes.hard" -}} -requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: {{ .key }} - operator: In - values: - {{- range .values }} - - {{ . }} - {{- end }} -{{- end -}} - -{{/* -Return a nodeAffinity definition -{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} -*/}} -{{- define "common.affinities.nodes" -}} - {{- if eq .type "soft" }} - {{- include "common.affinities.nodes.soft" . -}} - {{- else if eq .type "hard" }} - {{- include "common.affinities.nodes.hard" . -}} - {{- end -}} -{{- end -}} - -{{/* -Return a soft podAffinity/podAntiAffinity definition -{{ include "common.affinities.pods.soft" (dict "component" "FOO" "context" $) -}} -*/}} -{{- define "common.affinities.pods.soft" -}} -{{- $component := default "" .component -}} -preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 10 }} - {{- if not (empty $component) }} - {{ printf "app.kubernetes.io/component: %s" $component }} - {{- end }} - namespaces: - - {{ .context.Release.Namespace | quote }} - topologyKey: kubernetes.io/hostname - weight: 1 -{{- end -}} - -{{/* -Return a hard podAffinity/podAntiAffinity definition -{{ include "common.affinities.pods.hard" (dict "component" "FOO" "context" $) -}} -*/}} -{{- define "common.affinities.pods.hard" -}} -{{- $component := default "" .component -}} -requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 8 }} - {{- if not (empty $component) }} - {{ printf "app.kubernetes.io/component: %s" $component }} - {{- end }} - namespaces: - - {{ .context.Release.Namespace | quote }} - topologyKey: kubernetes.io/hostname -{{- end -}} - -{{/* -Return a podAffinity/podAntiAffinity definition -{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} -*/}} -{{- define "common.affinities.pods" -}} - {{- if eq .type "soft" }} - {{- include "common.affinities.pods.soft" . -}} - {{- else if eq .type "hard" }} - {{- include "common.affinities.pods.hard" . -}} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_capabilities.tpl b/scripts/helm/db/redis/charts/common/templates/_capabilities.tpl deleted file mode 100644 index 4dde56a38..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_capabilities.tpl +++ /dev/null @@ -1,95 +0,0 @@ -{{/* vim: set filetype=mustache: */}} - -{{/* -Return the target Kubernetes version -*/}} -{{- define "common.capabilities.kubeVersion" -}} -{{- if .Values.global }} - {{- if .Values.global.kubeVersion }} - {{- .Values.global.kubeVersion -}} - {{- else }} - {{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} - {{- end -}} -{{- else }} -{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for deployment. -*/}} -{{- define "common.capabilities.deployment.apiVersion" -}} -{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "extensions/v1beta1" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for statefulset. -*/}} -{{- define "common.capabilities.statefulset.apiVersion" -}} -{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "apps/v1beta1" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for ingress. -*/}} -{{- define "common.capabilities.ingress.apiVersion" -}} -{{- if .Values.ingress -}} -{{- if .Values.ingress.apiVersion -}} -{{- .Values.ingress.apiVersion -}} -{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "extensions/v1beta1" -}} -{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "networking.k8s.io/v1beta1" -}} -{{- else -}} -{{- print "networking.k8s.io/v1" -}} -{{- end }} -{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "extensions/v1beta1" -}} -{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "networking.k8s.io/v1beta1" -}} -{{- else -}} -{{- print "networking.k8s.io/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for RBAC resources. -*/}} -{{- define "common.capabilities.rbac.apiVersion" -}} -{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "rbac.authorization.k8s.io/v1beta1" -}} -{{- else -}} -{{- print "rbac.authorization.k8s.io/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for CRDs. -*/}} -{{- define "common.capabilities.crd.apiVersion" -}} -{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "apiextensions.k8s.io/v1beta1" -}} -{{- else -}} -{{- print "apiextensions.k8s.io/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Returns true if the used Helm version is 3.3+. -A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. -This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. -**To be removed when the catalog's minimun Helm version is 3.3** -*/}} -{{- define "common.capabilities.supportsHelmVersion" -}} -{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} - {{- true -}} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_errors.tpl b/scripts/helm/db/redis/charts/common/templates/_errors.tpl deleted file mode 100644 index a79cc2e32..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_errors.tpl +++ /dev/null @@ -1,23 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Through error when upgrading using empty passwords values that must not be empty. - -Usage: -{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} -{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} -{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} - -Required password params: - - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. - - context - Context - Required. Parent context. -*/}} -{{- define "common.errors.upgrade.passwords.empty" -}} - {{- $validationErrors := join "" .validationErrors -}} - {{- if and $validationErrors .context.Release.IsUpgrade -}} - {{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}} - {{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}} - {{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}} - {{- $errorString = print $errorString "\n%s" -}} - {{- printf $errorString $validationErrors | fail -}} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_images.tpl b/scripts/helm/db/redis/charts/common/templates/_images.tpl deleted file mode 100644 index 60f04fd6e..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_images.tpl +++ /dev/null @@ -1,47 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Return the proper image name -{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" $) }} -*/}} -{{- define "common.images.image" -}} -{{- $registryName := .imageRoot.registry -}} -{{- $repositoryName := .imageRoot.repository -}} -{{- $tag := .imageRoot.tag | toString -}} -{{- if .global }} - {{- if .global.imageRegistry }} - {{- $registryName = .global.imageRegistry -}} - {{- end -}} -{{- end -}} -{{- if $registryName }} -{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- else -}} -{{- printf "%s:%s" $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names -{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} -*/}} -{{- define "common.images.pullSecrets" -}} - {{- $pullSecrets := list }} - - {{- if .global }} - {{- range .global.imagePullSecrets -}} - {{- $pullSecrets = append $pullSecrets . -}} - {{- end -}} - {{- end -}} - - {{- range .images -}} - {{- range .pullSecrets -}} - {{- $pullSecrets = append $pullSecrets . -}} - {{- end -}} - {{- end -}} - - {{- if (not (empty $pullSecrets)) }} -imagePullSecrets: - {{- range $pullSecrets }} - - name: {{ . }} - {{- end }} - {{- end }} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_ingress.tpl b/scripts/helm/db/redis/charts/common/templates/_ingress.tpl deleted file mode 100644 index 622ef50e3..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_ingress.tpl +++ /dev/null @@ -1,42 +0,0 @@ -{{/* vim: set filetype=mustache: */}} - -{{/* -Generate backend entry that is compatible with all Kubernetes API versions. - -Usage: -{{ include "common.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }} - -Params: - - serviceName - String. Name of an existing service backend - - servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer. - - context - Dict - Required. The context for the template evaluation. -*/}} -{{- define "common.ingress.backend" -}} -{{- $apiVersion := (include "common.capabilities.ingress.apiVersion" .context) -}} -{{- if or (eq $apiVersion "extensions/v1beta1") (eq $apiVersion "networking.k8s.io/v1beta1") -}} -serviceName: {{ .serviceName }} -servicePort: {{ .servicePort }} -{{- else -}} -service: - name: {{ .serviceName }} - port: - {{- if typeIs "string" .servicePort }} - name: {{ .servicePort }} - {{- else if typeIs "int" .servicePort }} - number: {{ .servicePort }} - {{- end }} -{{- end -}} -{{- end -}} - -{{/* -Print "true" if the API pathType field is supported -Usage: -{{ include "common.ingress.supportsPathType" . }} -*/}} -{{- define "common.ingress.supportsPathType" -}} -{{- if (semverCompare "<1.18-0" (include "common.capabilities.kubeVersion" .)) -}} -{{- print "false" -}} -{{- else -}} -{{- print "true" -}} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_labels.tpl b/scripts/helm/db/redis/charts/common/templates/_labels.tpl deleted file mode 100644 index 252066c7e..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_labels.tpl +++ /dev/null @@ -1,18 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Kubernetes standard labels -*/}} -{{- define "common.labels.standard" -}} -app.kubernetes.io/name: {{ include "common.names.name" . }} -helm.sh/chart: {{ include "common.names.chart" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector -*/}} -{{- define "common.labels.matchLabels" -}} -app.kubernetes.io/name: {{ include "common.names.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_names.tpl b/scripts/helm/db/redis/charts/common/templates/_names.tpl deleted file mode 100644 index adf2a74f4..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_names.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "common.names.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "common.names.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "common.names.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_secrets.tpl b/scripts/helm/db/redis/charts/common/templates/_secrets.tpl deleted file mode 100644 index 60b84a701..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_secrets.tpl +++ /dev/null @@ -1,129 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Generate secret name. - -Usage: -{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} - -Params: - - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user - to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. - +info: https://github.com/bitnami/charts/tree/master/bitnami/common#existingsecret - - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. - - context - Dict - Required. The context for the template evaluation. -*/}} -{{- define "common.secrets.name" -}} -{{- $name := (include "common.names.fullname" .context) -}} - -{{- if .defaultNameSuffix -}} -{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{- with .existingSecret -}} -{{- if not (typeIs "string" .) -}} -{{- with .name -}} -{{- $name = . -}} -{{- end -}} -{{- else -}} -{{- $name = . -}} -{{- end -}} -{{- end -}} - -{{- printf "%s" $name -}} -{{- end -}} - -{{/* -Generate secret key. - -Usage: -{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} - -Params: - - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user - to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. - +info: https://github.com/bitnami/charts/tree/master/bitnami/common#existingsecret - - key - String - Required. Name of the key in the secret. -*/}} -{{- define "common.secrets.key" -}} -{{- $key := .key -}} - -{{- if .existingSecret -}} - {{- if not (typeIs "string" .existingSecret) -}} - {{- if .existingSecret.keyMapping -}} - {{- $key = index .existingSecret.keyMapping $.key -}} - {{- end -}} - {{- end }} -{{- end -}} - -{{- printf "%s" $key -}} -{{- end -}} - -{{/* -Generate secret password or retrieve one if already created. - -Usage: -{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} - -Params: - - secret - String - Required - Name of the 'Secret' resource where the password is stored. - - key - String - Required - Name of the key in the secret. - - providedValues - List<String> - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. - - length - int - Optional - Length of the generated random password. - - strong - Boolean - Optional - Whether to add symbols to the generated random password. - - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. - - context - Context - Required - Parent context. -*/}} -{{- define "common.secrets.passwords.manage" -}} - -{{- $password := "" }} -{{- $subchart := "" }} -{{- $chartName := default "" .chartName }} -{{- $passwordLength := default 10 .length }} -{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} -{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} -{{- $secret := (lookup "v1" "Secret" $.context.Release.Namespace .secret) }} -{{- if $secret }} - {{- if index $secret.data .key }} - {{- $password = index $secret.data .key }} - {{- end -}} -{{- else if $providedPasswordValue }} - {{- $password = $providedPasswordValue | toString | b64enc | quote }} -{{- else }} - - {{- if .context.Values.enabled }} - {{- $subchart = $chartName }} - {{- end -}} - - {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} - {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} - {{- $passwordValidationErrors := list $requiredPasswordError -}} - {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} - - {{- if .strong }} - {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} - {{- $password = randAscii $passwordLength }} - {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} - {{- $password = printf "%s%s" $subStr $password | toString | shuffle | b64enc | quote }} - {{- else }} - {{- $password = randAlphaNum $passwordLength | b64enc | quote }} - {{- end }} -{{- end -}} -{{- printf "%s" $password -}} -{{- end -}} - -{{/* -Returns whether a previous generated secret already exists - -Usage: -{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} - -Params: - - secret - String - Required - Name of the 'Secret' resource where the password is stored. - - context - Context - Required - Parent context. -*/}} -{{- define "common.secrets.exists" -}} -{{- $secret := (lookup "v1" "Secret" $.context.Release.Namespace .secret) }} -{{- if $secret }} - {{- true -}} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_storage.tpl b/scripts/helm/db/redis/charts/common/templates/_storage.tpl deleted file mode 100644 index 60e2a844f..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_storage.tpl +++ /dev/null @@ -1,23 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Return the proper Storage Class -{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} -*/}} -{{- define "common.storage.class" -}} - -{{- $storageClass := .persistence.storageClass -}} -{{- if .global -}} - {{- if .global.storageClass -}} - {{- $storageClass = .global.storageClass -}} - {{- end -}} -{{- end -}} - -{{- if $storageClass -}} - {{- if (eq "-" $storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" $storageClass -}} - {{- end -}} -{{- end -}} - -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_tplvalues.tpl b/scripts/helm/db/redis/charts/common/templates/_tplvalues.tpl deleted file mode 100644 index 2db166851..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_tplvalues.tpl +++ /dev/null @@ -1,13 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Renders a value that contains template. -Usage: -{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} -*/}} -{{- define "common.tplvalues.render" -}} - {{- if typeIs "string" .value }} - {{- tpl .value .context }} - {{- else }} - {{- tpl (.value | toYaml) .context }} - {{- end }} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_utils.tpl b/scripts/helm/db/redis/charts/common/templates/_utils.tpl deleted file mode 100644 index ea083a249..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_utils.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Print instructions to get a secret value. -Usage: -{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} -*/}} -{{- define "common.utils.secret.getvalue" -}} -{{- $varname := include "common.utils.fieldToEnvVar" . -}} -export {{ $varname }}=$(kubectl get secret --namespace {{ .context.Release.Namespace | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 --decode) -{{- end -}} - -{{/* -Build env var name given a field -Usage: -{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} -*/}} -{{- define "common.utils.fieldToEnvVar" -}} - {{- $fieldNameSplit := splitList "-" .field -}} - {{- $upperCaseFieldNameSplit := list -}} - - {{- range $fieldNameSplit -}} - {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} - {{- end -}} - - {{ join "_" $upperCaseFieldNameSplit }} -{{- end -}} - -{{/* -Gets a value from .Values given -Usage: -{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} -*/}} -{{- define "common.utils.getValueFromKey" -}} -{{- $splitKey := splitList "." .key -}} -{{- $value := "" -}} -{{- $latestObj := $.context.Values -}} -{{- range $splitKey -}} - {{- if not $latestObj -}} - {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} - {{- end -}} - {{- $value = ( index $latestObj . ) -}} - {{- $latestObj = $value -}} -{{- end -}} -{{- printf "%v" (default "" $value) -}} -{{- end -}} - -{{/* -Returns first .Values key with a defined value or first of the list if all non-defined -Usage: -{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} -*/}} -{{- define "common.utils.getKeyFromList" -}} -{{- $key := first .keys -}} -{{- $reverseKeys := reverse .keys }} -{{- range $reverseKeys }} - {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} - {{- if $value -}} - {{- $key = . }} - {{- end -}} -{{- end -}} -{{- printf "%s" $key -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/_warnings.tpl b/scripts/helm/db/redis/charts/common/templates/_warnings.tpl deleted file mode 100644 index ae10fa41e..000000000 --- a/scripts/helm/db/redis/charts/common/templates/_warnings.tpl +++ /dev/null @@ -1,14 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Warning about using rolling tag. -Usage: -{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} -*/}} -{{- define "common.warnings.rollingTag" -}} - -{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} -WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. -+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ -{{- end }} - -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/validations/_cassandra.tpl b/scripts/helm/db/redis/charts/common/templates/validations/_cassandra.tpl deleted file mode 100644 index 8679ddffb..000000000 --- a/scripts/helm/db/redis/charts/common/templates/validations/_cassandra.tpl +++ /dev/null @@ -1,72 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Validate Cassandra required passwords are not empty. - -Usage: -{{ include "common.validations.values.cassandra.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} -Params: - - secret - String - Required. Name of the secret where Cassandra values are stored, e.g: "cassandra-passwords-secret" - - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false -*/}} -{{- define "common.validations.values.cassandra.passwords" -}} - {{- $existingSecret := include "common.cassandra.values.existingSecret" . -}} - {{- $enabled := include "common.cassandra.values.enabled" . -}} - {{- $dbUserPrefix := include "common.cassandra.values.key.dbUser" . -}} - {{- $valueKeyPassword := printf "%s.password" $dbUserPrefix -}} - - {{- if and (not $existingSecret) (eq $enabled "true") -}} - {{- $requiredPasswords := list -}} - - {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "cassandra-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} - - {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} - - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for existingSecret. - -Usage: -{{ include "common.cassandra.values.existingSecret" (dict "context" $) }} -Params: - - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false -*/}} -{{- define "common.cassandra.values.existingSecret" -}} - {{- if .subchart -}} - {{- .context.Values.cassandra.dbUser.existingSecret | quote -}} - {{- else -}} - {{- .context.Values.dbUser.existingSecret | quote -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for enabled cassandra. - -Usage: -{{ include "common.cassandra.values.enabled" (dict "context" $) }} -*/}} -{{- define "common.cassandra.values.enabled" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.cassandra.enabled -}} - {{- else -}} - {{- printf "%v" (not .context.Values.enabled) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for the key dbUser - -Usage: -{{ include "common.cassandra.values.key.dbUser" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether Cassandra is used as subchart or not. Default: false -*/}} -{{- define "common.cassandra.values.key.dbUser" -}} - {{- if .subchart -}} - cassandra.dbUser - {{- else -}} - dbUser - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/validations/_mariadb.tpl b/scripts/helm/db/redis/charts/common/templates/validations/_mariadb.tpl deleted file mode 100644 index bb5ed7253..000000000 --- a/scripts/helm/db/redis/charts/common/templates/validations/_mariadb.tpl +++ /dev/null @@ -1,103 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Validate MariaDB required passwords are not empty. - -Usage: -{{ include "common.validations.values.mariadb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} -Params: - - secret - String - Required. Name of the secret where MariaDB values are stored, e.g: "mysql-passwords-secret" - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.validations.values.mariadb.passwords" -}} - {{- $existingSecret := include "common.mariadb.values.auth.existingSecret" . -}} - {{- $enabled := include "common.mariadb.values.enabled" . -}} - {{- $architecture := include "common.mariadb.values.architecture" . -}} - {{- $authPrefix := include "common.mariadb.values.key.auth" . -}} - {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} - {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} - {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} - {{- $valueKeyReplicationPassword := printf "%s.replicationPassword" $authPrefix -}} - - {{- if and (not $existingSecret) (eq $enabled "true") -}} - {{- $requiredPasswords := list -}} - - {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mariadb-root-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} - - {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} - {{- if not (empty $valueUsername) -}} - {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mariadb-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} - {{- end -}} - - {{- if (eq $architecture "replication") -}} - {{- $requiredReplicationPassword := dict "valueKey" $valueKeyReplicationPassword "secret" .secret "field" "mariadb-replication-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredReplicationPassword -}} - {{- end -}} - - {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} - - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for existingSecret. - -Usage: -{{ include "common.mariadb.values.auth.existingSecret" (dict "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.mariadb.values.auth.existingSecret" -}} - {{- if .subchart -}} - {{- .context.Values.mariadb.auth.existingSecret | quote -}} - {{- else -}} - {{- .context.Values.auth.existingSecret | quote -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for enabled mariadb. - -Usage: -{{ include "common.mariadb.values.enabled" (dict "context" $) }} -*/}} -{{- define "common.mariadb.values.enabled" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.mariadb.enabled -}} - {{- else -}} - {{- printf "%v" (not .context.Values.enabled) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for architecture - -Usage: -{{ include "common.mariadb.values.architecture" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.mariadb.values.architecture" -}} - {{- if .subchart -}} - {{- .context.Values.mariadb.architecture -}} - {{- else -}} - {{- .context.Values.architecture -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for the key auth - -Usage: -{{ include "common.mariadb.values.key.auth" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.mariadb.values.key.auth" -}} - {{- if .subchart -}} - mariadb.auth - {{- else -}} - auth - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/validations/_mongodb.tpl b/scripts/helm/db/redis/charts/common/templates/validations/_mongodb.tpl deleted file mode 100644 index 7d5ecbccb..000000000 --- a/scripts/helm/db/redis/charts/common/templates/validations/_mongodb.tpl +++ /dev/null @@ -1,108 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Validate MongoDB(R) required passwords are not empty. - -Usage: -{{ include "common.validations.values.mongodb.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} -Params: - - secret - String - Required. Name of the secret where MongoDB(R) values are stored, e.g: "mongodb-passwords-secret" - - subchart - Boolean - Optional. Whether MongoDB(R) is used as subchart or not. Default: false -*/}} -{{- define "common.validations.values.mongodb.passwords" -}} - {{- $existingSecret := include "common.mongodb.values.auth.existingSecret" . -}} - {{- $enabled := include "common.mongodb.values.enabled" . -}} - {{- $authPrefix := include "common.mongodb.values.key.auth" . -}} - {{- $architecture := include "common.mongodb.values.architecture" . -}} - {{- $valueKeyRootPassword := printf "%s.rootPassword" $authPrefix -}} - {{- $valueKeyUsername := printf "%s.username" $authPrefix -}} - {{- $valueKeyDatabase := printf "%s.database" $authPrefix -}} - {{- $valueKeyPassword := printf "%s.password" $authPrefix -}} - {{- $valueKeyReplicaSetKey := printf "%s.replicaSetKey" $authPrefix -}} - {{- $valueKeyAuthEnabled := printf "%s.enabled" $authPrefix -}} - - {{- $authEnabled := include "common.utils.getValueFromKey" (dict "key" $valueKeyAuthEnabled "context" .context) -}} - - {{- if and (not $existingSecret) (eq $enabled "true") (eq $authEnabled "true") -}} - {{- $requiredPasswords := list -}} - - {{- $requiredRootPassword := dict "valueKey" $valueKeyRootPassword "secret" .secret "field" "mongodb-root-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredRootPassword -}} - - {{- $valueUsername := include "common.utils.getValueFromKey" (dict "key" $valueKeyUsername "context" .context) }} - {{- $valueDatabase := include "common.utils.getValueFromKey" (dict "key" $valueKeyDatabase "context" .context) }} - {{- if and $valueUsername $valueDatabase -}} - {{- $requiredPassword := dict "valueKey" $valueKeyPassword "secret" .secret "field" "mongodb-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredPassword -}} - {{- end -}} - - {{- if (eq $architecture "replicaset") -}} - {{- $requiredReplicaSetKey := dict "valueKey" $valueKeyReplicaSetKey "secret" .secret "field" "mongodb-replica-set-key" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredReplicaSetKey -}} - {{- end -}} - - {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} - - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for existingSecret. - -Usage: -{{ include "common.mongodb.values.auth.existingSecret" (dict "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MongoDb is used as subchart or not. Default: false -*/}} -{{- define "common.mongodb.values.auth.existingSecret" -}} - {{- if .subchart -}} - {{- .context.Values.mongodb.auth.existingSecret | quote -}} - {{- else -}} - {{- .context.Values.auth.existingSecret | quote -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for enabled mongodb. - -Usage: -{{ include "common.mongodb.values.enabled" (dict "context" $) }} -*/}} -{{- define "common.mongodb.values.enabled" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.mongodb.enabled -}} - {{- else -}} - {{- printf "%v" (not .context.Values.enabled) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for the key auth - -Usage: -{{ include "common.mongodb.values.key.auth" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MongoDB(R) is used as subchart or not. Default: false -*/}} -{{- define "common.mongodb.values.key.auth" -}} - {{- if .subchart -}} - mongodb.auth - {{- else -}} - auth - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for architecture - -Usage: -{{ include "common.mongodb.values.architecture" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether MariaDB is used as subchart or not. Default: false -*/}} -{{- define "common.mongodb.values.architecture" -}} - {{- if .subchart -}} - {{- .context.Values.mongodb.architecture -}} - {{- else -}} - {{- .context.Values.architecture -}} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/validations/_postgresql.tpl b/scripts/helm/db/redis/charts/common/templates/validations/_postgresql.tpl deleted file mode 100644 index 992bcd390..000000000 --- a/scripts/helm/db/redis/charts/common/templates/validations/_postgresql.tpl +++ /dev/null @@ -1,131 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Validate PostgreSQL required passwords are not empty. - -Usage: -{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} -Params: - - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret" - - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false -*/}} -{{- define "common.validations.values.postgresql.passwords" -}} - {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} - {{- $enabled := include "common.postgresql.values.enabled" . -}} - {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} - {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} - - {{- if and (not $existingSecret) (eq $enabled "true") -}} - {{- $requiredPasswords := list -}} - - {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} - - {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} - {{- if (eq $enabledReplication "true") -}} - {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} - {{- end -}} - - {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to decide whether evaluate global values. - -Usage: -{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} -Params: - - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" -*/}} -{{- define "common.postgresql.values.use.global" -}} - {{- if .context.Values.global -}} - {{- if .context.Values.global.postgresql -}} - {{- index .context.Values.global.postgresql .key | quote -}} - {{- end -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for existingSecret. - -Usage: -{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} -*/}} -{{- define "common.postgresql.values.existingSecret" -}} - {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} - - {{- if .subchart -}} - {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} - {{- else -}} - {{- default (.context.Values.existingSecret | quote) $globalValue -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for enabled postgresql. - -Usage: -{{ include "common.postgresql.values.enabled" (dict "context" $) }} -*/}} -{{- define "common.postgresql.values.enabled" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.postgresql.enabled -}} - {{- else -}} - {{- printf "%v" (not .context.Values.enabled) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for the key postgressPassword. - -Usage: -{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false -*/}} -{{- define "common.postgresql.values.key.postgressPassword" -}} - {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} - - {{- if not $globalValue -}} - {{- if .subchart -}} - postgresql.postgresqlPassword - {{- else -}} - postgresqlPassword - {{- end -}} - {{- else -}} - global.postgresql.postgresqlPassword - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for enabled.replication. - -Usage: -{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false -*/}} -{{- define "common.postgresql.values.enabled.replication" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.postgresql.replication.enabled -}} - {{- else -}} - {{- printf "%v" .context.Values.replication.enabled -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for the key replication.password. - -Usage: -{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false -*/}} -{{- define "common.postgresql.values.key.replicationPassword" -}} - {{- if .subchart -}} - postgresql.replication.password - {{- else -}} - replication.password - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/validations/_redis.tpl b/scripts/helm/db/redis/charts/common/templates/validations/_redis.tpl deleted file mode 100644 index 3e2a47c03..000000000 --- a/scripts/helm/db/redis/charts/common/templates/validations/_redis.tpl +++ /dev/null @@ -1,72 +0,0 @@ - -{{/* vim: set filetype=mustache: */}} -{{/* -Validate Redis(TM) required passwords are not empty. - -Usage: -{{ include "common.validations.values.redis.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} -Params: - - secret - String - Required. Name of the secret where redis values are stored, e.g: "redis-passwords-secret" - - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false -*/}} -{{- define "common.validations.values.redis.passwords" -}} - {{- $existingSecret := include "common.redis.values.existingSecret" . -}} - {{- $enabled := include "common.redis.values.enabled" . -}} - {{- $valueKeyPrefix := include "common.redis.values.keys.prefix" . -}} - {{- $valueKeyRedisPassword := printf "%s%s" $valueKeyPrefix "password" -}} - {{- $valueKeyRedisUsePassword := printf "%s%s" $valueKeyPrefix "usePassword" -}} - - {{- if and (not $existingSecret) (eq $enabled "true") -}} - {{- $requiredPasswords := list -}} - - {{- $usePassword := include "common.utils.getValueFromKey" (dict "key" $valueKeyRedisUsePassword "context" .context) -}} - {{- if eq $usePassword "true" -}} - {{- $requiredRedisPassword := dict "valueKey" $valueKeyRedisPassword "secret" .secret "field" "redis-password" -}} - {{- $requiredPasswords = append $requiredPasswords $requiredRedisPassword -}} - {{- end -}} - - {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} - {{- end -}} -{{- end -}} - -{{/* -Redis Auxiliary function to get the right value for existingSecret. - -Usage: -{{ include "common.redis.values.existingSecret" (dict "context" $) }} -Params: - - subchart - Boolean - Optional. Whether Redis(TM) is used as subchart or not. Default: false -*/}} -{{- define "common.redis.values.existingSecret" -}} - {{- if .subchart -}} - {{- .context.Values.redis.existingSecret | quote -}} - {{- else -}} - {{- .context.Values.existingSecret | quote -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right value for enabled redis. - -Usage: -{{ include "common.redis.values.enabled" (dict "context" $) }} -*/}} -{{- define "common.redis.values.enabled" -}} - {{- if .subchart -}} - {{- printf "%v" .context.Values.redis.enabled -}} - {{- else -}} - {{- printf "%v" (not .context.Values.enabled) -}} - {{- end -}} -{{- end -}} - -{{/* -Auxiliary function to get the right prefix path for the values - -Usage: -{{ include "common.redis.values.key.prefix" (dict "subchart" "true" "context" $) }} -Params: - - subchart - Boolean - Optional. Whether redis is used as subchart or not. Default: false -*/}} -{{- define "common.redis.values.keys.prefix" -}} - {{- if .subchart -}}redis.{{- else -}}{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/templates/validations/_validations.tpl b/scripts/helm/db/redis/charts/common/templates/validations/_validations.tpl deleted file mode 100644 index 9a814cf40..000000000 --- a/scripts/helm/db/redis/charts/common/templates/validations/_validations.tpl +++ /dev/null @@ -1,46 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Validate values must not be empty. - -Usage: -{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} -{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} -{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} - -Validate value params: - - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" - - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" - - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" -*/}} -{{- define "common.validations.values.multiple.empty" -}} - {{- range .required -}} - {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} - {{- end -}} -{{- end -}} - -{{/* -Validate a value must not be empty. - -Usage: -{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} - -Validate value params: - - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" - - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" - - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" - - subchart - String - Optional - Name of the subchart that the validated password is part of. -*/}} -{{- define "common.validations.values.single.empty" -}} - {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} - {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} - - {{- if not $value -}} - {{- $varname := "my-value" -}} - {{- $getCurrentValue := "" -}} - {{- if and .secret .field -}} - {{- $varname = include "common.utils.fieldToEnvVar" . -}} - {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} - {{- end -}} - {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/charts/common/values.yaml b/scripts/helm/db/redis/charts/common/values.yaml deleted file mode 100644 index 9ecdc93f5..000000000 --- a/scripts/helm/db/redis/charts/common/values.yaml +++ /dev/null @@ -1,3 +0,0 @@ -## bitnami/common -## It is required by CI/CD tools and processes. -exampleValue: common-chart diff --git a/scripts/helm/db/redis/ci/default-values.yaml b/scripts/helm/db/redis/ci/default-values.yaml deleted file mode 100644 index fc2ba605a..000000000 --- a/scripts/helm/db/redis/ci/default-values.yaml +++ /dev/null @@ -1 +0,0 @@ -# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml. diff --git a/scripts/helm/db/redis/ci/extra-flags-values.yaml b/scripts/helm/db/redis/ci/extra-flags-values.yaml deleted file mode 100644 index 71132f76e..000000000 --- a/scripts/helm/db/redis/ci/extra-flags-values.yaml +++ /dev/null @@ -1,11 +0,0 @@ -master: - extraFlags: - - --maxmemory-policy allkeys-lru - persistence: - enabled: false -slave: - extraFlags: - - --maxmemory-policy allkeys-lru - persistence: - enabled: false -usePassword: false diff --git a/scripts/helm/db/redis/ci/production-sentinel-values.yaml b/scripts/helm/db/redis/ci/production-sentinel-values.yaml deleted file mode 100644 index 009a3718a..000000000 --- a/scripts/helm/db/redis/ci/production-sentinel-values.yaml +++ /dev/null @@ -1,682 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -global: - # imageRegistry: myRegistryName - # imagePullSecrets: - # - myRegistryKeySecretName - # storageClass: myStorageClass - redis: {} - -## Bitnami Redis(TM) image version -## ref: https://hub.docker.com/r/bitnami/redis/tags/ -## -image: - registry: docker.io - repository: bitnami/redis - ## Bitnami Redis(TM) image tag - ## ref: https://github.com/bitnami/bitnami-docker-redis#supported-tags-and-respective-dockerfile-links - ## - tag: 5.0.9-debian-10-r0 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - -## String to partially override redis.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override redis.fullname template -## -# fullnameOverride: - -## Cluster settings -cluster: - enabled: true - slaveCount: 3 - -## Use redis sentinel in the redis pod. This will disable the master and slave services and -## create one redis service with ports to the sentinel and the redis instances -sentinel: - enabled: true - ## Require password authentication on the sentinel itself - ## ref: https://redis.io/topics/sentinel - usePassword: true - ## Bitnami Redis(TM) Sentintel image version - ## ref: https://hub.docker.com/r/bitnami/redis-sentinel/tags/ - ## - image: - registry: docker.io - repository: bitnami/redis-sentinel - ## Bitnami Redis(TM) image tag - ## ref: https://github.com/bitnami/bitnami-docker-redis-sentinel#supported-tags-and-respective-dockerfile-links - ## - tag: 5.0.9-debian-10-r0 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - masterSet: mymaster - initialCheckTimeout: 5 - quorum: 2 - downAfterMilliseconds: 60000 - failoverTimeout: 18000 - parallelSyncs: 1 - port: 26379 - ## Additional Redis(TM) configuration for the sentinel nodes - ## ref: https://redis.io/topics/config - ## - configmap: - ## Enable or disable static sentinel IDs for each replicas - ## If disabled each sentinel will generate a random id at startup - ## If enabled, each replicas will have a constant ID on each start-up - ## - staticID: false - ## Configure extra options for Redis(TM) Sentinel liveness and readiness probes - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) - ## - livenessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 5 - customLivenessProbe: {} - customReadinessProbe: {} - ## Redis(TM) Sentinel resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - # resources: - # requests: - # memory: 256Mi - # cpu: 100m - ## Redis(TM) Sentinel Service properties - service: - ## Redis(TM) Sentinel Service type - type: ClusterIP - sentinelPort: 26379 - redisPort: 6379 - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # sentinelNodePort: - # redisNodePort: - - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - annotations: {} - labels: {} - loadBalancerIP: - -## Specifies the Kubernetes Cluster's Domain Name. -## -clusterDomain: cluster.local - -networkPolicy: - ## Specifies whether a NetworkPolicy should be created - ## - enabled: true - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port Redis(TM) is listening - ## on. When true, Redis(TM) will accept connections from any source - ## (with the correct destination port). - ## - # allowExternal: true - - ## Allow connections from other namespacess. Just set label for namespace and set label for pods (optional). - ## - ingressNSMatchLabels: {} - ingressNSPodMatchLabels: {} - -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: false - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the fullname template - name: - -rbac: - ## Specifies whether RBAC resources should be created - ## - create: false - - role: - ## Rules to create. It follows the role specification - # rules: - # - apiGroups: - # - extensions - # resources: - # - podsecuritypolicies - # verbs: - # - use - # resourceNames: - # - gce.unprivileged - rules: [] - -## Redis(TM) pod Security Context -securityContext: - enabled: true - fsGroup: 1001 - runAsUser: 1001 - ## sysctl settings for master and slave pods - ## - ## Uncomment the setting below to increase the net.core.somaxconn value - ## - # sysctls: - # - name: net.core.somaxconn - # value: "10000" - -## Use password authentication -usePassword: true -## Redis(TM) password (both master and slave) -## Defaults to a random 10-character alphanumeric string if not set and usePassword is true -## ref: https://github.com/bitnami/bitnami-docker-redis#setting-the-server-password-on-first-run -## -password: -## Use existing secret (ignores previous password) -# existingSecret: -## Password key to be retrieved from Redis(TM) secret -## -# existingSecretPasswordKey: - -## Mount secrets as files instead of environment variables -usePasswordFile: false - -## Persist data to a persistent volume (Redis(TM) Master) -persistence: - ## A manually managed Persistent Volume and Claim - ## Requires persistence.enabled: true - ## If defined, PVC must be created manually before volume will be bound - existingClaim: - -# Redis(TM) port -redisPort: 6379 - -## -## Redis(TM) Master parameters -## -master: - ## Redis(TM) command arguments - ## - ## Can be used to specify command line arguments, for example: - ## - command: "/run.sh" - ## Additional Redis(TM) configuration for the master nodes - ## ref: https://redis.io/topics/config - ## - configmap: - ## Redis(TM) additional command line flags - ## - ## Can be used to specify command line flags, for example: - ## - ## extraFlags: - ## - "--maxmemory-policy volatile-ttl" - ## - "--repl-backlog-size 1024mb" - extraFlags: [] - ## Comma-separated list of Redis(TM) commands to disable - ## - ## Can be used to disable Redis(TM) commands for security reasons. - ## Commands will be completely disabled by renaming each to an empty string. - ## ref: https://redis.io/topics/security#disabling-of-specific-commands - ## - disableCommands: - - FLUSHDB - - FLUSHALL - - ## Redis(TM) Master additional pod labels and annotations - ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - podLabels: {} - podAnnotations: {} - - ## Redis(TM) Master resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - # resources: - # requests: - # memory: 256Mi - # cpu: 100m - ## Use an alternate scheduler, e.g. "stork". - ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ - ## - # schedulerName: - - ## Configure extra options for Redis(TM) Master liveness and readiness probes - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) - ## - livenessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 5 - - ## Configure custom probes for images other images like - ## rhscl/redis-32-rhel7 rhscl/redis-5-rhel7 - ## Only used if readinessProbe.enabled: false / livenessProbe.enabled: false - ## - # customLivenessProbe: - # tcpSocket: - # port: 6379 - # initialDelaySeconds: 10 - # periodSeconds: 5 - # customReadinessProbe: - # initialDelaySeconds: 30 - # periodSeconds: 10 - # timeoutSeconds: 5 - # exec: - # command: - # - "container-entrypoint" - # - "bash" - # - "-c" - # - "redis-cli set liveness-probe \"`date`\" | grep OK" - customLivenessProbe: {} - customReadinessProbe: {} - - ## Redis(TM) Master Node selectors and tolerations for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature - ## - # nodeSelector: {"beta.kubernetes.io/arch": "amd64"} - # tolerations: [] - ## Redis(TM) Master pod/node affinity/anti-affinity - ## - affinity: {} - - ## Redis(TM) Master Service properties - service: - ## Redis(TM) Master Service type - type: ClusterIP - port: 6379 - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - annotations: {} - labels: {} - loadBalancerIP: - # loadBalancerSourceRanges: ["10.0.0.0/8"] - - ## Enable persistence using Persistent Volume Claims - ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ - ## - persistence: - enabled: true - ## The path the volume will be mounted at, useful when using different - ## Redis(TM) images. - path: /data - ## The subdirectory of the volume to mount to, useful in dev environments - ## and one PV for multiple services. - subPath: "" - ## redis data Persistent Volume Storage Class - ## If defined, storageClassName: <storageClass> - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - ## Persistent Volume selectors - ## https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector - matchLabels: {} - matchExpressions: {} - - ## Update strategy, can be set to RollingUpdate or onDelete by default. - ## https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets - statefulset: - updateStrategy: RollingUpdate - ## Partition update strategy - ## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions - # rollingUpdatePartition: - - ## Redis(TM) Master pod priorityClassName - ## - priorityClassName: {} - -## -## Redis(TM) Slave properties -## Note: service.type is a mandatory parameter -## The rest of the parameters are either optional or, if undefined, will inherit those declared in Redis(TM) Master -## -slave: - ## Slave Service properties - service: - ## Redis(TM) Slave Service type - type: ClusterIP - ## Redis(TM) port - port: 6379 - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - annotations: {} - labels: {} - loadBalancerIP: - # loadBalancerSourceRanges: ["10.0.0.0/8"] - - ## Redis(TM) slave port - port: 6379 - ## Can be used to specify command line arguments, for example: - ## - command: "/run.sh" - ## Additional Redis(TM) configuration for the slave nodes - ## ref: https://redis.io/topics/config - ## - configmap: - ## Redis(TM) extra flags - extraFlags: [] - ## List of Redis(TM) commands to disable - disableCommands: - - FLUSHDB - - FLUSHALL - - ## Redis(TM) Slave pod/node affinity/anti-affinity - ## - affinity: {} - - ## Configure extra options for Redis(TM) Slave liveness and readiness probes - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) - ## - livenessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 10 - successThreshold: 1 - failureThreshold: 5 - - ## Configure custom probes for images other images like - ## rhscl/redis-32-rhel7 rhscl/redis-5-rhel7 - ## Only used if readinessProbe.enabled: false / livenessProbe.enabled: false - ## - # customLivenessProbe: - # tcpSocket: - # port: 6379 - # initialDelaySeconds: 10 - # periodSeconds: 5 - # customReadinessProbe: - # initialDelaySeconds: 30 - # periodSeconds: 10 - # timeoutSeconds: 5 - # exec: - # command: - # - "container-entrypoint" - # - "bash" - # - "-c" - # - "redis-cli set liveness-probe \"`date`\" | grep OK" - customLivenessProbe: {} - customReadinessProbe: {} - - ## Redis(TM) slave Resource - # resources: - # requests: - # memory: 256Mi - # cpu: 100m - - ## Redis(TM) slave selectors and tolerations for pod assignment - # nodeSelector: {"beta.kubernetes.io/arch": "amd64"} - # tolerations: [] - - ## Use an alternate scheduler, e.g. "stork". - ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ - ## - # schedulerName: - - ## Redis(TM) slave pod Annotation and Labels - podLabels: {} - podAnnotations: {} - - ## Redis(TM) slave pod priorityClassName - # priorityClassName: {} - - ## Enable persistence using Persistent Volume Claims - ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ - ## - persistence: - enabled: true - ## The path the volume will be mounted at, useful when using different - ## Redis(TM) images. - path: /data - ## The subdirectory of the volume to mount to, useful in dev environments - ## and one PV for multiple services. - subPath: "" - ## redis data Persistent Volume Storage Class - ## If defined, storageClassName: <storageClass> - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - ## Persistent Volume selectors - ## https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector - matchLabels: {} - matchExpressions: {} - - ## Update strategy, can be set to RollingUpdate or onDelete by default. - ## https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets - statefulset: - updateStrategy: RollingUpdate - ## Partition update strategy - ## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions - # rollingUpdatePartition: - -## Prometheus Exporter / Metrics -## -metrics: - enabled: true - - image: - registry: docker.io - repository: bitnami/redis-exporter - tag: 1.5.3-debian-10-r14 - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - - ## Metrics exporter resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - # resources: {} - - ## Extra arguments for Metrics exporter, for example: - ## extraArgs: - ## check-keys: myKey,myOtherKey - # extraArgs: {} - - ## Metrics exporter pod Annotation and Labels - podAnnotations: - prometheus.io/scrape: "true" - prometheus.io/port: "9121" - # podLabels: {} - - # Enable this if you're using https://github.com/coreos/prometheus-operator - serviceMonitor: - enabled: false - ## Specify a namespace if needed - # namespace: monitoring - # fallback to the prometheus default unless specified - # interval: 10s - ## Defaults to what's used if you follow CoreOS [Prometheus Install Instructions](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#tldr) - ## [Prometheus Selector Label](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-operator-1) - ## [Kube Prometheus Selector Label](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#exporters) - selector: - prometheus: kube-prometheus - - ## Custom PrometheusRule to be defined - ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart - ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions - prometheusRule: - enabled: false - additionalLabels: {} - namespace: "" - ## Redis(TM) prometheus rules - ## These are just examples rules, please adapt them to your needs. - ## Make sure to constraint the rules to the current postgresql service. - # rules: - # - alert: RedisDown - # expr: redis_up{service="{{ template "redis.fullname" . }}-metrics"} == 0 - # for: 2m - # labels: - # severity: error - # annotations: - # summary: Redis(TM) instance {{ "{{ $labels.instance }}" }} down - # description: Redis(TM) instance {{ "{{ $labels.instance }}" }} is down - # - alert: RedisMemoryHigh - # expr: > - # redis_memory_used_bytes{service="{{ template "redis.fullname" . }}-metrics"} * 100 - # / - # redis_memory_max_bytes{service="{{ template "redis.fullname" . }}-metrics"} - # > 90 - # for: 2m - # labels: - # severity: error - # annotations: - # summary: Redis(TM) instance {{ "{{ $labels.instance }}" }} is using too much memory - # description: | - # Redis(TM) instance {{ "{{ $labels.instance }}" }} is using {{ "{{ $value }}" }}% of its available memory. - # - alert: RedisKeyEviction - # expr: | - # increase(redis_evicted_keys_total{service="{{ template "redis.fullname" . }}-metrics"}[5m]) > 0 - # for: 1s - # labels: - # severity: error - # annotations: - # summary: Redis(TM) instance {{ "{{ $labels.instance }}" }} has evicted keys - # description: | - # Redis(TM) instance {{ "{{ $labels.instance }}" }} has evicted {{ "{{ $value }}" }} keys in the last 5 minutes. - rules: [] - - ## Metrics exporter pod priorityClassName - # priorityClassName: {} - service: - type: ClusterIP - ## Use serviceLoadBalancerIP to request a specific static IP, - ## otherwise leave blank - # loadBalancerIP: - annotations: {} - labels: {} - -## -## Init containers parameters: -## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/bitnami-shell - tag: "10" - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - resources: {} - # resources: - # requests: - # memory: 128Mi - # cpu: 100m - -## Redis(TM) config file -## ref: https://redis.io/topics/config -## -configmap: |- - # Enable AOF https://redis.io/topics/persistence#append-only-file - appendonly yes - # Disable RDB persistence, AOF persistence already enabled. - save "" - -## Sysctl InitContainer -## used to perform sysctl operation to modify Kernel settings (needed sometimes to avoid warnings) -sysctlImage: - enabled: false - command: [] - registry: docker.io - repository: bitnami/bitnami-shell - tag: "10" - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - mountHostSys: false - resources: {} - # resources: - # requests: - # memory: 128Mi - # cpu: 100m - -## PodSecurityPolicy configuration -## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ -## -podSecurityPolicy: - ## Specifies whether a PodSecurityPolicy should be created - ## - create: false diff --git a/scripts/helm/db/redis/img/redis-cluster-topology.png b/scripts/helm/db/redis/img/redis-cluster-topology.png deleted file mode 100644 index f0a02a9f8..000000000 Binary files a/scripts/helm/db/redis/img/redis-cluster-topology.png and /dev/null differ diff --git a/scripts/helm/db/redis/img/redis-topology.png b/scripts/helm/db/redis/img/redis-topology.png deleted file mode 100644 index 3f5280feb..000000000 Binary files a/scripts/helm/db/redis/img/redis-topology.png and /dev/null differ diff --git a/scripts/helm/db/redis/templates/NOTES.txt b/scripts/helm/db/redis/templates/NOTES.txt deleted file mode 100644 index 5c27951d1..000000000 --- a/scripts/helm/db/redis/templates/NOTES.txt +++ /dev/null @@ -1,136 +0,0 @@ -** Please be patient while the chart is being deployed ** - -{{- if contains .Values.master.service.type "LoadBalancer" }} -{{- if not .Values.usePassword }} -{{ if and (not .Values.networkPolicy.enabled) (.Values.networkPolicy.allowExternal) }} - -------------------------------------------------------------------------------- - WARNING - - By specifying "master.service.type=LoadBalancer" and "usePassword=false" you have - most likely exposed the Redis(TM) service externally without any authentication - mechanism. - - For security reasons, we strongly suggest that you switch to "ClusterIP" or - "NodePort". As alternative, you can also switch to "usePassword=true" - providing a valid password on "password" parameter. - -------------------------------------------------------------------------------- -{{- end }} -{{- end }} -{{- end }} - -{{- if and .Values.sentinel.enabled (not .Values.cluster.enabled)}} - -------------------------------------------------------------------------------- - WARNING - - Using redis sentinel without a cluster is not supported. A single pod with - standalone redis has been deployed. - - To deploy redis sentinel, please use the values "cluster.enabled=true" and - "sentinel.enabled=true". - -------------------------------------------------------------------------------- -{{- end }} - -{{- if .Values.cluster.enabled }} -{{- if .Values.sentinel.enabled }} -Redis(TM) can be accessed via port {{ .Values.sentinel.service.redisPort }} on the following DNS name from within your cluster: - -{{ template "redis.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} for read only operations - -For read/write operations, first access the Redis(TM) Sentinel cluster, which is available in port {{ .Values.sentinel.service.sentinelPort }} using the same domain name above. - -{{- else }} -Redis(TM) can be accessed via port {{ .Values.redisPort }} on the following DNS names from within your cluster: - -{{ template "redis.fullname" . }}-master.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} for read/write operations -{{ template "redis.fullname" . }}-slave.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} for read-only operations -{{- end }} - -{{- else }} -Redis(TM) can be accessed via port {{ .Values.redisPort }} on the following DNS name from within your cluster: - -{{ template "redis.fullname" . }}-master.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} - -{{- end }} - -{{ if .Values.usePassword }} -To get your password run: - - export REDIS_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "redis.secretName" . }} -o jsonpath="{.data.redis-password}" | base64 --decode) -{{- end }} - -To connect to your Redis(TM) server: - -1. Run a Redis(TM) pod that you can use as a client: - -{{- if .Values.tls.enabled }} - kubectl run --namespace {{ .Release.Namespace }} {{ template "redis.fullname" . }}-client --restart='Never' --env REDIS_PASSWORD=$REDIS_PASSWORD --image {{ template "redis.image" . }} --command -- sleep infinity - - Copy your TLS certificates to the pod: - - kubectl cp --namespace {{ .Release.Namespace }} /path/to/client.cert {{ template "redis.fullname" . }}-client:/tmp/client.cert - kubectl cp --namespace {{ .Release.Namespace }} /path/to/client.key {{ template "redis.fullname" . }}-client:/tmp/client.key - kubectl cp --namespace {{ .Release.Namespace }} /path/to/CA.cert {{ template "redis.fullname" . }}-client:/tmp/CA.cert - - Use the following command to attach to the pod: - - kubectl exec --tty -i {{ template "redis.fullname" . }}-client \ - {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}--labels="{{ template "redis.fullname" . }}-client=true" \{{- end }} - --namespace {{ .Release.Namespace }} -- bash -{{- else }} - kubectl run --namespace {{ .Release.Namespace }} {{ template "redis.fullname" . }}-client --rm --tty -i --restart='Never' \ - {{ if .Values.usePassword }} --env REDIS_PASSWORD=$REDIS_PASSWORD \{{ end }} - {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}--labels="{{ template "redis.fullname" . }}-client=true" \{{- end }} - --image {{ template "redis.image" . }} -- bash -{{- end }} - -2. Connect using the Redis(TM) CLI: - -{{- if .Values.cluster.enabled }} - {{- if .Values.sentinel.enabled }} - redis-cli -h {{ template "redis.fullname" . }} -p {{ .Values.sentinel.service.redisPort }}{{ if .Values.usePassword }} -a $REDIS_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} # Read only operations - redis-cli -h {{ template "redis.fullname" . }} -p {{ .Values.sentinel.service.sentinelPort }}{{ if .Values.usePassword }} -a $REDIS_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} # Sentinel access - {{- else }} - redis-cli -h {{ template "redis.fullname" . }}-master{{ if .Values.usePassword }} -a $REDIS_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} - redis-cli -h {{ template "redis.fullname" . }}-slave{{ if .Values.usePassword }} -a $REDIS_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} - {{- end }} -{{- else }} - redis-cli -h {{ template "redis.fullname" . }}-master{{ if .Values.usePassword }} -a $REDIS_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} -{{- end }} - -{{ if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} -Note: Since NetworkPolicy is enabled, only pods with label -{{ template "redis.fullname" . }}-client=true" -will be able to connect to redis. -{{- else -}} - -To connect to your database from outside the cluster execute the following commands: - -{{- if contains "NodePort" .Values.master.service.type }} - - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "redis.fullname" . }}-master) - redis-cli -h $NODE_IP -p $NODE_PORT {{- if .Values.usePassword }} -a $REDIS_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} - -{{- else if contains "LoadBalancer" .Values.master.service.type }} - - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "redis.fullname" . }}' - - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "redis.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - redis-cli -h $SERVICE_IP -p {{ .Values.master.service.port }} {{- if .Values.usePassword }} -a $REDIS_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} - -{{- else if contains "ClusterIP" .Values.master.service.type }} - - kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "redis.fullname" . }}-master {{ .Values.redisPort }}:{{ .Values.redisPort }} & - redis-cli -h 127.0.0.1 -p {{ .Values.redisPort }} {{- if .Values.usePassword }} -a $REDIS_PASSWORD{{ end }}{{ if .Values.tls.enabled }} --tls --cert /tmp/client.cert --key /tmp/client.key --cacert /tmp/CA.cert{{ end }} - -{{- end }} -{{- end }} - -{{ include "redis.checkRollingTags" . }} - -{{- include "redis.validateValues" . }} diff --git a/scripts/helm/db/redis/templates/_helpers.tpl b/scripts/helm/db/redis/templates/_helpers.tpl deleted file mode 100644 index e76b9ce9d..000000000 --- a/scripts/helm/db/redis/templates/_helpers.tpl +++ /dev/null @@ -1,445 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "redis.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Expand the chart plus release name (used by the chart label) -*/}} -{{- define "redis.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "redis.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for networkpolicy. -*/}} -{{- define "networkPolicy.apiVersion" -}} -{{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "extensions/v1beta1" -}} -{{- else -}} -{{- print "networking.k8s.io/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiGroup for PodSecurityPolicy. -*/}} -{{- define "podSecurityPolicy.apiGroup" -}} -{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "policy" -}} -{{- else -}} -{{- print "extensions" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for PodSecurityPolicy. -*/}} -{{- define "podSecurityPolicy.apiVersion" -}} -{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "policy/v1beta1" -}} -{{- else -}} -{{- print "extensions/v1beta1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Redis(TM) image name -*/}} -{{- define "redis.image" -}} -{{- $registryName := .Values.image.registry -}} -{{- $repositoryName := .Values.image.repository -}} -{{- $tag := .Values.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Redis(TM) Sentinel image name -*/}} -{{- define "sentinel.image" -}} -{{- $registryName := .Values.sentinel.image.registry -}} -{{- $repositoryName := .Values.sentinel.image.repository -}} -{{- $tag := .Values.sentinel.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper image name (for the metrics image) -*/}} -{{- define "redis.metrics.image" -}} -{{- $registryName := .Values.metrics.image.registry -}} -{{- $repositoryName := .Values.metrics.image.repository -}} -{{- $tag := .Values.metrics.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper image name (for the sentinel metrics image) -*/}} -{{- define "sentinel.metrics.image" -}} -{{- $registryName := .Values.sentinel.metrics.image.registry -}} -{{- $repositoryName := .Values.sentinel.metrics.image.repository -}} -{{- $tag := .Values.sentinel.metrics.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - - -{{/* -Return the proper image name (for the init container volume-permissions image) -*/}} -{{- define "redis.volumePermissions.image" -}} -{{- $registryName := .Values.volumePermissions.image.registry -}} -{{- $repositoryName := .Values.volumePermissions.image.repository -}} -{{- $tag := .Values.volumePermissions.image.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the path to the cert file. -*/}} -{{- define "redis.tlsCert" -}} -{{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/redis/certs/%s" -}} -{{- end -}} - -{{/* -Return the path to the cert key file. -*/}} -{{- define "redis.tlsCertKey" -}} -{{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/redis/certs/%s" -}} -{{- end -}} - -{{/* -Return the path to the CA cert file. -*/}} -{{- define "redis.tlsCACert" -}} -{{- required "Certificate CA filename is required when TLS in enabled" .Values.tls.certCAFilename | printf "/opt/bitnami/redis/certs/%s" -}} -{{- end -}} - -{{/* -Return the path to the DH params file. -*/}} -{{- define "redis.tlsDHParams" -}} -{{- if .Values.tls.dhParamsFilename -}} -{{- printf "/opt/bitnami/redis/certs/%s" .Values.tls.dhParamsFilename -}} -{{- end -}} -{{- end -}} - -{{/* -Create the name of the service account to use -*/}} -{{- define "redis.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (include "redis.fullname" .) .Values.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* -Get the password secret. -*/}} -{{- define "redis.secretName" -}} -{{- if .Values.existingSecret -}} -{{- printf "%s" .Values.existingSecret -}} -{{- else -}} -{{- printf "%s" (include "redis.fullname" .) -}} -{{- end -}} -{{- end -}} - -{{/* -Get the password key to be retrieved from Redis(TM) secret. -*/}} -{{- define "redis.secretPasswordKey" -}} -{{- if and .Values.existingSecret .Values.existingSecretPasswordKey -}} -{{- printf "%s" .Values.existingSecretPasswordKey -}} -{{- else -}} -{{- printf "redis-password" -}} -{{- end -}} -{{- end -}} - -{{/* -Return Redis(TM) password -*/}} -{{- define "redis.password" -}} -{{- if not (empty .Values.global.redis.password) }} - {{- .Values.global.redis.password -}} -{{- else if not (empty .Values.password) -}} - {{- .Values.password -}} -{{- else -}} - {{- randAlphaNum 10 -}} -{{- end -}} -{{- end -}} - -{{/* -Return sysctl image -*/}} -{{- define "redis.sysctl.image" -}} -{{- $registryName := default "docker.io" .Values.sysctlImage.registry -}} -{{- $repositoryName := .Values.sysctlImage.repository -}} -{{- $tag := default "buster" .Values.sysctlImage.tag | toString -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. -Also, we can't use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} - {{- if .Values.global.imageRegistry }} - {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} - {{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} - {{- end -}} -{{- else -}} - {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names -*/}} -{{- define "redis.imagePullSecrets" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -Also, we can not use a single if because lazy evaluation is not an option -*/}} -{{- if .Values.global }} -{{- if .Values.global.imagePullSecrets }} -imagePullSecrets: -{{- range .Values.global.imagePullSecrets }} - - name: {{ . }} -{{- end }} -{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets .Values.sysctlImage.pullSecrets .Values.volumePermissions.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.metrics.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.sysctlImage.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.volumePermissions.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- end -}} -{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets .Values.sysctlImage.pullSecrets .Values.volumePermissions.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.metrics.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.sysctlImage.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- range .Values.volumePermissions.image.pullSecrets }} - - name: {{ . }} -{{- end }} -{{- end -}} -{{- end -}} - -{{/* Check if there are rolling tags in the images */}} -{{- define "redis.checkRollingTags" -}} -{{- if and (contains "bitnami/" .Values.image.repository) (not (.Values.image.tag | toString | regexFind "-r\\d+$|sha256:")) }} -WARNING: Rolling tag detected ({{ .Values.image.repository }}:{{ .Values.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. -+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ -{{- end }} -{{- if and (contains "bitnami/" .Values.sentinel.image.repository) (not (.Values.sentinel.image.tag | toString | regexFind "-r\\d+$|sha256:")) }} -WARNING: Rolling tag detected ({{ .Values.sentinel.image.repository }}:{{ .Values.sentinel.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. -+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ -{{- end }} -{{- end -}} - -{{/* -Return the proper Storage Class for master -*/}} -{{- define "redis.master.storageClass" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -*/}} -{{- if .Values.global -}} - {{- if .Values.global.storageClass -}} - {{- if (eq "-" .Values.global.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.global.storageClass -}} - {{- end -}} - {{- else -}} - {{- if .Values.master.persistence.storageClass -}} - {{- if (eq "-" .Values.master.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.master.persistence.storageClass -}} - {{- end -}} - {{- end -}} - {{- end -}} -{{- else -}} - {{- if .Values.master.persistence.storageClass -}} - {{- if (eq "-" .Values.master.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.master.persistence.storageClass -}} - {{- end -}} - {{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Storage Class for slave -*/}} -{{- define "redis.slave.storageClass" -}} -{{/* -Helm 2.11 supports the assignment of a value to a variable defined in a different scope, -but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. -*/}} -{{- if .Values.global -}} - {{- if .Values.global.storageClass -}} - {{- if (eq "-" .Values.global.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.global.storageClass -}} - {{- end -}} - {{- else -}} - {{- if .Values.slave.persistence.storageClass -}} - {{- if (eq "-" .Values.slave.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.slave.persistence.storageClass -}} - {{- end -}} - {{- end -}} - {{- end -}} -{{- else -}} - {{- if .Values.slave.persistence.storageClass -}} - {{- if (eq "-" .Values.slave.persistence.storageClass) -}} - {{- printf "storageClassName: \"\"" -}} - {{- else }} - {{- printf "storageClassName: %s" .Values.slave.persistence.storageClass -}} - {{- end -}} - {{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Compile all warnings into a single message, and call fail. -*/}} -{{- define "redis.validateValues" -}} -{{- $messages := list -}} -{{- $messages := append $messages (include "redis.validateValues.spreadConstraints" .) -}} -{{- $messages := without $messages "" -}} -{{- $message := join "\n" $messages -}} - -{{- if $message -}} -{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} -{{- end -}} -{{- end -}} - -{{/* Validate values of Redis(TM) - spreadConstrainsts K8s version */}} -{{- define "redis.validateValues.spreadConstraints" -}} -{{- if and (semverCompare "<1.16-0" .Capabilities.KubeVersion.GitVersion) .Values.slave.spreadConstraints -}} -redis: spreadConstraints - Pod Topology Spread Constraints are only available on K8s >= 1.16 - Find more information at https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ -{{- end -}} -{{- end -}} - -{{/* -Renders a value that contains template. -Usage: -{{ include "redis.tplValue" (dict "value" .Values.path.to.the.Value "context" $) }} -*/}} -{{- define "redis.tplValue" -}} - {{- if typeIs "string" .value }} - {{- tpl .value .context }} - {{- else }} - {{- tpl (.value | toYaml) .context }} - {{- end }} -{{- end -}} diff --git a/scripts/helm/db/redis/templates/configmap-scripts.yaml b/scripts/helm/db/redis/templates/configmap-scripts.yaml deleted file mode 100644 index 6d7402721..000000000 --- a/scripts/helm/db/redis/templates/configmap-scripts.yaml +++ /dev/null @@ -1,430 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "redis.fullname" . }}-scripts - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -data: -{{- if and .Values.cluster.enabled .Values.sentinel.enabled }} - start-node.sh: | - #!/bin/bash - - . /opt/bitnami/scripts/libos.sh - . /opt/bitnami/scripts/liblog.sh - . /opt/bitnami/scripts/libvalidations.sh - - not_exists_dns_entry() { - myip=$(hostname -i) - - if [[ -z "$(getent ahosts "$HEADLESS_SERVICE" | grep "^${myip}" )" ]]; then - warn "$HEADLESS_SERVICE does not contain the IP of this pod: ${myip}" - return 1 - fi - info "$HEADLESS_SERVICE has my IP: ${myip}" - return 0 - } - - HEADLESS_SERVICE="{{ template "redis.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" - REDIS_SERVICE="{{ template "redis.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" - - # Waits for DNS to add this ip to the service DNS entry - retry_while not_exists_dns_entry - - export REDIS_REPLICATION_MODE="slave" - if [[ -z "$(getent ahosts "$HEADLESS_SERVICE" | grep -v "^$(hostname -i) ")" ]]; then - export REDIS_REPLICATION_MODE="master" - fi - - {{- if and .Values.securityContext.runAsUser (eq (.Values.securityContext.runAsUser | int) 0) }} - useradd redis - chown -R redis {{ .Values.slave.persistence.path }} - {{- end }} - - if [[ -n $REDIS_PASSWORD_FILE ]]; then - password_aux=`cat ${REDIS_PASSWORD_FILE}` - export REDIS_PASSWORD=$password_aux - fi - - if [[ -n $REDIS_MASTER_PASSWORD_FILE ]]; then - password_aux=`cat ${REDIS_MASTER_PASSWORD_FILE}` - export REDIS_MASTER_PASSWORD=$password_aux - fi - - if [[ "$REDIS_REPLICATION_MODE" == "master" ]]; then - echo "I am master" - if [[ ! -f /opt/bitnami/redis/etc/master.conf ]];then - cp /opt/bitnami/redis/mounted-etc/master.conf /opt/bitnami/redis/etc/master.conf - fi - else - if [[ ! -f /opt/bitnami/redis/etc/replica.conf ]];then - cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf - fi - - if is_boolean_yes "$REDIS_TLS_ENABLED"; then - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $REDIS_SERVICE -p {{ .Values.sentinel.port }} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - else - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $REDIS_SERVICE -p {{ .Values.sentinel.port }} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - fi - REDIS_SENTINEL_INFO=($($sentinel_info_command)) - REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]} - REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} - - - # Immediately attempt to connect to the reported master. If it doesn't exist the connection attempt will either hang - # or fail with "port unreachable" and give no data. The liveness check will then timeout waiting for the redis - # container to be ready and restart the it. By then the new master will likely have been elected - if is_boolean_yes "$REDIS_TLS_ENABLED"; then - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $REDIS_MASTER_HOST -p {{ .Values.sentinel.port }} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - else - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $REDIS_MASTER_HOST -p {{ .Values.sentinel.port }} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - fi - - if [[ ! ($($sentinel_info_command)) ]]; then - # master doesn't actually exist, this probably means the remaining pods haven't elected a new one yet - # and are reporting the old one still. Once this happens the container will get stuck and never see the new - # master. We stop here to allow the container to not pass the liveness check and be restarted. - exit 1 - fi - fi - - if [[ ! -f /opt/bitnami/redis/etc/redis.conf ]];then - cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf - fi - {{- if .Values.tls.enabled }} - ARGS=("--port" "0") - ARGS+=("--tls-port" "${REDIS_TLS_PORT}") - ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") - ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") - ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") - ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") - ARGS+=("--tls-replication" "yes") - {{- if .Values.tls.dhParamsFilename }} - ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") - {{- end }} - {{- else }} - ARGS=("--port" "${REDIS_PORT}") - {{- end }} - - if [[ "$REDIS_REPLICATION_MODE" == "slave" ]]; then - ARGS+=("--slaveof" "${REDIS_MASTER_HOST}" "${REDIS_MASTER_PORT_NUMBER}") - fi - - {{- if .Values.usePassword }} - ARGS+=("--requirepass" "${REDIS_PASSWORD}") - ARGS+=("--masterauth" "${REDIS_MASTER_PASSWORD}") - {{- else }} - ARGS+=("--protected-mode" "no") - {{- end }} - - if [[ "$REDIS_REPLICATION_MODE" == "master" ]]; then - ARGS+=("--include" "/opt/bitnami/redis/etc/master.conf") - else - ARGS+=("--include" "/opt/bitnami/redis/etc/replica.conf") - fi - - ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") - {{- if .Values.slave.extraFlags }} - {{- range .Values.slave.extraFlags }} - ARGS+=({{ . | quote }}) - {{- end }} - {{- end }} - - {{- if .Values.slave.preExecCmds }} - {{ .Values.slave.preExecCmds | nindent 4}} - {{- end }} - - {{- if .Values.slave.command }} - exec {{ .Values.slave.command }} "${ARGS[@]}" - {{- else }} - exec redis-server "${ARGS[@]}" - {{- end }} - - start-sentinel.sh: | - #!/bin/bash - - . /opt/bitnami/scripts/libos.sh - . /opt/bitnami/scripts/libvalidations.sh - . /opt/bitnami/scripts/libfile.sh - - sentinel_conf_set() { - local -r key="${1:?missing key}" - local value="${2:-}" - - # Sanitize inputs - value="${value//\\/\\\\}" - value="${value//&/\\&}" - value="${value//\?/\\?}" - [[ "$value" = "" ]] && value="\"$value\"" - - replace_in_file "/opt/bitnami/redis-sentinel/etc/sentinel.conf" "^#*\s*${key} .*" "${key} ${value}" false - } - sentinel_conf_add() { - echo $'\n'"$@" >> "/opt/bitnami/redis-sentinel/etc/sentinel.conf" - } - host_id() { - echo "$1" | openssl sha1 | awk '{print $2}' - } - not_exists_dns_entry() { - myip=$(hostname -i) - - if [[ -z "$(getent ahosts "$HEADLESS_SERVICE" | grep "^${myip}" )" ]]; then - warn "$HEADLESS_SERVICE does not contain the IP of this pod: ${myip}" - return 1 - fi - info "$HEADLESS_SERVICE has my IP: ${myip}" - return 0 - } - - HEADLESS_SERVICE="{{ template "redis.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" - REDIS_SERVICE="{{ template "redis.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" - - if [[ -n $REDIS_PASSWORD_FILE ]]; then - password_aux=`cat ${REDIS_PASSWORD_FILE}` - export REDIS_PASSWORD=$password_aux - fi - - if [[ ! -f /opt/bitnami/redis-sentinel/etc/sentinel.conf ]]; then - cp /opt/bitnami/redis-sentinel/mounted-etc/sentinel.conf /opt/bitnami/redis-sentinel/etc/sentinel.conf - {{- if .Values.usePassword }} - printf "\nsentinel auth-pass %s %s" "{{ .Values.sentinel.masterSet }}" "$REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf - {{- if .Values.sentinel.usePassword }} - printf "\nrequirepass %s" "$REDIS_PASSWORD" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf - {{- end }} - {{- end }} - {{- if .Values.sentinel.staticID }} - printf "\nsentinel myid %s" "$(host_id "$HOSTNAME")" >> /opt/bitnami/redis-sentinel/etc/sentinel.conf - {{- end }} - fi - - export REDIS_REPLICATION_MODE="slave" - - # Waits for DNS to add this ip to the service DNS entry - retry_while not_exists_dns_entry - - if [[ -z "$(getent ahosts "$HEADLESS_SERVICE" | grep -v "^$(hostname -i)")" ]]; then - export REDIS_REPLICATION_MODE="master" - fi - - # Clean sentineles from the current sentinel nodes - for node in $( getent ahosts "$HEADLESS_SERVICE" | grep -v "^$(hostname -i)" | cut -f 1 -d ' ' | uniq ); do - info "Cleaning sentinels in sentinel node: $node" - if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then - redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $node -p {{ .Values.sentinel.port }} --tls --cert ${REDIS_SENTINEL_TLS_CERT_FILE} --key ${REDIS_SENTINEL_TLS_KEY_FILE} --cacert ${REDIS_SENTINEL_TLS_CA_FILE} sentinel reset "*" - else - redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $node -p {{ .Values.sentinel.port }} sentinel reset "*" - fi - sleep {{ .Values.sentinel.cleanDelaySeconds }} - done - info "Sentinels clean up done" - - if [[ "$REDIS_REPLICATION_MODE" == "master" ]]; then - REDIS_MASTER_HOST="$(hostname -i)" - REDIS_MASTER_PORT_NUMBER="{{ .Values.redisPort }}" - else - if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $REDIS_SERVICE -p {{ .Values.sentinel.port }} --tls --cert ${REDIS_SENTINEL_TLS_CERT_FILE} --key ${REDIS_SENTINEL_TLS_KEY_FILE} --cacert ${REDIS_SENTINEL_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - else - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $REDIS_SERVICE -p {{ .Values.sentinel.port }} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - fi - REDIS_SENTINEL_INFO=($($sentinel_info_command)) - REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]} - REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} - - # Immediately attempt to connect to the reported master. If it doesn't exist the connection attempt will either hang - # or fail with "port unreachable" and give no data. The liveness check will then timeout waiting for the sentinel - # container to be ready and restart the it. By then the new master will likely have been elected - if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $REDIS_MASTER_HOST -p {{ .Values.sentinel.port }} --tls --cert ${REDIS_SENTINEL_TLS_CERT_FILE} --key ${REDIS_SENTINEL_TLS_KEY_FILE} --cacert ${REDIS_SENTINEL_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - else - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a $REDIS_PASSWORD {{- end }} -h $REDIS_MASTER_HOST -p {{ .Values.sentinel.port }} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - fi - - if [[ ! ($($sentinel_info_command)) ]]; then - # master doesn't actually exist, this probably means the remaining pods haven't elected a new one yet - # and are reporting the old one still. Once this happens the container will get stuck and never see the new - # master. We stop here to allow the container to not pass the liveness check and be restarted. - exit 1 - fi - fi - sentinel_conf_set "sentinel monitor" "{{ .Values.sentinel.masterSet }} "$REDIS_MASTER_HOST" "$REDIS_MASTER_PORT_NUMBER" {{ .Values.sentinel.quorum }}" - - add_replica() { - if [[ "$1" != "$REDIS_MASTER_HOST" ]]; then - sentinel_conf_add "sentinel known-replica {{ .Values.sentinel.masterSet }} $1 {{ .Values.redisPort }}" - fi - } - - {{- if .Values.sentinel.staticID }} - # remove generated known sentinels and replicas - tmp="$(sed -e '/^sentinel known-/d' -e '/^$/d' /opt/bitnami/redis-sentinel/etc/sentinel.conf)" - echo "$tmp" > /opt/bitnami/redis-sentinel/etc/sentinel.conf - - for node in $(seq 0 {{ .Values.cluster.slaveCount }}); do - NAME="{{ template "redis.fullname" . }}-node-$node" - IP="$(getent hosts "$NAME.$HEADLESS_SERVICE" | awk ' {print $1 }')" - if [[ "$NAME" != "$HOSTNAME" && -n "$IP" ]]; then - sentinel_conf_add "sentinel known-sentinel {{ .Values.sentinel.masterSet }} $IP {{ .Values.sentinel.port }} $(host_id "$NAME")" - add_replica "$IP" - fi - done - add_replica "$(hostname -i)" - {{- end }} - - {{- if .Values.tls.enabled }} - ARGS=("--port" "0") - ARGS+=("--tls-port" "${REDIS_SENTINEL_TLS_PORT_NUMBER}") - ARGS+=("--tls-cert-file" "${REDIS_SENTINEL_TLS_CERT_FILE}") - ARGS+=("--tls-key-file" "${REDIS_SENTINEL_TLS_KEY_FILE}") - ARGS+=("--tls-ca-cert-file" "${REDIS_SENTINEL_TLS_CA_FILE}") - ARGS+=("--tls-replication" "yes") - ARGS+=("--tls-auth-clients" "${REDIS_SENTINEL_TLS_AUTH_CLIENTS}") - {{- if .Values.tls.dhParamsFilename }} - ARGS+=("--tls-dh-params-file" "${REDIS_SENTINEL_TLS_DH_PARAMS_FILE}") - {{- end }} - {{- end }} - {{- if .Values.sentinel.preExecCmds }} - {{ .Values.sentinel.preExecCmds | nindent 4 }} - {{- end }} - exec redis-server /opt/bitnami/redis-sentinel/etc/sentinel.conf --sentinel {{- if .Values.tls.enabled }} "${ARGS[@]}" {{- end }} - prestop-sentinel.sh: | - #!/bin/bash - - . /opt/bitnami/scripts/libvalidations.sh - - REDIS_SERVICE="{{ include "redis.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}" - - if [[ -n "$REDIS_PASSWORD_FILE" ]]; then - password_aux=$(cat "$REDIS_PASSWORD_FILE") - export REDIS_PASSWORD="$password_aux" - fi - - if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a ${REDIS_PASSWORD} {{- end }} -h ${REDIS_SERVICE} -p {{ .Values.sentinel.port }} --tls --cert ${REDIS_SENTINEL_TLS_CERT_FILE} --key ${REDIS_SENTINEL_TLS_KEY_FILE} --cacert ${REDIS_SENTINEL_TLS_CA_FILE} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - else - sentinel_info_command="redis-cli {{- if .Values.usePassword }} -a ${REDIS_PASSWORD} {{- end }} -h ${REDIS_SERVICE} -p {{ .Values.sentinel.port }} sentinel get-master-addr-by-name {{ .Values.sentinel.masterSet }}" - fi - REDIS_SENTINEL_INFO=($($sentinel_info_command)) - REDIS_MASTER_HOST="${REDIS_SENTINEL_INFO[0]}" - - if [[ "$REDIS_MASTER_HOST" == "$(hostname -i)" ]]; then - if is_boolean_yes "$REDIS_SENTINEL_TLS_ENABLED"; then - redis-cli {{- if .Values.usePassword }} -a "$REDIS_PASSWORD" {{- end }} -h "$REDIS_SERVICE" -p {{ .Values.sentinel.port }} --tls --cert "$REDIS_SENTINEL_TLS_CERT_FILE" --key "$REDIS_SENTINEL_TLS_KEY_FILE" --cacert "$REDIS_SENTINEL_TLS_CA_FILE" sentinel failover mymaster - else - redis-cli {{- if .Values.usePassword }} -a "$REDIS_PASSWORD" {{- end }} -h "$REDIS_SERVICE" -p {{ .Values.sentinel.port }} sentinel failover mymaster - fi - fi -{{- else }} - start-master.sh: | - #!/bin/bash - {{- if and .Values.securityContext.runAsUser (eq (.Values.securityContext.runAsUser | int) 0) }} - useradd redis - chown -R redis {{ .Values.master.persistence.path }} - {{- end }} - if [[ -n $REDIS_PASSWORD_FILE ]]; then - password_aux=`cat ${REDIS_PASSWORD_FILE}` - export REDIS_PASSWORD=$password_aux - fi - if [[ ! -f /opt/bitnami/redis/etc/master.conf ]];then - cp /opt/bitnami/redis/mounted-etc/master.conf /opt/bitnami/redis/etc/master.conf - fi - if [[ ! -f /opt/bitnami/redis/etc/redis.conf ]];then - cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf - fi - {{- if .Values.tls.enabled }} - ARGS=("--port" "0") - ARGS+=("--tls-port" "${REDIS_TLS_PORT}") - ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") - ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") - ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") - ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") - {{- if .Values.tls.dhParamsFilename }} - ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") - {{- end }} - {{- else }} - ARGS=("--port" "${REDIS_PORT}") - {{- end }} - {{- if .Values.usePassword }} - ARGS+=("--requirepass" "${REDIS_PASSWORD}") - ARGS+=("--masterauth" "${REDIS_PASSWORD}") - {{- else }} - ARGS+=("--protected-mode" "no") - {{- end }} - ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") - ARGS+=("--include" "/opt/bitnami/redis/etc/master.conf") - {{- if .Values.master.extraFlags }} - {{- range .Values.master.extraFlags }} - ARGS+=({{ . | quote }}) - {{- end }} - {{- end }} - {{- if .Values.master.preExecCmds }} - {{ .Values.master.preExecCmds | nindent 4}} - {{- end }} - {{- if .Values.master.command }} - exec {{ .Values.master.command }} "${ARGS[@]}" - {{- else }} - exec redis-server "${ARGS[@]}" - {{- end }} - {{- if .Values.cluster.enabled }} - start-slave.sh: | - #!/bin/bash - {{- if and .Values.securityContext.runAsUser (eq (.Values.securityContext.runAsUser | int) 0) }} - useradd redis - chown -R redis {{ .Values.slave.persistence.path }} - {{- end }} - if [[ -n $REDIS_PASSWORD_FILE ]]; then - password_aux=`cat ${REDIS_PASSWORD_FILE}` - export REDIS_PASSWORD=$password_aux - fi - if [[ -n $REDIS_MASTER_PASSWORD_FILE ]]; then - password_aux=`cat ${REDIS_MASTER_PASSWORD_FILE}` - export REDIS_MASTER_PASSWORD=$password_aux - fi - if [[ ! -f /opt/bitnami/redis/etc/replica.conf ]];then - cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf - fi - if [[ ! -f /opt/bitnami/redis/etc/redis.conf ]];then - cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf - fi - {{- if .Values.tls.enabled }} - ARGS=("--port" "0") - ARGS+=("--tls-port" "${REDIS_TLS_PORT}") - ARGS+=("--tls-cert-file" "${REDIS_TLS_CERT_FILE}") - ARGS+=("--tls-key-file" "${REDIS_TLS_KEY_FILE}") - ARGS+=("--tls-ca-cert-file" "${REDIS_TLS_CA_FILE}") - ARGS+=("--tls-auth-clients" "${REDIS_TLS_AUTH_CLIENTS}") - ARGS+=("--tls-replication" "yes") - {{- if .Values.tls.dhParamsFilename }} - ARGS+=("--tls-dh-params-file" "${REDIS_TLS_DH_PARAMS_FILE}") - {{- end }} - {{- else }} - ARGS=("--port" "${REDIS_PORT}") - {{- end }} - ARGS+=("--slaveof" "${REDIS_MASTER_HOST}" "${REDIS_MASTER_PORT_NUMBER}") - {{- if .Values.usePassword }} - ARGS+=("--requirepass" "${REDIS_PASSWORD}") - ARGS+=("--masterauth" "${REDIS_MASTER_PASSWORD}") - {{- else }} - ARGS+=("--protected-mode" "no") - {{- end }} - ARGS+=("--include" "/opt/bitnami/redis/etc/redis.conf") - ARGS+=("--include" "/opt/bitnami/redis/etc/replica.conf") - {{- if .Values.slave.extraFlags }} - {{- range .Values.slave.extraFlags }} - ARGS+=({{ . | quote }}) - {{- end }} - {{- end }} - {{- if .Values.slave.preExecCmds }} - {{ .Values.slave.preExecCmds | nindent 4}} - {{- end }} - {{- if .Values.slave.command }} - exec {{ .Values.slave.command }} "${ARGS[@]}" - {{- else }} - exec redis-server "${ARGS[@]}" - {{- end }} - {{- end }} - -{{- end -}} diff --git a/scripts/helm/db/redis/templates/configmap.yaml b/scripts/helm/db/redis/templates/configmap.yaml deleted file mode 100644 index 77bdc81e8..000000000 --- a/scripts/helm/db/redis/templates/configmap.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "redis.fullname" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -data: - redis.conf: |- -{{- if .Values.configmap }} - # User-supplied configuration: -{{- tpl .Values.configmap . | nindent 4 }} -{{- end }} - master.conf: |- - dir {{ .Values.master.persistence.path }} -{{- if .Values.master.configmap }} - # User-supplied master configuration: -{{- tpl .Values.master.configmap . | nindent 4 }} -{{- end }} -{{- if .Values.master.disableCommands }} -{{- range .Values.master.disableCommands }} - rename-command {{ . }} "" -{{- end }} -{{- end }} - replica.conf: |- - dir {{ .Values.slave.persistence.path }} - slave-read-only yes -{{- if .Values.slave.configmap }} - # User-supplied slave configuration: -{{- tpl .Values.slave.configmap . | nindent 4 }} -{{- end }} -{{- if .Values.slave.disableCommands }} -{{- range .Values.slave.disableCommands }} - rename-command {{ . }} "" -{{- end }} -{{- end }} -{{- if .Values.sentinel.enabled }} - sentinel.conf: |- - dir "/tmp" - bind 0.0.0.0 - port {{ .Values.sentinel.port }} - sentinel monitor {{ .Values.sentinel.masterSet }} {{ template "redis.fullname" . }}-node-0.{{ template "redis.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} {{ .Values.redisPort }} {{ .Values.sentinel.quorum }} - sentinel down-after-milliseconds {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.downAfterMilliseconds }} - sentinel failover-timeout {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.failoverTimeout }} - sentinel parallel-syncs {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.parallelSyncs }} -{{- if .Values.sentinel.configmap }} - # User-supplied sentinel configuration: -{{- tpl .Values.sentinel.configmap . | nindent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/headless-svc.yaml b/scripts/helm/db/redis/templates/headless-svc.yaml deleted file mode 100644 index d758c0d23..000000000 --- a/scripts/helm/db/redis/templates/headless-svc.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "redis.fullname" . }}-headless - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: ClusterIP - clusterIP: None - {{- if .Values.sentinel.enabled }} - publishNotReadyAddresses: true - {{- end }} - ports: - - name: tcp-redis - port: {{ .Values.redisPort }} - targetPort: redis - {{- if .Values.sentinel.enabled }} - - name: tcp-sentinel - port: {{ .Values.sentinel.port }} - targetPort: redis-sentinel - {{- end }} - selector: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} diff --git a/scripts/helm/db/redis/templates/health-configmap.yaml b/scripts/helm/db/redis/templates/health-configmap.yaml deleted file mode 100644 index 1bb8e74d9..000000000 --- a/scripts/helm/db/redis/templates/health-configmap.yaml +++ /dev/null @@ -1,176 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "redis.fullname" . }}-health - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -data: - ping_readiness_local.sh: |- - #!/bin/bash -{{- if .Values.usePasswordFile }} - password_aux=`cat ${REDIS_PASSWORD_FILE}` - export REDIS_PASSWORD=$password_aux -{{- end }} - export REDISCLI_AUTH="$REDIS_PASSWORD" - response=$( - timeout -s 3 $1 \ - redis-cli \ - -h localhost \ -{{- if .Values.tls.enabled }} - -p $REDIS_TLS_PORT \ - --tls \ - --cacert {{ template "redis.tlsCACert" . }} \ - {{- if .Values.tls.authClients }} - --cert {{ template "redis.tlsCert" . }} \ - --key {{ template "redis.tlsCertKey" . }} \ - {{- end }} -{{- else }} - -p $REDIS_PORT \ -{{- end }} - ping - ) - if [ "$response" != "PONG" ]; then - echo "$response" - exit 1 - fi - ping_liveness_local.sh: |- - #!/bin/bash -{{- if .Values.usePasswordFile }} - password_aux=`cat ${REDIS_PASSWORD_FILE}` - export REDIS_PASSWORD=$password_aux -{{- end }} - export REDISCLI_AUTH="$REDIS_PASSWORD" - response=$( - timeout -s 3 $1 \ - redis-cli \ - -h localhost \ -{{- if .Values.tls.enabled }} - -p $REDIS_TLS_PORT \ - --tls \ - --cacert {{ template "redis.tlsCACert" . }} \ - {{- if .Values.tls.authClients }} - --cert {{ template "redis.tlsCert" . }} \ - --key {{ template "redis.tlsCertKey" . }} \ - {{- end }} -{{- else }} - -p $REDIS_PORT \ -{{- end }} - ping - ) - if [ "$response" != "PONG" ] && [ "$response" != "LOADING Redis is loading the dataset in memory" ]; then - echo "$response" - exit 1 - fi -{{- if .Values.sentinel.enabled }} - ping_sentinel.sh: |- - #!/bin/bash -{{- if .Values.usePasswordFile }} - password_aux=`cat ${REDIS_PASSWORD_FILE}` - export REDIS_PASSWORD=$password_aux -{{- end }} - export REDISCLI_AUTH="$REDIS_PASSWORD" - response=$( - timeout -s 3 $1 \ - redis-cli \ - -h localhost \ -{{- if .Values.tls.enabled }} - -p $REDIS_SENTINEL_TLS_PORT_NUMBER \ - --tls \ - --cacert {{ template "redis.tlsCACert" . }} \ - {{- if .Values.tls.authClients }} - --cert {{ template "redis.tlsCert" . }} \ - --key {{ template "redis.tlsCertKey" . }} \ - {{- end }} -{{- else }} - -p $REDIS_SENTINEL_PORT \ -{{- end }} - ping - ) - if [ "$response" != "PONG" ]; then - echo "$response" - exit 1 - fi - parse_sentinels.awk: |- - /ip/ {FOUND_IP=1} - /port/ {FOUND_PORT=1} - /runid/ {FOUND_RUNID=1} - !/ip|port|runid/ { - if (FOUND_IP==1) { - IP=$1; FOUND_IP=0; - } - else if (FOUND_PORT==1) { - PORT=$1; - FOUND_PORT=0; - } else if (FOUND_RUNID==1) { - printf "\nsentinel known-sentinel {{ .Values.sentinel.masterSet }} %s %s %s", IP, PORT, $0; FOUND_RUNID=0; - } - } -{{- end }} - ping_readiness_master.sh: |- - #!/bin/bash -{{- if .Values.usePasswordFile }} - password_aux=`cat ${REDIS_MASTER_PASSWORD_FILE}` - export REDIS_MASTER_PASSWORD=$password_aux -{{- end }} - export REDISCLI_AUTH="$REDIS_MASTER_PASSWORD" - response=$( - timeout -s 3 $1 \ - redis-cli \ - -h $REDIS_MASTER_HOST \ - -p $REDIS_MASTER_PORT_NUMBER \ -{{- if .Values.tls.enabled }} - --tls \ - --cacert {{ template "redis.tlsCACert" . }} \ - {{- if .Values.tls.authClients }} - --cert {{ template "redis.tlsCert" . }} \ - --key {{ template "redis.tlsCertKey" . }} \ - {{- end }} -{{- end }} - ping - ) - if [ "$response" != "PONG" ]; then - echo "$response" - exit 1 - fi - ping_liveness_master.sh: |- - #!/bin/bash -{{- if .Values.usePasswordFile }} - password_aux=`cat ${REDIS_MASTER_PASSWORD_FILE}` - export REDIS_MASTER_PASSWORD=$password_aux -{{- end }} - export REDISCLI_AUTH="$REDIS_MASTER_PASSWORD" - response=$( - timeout -s 3 $1 \ - redis-cli \ - -h $REDIS_MASTER_HOST \ - -p $REDIS_MASTER_PORT_NUMBER \ -{{- if .Values.tls.enabled }} - --tls \ - --cacert {{ template "redis.tlsCACert" . }} \ - {{- if .Values.tls.authClients }} - --cert {{ template "redis.tlsCert" . }} \ - --key {{ template "redis.tlsCertKey" . }} \ - {{- end }} -{{- end }} - ping - ) - if [ "$response" != "PONG" ] && [ "$response" != "LOADING Redis is loading the dataset in memory" ]; then - echo "$response" - exit 1 - fi - ping_readiness_local_and_master.sh: |- - script_dir="$(dirname "$0")" - exit_status=0 - "$script_dir/ping_readiness_local.sh" $1 || exit_status=$? - "$script_dir/ping_readiness_master.sh" $1 || exit_status=$? - exit $exit_status - ping_liveness_local_and_master.sh: |- - script_dir="$(dirname "$0")" - exit_status=0 - "$script_dir/ping_liveness_local.sh" $1 || exit_status=$? - "$script_dir/ping_liveness_master.sh" $1 || exit_status=$? - exit $exit_status diff --git a/scripts/helm/db/redis/templates/metrics-prometheus.yaml b/scripts/helm/db/redis/templates/metrics-prometheus.yaml deleted file mode 100644 index ed53dc6e2..000000000 --- a/scripts/helm/db/redis/templates/metrics-prometheus.yaml +++ /dev/null @@ -1,39 +0,0 @@ -{{- if and (.Values.metrics.enabled) (.Values.metrics.serviceMonitor.enabled) }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "redis.fullname" . }} - {{- if .Values.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.metrics.serviceMonitor.namespace }} - {{- else }} - namespace: {{ .Release.Namespace | quote }} - {{- end }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- range $key, $value := .Values.metrics.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - endpoints: - - port: metrics - {{- if .Values.metrics.serviceMonitor.interval }} - interval: {{ .Values.metrics.serviceMonitor.interval }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.relabelings }} - relabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.relabelings "context" $) | nindent 6 }} - {{- end }} - {{- if .Values.metrics.serviceMonitor.metricRelabelings }} - metricRelabelings: {{- include "common.tplvalues.render" ( dict "value" .Values.metrics.serviceMonitor.metricRelabelings "context" $) | nindent 6 }} - {{- end }} - selector: - matchLabels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - app.kubernetes.io/component: "metrics" - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end -}} diff --git a/scripts/helm/db/redis/templates/metrics-sentinel-prometheus.yaml b/scripts/helm/db/redis/templates/metrics-sentinel-prometheus.yaml deleted file mode 100644 index 43cc2aa3c..000000000 --- a/scripts/helm/db/redis/templates/metrics-sentinel-prometheus.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if and .Values.sentinel.enabled .Values.sentinel.metrics.enabled .Values.sentinel.metrics.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "redis.fullname" . }}-sentinel-metrics - {{- if .Values.sentinel.metrics.serviceMonitor.namespace }} - namespace: {{ .Values.sentinel.metrics.serviceMonitor.namespace }} - {{- else }} - namespace: {{ .Release.Namespace | quote }} - {{- end }} - labels: - app: {{ include "redis.name" . }} - chart: {{ include "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- range $key, $value := .Values.sentinel.metrics.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - endpoints: - - port: sentinelmetrics - {{- if .Values.sentinel.metrics.serviceMonitor.interval }} - interval: {{ .Values.sentinel.metrics.serviceMonitor.interval }} - {{- end }} - selector: - matchLabels: - app: {{ include "redis.name" . }} - release: {{ .Release.Name }} - app.kubernetes.io/component: "sentinel-metrics" - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end -}} diff --git a/scripts/helm/db/redis/templates/metrics-sentinel-svc.yaml b/scripts/helm/db/redis/templates/metrics-sentinel-svc.yaml deleted file mode 100644 index 25f3770de..000000000 --- a/scripts/helm/db/redis/templates/metrics-sentinel-svc.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- if and .Values.sentinel.enabled .Values.sentinel.metrics.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "redis.fullname" . }}-sentinel-metrics - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ include "redis.name" . }} - chart: {{ include "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - app.kubernetes.io/component: "sentinel-metrics" - {{- if .Values.sentinel.metrics.service.labels -}} - {{- include "common.tplvalues.render" (dict "value" .Values.sentinel.metrics.service.labels "context" $) | nindent 4 }} - {{- end -}} - {{- if .Values.sentinel.metrics.service.annotations }} - annotations: {{- toYaml .Values.sentinel.metrics.service.annotations | nindent 4 }} - {{- end }} -spec: - type: {{ .Values.sentinel.metrics.service.type }} - {{- if eq .Values.sentinel.metrics.service.type "LoadBalancer" }} - externalTrafficPolicy: {{ .Values.sentinel.metrics.service.externalTrafficPolicy }} - {{- end }} - {{- if and (eq .Values.sentinel.metrics.service.type "LoadBalancer") .Values.sentinel.metrics.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.sentinel.metrics.service.loadBalancerIP }} - {{- end }} - ports: - - port: {{ .Values.sentinel.metrics.service.port }} - targetPort: sentinelmetrics - protocol: TCP - name: sentinelmetrics - selector: - app: {{ include "redis.name" . }} - release: {{ .Release.Name }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/metrics-svc.yaml b/scripts/helm/db/redis/templates/metrics-svc.yaml deleted file mode 100644 index 767a464e5..000000000 --- a/scripts/helm/db/redis/templates/metrics-svc.yaml +++ /dev/null @@ -1,34 +0,0 @@ -{{- if .Values.metrics.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "redis.fullname" . }}-metrics - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - app.kubernetes.io/component: "metrics" - {{- if .Values.metrics.service.labels -}} - {{- toYaml .Values.metrics.service.labels | nindent 4 }} - {{- end -}} - {{- if .Values.metrics.service.annotations }} - annotations: {{- toYaml .Values.metrics.service.annotations | nindent 4 }} - {{- end }} -spec: - type: {{ .Values.metrics.service.type }} - {{ if eq .Values.metrics.service.type "LoadBalancer" }} - externalTrafficPolicy: {{ .Values.metrics.service.externalTrafficPolicy }} - {{- end }} - {{ if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} - {{- end }} - ports: - - name: metrics - port: 9121 - targetPort: metrics - selector: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/networkpolicy.yaml b/scripts/helm/db/redis/templates/networkpolicy.yaml deleted file mode 100644 index 0249bc0e6..000000000 --- a/scripts/helm/db/redis/templates/networkpolicy.yaml +++ /dev/null @@ -1,74 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -kind: NetworkPolicy -apiVersion: {{ template "networkPolicy.apiVersion" . }} -metadata: - name: {{ template "redis.fullname" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - podSelector: - matchLabels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - {{- if .Values.cluster.enabled }} - policyTypes: - - Ingress - - Egress - egress: - # Allow dns resolution - - ports: - - port: 53 - protocol: UDP - # Allow outbound connections to other cluster pods - - ports: - - port: {{ .Values.redisPort }} - {{- if .Values.sentinel.enabled }} - - port: {{ .Values.sentinel.port }} - {{- end }} - to: - - podSelector: - matchLabels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - {{- end }} - ingress: - # Allow inbound connections - - ports: - - port: {{ .Values.redisPort }} - {{- if .Values.sentinel.enabled }} - - port: {{ .Values.sentinel.port }} - {{- end }} - {{- if not .Values.networkPolicy.allowExternal }} - from: - - podSelector: - matchLabels: - {{ template "redis.fullname" . }}-client: "true" - - podSelector: - matchLabels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - {{- if .Values.networkPolicy.ingressNSMatchLabels }} - - namespaceSelector: - matchLabels: - {{- range $key, $value := .Values.networkPolicy.ingressNSMatchLabels }} - {{ $key | quote }}: {{ $value | quote }} - {{- end }} - {{- if .Values.networkPolicy.ingressNSPodMatchLabels }} - podSelector: - matchLabels: - {{- range $key, $value := .Values.networkPolicy.ingressNSPodMatchLabels }} - {{ $key | quote }}: {{ $value | quote }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{- if .Values.metrics.enabled }} - # Allow prometheus scrapes for metrics - - ports: - - port: 9121 - {{- end }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/pdb.yaml b/scripts/helm/db/redis/templates/pdb.yaml deleted file mode 100644 index b9dc54b36..000000000 --- a/scripts/helm/db/redis/templates/pdb.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.podDisruptionBudget.enabled }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "redis.fullname" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} -spec: - {{- if .Values.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} - {{- end }} - {{- if .Values.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} - {{- end }} - selector: - matchLabels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/prometheusrule.yaml b/scripts/helm/db/redis/templates/prometheusrule.yaml deleted file mode 100644 index 48ae017f6..000000000 --- a/scripts/helm/db/redis/templates/prometheusrule.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ template "redis.fullname" . }} - {{- if .Values.metrics.prometheusRule.namespace }} - namespace: {{ .Values.metrics.prometheusRule.namespace }} - {{- else }} - namespace: {{ .Release.Namespace | quote }} - {{- end }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name | quote }} - heritage: {{ .Release.Service | quote }} -{{- with .Values.metrics.prometheusRule.additionalLabels }} -{{- toYaml . | nindent 4 }} -{{- end }} -spec: -{{- with .Values.metrics.prometheusRule.rules }} - groups: - - name: {{ template "redis.name" $ }} - rules: {{- tpl (toYaml .) $ | nindent 8 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/psp.yaml b/scripts/helm/db/redis/templates/psp.yaml deleted file mode 100644 index eca04c134..000000000 --- a/scripts/helm/db/redis/templates/psp.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.podSecurityPolicy.create }} -apiVersion: {{ template "podSecurityPolicy.apiVersion" . }} -kind: PodSecurityPolicy -metadata: - name: {{ template "redis.fullname" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - allowPrivilegeEscalation: false - fsGroup: - rule: 'MustRunAs' - ranges: - - min: {{ .Values.securityContext.fsGroup }} - max: {{ .Values.securityContext.fsGroup }} - hostIPC: false - hostNetwork: false - hostPID: false - privileged: false - readOnlyRootFilesystem: false - requiredDropCapabilities: - - ALL - runAsUser: - rule: 'MustRunAs' - ranges: - - min: {{ .Values.containerSecurityContext.runAsUser }} - max: {{ .Values.containerSecurityContext.runAsUser }} - seLinux: - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - - min: {{ .Values.containerSecurityContext.runAsUser }} - max: {{ .Values.containerSecurityContext.runAsUser }} - volumes: - - 'configMap' - - 'secret' - - 'emptyDir' - - 'persistentVolumeClaim' -{{- end }} diff --git a/scripts/helm/db/redis/templates/redis-master-statefulset.yaml b/scripts/helm/db/redis/templates/redis-master-statefulset.yaml deleted file mode 100644 index 80dc112a5..000000000 --- a/scripts/helm/db/redis/templates/redis-master-statefulset.yaml +++ /dev/null @@ -1,394 +0,0 @@ -{{- if or (not .Values.cluster.enabled) (not .Values.sentinel.enabled) }} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "redis.fullname" . }}-master - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- if .Values.master.statefulset.labels }} - {{- toYaml .Values.master.statefulset.labels | nindent 4 }} - {{- end }} -{{- if .Values.master.statefulset.annotations }} - annotations: - {{- toYaml .Values.master.statefulset.annotations | nindent 4 }} -{{- end }} -spec: - selector: - matchLabels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - role: master - serviceName: {{ template "redis.fullname" . }}-headless - template: - metadata: - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - role: master - {{- if .Values.master.podLabels }} - {{- toYaml .Values.master.podLabels | nindent 8 }} - {{- end }} - {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} - {{- toYaml .Values.metrics.podLabels | nindent 8 }} - {{- end }} - annotations: - checksum/health: {{ include (print $.Template.BasePath "/health-configmap.yaml") . | sha256sum }} - checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} - {{- if .Values.master.podAnnotations }} - {{- toYaml .Values.master.podAnnotations | nindent 8 }} - {{- end }} - {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} - {{- toYaml .Values.metrics.podAnnotations | nindent 8 }} - {{- end }} - spec: - {{- include "redis.imagePullSecrets" . | nindent 6 }} - {{- if .Values.master.hostAliases }} - hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.master.hostAliases "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.securityContext.enabled }} - securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} - {{- end }} - serviceAccountName: {{ template "redis.serviceAccountName" . }} - {{- if .Values.master.priorityClassName }} - priorityClassName: {{ .Values.master.priorityClassName | quote }} - {{- end }} - {{- with .Values.master.affinity }} - affinity: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} - {{- if .Values.master.nodeSelector }} - nodeSelector: {{- toYaml .Values.master.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.master.tolerations }} - tolerations: {{- toYaml .Values.master.tolerations | nindent 8 }} - {{- end }} - {{- if .Values.master.shareProcessNamespace }} - shareProcessNamespace: {{ .Values.master.shareProcessNamespace }} - {{- end }} - {{- if .Values.master.schedulerName }} - schedulerName: {{ .Values.master.schedulerName }} - {{- end }} - containers: - - name: {{ template "redis.name" . }} - image: {{ template "redis.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - command: - - /bin/bash - - -c - - /opt/bitnami/scripts/start-scripts/start-master.sh - env: - - name: REDIS_REPLICATION_MODE - value: master - {{- if .Values.usePassword }} - {{- if .Values.usePasswordFile }} - - name: REDIS_PASSWORD_FILE - value: "/opt/bitnami/redis/secrets/redis-password" - {{- else }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - {{- end }} - {{- else }} - - name: ALLOW_EMPTY_PASSWORD - value: "yes" - {{- end }} - - name: REDIS_TLS_ENABLED - value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} - {{- if .Values.tls.enabled }} - - name: REDIS_TLS_PORT - value: {{ .Values.redisPort | quote }} - - name: REDIS_TLS_AUTH_CLIENTS - value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} - - name: REDIS_TLS_CERT_FILE - value: {{ template "redis.tlsCert" . }} - - name: REDIS_TLS_KEY_FILE - value: {{ template "redis.tlsCertKey" . }} - - name: REDIS_TLS_CA_FILE - value: {{ template "redis.tlsCACert" . }} - {{- if .Values.tls.dhParamsFilename }} - - name: REDIS_TLS_DH_PARAMS_FILE - value: {{ template "redis.tlsDHParams" . }} - {{- end }} - {{- else }} - - name: REDIS_PORT - value: {{ .Values.redisPort | quote }} - {{- end }} - {{- if .Values.master.extraEnvVars }} - {{- include "redis.tplValue" (dict "value" .Values.master.extraEnvVars "context" $) | nindent 12 }} - {{- end }} - {{- if or .Values.master.extraEnvVarsCM .Values.master.extraEnvVarsSecret }} - envFrom: - {{- if .Values.master.extraEnvVarsCM }} - - configMapRef: - name: {{ .Values.master.extraEnvVarsCM }} - {{- end }} - {{- if .Values.master.extraEnvVarsSecret }} - - secretRef: - name: {{ .Values.master.extraEnvVarsSecret }} - {{- end }} - {{- end }} - ports: - - name: redis - containerPort: {{ .Values.redisPort }} - {{- if .Values.master.livenessProbe.enabled }} - livenessProbe: - initialDelaySeconds: {{ .Values.master.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.master.livenessProbe.periodSeconds }} - # One second longer than command timeout should prevent generation of zombie processes. - timeoutSeconds: {{ add1 .Values.master.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.master.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.master.livenessProbe.failureThreshold }} - exec: - command: - - sh - - -c - - /health/ping_liveness_local.sh {{ .Values.master.livenessProbe.timeoutSeconds }} - {{- else if .Values.master.customLivenessProbe }} - livenessProbe: {{- toYaml .Values.master.customLivenessProbe | nindent 12 }} - {{- end }} - {{- if .Values.master.readinessProbe.enabled}} - readinessProbe: - initialDelaySeconds: {{ .Values.master.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.master.readinessProbe.periodSeconds }} - timeoutSeconds: {{ add1 .Values.master.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.master.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.master.readinessProbe.failureThreshold }} - exec: - command: - - sh - - -c - - /health/ping_readiness_local.sh {{ .Values.master.readinessProbe.timeoutSeconds }} - {{- else if .Values.master.customReadinessProbe }} - readinessProbe: {{- toYaml .Values.master.customReadinessProbe | nindent 12 }} - {{- end }} - resources: {{- toYaml .Values.master.resources | nindent 12 }} - volumeMounts: - - name: start-scripts - mountPath: /opt/bitnami/scripts/start-scripts - - name: health - mountPath: /health - {{- if .Values.usePasswordFile }} - - name: redis-password - mountPath: /opt/bitnami/redis/secrets/ - {{- end }} - - name: redis-data - mountPath: {{ .Values.master.persistence.path }} - subPath: {{ .Values.master.persistence.subPath }} - - name: config - mountPath: /opt/bitnami/redis/mounted-etc - - name: redis-tmp-conf - mountPath: /opt/bitnami/redis/etc/ - - name: tmp - mountPath: /tmp - {{- if .Values.tls.enabled }} - - name: redis-certificates - mountPath: /opt/bitnami/redis/certs - readOnly: true - {{- end }} - {{- if .Values.master.extraVolumeMounts }} - {{- include "common.tplvalues.render" ( dict "value" .Values.master.extraVolumeMounts "context" $ ) | nindent 12 }} - {{- end }} - {{- if .Values.metrics.enabled }} - - name: metrics - image: {{ template "redis.metrics.image" . }} - imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - command: - - /bin/bash - - -c - - | - if [[ -f '/secrets/redis-password' ]]; then - export REDIS_PASSWORD=$(cat /secrets/redis-password) - fi - redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} - env: - - name: REDIS_ALIAS - value: {{ template "redis.fullname" . }} - {{- if .Values.usePassword }} - - name: REDIS_USER - value: default - {{- if (not .Values.usePasswordFile) }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - {{- end }} - {{- end }} - {{- if .Values.tls.enabled }} - - name: REDIS_ADDR - value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.redisPort }} - {{- if .Values.tls.authClients }} - - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE - value: {{ template "redis.tlsCertKey" . }} - - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE - value: {{ template "redis.tlsCert" . }} - {{- end }} - - name: REDIS_EXPORTER_TLS_CA_CERT_FILE - value: {{ template "redis.tlsCACert" . }} - {{- end }} - volumeMounts: - {{- if .Values.usePasswordFile }} - - name: redis-password - mountPath: /secrets/ - {{- end }} - {{- if .Values.tls.enabled }} - - name: redis-certificates - mountPath: /opt/bitnami/redis/certs - readOnly: true - {{- end }} - ports: - - name: metrics - containerPort: 9121 - resources: {{- toYaml .Values.metrics.resources | nindent 12 }} - {{- end }} - {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.master.persistence.enabled .Values.securityContext.enabled .Values.containerSecurityContext.enabled }} - {{- if or $needsVolumePermissions .Values.sysctlImage.enabled }} - initContainers: - {{- if $needsVolumePermissions }} - - name: volume-permissions - image: "{{ template "redis.volumePermissions.image" . }}" - imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} - command: - - /bin/bash - - -ec - - | - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.master.persistence.path }} - {{- else }} - chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.master.persistence.path }} - {{- end }} - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto "}} - securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} - {{- else }} - securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} - {{- end }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 10 }} - volumeMounts: - - name: redis-data - mountPath: {{ .Values.master.persistence.path }} - subPath: {{ .Values.master.persistence.subPath }} - {{- end }} - {{- if .Values.sysctlImage.enabled }} - - name: init-sysctl - image: {{ template "redis.sysctl.image" . }} - imagePullPolicy: {{ default "" .Values.sysctlImage.pullPolicy | quote }} - resources: {{- toYaml .Values.sysctlImage.resources | nindent 10 }} - {{- if .Values.sysctlImage.mountHostSys }} - volumeMounts: - - name: host-sys - mountPath: /host-sys - {{- end }} - command: {{- toYaml .Values.sysctlImage.command | nindent 10 }} - securityContext: - privileged: true - runAsUser: 0 - {{- end }} - {{- end }} - volumes: - - name: start-scripts - configMap: - name: {{ include "redis.fullname" . }}-scripts - defaultMode: 0755 - - name: health - configMap: - name: {{ template "redis.fullname" . }}-health - defaultMode: 0755 - {{- if .Values.usePasswordFile }} - - name: redis-password - secret: - secretName: {{ template "redis.secretName" . }} - items: - - key: {{ template "redis.secretPasswordKey" . }} - path: redis-password - {{- end }} - - name: config - configMap: - name: {{ template "redis.fullname" . }} - {{- if not .Values.master.persistence.enabled }} - - name: "redis-data" - emptyDir: {} - {{- else }} - {{- if .Values.persistence.existingClaim }} - - name: "redis-data" - persistentVolumeClaim: - claimName: {{ include "redis.tplValue" (dict "value" .Values.persistence.existingClaim "context" $) }} - {{- end }} - {{- if .Values.master.persistence.volumes }} - {{- toYaml .Values.master.persistence.volumes | nindent 8 }} - {{- end }} - {{- end }} - {{- if .Values.sysctlImage.mountHostSys }} - - name: host-sys - hostPath: - path: /sys - {{- end }} - - name: redis-tmp-conf - emptyDir: {} - - name: tmp - emptyDir: {} - {{- if .Values.master.extraVolumes }} - {{- include "common.tplvalues.render" ( dict "value" .Values.master.extraVolumes "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.tls.enabled }} - - name: redis-certificates - secret: - secretName: {{ required "A secret containing the certificates for the TLS traffic is required when TLS in enabled" .Values.tls.certificatesSecret }} - defaultMode: 256 - {{- end }} - {{- if and .Values.master.persistence.enabled (not .Values.persistence.existingClaim) (not .Values.master.persistence.volumes) }} - volumeClaimTemplates: - - metadata: - name: redis-data - labels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: master - {{- if .Values.master.statefulset.volumeClaimTemplates.labels }} - {{- toYaml .Values.master.statefulset.volumeClaimTemplates.labels | nindent 10 }} - {{- end }} - {{- if .Values.master.statefulset.volumeClaimTemplates.annotations }} - annotations: - {{- toYaml .Values.master.statefulset.volumeClaimTemplates.annotations | nindent 10 }} - {{- end }} - spec: - accessModes: - {{- range .Values.master.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.master.persistence.size | quote }} - {{ include "redis.master.storageClass" . }} - selector: - {{- if .Values.master.persistence.matchLabels }} - matchLabels: {{- toYaml .Values.master.persistence.matchLabels | nindent 12 }} - {{- end -}} - {{- if .Values.master.persistence.matchExpressions }} - matchExpressions: {{- toYaml .Values.master.persistence.matchExpressions | nindent 12 }} - {{- end -}} - {{- end }} - updateStrategy: - type: {{ .Values.master.statefulset.updateStrategy }} - {{- if .Values.master.statefulset.rollingUpdatePartition }} - {{- if (eq "Recreate" .Values.master.statefulset.updateStrategy) }} - rollingUpdate: null - {{- else }} - rollingUpdate: - partition: {{ .Values.master.statefulset.rollingUpdatePartition }} - {{- end }} - {{- end }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/redis-master-svc.yaml b/scripts/helm/db/redis/templates/redis-master-svc.yaml deleted file mode 100644 index 8bd2f8c1c..000000000 --- a/scripts/helm/db/redis/templates/redis-master-svc.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if not .Values.sentinel.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "redis.fullname" . }}-master - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- if .Values.master.service.labels -}} - {{- toYaml .Values.master.service.labels | nindent 4 }} - {{- end -}} -{{- if .Values.master.service.annotations }} - annotations: {{- toYaml .Values.master.service.annotations | nindent 4 }} -{{- end }} -spec: - type: {{ .Values.master.service.type }} - {{ if eq .Values.master.service.type "LoadBalancer" }} - externalTrafficPolicy: {{ .Values.master.service.externalTrafficPolicy }} - {{- end }} - {{- if and (eq .Values.master.service.type "LoadBalancer") .Values.master.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.master.service.loadBalancerIP }} - {{- end }} - {{- if and (eq .Values.master.service.type "LoadBalancer") .Values.master.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- with .Values.master.service.loadBalancerSourceRanges }} -{{- toYaml . | nindent 4 }} -{{- end }} - {{- end }} - ports: - - name: tcp-redis - port: {{ .Values.master.service.port }} - targetPort: redis - {{- if .Values.master.service.nodePort }} - nodePort: {{ .Values.master.service.nodePort }} - {{- end }} - selector: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - role: master -{{- end }} diff --git a/scripts/helm/db/redis/templates/redis-node-statefulset.yaml b/scripts/helm/db/redis/templates/redis-node-statefulset.yaml deleted file mode 100644 index 9ede64175..000000000 --- a/scripts/helm/db/redis/templates/redis-node-statefulset.yaml +++ /dev/null @@ -1,556 +0,0 @@ -{{- if and .Values.cluster.enabled .Values.sentinel.enabled }} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "redis.fullname" . }}-node - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- if .Values.slave.statefulset.labels }} - {{- toYaml .Values.slave.statefulset.labels | nindent 4 }} - {{- end }} -{{- if .Values.slave.statefulset.annotations }} - annotations: - {{- toYaml .Values.slave.statefulset.annotations | nindent 4 }} -{{- end }} -spec: -{{- if .Values.slave.updateStrategy }} - strategy: {{- toYaml .Values.slave.updateStrategy | nindent 4 }} -{{- end }} - replicas: {{ .Values.cluster.slaveCount }} - serviceName: {{ template "redis.fullname" . }}-headless - selector: - matchLabels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - role: node - template: - metadata: - labels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - chart: {{ template "redis.chart" . }} - role: node - {{- if .Values.slave.podLabels }} - {{- toYaml .Values.slave.podLabels | nindent 8 }} - {{- end }} - {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} - {{- toYaml .Values.metrics.podLabels | nindent 8 }} - {{- end }} - annotations: - checksum/health: {{ include (print $.Template.BasePath "/health-configmap.yaml") . | sha256sum }} - checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} - {{- if .Values.slave.podAnnotations }} - {{- toYaml .Values.slave.podAnnotations | nindent 8 }} - {{- end }} - {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} - {{- toYaml .Values.metrics.podAnnotations | nindent 8 }} - {{- end }} - spec: - {{- include "redis.imagePullSecrets" . | nindent 6 }} - {{- if .Values.slave.hostAliases }} - hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.slave.hostAliases "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.securityContext.enabled }} - securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} - {{- end }} - serviceAccountName: {{ template "redis.serviceAccountName" . }} - {{- if .Values.slave.priorityClassName }} - priorityClassName: "{{ .Values.slave.priorityClassName }}" - {{- end }} - {{- if .Values.slave.nodeSelector }} - nodeSelector: {{- toYaml .Values.slave.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.slave.tolerations }} - tolerations: {{- toYaml .Values.slave.tolerations | nindent 8 }} - {{- end }} - {{- if .Values.slave.schedulerName }} - schedulerName: {{ .Values.slave.schedulerName }} - {{- end }} - {{- if .Values.master.spreadConstraints }} - topologySpreadConstraints: {{- toYaml .Values.master.spreadConstraints | nindent 8 }} - {{- end }} - {{- with .Values.slave.affinity }} - affinity: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} - containers: - - name: {{ template "redis.name" . }} - image: {{ template "redis.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - command: - - /bin/bash - - -c - - /opt/bitnami/scripts/start-scripts/start-node.sh - env: - - name: REDIS_MASTER_PORT_NUMBER - value: {{ .Values.redisPort | quote }} - {{- if .Values.usePassword }} - {{- if .Values.usePasswordFile }} - - name: REDIS_PASSWORD_FILE - value: "/opt/bitnami/redis/secrets/redis-password" - - name: REDIS_MASTER_PASSWORD_FILE - value: "/opt/bitnami/redis/secrets/redis-password" - {{- else }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - - name: REDIS_MASTER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - {{- end }} - {{- else }} - - name: ALLOW_EMPTY_PASSWORD - value: "yes" - {{- end }} - - name: REDIS_TLS_ENABLED - value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} - {{- if .Values.tls.enabled }} - - name: REDIS_TLS_PORT - value: {{ .Values.redisPort | quote }} - - name: REDIS_TLS_AUTH_CLIENTS - value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} - - name: REDIS_TLS_CERT_FILE - value: {{ template "redis.tlsCert" . }} - - name: REDIS_TLS_KEY_FILE - value: {{ template "redis.tlsCertKey" . }} - - name: REDIS_TLS_CA_FILE - value: {{ template "redis.tlsCACert" . }} - {{- if .Values.tls.dhParamsFilename }} - - name: REDIS_TLS_DH_PARAMS_FILE - value: {{ template "redis.tlsDHParams" . }} - {{- end }} - {{- else }} - - name: REDIS_PORT - value: {{ .Values.redisPort | quote }} - {{- end }} - - name: REDIS_DATA_DIR - value: {{ .Values.slave.persistence.path }} - {{- if .Values.sentinel.extraEnvVars }} - {{- include "redis.tplValue" (dict "value" .Values.sentinel.extraEnvVars "context" $) | nindent 12 }} - {{- end }} - {{- if or .Values.sentinel.extraEnvVarsCM .Values.sentinel.extraEnvVarsSecret }} - envFrom: - {{- if .Values.sentinel.extraEnvVarsCM }} - - configMapRef: - name: {{ .Values.sentinel.extraEnvVarsCM }} - {{- end }} - {{- if .Values.sentinel.extraEnvVarsSecret }} - - secretRef: - name: {{ .Values.sentinel.extraEnvVarsSecret }} - {{- end }} - {{- end }} - ports: - - name: redis - containerPort: {{ .Values.redisPort }} - {{- if .Values.slave.livenessProbe.enabled }} - livenessProbe: - initialDelaySeconds: {{ .Values.slave.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.slave.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.slave.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.slave.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.slave.livenessProbe.failureThreshold}} - exec: - command: - - sh - - -c - {{- if .Values.sentinel.enabled }} - - /health/ping_liveness_local.sh {{ .Values.slave.livenessProbe.timeoutSeconds }} - {{- else }} - - /health/ping_liveness_local_and_master.sh {{ .Values.slave.livenessProbe.timeoutSeconds }} - {{- end }} - {{- else if .Values.slave.customLivenessProbe }} - livenessProbe: {{- toYaml .Values.slave.customLivenessProbe | nindent 12 }} - {{- end }} - {{- if .Values.slave.readinessProbe.enabled }} - readinessProbe: - initialDelaySeconds: {{ .Values.slave.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.slave.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.slave.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.slave.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.slave.readinessProbe.failureThreshold }} - exec: - command: - - sh - - -c - {{- if .Values.sentinel.enabled }} - - /health/ping_readiness_local.sh {{ .Values.slave.livenessProbe.timeoutSeconds }} - {{- else }} - - /health/ping_readiness_local_and_master.sh {{ .Values.slave.livenessProbe.timeoutSeconds }} - {{- end }} - {{- else if .Values.slave.customReadinessProbe }} - readinessProbe: {{- toYaml .Values.slave.customReadinessProbe | nindent 12 }} - {{- end }} - resources: {{- toYaml .Values.slave.resources | nindent 12 }} - volumeMounts: - - name: start-scripts - mountPath: /opt/bitnami/scripts/start-scripts - - name: health - mountPath: /health - {{- if .Values.usePasswordFile }} - - name: redis-password - mountPath: /opt/bitnami/redis/secrets/ - {{- end }} - - name: redis-data - mountPath: {{ .Values.slave.persistence.path }} - subPath: {{ .Values.slave.persistence.subPath }} - - name: config - mountPath: /opt/bitnami/redis/mounted-etc - - name: redis-tmp-conf - mountPath: /opt/bitnami/redis/etc - - name: tmp - mountPath: /tmp - {{- if .Values.tls.enabled }} - - name: redis-certificates - mountPath: /opt/bitnami/redis/certs - readOnly: true - {{- end }} - {{- if .Values.extraVolumeMounts }} - {{- include "common.tplvalues.render" ( dict "value" .Values.extraVolumeMounts "context" $ ) | nindent 12 }} - {{- end }} - {{- if and .Values.cluster.enabled .Values.sentinel.enabled }} - - name: sentinel - image: {{ template "sentinel.image" . }} - imagePullPolicy: {{ .Values.sentinel.image.pullPolicy | quote }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - command: - - /bin/bash - - -c - - /opt/bitnami/scripts/start-scripts/start-sentinel.sh - env: - {{- if .Values.usePassword }} - {{- if .Values.usePasswordFile }} - - name: REDIS_PASSWORD_FILE - value: "/opt/bitnami/redis/secrets/redis-password" - {{- else }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - {{- end }} - {{- else }} - - name: ALLOW_EMPTY_PASSWORD - value: "yes" - {{- end }} - - name: REDIS_SENTINEL_TLS_ENABLED - value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} - {{- if .Values.tls.enabled }} - - name: REDIS_SENTINEL_TLS_PORT_NUMBER - value: {{ .Values.sentinel.port | quote }} - - name: REDIS_SENTINEL_TLS_AUTH_CLIENTS - value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} - - name: REDIS_SENTINEL_TLS_CERT_FILE - value: {{ template "redis.tlsCert" . }} - - name: REDIS_SENTINEL_TLS_KEY_FILE - value: {{ template "redis.tlsCertKey" . }} - - name: REDIS_SENTINEL_TLS_CA_FILE - value: {{ template "redis.tlsCACert" . }} - {{- if .Values.tls.dhParamsFilename }} - - name: REDIS_SENTINEL_TLS_DH_PARAMS_FILE - value: {{ template "redis.dhParams" . }} - {{- end }} - {{- else }} - - name: REDIS_SENTINEL_PORT - value: {{ .Values.sentinel.port | quote }} - {{- end }} - ports: - - name: redis-sentinel - containerPort: {{ .Values.sentinel.port }} - {{- if .Values.sentinel.livenessProbe.enabled }} - livenessProbe: - initialDelaySeconds: {{ .Values.sentinel.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.sentinel.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.sentinel.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.sentinel.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.sentinel.livenessProbe.failureThreshold }} - exec: - command: - - sh - - -c - - /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }} - {{- else if .Values.sentinel.customLivenessProbe }} - livenessProbe: {{- toYaml .Values.sentinel.customLivenessProbe | nindent 12 }} - {{- end }} - {{- if .Values.sentinel.readinessProbe.enabled}} - readinessProbe: - initialDelaySeconds: {{ .Values.sentinel.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.sentinel.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.sentinel.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.sentinel.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.sentinel.readinessProbe.failureThreshold }} - exec: - command: - - sh - - -c - - /health/ping_sentinel.sh {{ .Values.sentinel.livenessProbe.timeoutSeconds }} - {{- else if .Values.sentinel.customReadinessProbe }} - readinessProbe: {{- toYaml .Values.sentinel.customReadinessProbe | nindent 12 }} - {{- end }} - lifecycle: - preStop: - exec: - command: - - /bin/bash - - -c - - /opt/bitnami/scripts/start-scripts/prestop-sentinel.sh - resources: {{- toYaml .Values.sentinel.resources | nindent 12 }} - volumeMounts: - - name: start-scripts - mountPath: /opt/bitnami/scripts/start-scripts - - name: health - mountPath: /health - {{- if .Values.usePasswordFile }} - - name: redis-password - mountPath: /opt/bitnami/redis/secrets/ - {{- end }} - - name: redis-data - mountPath: {{ .Values.slave.persistence.path }} - subPath: {{ .Values.slave.persistence.subPath }} - - name: config - mountPath: /opt/bitnami/redis-sentinel/mounted-etc - - name: sentinel-tmp-conf - mountPath: /opt/bitnami/redis-sentinel/etc - {{- if .Values.tls.enabled }} - - name: redis-certificates - mountPath: /opt/bitnami/redis/certs - readOnly: true - {{- end }} - {{- if .Values.sentinel.extraVolumeMounts }} - {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraVolumeMounts "context" $ ) | nindent 12 }} - {{- end }} - {{- end }} - {{- if .Values.metrics.enabled }} - - name: metrics - image: {{ template "redis.metrics.image" . }} - imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - command: - - /bin/bash - - -c - - | - if [[ -f '/secrets/redis-password' ]]; then - export REDIS_PASSWORD=$(cat /secrets/redis-password) - fi - redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} - env: - - name: REDIS_ALIAS - value: {{ template "redis.fullname" . }} - {{- if .Values.usePassword }} - - name: REDIS_USER - value: default - {{- if (not .Values.usePasswordFile) }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - {{- end }} - {{- end }} - {{- if .Values.tls.enabled }} - - name: REDIS_ADDR - value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.redisPort }} - {{- if .Values.tls.authClients }} - - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE - value: {{ template "redis.tlsCertKey" . }} - - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE - value: {{ template "redis.tlsCert" . }} - {{- end }} - - name: REDIS_EXPORTER_TLS_CA_CERT_FILE - value: {{ template "redis.tlsCACert" . }} - {{- end }} - volumeMounts: - {{- if .Values.usePasswordFile }} - - name: redis-password - mountPath: /secrets/ - {{- end }} - {{- if .Values.tls.enabled }} - - name: redis-certificates - mountPath: /opt/bitnami/redis/certs - readOnly: true - {{- end }} - ports: - - name: metrics - containerPort: 9121 - resources: {{- toYaml .Values.metrics.resources | nindent 12 }} - {{- end }} - {{- if .Values.sentinel.metrics.enabled }} - - name: sentinel-metrics - image: {{ include "sentinel.metrics.image" . }} - imagePullPolicy: {{ .Values.sentinel.metrics.image.pullPolicy | quote }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - command: - - redis_sentinel_exporter{{- range $key, $value := .Values.sentinel.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} - env: - {{- if and .Values.sentinel.usePassword (and .Values.usePassword (not .Values.usePasswordFile)) }} - - name: SENTINEL_PASSWORD - valueFrom: - secretKeyRef: - name: {{ include "redis.secretName" . }} - key: {{ include "redis.secretPasswordKey" . }} - {{- end }} - {{- if and .Values.sentinel.usePassword .Values.usePassword .Values.usePasswordFile }} - - name: SENTINEL_PASSWORD_FILE - value: /secrets/redis-password - {{- end }} - volumeMounts: - {{- if and .Values.sentinel.usePassword .Values.usePassword .Values.usePasswordFile }} - - name: redis-password - mountPath: /secrets/ - {{- end }} - ports: - - name: sentinelmetrics - containerPort: 9355 - resources: {{- include "common.tplvalues.render" (dict "value" .Values.metrics.resources "context" $) | nindent 12 }} - {{- end }} - {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.slave.persistence.enabled .Values.securityContext.enabled .Values.containerSecurityContext.enabled }} - {{- if or $needsVolumePermissions .Values.sysctlImage.enabled }} - initContainers: - {{- if $needsVolumePermissions }} - - name: volume-permissions - image: {{ template "redis.volumePermissions.image" . }} - imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} - command: - - /bin/bash - - -ec - - | - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.slave.persistence.path }} - {{- else }} - chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.slave.persistence.path }} - {{- end }} - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto "}} - securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} - {{- else }} - securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} - {{- end }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} - volumeMounts: - - name: redis-data - mountPath: {{ .Values.slave.persistence.path }} - subPath: {{ .Values.slave.persistence.subPath }} - {{- end }} - {{- if .Values.sysctlImage.enabled }} - - name: init-sysctl - image: {{ template "redis.sysctl.image" . }} - imagePullPolicy: {{ default "" .Values.sysctlImage.pullPolicy | quote }} - resources: {{- toYaml .Values.sysctlImage.resources | nindent 12 }} - {{- if .Values.sysctlImage.mountHostSys }} - volumeMounts: - - name: host-sys - mountPath: /host-sys - {{- end }} - command: {{- toYaml .Values.sysctlImage.command | nindent 12 }} - securityContext: - privileged: true - runAsUser: 0 - {{- end }} - {{- end }} - volumes: - - name: start-scripts - configMap: - name: {{ include "redis.fullname" . }}-scripts - defaultMode: 0755 - - name: health - configMap: - name: {{ template "redis.fullname" . }}-health - defaultMode: 0755 - {{- if .Values.usePasswordFile }} - - name: redis-password - secret: - secretName: {{ template "redis.secretName" . }} - items: - - key: {{ template "redis.secretPasswordKey" . }} - path: redis-password - {{- end }} - - name: config - configMap: - name: {{ template "redis.fullname" . }} - {{- if .Values.sysctlImage.mountHostSys }} - - name: host-sys - hostPath: - path: /sys - {{- end }} - - name: sentinel-tmp-conf - emptyDir: {} - - name: redis-tmp-conf - emptyDir: {} - - name: tmp - emptyDir: {} - {{- if .Values.extraVolumes }} - {{- include "common.tplvalues.render" ( dict "value" .Values.extraVolumes "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.sentinel.extraVolumes }} - {{- include "common.tplvalues.render" ( dict "value" .Values.sentinel.extraVolumes "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.tls.enabled }} - - name: redis-certificates - secret: - secretName: {{ required "A secret containing the certificates for the TLS traffic is required when TLS in enabled" .Values.tls.certificatesSecret }} - defaultMode: 256 - {{- end }} - {{- if not .Values.slave.persistence.enabled }} - - name: redis-data - emptyDir: {} - {{- else }} - volumeClaimTemplates: - - metadata: - name: redis-data - labels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: slave - {{- if .Values.slave.statefulset.volumeClaimTemplates }} - {{- if .Values.slave.statefulset.volumeClaimTemplates.labels }} - {{- toYaml .Values.slave.statefulset.volumeClaimTemplates.labels | nindent 10 }} - {{- end }} - {{- if .Values.slave.statefulset.volumeClaimTemplates.annotations }} - annotations: - {{- toYaml .Values.slave.statefulset.volumeClaimTemplates.annotations | nindent 10 }} - {{- end }} - {{- end }} - spec: - accessModes: - {{- range .Values.slave.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.slave.persistence.size | quote }} - {{ include "redis.slave.storageClass" . }} - selector: - {{- if .Values.slave.persistence.matchLabels }} - matchLabels: {{- toYaml .Values.slave.persistence.matchLabels | nindent 12 }} - {{- end -}} - {{- if .Values.slave.persistence.matchExpressions }} - matchExpressions: {{- toYaml .Values.slave.persistence.matchExpressions | nindent 12 }} - {{- end -}} - {{- end }} - updateStrategy: - type: {{ .Values.slave.statefulset.updateStrategy }} - {{- if .Values.slave.statefulset.rollingUpdatePartition }} - {{- if (eq "Recreate" .Values.slave.statefulset.updateStrategy) }} - rollingUpdate: null - {{- else }} - rollingUpdate: - partition: {{ .Values.slave.statefulset.rollingUpdatePartition }} - {{- end }} - {{- end }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/redis-role.yaml b/scripts/helm/db/redis/templates/redis-role.yaml deleted file mode 100644 index 080a7f960..000000000 --- a/scripts/helm/db/redis/templates/redis-role.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} -kind: Role -metadata: - name: {{ template "redis.fullname" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -rules: -{{- if .Values.podSecurityPolicy.create }} - - apiGroups: ['{{ template "podSecurityPolicy.apiGroup" . }}'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: [{{ template "redis.fullname" . }}] -{{- end -}} -{{- if .Values.rbac.role.rules }} -{{- toYaml .Values.rbac.role.rules | nindent 2 }} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/db/redis/templates/redis-rolebinding.yaml b/scripts/helm/db/redis/templates/redis-rolebinding.yaml deleted file mode 100644 index 835aa0361..000000000 --- a/scripts/helm/db/redis/templates/redis-rolebinding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} -kind: RoleBinding -metadata: - name: {{ template "redis.fullname" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "redis.fullname" . }} -subjects: -- kind: ServiceAccount - name: {{ template "redis.serviceAccountName" . }} -{{- end -}} diff --git a/scripts/helm/db/redis/templates/redis-serviceaccount.yaml b/scripts/helm/db/redis/templates/redis-serviceaccount.yaml deleted file mode 100644 index 081691de6..000000000 --- a/scripts/helm/db/redis/templates/redis-serviceaccount.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "redis.serviceAccountName" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- if .Values.serviceAccount.annotations }} - annotations: {{ toYaml .Values.serviceAccount.annotations | nindent 4 }} - {{- end }} -{{- end -}} diff --git a/scripts/helm/db/redis/templates/redis-slave-statefulset.yaml b/scripts/helm/db/redis/templates/redis-slave-statefulset.yaml deleted file mode 100644 index 778cac5cf..000000000 --- a/scripts/helm/db/redis/templates/redis-slave-statefulset.yaml +++ /dev/null @@ -1,398 +0,0 @@ -{{- if and .Values.cluster.enabled (not .Values.sentinel.enabled) }} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "redis.fullname" . }}-slave - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- if .Values.slave.statefulset.labels }} - {{- toYaml .Values.slave.statefulset.labels | nindent 4 }} - {{- end }} -{{- if .Values.slave.statefulset.annotations }} - annotations: - {{- toYaml .Values.slave.statefulset.annotations | nindent 4 }} -{{- end }} -spec: -{{- if .Values.slave.updateStrategy }} - strategy: {{- toYaml .Values.slave.updateStrategy | nindent 4 }} -{{- end }} - replicas: {{ .Values.cluster.slaveCount }} - serviceName: {{ template "redis.fullname" . }}-headless - selector: - matchLabels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - role: slave - template: - metadata: - labels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - chart: {{ template "redis.chart" . }} - role: slave - {{- if .Values.slave.podLabels }} - {{- toYaml .Values.slave.podLabels | nindent 8 }} - {{- end }} - {{- if and .Values.metrics.enabled .Values.metrics.podLabels }} - {{- toYaml .Values.metrics.podLabels | nindent 8 }} - {{- end }} - annotations: - checksum/health: {{ include (print $.Template.BasePath "/health-configmap.yaml") . | sha256sum }} - checksum/configmap: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} - {{- if .Values.slave.podAnnotations }} - {{- toYaml .Values.slave.podAnnotations | nindent 8 }} - {{- end }} - {{- if and .Values.metrics.enabled .Values.metrics.podAnnotations }} - {{- toYaml .Values.metrics.podAnnotations | nindent 8 }} - {{- end }} - spec: - {{- include "redis.imagePullSecrets" . | nindent 6 }} - {{- if .Values.slave.hostAliases }} - hostAliases: {{- include "common.tplvalues.render" (dict "value" .Values.slave.hostAliases "context" $) | nindent 8 }} - {{- end }} - {{- if .Values.securityContext.enabled }} - securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} - {{- end }} - serviceAccountName: {{ template "redis.serviceAccountName" . }} - {{- if .Values.slave.priorityClassName }} - priorityClassName: {{ .Values.slave.priorityClassName | quote }} - {{- end }} - {{- if .Values.slave.nodeSelector }} - nodeSelector: {{- toYaml .Values.slave.nodeSelector | nindent 8 }} - {{- end }} - {{- if .Values.slave.tolerations }} - tolerations: {{- toYaml .Values.slave.tolerations | nindent 8 }} - {{- end }} - {{- if .Values.slave.shareProcessNamespace }} - shareProcessNamespace: {{ .Values.slave.shareProcessNamespace }} - {{- end }} - {{- if .Values.slave.schedulerName }} - schedulerName: {{ .Values.slave.schedulerName }} - {{- end }} - {{- if .Values.master.spreadConstraints }} - topologySpreadConstraints: {{- toYaml .Values.master.spreadConstraints | nindent 8 }} - {{- end }} - {{- with .Values.slave.affinity }} - affinity: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} - containers: - - name: {{ template "redis.name" . }} - image: {{ template "redis.image" . }} - imagePullPolicy: {{ .Values.image.pullPolicy | quote }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - command: - - /bin/bash - - -c - - /opt/bitnami/scripts/start-scripts/start-slave.sh - env: - - name: REDIS_REPLICATION_MODE - value: slave - - name: REDIS_MASTER_HOST - value: {{ template "redis.fullname" . }}-master-0.{{ template "redis.fullname" . }}-headless.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} - - name: REDIS_MASTER_PORT_NUMBER - value: {{ .Values.redisPort | quote }} - {{- if .Values.usePassword }} - {{- if .Values.usePasswordFile }} - - name: REDIS_PASSWORD_FILE - value: "/opt/bitnami/redis/secrets/redis-password" - - name: REDIS_MASTER_PASSWORD_FILE - value: "/opt/bitnami/redis/secrets/redis-password" - {{- else }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - - name: REDIS_MASTER_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - {{- end }} - {{- else }} - - name: ALLOW_EMPTY_PASSWORD - value: "yes" - {{- end }} - - name: REDIS_TLS_ENABLED - value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} - {{- if .Values.tls.enabled }} - - name: REDIS_TLS_PORT - value: {{ .Values.redisPort | quote }} - - name: REDIS_TLS_AUTH_CLIENTS - value: {{ ternary "yes" "no" .Values.tls.authClients | quote }} - - name: REDIS_TLS_CERT_FILE - value: {{ template "redis.tlsCert" . }} - - name: REDIS_TLS_KEY_FILE - value: {{ template "redis.tlsCertKey" . }} - - name: REDIS_TLS_CA_FILE - value: {{ template "redis.tlsCACert" . }} - {{- if .Values.tls.dhParamsFilename }} - - name: REDIS_TLS_DH_PARAMS_FILE - value: {{ template "redis.tlsDHParams" . }} - {{- end }} - {{- else }} - - name: REDIS_PORT - value: {{ .Values.redisPort | quote }} - {{- end }} - {{- if .Values.slave.extraEnvVars }} - {{- include "redis.tplValue" (dict "value" .Values.slave.extraEnvVars "context" $) | nindent 12 }} - {{- end }} - {{- if or .Values.slave.extraEnvVarsCM .Values.slave.extraEnvVarsSecret }} - envFrom: - {{- if .Values.slave.extraEnvVarsCM }} - - configMapRef: - name: {{ .Values.slave.extraEnvVarsCM }} - {{- end }} - {{- if .Values.slave.extraEnvVarsSecret }} - - secretRef: - name: {{ .Values.slave.extraEnvVarsSecret }} - {{- end }} - {{- end }} - ports: - - name: redis - containerPort: {{ .Values.redisPort }} - {{- if .Values.slave.livenessProbe.enabled }} - livenessProbe: - initialDelaySeconds: {{ .Values.slave.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.slave.livenessProbe.periodSeconds }} - timeoutSeconds: {{ add1 .Values.slave.livenessProbe.timeoutSeconds }} - successThreshold: {{ .Values.slave.livenessProbe.successThreshold }} - failureThreshold: {{ .Values.slave.livenessProbe.failureThreshold}} - exec: - command: - - sh - - -c - - /health/ping_liveness_local_and_master.sh {{ .Values.slave.livenessProbe.timeoutSeconds }} - {{- else if .Values.slave.customLivenessProbe }} - livenessProbe: {{- toYaml .Values.slave.customLivenessProbe | nindent 12 }} - {{- end }} - {{- if .Values.slave.readinessProbe.enabled }} - readinessProbe: - initialDelaySeconds: {{ .Values.slave.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.slave.readinessProbe.periodSeconds }} - timeoutSeconds: {{ add1 .Values.slave.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.slave.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.slave.readinessProbe.failureThreshold }} - exec: - command: - - sh - - -c - - /health/ping_readiness_local_and_master.sh {{ .Values.slave.readinessProbe.timeoutSeconds }} - {{- else if .Values.slave.customReadinessProbe }} - readinessProbe: {{- toYaml .Values.slave.customReadinessProbe | nindent 12 }} - {{- end }} - resources: {{- toYaml .Values.slave.resources | nindent 12 }} - volumeMounts: - - name: start-scripts - mountPath: /opt/bitnami/scripts/start-scripts - - name: health - mountPath: /health - {{- if .Values.usePasswordFile }} - - name: redis-password - mountPath: /opt/bitnami/redis/secrets/ - {{- end }} - - name: redis-data - mountPath: /data - - name: config - mountPath: /opt/bitnami/redis/mounted-etc - - name: redis-tmp-conf - mountPath: /opt/bitnami/redis/etc - {{- if .Values.tls.enabled }} - - name: redis-certificates - mountPath: /opt/bitnami/redis/certs - readOnly: true - {{- end }} - {{- if .Values.slave.extraVolumeMounts }} - {{- include "common.tplvalues.render" ( dict "value" .Values.slave.extraVolumeMounts "context" $ ) | nindent 12 }} - {{- end }} - {{- if .Values.metrics.enabled }} - - name: metrics - image: {{ template "redis.metrics.image" . }} - imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} - {{- if .Values.containerSecurityContext.enabled }} - securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} - {{- end }} - command: - - /bin/bash - - -c - - | - if [[ -f '/secrets/redis-password' ]]; then - export REDIS_PASSWORD=$(cat /secrets/redis-password) - fi - redis_exporter{{- range $key, $value := .Values.metrics.extraArgs }} --{{ $key }}={{ $value }}{{- end }} - env: - - name: REDIS_ALIAS - value: {{ template "redis.fullname" . }} - {{- if .Values.usePassword }} - - name: REDIS_USER - value: default - {{- if (not .Values.usePasswordFile) }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "redis.secretName" . }} - key: {{ template "redis.secretPasswordKey" . }} - {{- end }} - {{- end }} - {{- if .Values.tls.enabled }} - - name: REDIS_ADDR - value: rediss://{{ .Values.metrics.redisTargetHost }}:{{ .Values.redisPort }} - {{- if .Values.tls.authClients }} - - name: REDIS_EXPORTER_TLS_CLIENT_KEY_FILE - value: {{ template "redis.tlsCertKey" . }} - - name: REDIS_EXPORTER_TLS_CLIENT_CERT_FILE - value: {{ template "redis.tlsCert" . }} - {{- end }} - - name: REDIS_EXPORTER_TLS_CA_CERT_FILE - value: {{ template "redis.tlsCACert" . }} - {{- end }} - volumeMounts: - {{- if .Values.usePasswordFile }} - - name: redis-password - mountPath: /secrets/ - {{- end }} - {{- if .Values.tls.enabled }} - - name: redis-certificates - mountPath: /opt/bitnami/redis/certs - readOnly: true - {{- end }} - ports: - - name: metrics - containerPort: 9121 - resources: {{- toYaml .Values.metrics.resources | nindent 12 }} - {{- end }} - {{- $needsVolumePermissions := and .Values.volumePermissions.enabled .Values.slave.persistence.enabled .Values.securityContext.enabled .Values.containerSecurityContext.enabled }} - {{- if or $needsVolumePermissions .Values.sysctlImage.enabled }} - initContainers: - {{- if $needsVolumePermissions }} - - name: volume-permissions - image: {{ template "redis.volumePermissions.image" . }} - imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} - command: - - /bin/bash - - -ec - - | - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} - chown -R `id -u`:`id -G | cut -d " " -f2` {{ .Values.slave.persistence.path }} - {{- else }} - chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.slave.persistence.path }} - {{- end }} - {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto "}} - securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} - {{- else }} - securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} - {{- end }} - resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} - volumeMounts: - - name: redis-data - mountPath: {{ .Values.slave.persistence.path }} - subPath: {{ .Values.slave.persistence.subPath }} - {{- end }} - {{- if .Values.sysctlImage.enabled }} - - name: init-sysctl - image: {{ template "redis.sysctl.image" . }} - imagePullPolicy: {{ default "" .Values.sysctlImage.pullPolicy | quote }} - resources: {{- toYaml .Values.sysctlImage.resources | nindent 12 }} - {{- if .Values.sysctlImage.mountHostSys }} - volumeMounts: - - name: host-sys - mountPath: /host-sys - {{- end }} - command: {{- toYaml .Values.sysctlImage.command | nindent 12 }} - securityContext: - privileged: true - runAsUser: 0 - {{- end }} - {{- end }} - volumes: - - name: start-scripts - configMap: - name: {{ include "redis.fullname" . }}-scripts - defaultMode: 0755 - - name: health - configMap: - name: {{ template "redis.fullname" . }}-health - defaultMode: 0755 - {{- if .Values.usePasswordFile }} - - name: redis-password - secret: - secretName: {{ template "redis.secretName" . }} - items: - - key: {{ template "redis.secretPasswordKey" . }} - path: redis-password - {{- end }} - - name: config - configMap: - name: {{ template "redis.fullname" . }} - {{- if .Values.sysctlImage.mountHostSys }} - - name: host-sys - hostPath: - path: /sys - {{- end }} - - name: redis-tmp-conf - emptyDir: {} - {{- if .Values.slave.extraVolumes }} - {{- include "common.tplvalues.render" ( dict "value" .Values.slave.extraVolumes "context" $ ) | nindent 8 }} - {{- end }} - {{- if .Values.tls.enabled }} - - name: redis-certificates - secret: - secretName: {{ required "A secret containing the certificates for the TLS traffic is required when TLS in enabled" .Values.tls.certificatesSecret }} - defaultMode: 256 - {{- end }} - {{- if not .Values.slave.persistence.enabled }} - - name: redis-data - emptyDir: {} - {{- else }} - volumeClaimTemplates: - - metadata: - name: redis-data - labels: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - component: slave - {{- if .Values.slave.statefulset.volumeClaimTemplates }} - {{- if .Values.slave.statefulset.volumeClaimTemplates.labels }} - {{- toYaml .Values.slave.statefulset.volumeClaimTemplates.labels | nindent 10 }} - {{- end }} - {{- if .Values.slave.statefulset.volumeClaimTemplates.annotations }} - annotations: - {{- toYaml .Values.slave.statefulset.volumeClaimTemplates.annotations | nindent 10 }} - {{- end }} - {{- end }} - spec: - accessModes: - {{- range .Values.slave.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.slave.persistence.size | quote }} - {{ include "redis.slave.storageClass" . }} - selector: - {{- if .Values.slave.persistence.matchLabels }} - matchLabels: {{- toYaml .Values.slave.persistence.matchLabels | nindent 12 }} - {{- end -}} - {{- if .Values.slave.persistence.matchExpressions }} - matchExpressions: {{- toYaml .Values.slave.persistence.matchExpressions | nindent 12 }} - {{- end -}} - {{- end }} - updateStrategy: - type: {{ .Values.slave.statefulset.updateStrategy }} - {{- if .Values.slave.statefulset.rollingUpdatePartition }} - {{- if (eq "Recreate" .Values.slave.statefulset.updateStrategy) }} - rollingUpdate: null - {{- else }} - rollingUpdate: - partition: {{ .Values.slave.statefulset.rollingUpdatePartition }} - {{- end }} - {{- end }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/redis-slave-svc.yaml b/scripts/helm/db/redis/templates/redis-slave-svc.yaml deleted file mode 100644 index a67ebb05e..000000000 --- a/scripts/helm/db/redis/templates/redis-slave-svc.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if and .Values.cluster.enabled (not .Values.sentinel.enabled) }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "redis.fullname" . }}-slave - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- if .Values.slave.service.labels -}} - {{- toYaml .Values.slave.service.labels | nindent 4 }} - {{- end -}} -{{- if .Values.slave.service.annotations }} - annotations: {{- toYaml .Values.slave.service.annotations | nindent 4 }} -{{- end }} -spec: - type: {{ .Values.slave.service.type }} - {{ if eq .Values.slave.service.type "LoadBalancer" }} - externalTrafficPolicy: {{ .Values.slave.service.externalTrafficPolicy }} - {{- end }} - {{- if and (eq .Values.slave.service.type "LoadBalancer") .Values.slave.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.slave.service.loadBalancerIP }} - {{- end }} - {{- if and (eq .Values.slave.service.type "LoadBalancer") .Values.slave.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- with .Values.slave.service.loadBalancerSourceRanges }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- end }} - ports: - - name: tcp-redis - port: {{ .Values.slave.service.port }} - targetPort: redis - {{- if .Values.slave.service.nodePort }} - nodePort: {{ .Values.slave.service.nodePort }} - {{- end }} - selector: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} - role: slave -{{- end }} diff --git a/scripts/helm/db/redis/templates/redis-with-sentinel-svc.yaml b/scripts/helm/db/redis/templates/redis-with-sentinel-svc.yaml deleted file mode 100644 index e1c9073a4..000000000 --- a/scripts/helm/db/redis/templates/redis-with-sentinel-svc.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.sentinel.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "redis.fullname" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} - {{- if .Values.sentinel.service.labels }} - {{- toYaml .Values.sentinel.service.labels | nindent 4 }} - {{- end }} -{{- if .Values.sentinel.service.annotations }} - annotations: {{- toYaml .Values.sentinel.service.annotations | nindent 4 }} -{{- end }} -spec: - type: {{ .Values.sentinel.service.type }} - {{ if eq .Values.sentinel.service.type "LoadBalancer" }} - externalTrafficPolicy: {{ .Values.sentinel.service.externalTrafficPolicy }} - {{- end }} - {{ if eq .Values.sentinel.service.type "LoadBalancer" -}} {{ if .Values.sentinel.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.sentinel.service.loadBalancerIP }} - {{ end -}} - {{- end -}} - ports: - - name: tcp-redis - port: {{ .Values.sentinel.service.redisPort }} - targetPort: redis - {{- if .Values.sentinel.service.redisNodePort }} - nodePort: {{ .Values.sentinel.service.redisNodePort }} - {{- end }} - - name: tcp-sentinel - port: {{ .Values.sentinel.service.sentinelPort }} - targetPort: redis-sentinel - {{- if .Values.sentinel.service.sentinelNodePort }} - nodePort: {{ .Values.sentinel.service.sentinelNodePort }} - {{- end }} - selector: - app: {{ template "redis.name" . }} - release: {{ .Release.Name }} -{{- end }} diff --git a/scripts/helm/db/redis/templates/secret.yaml b/scripts/helm/db/redis/templates/secret.yaml deleted file mode 100644 index 197aa1890..000000000 --- a/scripts/helm/db/redis/templates/secret.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if and .Values.usePassword (not .Values.existingSecret) -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "redis.fullname" . }} - namespace: {{ .Release.Namespace | quote }} - labels: - app: {{ template "redis.name" . }} - chart: {{ template "redis.chart" . }} - release: "{{ .Release.Name }}" - heritage: "{{ .Release.Service }}" -type: Opaque -data: - redis-password: {{ include "redis.password" . | b64enc | quote }} -{{- end -}} diff --git a/scripts/helm/db/redis/values.schema.json b/scripts/helm/db/redis/values.schema.json deleted file mode 100644 index 3188d0c93..000000000 --- a/scripts/helm/db/redis/values.schema.json +++ /dev/null @@ -1,168 +0,0 @@ -{ - "$schema": "http://json-schema.org/schema#", - "type": "object", - "properties": { - "usePassword": { - "type": "boolean", - "title": "Use password authentication", - "form": true - }, - "password": { - "type": "string", - "title": "Password", - "form": true, - "description": "Defaults to a random 10-character alphanumeric string if not set", - "hidden": { - "value": false, - "path": "usePassword" - } - }, - "cluster": { - "type": "object", - "title": "Cluster Settings", - "form": true, - "properties": { - "enabled": { - "type": "boolean", - "form": true, - "title": "Enable master-slave", - "description": "Enable master-slave architecture" - }, - "slaveCount": { - "type": "integer", - "title": "Slave Replicas", - "form": true, - "hidden": { - "value": false, - "path": "cluster/enabled" - } - } - } - }, - "master": { - "type": "object", - "title": "Master replicas settings", - "form": true, - "properties": { - "persistence": { - "type": "object", - "title": "Persistence for master replicas", - "form": true, - "properties": { - "enabled": { - "type": "boolean", - "form": true, - "title": "Enable persistence", - "description": "Enable persistence using Persistent Volume Claims" - }, - "size": { - "type": "string", - "title": "Persistent Volume Size", - "form": true, - "render": "slider", - "sliderMin": 1, - "sliderMax": 100, - "sliderUnit": "Gi", - "hidden": { - "value": false, - "path": "master/persistence/enabled" - } - }, - "matchLabels": { - "type": "object", - "title": "Persistent Match Labels Selector" - }, - "matchExpressions": { - "type": "object", - "title": "Persistent Match Expressions Selector" - } - } - } - } - }, - "slave": { - "type": "object", - "title": "Slave replicas settings", - "form": true, - "hidden": { - "value": false, - "path": "cluster/enabled" - }, - "properties": { - "persistence": { - "type": "object", - "title": "Persistence for slave replicas", - "form": true, - "properties": { - "enabled": { - "type": "boolean", - "form": true, - "title": "Enable persistence", - "description": "Enable persistence using Persistent Volume Claims" - }, - "size": { - "type": "string", - "title": "Persistent Volume Size", - "form": true, - "render": "slider", - "sliderMin": 1, - "sliderMax": 100, - "sliderUnit": "Gi", - "hidden": { - "value": false, - "path": "slave/persistence/enabled" - } - }, - "matchLabels": { - "type": "object", - "title": "Persistent Match Labels Selector" - }, - "matchExpressions": { - "type": "object", - "title": "Persistent Match Expressions Selector" - } - } - } - } - }, - "volumePermissions": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "form": true, - "title": "Enable Init Containers", - "description": "Use an init container to set required folder permissions on the data volume before mounting it in the final destination" - } - } - }, - "metrics": { - "type": "object", - "form": true, - "title": "Prometheus metrics details", - "properties": { - "enabled": { - "type": "boolean", - "title": "Create Prometheus metrics exporter", - "description": "Create a side-car container to expose Prometheus metrics", - "form": true - }, - "serviceMonitor": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "title": "Create Prometheus Operator ServiceMonitor", - "description": "Create a ServiceMonitor to track metrics using Prometheus Operator", - "form": true, - "hidden": { - "value": false, - "path": "metrics/enabled" - } - } - } - } - } - } - } -} diff --git a/scripts/helm/db/redis/values.yaml b/scripts/helm/db/redis/values.yaml deleted file mode 100644 index 64e908211..000000000 --- a/scripts/helm/db/redis/values.yaml +++ /dev/null @@ -1,1008 +0,0 @@ -## Global Docker image parameters -## Please, note that this will override the image parameters, including dependencies, configured to use the global value -## Current available global Docker image parameters: imageRegistry and imagePullSecrets -## -global: - # imageRegistry: myRegistryName - # imagePullSecrets: - # - myRegistryKeySecretName - # storageClass: myStorageClass - redis: {} - -## Bitnami Redis(TM) image version -## ref: https://hub.docker.com/r/bitnami/redis/tags/ -## -image: - registry: docker.io - repository: bitnami/redis - ## Bitnami Redis(TM) image tag - ## ref: https://github.com/bitnami/bitnami-docker-redis#supported-tags-and-respective-dockerfile-links - ## - tag: 6.0.12-debian-10-r33 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - -## String to partially override redis.fullname template (will maintain the release name) -## -# nameOverride: - -## String to fully override redis.fullname template -## -# fullnameOverride: - -## Cluster settings -## -cluster: - enabled: true - slaveCount: 2 - -## Use redis sentinel in the redis pod. This will disable the master and slave services and -## create one redis service with ports to the sentinel and the redis instances -## -sentinel: - enabled: false - ## Require password authentication on the sentinel itself - ## ref: https://redis.io/topics/sentinel - ## - usePassword: true - ## Bitnami Redis(TM) Sentintel image version - ## ref: https://hub.docker.com/r/bitnami/redis-sentinel/tags/ - ## - image: - registry: docker.io - repository: bitnami/redis-sentinel - ## Bitnami Redis(TM) image tag - ## ref: https://github.com/bitnami/bitnami-docker-redis-sentinel#supported-tags-and-respective-dockerfile-links - ## - tag: 6.0.12-debian-10-r24 - ## Specify a imagePullPolicy - ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' - ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - masterSet: mymaster - initialCheckTimeout: 5 - quorum: 2 - downAfterMilliseconds: 20000 - failoverTimeout: 18000 - parallelSyncs: 1 - port: 26379 - - ## Delay seconds when cleaning nodes IPs - ## When starting it will clean the sentinels IP (RESET "*") in all the nodes - ## This is the delay time before sending the command to the next node - ## - cleanDelaySeconds: 5 - - ## Additional Redis(TM) configuration for the sentinel nodes - ## ref: https://redis.io/topics/config - ## - configmap: - ## Enable or disable static sentinel IDs for each replicas - ## If disabled each sentinel will generate a random id at startup - ## If enabled, each replicas will have a constant ID on each start-up - ## - staticID: false - ## Configure extra options for Redis(TM) Sentinel liveness and readiness probes - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) - ## - livenessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 5 - customLivenessProbe: {} - customReadinessProbe: {} - ## Redis(TM) Sentinel resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - # resources: - # requests: - # memory: 256Mi - # cpu: 100m - ## Redis(TM) Sentinel Service properties - ## - service: - ## Redis(TM) Sentinel Service type - ## - type: ClusterIP - sentinelPort: 26379 - redisPort: 6379 - - ## External traffic policy (when service type is LoadBalancer) - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip - ## - externalTrafficPolicy: Cluster - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # sentinelNodePort: - # redisNodePort: - - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - annotations: {} - labels: {} - loadBalancerIP: - - ## Additional commands to run prior to starting Redis(TM) node with sentinel - ## - preExecCmds: "" - - ## An array to add extra env var to the sentinel node configurations - ## For example: - ## extraEnvVars: - ## - name: name - ## value: value - ## - name: other_name - ## valueFrom: - ## fieldRef: - ## fieldPath: fieldPath - ## - extraEnvVars: [] - - ## ConfigMap with extra env vars: - ## - extraEnvVarsCM: [] - - ## Secret with extra env vars: - ## - extraEnvVarsSecret: [] - - ## Prometheus Exporter / Metrics for Redis Sentinel Exporter - ## - metrics: - enabled: false - - ## Bitnami Redis Sentinel Exporter image - ## ref: https://hub.docker.com/r/bitnami/redis-sentinel-exporter/tags/ - ## - image: - registry: docker.io - repository: bitnami/redis-sentinel-exporter - tag: 1.7.1-debian-10-r105 - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - - ## Sentinel metrics exporter resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - ## We usually recommend not to specify default resources and to leave this as a conscious - ## choice for the user. This also increases chances charts run on environments with little - ## resources, such as Minikube. If you do want to specify resources, uncomment the following - ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. - ## e.g: - ## limits: - ## cpu: 500m - ## memory: 1Gi - ## - limits: {} - requests: {} - - ## Extra arguments for Sentinel metrics exporter, for example: - ## extraArgs: - ## check-keys: myKey,myOtherKey - # extraArgs: {} - - ## Enable this if you're using https://github.com/coreos/prometheus-operator - ## - serviceMonitor: - enabled: false - ## Specify a namespace if needed - # namespace: monitoring - # fallback to the prometheus default unless specified - # interval: 10s - ## Defaults to what's used if you follow CoreOS [Prometheus Install Instructions](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#tldr) - ## [Prometheus Selector Label](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-operator-1) - ## [Kube Prometheus Selector Label](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#exporters) - ## - selector: - prometheus: kube-prometheus - - service: - type: ClusterIP - - ## Metrics port - ## - port: 9355 - ## External traffic policy (when service type is LoadBalancer) - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip - ## - externalTrafficPolicy: Cluster - - ## Use serviceLoadBalancerIP to request a specific static IP, otherwise leave blank - ## - # loadBalancerIP: - annotations: {} - labels: {} - -## Specifies the Kubernetes Cluster's Domain Name. -## -clusterDomain: cluster.local - -networkPolicy: - ## Specifies whether a NetworkPolicy should be created - ## - enabled: false - - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to the port Redis(TM) is listening - ## on. When true, Redis(TM) will accept connections from any source - ## (with the correct destination port). - ## - # allowExternal: true - - ## Allow connections from other namespaces. Just set label for namespace and set label for pods (optional). - ## - ingressNSMatchLabels: {} - ingressNSPodMatchLabels: {} - -serviceAccount: - ## Specifies whether a ServiceAccount should be created - ## - create: false - ## The name of the ServiceAccount to use. - ## If not set and create is true, a name is generated using the fullname template - ## - name: - ## Add annotations to service account - # annotations: - # iam.gke.io/gcp-service-account: "sa@project.iam.gserviceaccount.com" - -rbac: - ## Specifies whether RBAC resources should be created - ## - create: false - - role: - ## Rules to create. It follows the role specification - # rules: - # - apiGroups: - # - extensions - # resources: - # - podsecuritypolicies - # verbs: - # - use - # resourceNames: - # - gce.unprivileged - rules: [] - -## Redis(TM) pod Security Context -## -securityContext: - enabled: true - fsGroup: 1001 - ## sysctl settings for master and slave pods - ## - ## Uncomment the setting below to increase the net.core.somaxconn value - ## - # sysctls: - # - name: net.core.somaxconn - # value: "10000" - -## Container Security Context -## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ -## -containerSecurityContext: - enabled: true - runAsUser: 1001 - -## Use password authentication -## -usePassword: true -## Redis(TM) password (both master and slave) -## Defaults to a random 10-character alphanumeric string if not set and usePassword is true -## ref: https://github.com/bitnami/bitnami-docker-redis#setting-the-server-password-on-first-run -## -password: "" -## Use existing secret (ignores previous password) -# existingSecret: -## Password key to be retrieved from Redis(TM) secret -## -# existingSecretPasswordKey: - -## Mount secrets as files instead of environment variables -## -usePasswordFile: false - -## Persist data to a persistent volume (Redis(TM) Master) -## -persistence: - ## A manually managed Persistent Volume and Claim - ## Requires persistence.enabled: true - ## If defined, PVC must be created manually before volume will be bound - ## - existingClaim: - -# Redis(TM) port -redisPort: 6379 - -## -## TLS configuration -## -tls: - # Enable TLS traffic - enabled: false - # - # Whether to require clients to authenticate or not. - authClients: true - # - # Name of the Secret that contains the certificates - certificatesSecret: - # - # Certificate filename - certFilename: - # - # Certificate Key filename - certKeyFilename: - # - # CA Certificate filename - certCAFilename: - # - # File containing DH params (in order to support DH based ciphers) - # dhParamsFilename: - -## -## Redis(TM) Master parameters -## -master: - ## Redis(TM) command arguments - ## - ## Can be used to specify command line arguments, for example: - ## Note `exec` is prepended to command - ## - command: "/run.sh" - ## Additional commands to run prior to starting Redis(TM) - ## - preExecCmds: "" - ## Additional Redis(TM) configuration for the master nodes - ## ref: https://redis.io/topics/config - ## - configmap: - ## Deployment pod host aliases - ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ - ## - hostAliases: [] - ## Redis(TM) additional command line flags - ## - ## Can be used to specify command line flags, for example: - ## extraFlags: - ## - "--maxmemory-policy volatile-ttl" - ## - "--repl-backlog-size 1024mb" - ## - extraFlags: [] - ## Comma-separated list of Redis(TM) commands to disable - ## - ## Can be used to disable Redis(TM) commands for security reasons. - ## Commands will be completely disabled by renaming each to an empty string. - ## ref: https://redis.io/topics/security#disabling-of-specific-commands - ## - disableCommands: - - FLUSHDB - - FLUSHALL - - ## Redis(TM) Master additional pod labels and annotations - ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - ## - podLabels: {} - podAnnotations: {} - - ## Redis(TM) Master resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - # resources: - # requests: - # memory: 256Mi - # cpu: 100m - ## Use an alternate scheduler, e.g. "stork". - ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ - ## - # schedulerName: - - # Enable shared process namespace in a pod. - # If set to false (default), each container will run in separate namespace, redis will have PID=1. - # If set to true, the /pause will run as init process and will reap any zombie PIDs, - # for example, generated by a custom exec probe running longer than a probe timeoutSeconds. - # Enable this only if customLivenessProbe or customReadinessProbe is used and zombie PIDs are accumulating. - # Ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ - shareProcessNamespace: false - ## Configure extra options for Redis(TM) Master liveness and readiness probes - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) - ## - livenessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 5 - - ## Configure custom probes for images other images like - ## rhscl/redis-32-rhel7 rhscl/redis-5-rhel7 - ## Only used if readinessProbe.enabled: false / livenessProbe.enabled: false - ## - # customLivenessProbe: - # tcpSocket: - # port: 6379 - # initialDelaySeconds: 10 - # periodSeconds: 5 - # customReadinessProbe: - # initialDelaySeconds: 30 - # periodSeconds: 10 - # timeoutSeconds: 5 - # exec: - # command: - # - "container-entrypoint" - # - "bash" - # - "-c" - # - "redis-cli set liveness-probe \"`date`\" | grep OK" - customLivenessProbe: {} - customReadinessProbe: {} - - ## Redis(TM) Master Node selectors and tolerations for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature - ## - # nodeSelector: {"beta.kubernetes.io/arch": "amd64"} - # tolerations: [] - ## Redis(TM) Master pod/node affinity/anti-affinity - ## - affinity: {} - - ## Redis(TM) Master Service properties - ## - service: - ## Redis(TM) Master Service type - ## - type: ClusterIP - port: 6379 - - ## External traffic policy (when service type is LoadBalancer) - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip - ## - externalTrafficPolicy: Cluster - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - annotations: {} - labels: {} - loadBalancerIP: - # loadBalancerSourceRanges: ["10.0.0.0/8"] - - ## Enable persistence using Persistent Volume Claims - ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ - ## - persistence: - enabled: true - ## The path the volume will be mounted at, useful when using different - ## Redis(TM) images. - ## - path: /data - ## The subdirectory of the volume to mount to, useful in dev environments - ## and one PV for multiple services. - ## - subPath: "" - ## redis data Persistent Volume Storage Class - ## If defined, storageClassName: <storageClass> - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - ## Persistent Volume selectors - ## https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector - ## - matchLabels: {} - matchExpressions: {} - volumes: - # - name: volume_name - # emptyDir: {} - - ## Update strategy, can be set to RollingUpdate or onDelete by default. - ## https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets - ## - statefulset: - labels: {} - annotations: {} - updateStrategy: RollingUpdate - ## Partition update strategy - ## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions - # rollingUpdatePartition: - volumeClaimTemplates: - labels: {} - annotations: {} - - ## Redis(TM) Master pod priorityClassName - ## - priorityClassName: null - - ## An array to add extra env vars - ## For example: - ## extraEnvVars: - ## - name: name - ## value: value - ## - name: other_name - ## valueFrom: - ## fieldRef: - ## fieldPath: fieldPath - ## - extraEnvVars: [] - - ## ConfigMap with extra env vars: - ## - extraEnvVarsCM: [] - - ## Secret with extra env vars: - ## - extraEnvVarsSecret: [] - -## -## Redis(TM) Slave properties -## Note: service.type is a mandatory parameter -## The rest of the parameters are either optional or, if undefined, will inherit those declared in Redis(TM) Master -## -slave: - ## Slave Service properties - ## - service: - ## Redis(TM) Slave Service type - ## - type: ClusterIP - ## Redis(TM) port - ## - port: 6379 - - ## External traffic policy (when service type is LoadBalancer) - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip - ## - externalTrafficPolicy: Cluster - - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## - annotations: {} - labels: {} - loadBalancerIP: - # loadBalancerSourceRanges: ["10.0.0.0/8"] - - ## Redis(TM) slave port - ## - port: 6379 - ## Deployment pod host aliases - ## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ - ## - hostAliases: [] - ## Can be used to specify command line arguments, for example: - ## Note `exec` is prepended to command - ## - command: "/run.sh" - ## Additional commands to run prior to starting Redis(TM) - ## - preExecCmds: "" - ## Additional Redis(TM) configuration for the slave nodes - ## ref: https://redis.io/topics/config - ## - configmap: - ## Redis(TM) extra flags - ## - extraFlags: [] - ## List of Redis(TM) commands to disable - ## - disableCommands: - - FLUSHDB - - FLUSHALL - - ## Redis(TM) Slave pod/node affinity/anti-affinity - ## - affinity: {} - - ## Kubernetes Spread Constraints for pod assignment - ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ - ## - # - maxSkew: 1 - # topologyKey: node - # whenUnsatisfiable: DoNotSchedule - spreadConstraints: {} - - # Enable shared process namespace in a pod. - # If set to false (default), each container will run in separate namespace, redis will have PID=1. - # If set to true, the /pause will run as init process and will reap any zombie PIDs, - # for example, generated by a custom exec probe running longer than a probe timeoutSeconds. - # Enable this only if customLivenessProbe or customReadinessProbe is used and zombie PIDs are accumulating. - # Ref: https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ - shareProcessNamespace: false - ## Configure extra options for Redis(TM) Slave liveness and readiness probes - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) - ## - livenessProbe: - enabled: true - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - readinessProbe: - enabled: true - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 10 - successThreshold: 1 - failureThreshold: 5 - - ## Configure custom probes for images other images like - ## rhscl/redis-32-rhel7 rhscl/redis-5-rhel7 - ## Only used if readinessProbe.enabled: false / livenessProbe.enabled: false - ## - # customLivenessProbe: - # tcpSocket: - # port: 6379 - # initialDelaySeconds: 10 - # periodSeconds: 5 - # customReadinessProbe: - # initialDelaySeconds: 30 - # periodSeconds: 10 - # timeoutSeconds: 5 - # exec: - # command: - # - "container-entrypoint" - # - "bash" - # - "-c" - # - "redis-cli set liveness-probe \"`date`\" | grep OK" - customLivenessProbe: {} - customReadinessProbe: {} - - ## Redis(TM) slave Resource - # resources: - # requests: - # memory: 256Mi - # cpu: 100m - - ## Redis(TM) slave selectors and tolerations for pod assignment - # nodeSelector: {"beta.kubernetes.io/arch": "amd64"} - # tolerations: [] - - ## Use an alternate scheduler, e.g. "stork". - ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ - ## - # schedulerName: - - ## Redis(TM) slave pod Annotation and Labels - ## - podLabels: {} - podAnnotations: {} - - ## Redis(TM) slave pod priorityClassName - priorityClassName: null - - ## Enable persistence using Persistent Volume Claims - ## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ - ## - persistence: - enabled: true - ## The path the volume will be mounted at, useful when using different - ## Redis(TM) images. - ## - path: /data - ## The subdirectory of the volume to mount to, useful in dev environments - ## and one PV for multiple services. - ## - subPath: "" - ## redis data Persistent Volume Storage Class - ## If defined, storageClassName: <storageClass> - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - accessModes: - - ReadWriteOnce - size: 8Gi - ## Persistent Volume selectors - ## https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector - ## - matchLabels: {} - matchExpressions: {} - - ## Update strategy, can be set to RollingUpdate or onDelete by default. - ## https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets - ## - statefulset: - labels: {} - annotations: {} - updateStrategy: RollingUpdate - ## Partition update strategy - ## https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions - # rollingUpdatePartition: - volumeClaimTemplates: - labels: {} - annotations: {} - - ## An array to add extra env vars - ## For example: - ## extraEnvVars: - ## - name: name - ## value: value - ## - name: other_name - ## valueFrom: - ## fieldRef: - ## fieldPath: fieldPath - ## - extraEnvVars: [] - - ## ConfigMap with extra env vars: - ## - extraEnvVarsCM: [] - - ## Secret with extra env vars: - ## - extraEnvVarsSecret: [] - -## Prometheus Exporter / Metrics -## -metrics: - enabled: false - - image: - registry: docker.io - repository: bitnami/redis-exporter - tag: 1.20.0-debian-10-r12 - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - - # A way to specify an alternative redis hostname, if you set a local endpoint in hostAliases for example - # Useful for certificate CN/SAN matching - redisTargetHost: "localhost" - - ## Metrics exporter resource requests and limits - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - # resources: {} - - ## Extra arguments for Metrics exporter, for example: - ## extraArgs: - ## check-keys: myKey,myOtherKey - # extraArgs: {} - - ## Metrics exporter pod Annotation and Labels - ## - podAnnotations: - prometheus.io/scrape: "true" - prometheus.io/port: "9121" - # podLabels: {} - - # Enable this if you're using https://github.com/coreos/prometheus-operator - serviceMonitor: - enabled: false - ## Specify a namespace if needed - # namespace: monitoring - # fallback to the prometheus default unless specified - # interval: 10s - ## Defaults to what's used if you follow CoreOS [Prometheus Install Instructions](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#tldr) - ## [Prometheus Selector Label](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#prometheus-operator-1) - ## [Kube Prometheus Selector Label](https://github.com/bitnami/charts/tree/master/bitnami/prometheus-operator#exporters) - ## - selector: - prometheus: kube-prometheus - - ## RelabelConfigs to apply to samples before scraping - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig - ## Value is evalued as a template - ## - relabelings: [] - - ## MetricRelabelConfigs to apply to samples before ingestion - ## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#relabelconfig - ## Value is evalued as a template - ## - metricRelabelings: [] - # - sourceLabels: - # - "__name__" - # targetLabel: "__name__" - # action: replace - # regex: '(.*)' - # replacement: 'example_prefix_$1' - - ## Custom PrometheusRule to be defined - ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart - ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions - ## - prometheusRule: - enabled: false - additionalLabels: {} - namespace: "" - ## Redis(TM) prometheus rules - ## These are just examples rules, please adapt them to your needs. - ## Make sure to constraint the rules to the current redis service. - # rules: - # - alert: RedisDown - # expr: redis_up{service="{{ template "redis.fullname" . }}-metrics"} == 0 - # for: 2m - # labels: - # severity: error - # annotations: - # summary: Redis(TM) instance {{ "{{ $labels.instance }}" }} down - # description: Redis(TM) instance {{ "{{ $labels.instance }}" }} is down - # - alert: RedisMemoryHigh - # expr: > - # redis_memory_used_bytes{service="{{ template "redis.fullname" . }}-metrics"} * 100 - # / - # redis_memory_max_bytes{service="{{ template "redis.fullname" . }}-metrics"} - # > 90 - # for: 2m - # labels: - # severity: error - # annotations: - # summary: Redis(TM) instance {{ "{{ $labels.instance }}" }} is using too much memory - # description: | - # Redis(TM) instance {{ "{{ $labels.instance }}" }} is using {{ "{{ $value }}" }}% of its available memory. - # - alert: RedisKeyEviction - # expr: | - # increase(redis_evicted_keys_total{service="{{ template "redis.fullname" . }}-metrics"}[5m]) > 0 - # for: 1s - # labels: - # severity: error - # annotations: - # summary: Redis(TM) instance {{ "{{ $labels.instance }}" }} has evicted keys - # description: | - # Redis(TM) instance {{ "{{ $labels.instance }}" }} has evicted {{ "{{ $value }}" }} keys in the last 5 minutes. - rules: [] - - ## Metrics exporter pod priorityClassName - priorityClassName: null - service: - type: ClusterIP - - ## External traffic policy (when service type is LoadBalancer) - ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip - ## - externalTrafficPolicy: Cluster - - ## Use serviceLoadBalancerIP to request a specific static IP, - ## otherwise leave blank - # loadBalancerIP: - annotations: {} - labels: {} - -## -## Init containers parameters: -## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup -## -volumePermissions: - enabled: false - image: - registry: docker.io - repository: bitnami/bitnami-shell - tag: "10" - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - resources: {} - # resources: - # requests: - # memory: 128Mi - # cpu: 100m - - ## Init container Security Context - ## Note: the chown of the data folder is done to containerSecurityContext.runAsUser - ## and not the below volumePermissions.securityContext.runAsUser - ## When runAsUser is set to special value "auto", init container will try to chwon the - ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` - ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). - ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with - ## podSecurityContext.enabled=false,containerSecurityContext.enabled=false - ## - securityContext: - runAsUser: 0 - -## Redis(TM) config file -## ref: https://redis.io/topics/config -## -configmap: |- - # Enable AOF https://redis.io/topics/persistence#append-only-file - appendonly yes - # Disable RDB persistence, AOF persistence already enabled. - save "" - -## Sysctl InitContainer -## used to perform sysctl operation to modify Kernel settings (needed sometimes to avoid warnings) -## -sysctlImage: - enabled: false - command: [] - registry: docker.io - repository: bitnami/bitnami-shell - tag: "10" - pullPolicy: Always - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistryKeySecretName - mountHostSys: false - resources: {} - # resources: - # requests: - # memory: 128Mi - # cpu: 100m - -## PodSecurityPolicy configuration -## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ -## -podSecurityPolicy: - ## Specifies whether a PodSecurityPolicy should be created - ## - create: false - -## Define a disruption budget -## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ -## -podDisruptionBudget: - enabled: false - minAvailable: 1 - # maxUnavailable: 1 diff --git a/scripts/helm/db/resource_overrides/redis.yaml b/scripts/helm/db/resource_overrides/redis.yaml deleted file mode 100644 index ce1b4d7e9..000000000 --- a/scripts/helm/db/resource_overrides/redis.yaml +++ /dev/null @@ -1,12 +0,0 @@ -fullnameOverride: redis -cluster: - enabled: false -redis: - resources: - requests: - memory: 256Mi - cpu: 100m - limits: - memory: 512Mi - cpu: 100m -usePassword: false diff --git a/scripts/helm/install.sh b/scripts/helm/install.sh deleted file mode 100755 index 2bf39988c..000000000 --- a/scripts/helm/install.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -set -o errtrace - -# Check for a valid domain_name -domain_name=`grep domain_name vars.yaml | grep -v "example" | cut -d " " -f2 | cut -d '"' -f2` -# Ref: https://stackoverflow.com/questions/15268987/bash-based-regex-domain-name-validation -[[ $(echo $domain_name | grep -P '(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)') ]] || { - echo "OpenReplay requires a valid domain name to properly work (i.e. openreplay.mycompany.com)" - echo "Please enter your domain name:" - read domain_name - [[ -z domain_name ]] && { - echo "OpenReplay won't work without domain name. Exiting..." - exit 1 - } || { - sed -i "s#domain_name.*#domain_name: \"${domain_name}\" #g" vars.yaml - } -} - -sudo apt update -which docker &> /dev/null || { - echo "docker is not installed. Installing it..." - user=`whoami` - sudo apt install docker.io -y - sudo usermod -aG docker $user -} - - -# https://api.openreplay.com/os/license -# payload: {"mid": "UUID of the machine", "license": ""} -# response {"data":{"valid": TRUE|FALSE, "expiration": expiration date in ms}} - -# Installing k3s -curl -sL https://get.k3s.io | sudo K3S_KUBECONFIG_MODE="644" INSTALL_K3S_VERSION='v1.19.5+k3s2' INSTALL_K3S_EXEC="--no-deploy=traefik" sh - -mkdir ~/.kube -sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config -sudo chown $(whoami) ~/.kube/config -export KUBECONFIG=~/.kube/config -sed -i "s#kubeconfig.*#kubeconfig_path: ${HOME}/.kube/config#g" vars.yaml - -# Installing nfs common for NFS -sudo apt install -y nfs-common - -bash -x kube-install.sh $@ diff --git a/scripts/helm/kube-install.sh b/scripts/helm/kube-install.sh deleted file mode 100755 index 056a45de4..000000000 --- a/scripts/helm/kube-install.sh +++ /dev/null @@ -1,199 +0,0 @@ -#!/bin/bash - -set -o errtrace - -# color schemes -# Ansi color code variables -red="\e[0;91m" -blue="\e[0;94m" -expand_bg="\e[K" -blue_bg="\e[0;104m${expand_bg}" -red_bg="\e[0;101m${expand_bg}" -green_bg="\e[0;102m${expand_bg}" -green="\e[0;92m" -white="\e[0;97m" -bold="\e[1m" -uline="\e[4m" -reset="\e[0m" - -working_dir=$(pwd) -script_name=`basename "$0"` - -echo -e ${reset} - -## installing kubectl -which kubectl &> /dev/null || { - echo "kubectl not installed. Installing it..." - sudo curl -SsL https://dl.k8s.io/release/v1.20.0/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl ; sudo chmod +x /usr/local/bin/kubectl -} - -## installing stern -which stern &> /dev/null || { - echo "stern not installed. installing..." - sudo curl -SsL https://github.com/derdanne/stern/releases/download/2.1.16/stern_linux_amd64 -o /usr/local/bin/stern ; sudo chmod +x /usr/local/bin/stern -} - -## installing k9s -which k9s &> /dev/null || { - echo "k9s not installed. Installing it..." - sudo curl -SsL https://github.com/derailed/k9s/releases/download/v0.24.2/k9s_Linux_x86_64.tar.gz -o /tmp/k9s.tar.gz - cd /tmp - tar -xf k9s.tar.gz - sudo mv k9s /usr/local/bin/k9s - sudo chmod +x /usr/local/bin/k9s - cd - -} - -which ansible &> /dev/null || { - echo "ansible not installed. Installing it..." - which pip || (sudo apt update && sudo apt install python3-pip -y) - sudo pip3 install ansible==2.10.0 -} - -## installing helm -which helm &> /dev/null -if [[ $? -ne 0 ]]; then - echo "helm not installed. Installing it..." - curl -ssl https://get.helm.sh/helm-v3.4.2-linux-amd64.tar.gz -o /tmp/helm.tar.gz - tar -xf /tmp/helm.tar.gz - chmod +x linux-amd64/helm - sudo cp linux-amd64/helm /usr/local/bin/helm - rm -rf linux-amd64/helm /tmp/helm.tar.gz -fi - -# ## checking kubernetes access -# kubectl cluster-info &> /dev/null -# if [[ $? -ne 0 ]]; then -# echo -e "${red}kubernetes cluster is not accessible.\nplease check ${bold}kubeconfig${reset}${red} env variable is set or ${bold}~/.kube/config exists.${reset}" -# exit 1 -# fi - -# make all stderr red -color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1 - -usage() { -echo -e ${bold}${yellow} ''' -This script will install and configure OpenReplay apps and databases on the kubernetes cluster, -which is accesd with the ${HOME}/.kube/config or $KUBECONFIG env variable. -''' -cat <<"EOF" - ___ ____ _ - / _ \ _ __ ___ _ __ | _ \ ___ _ __ | | __ _ _ _ -| | | | '_ \ / _ \ '_ \| |_) / _ \ '_ \| |/ _` | | | | -| |_| | |_) | __/ | | | _ < __/ |_) | | (_| | |_| | - \___/| .__/ \___|_| |_|_| \_\___| .__/|_|\__,_|\__, | - |_| |_| |___/ - -EOF - echo -e "${green}Usage: openreplay-cli [ -h | --help ] - [ -v | --verbose ] - [ -m | --monitoring <Only for enterprise edition> ] - [ -e | --enterprise <enerprise_key> ] - [ -a | --app APP_NAME ] to install/reinstall specific application - [ -t | --type small|medium|ideal ]" - echo -e "${reset}${blue}type defines the resource limits applied for the installation: - small: 2core 8G machine - medium: 4core 16G machine - ideal: 8core 32G machine - -apps can specifically be installed/reinstalled: - alerts assets chalice ender http integrations ios-proxy pg redis sink storage frontend postgresql redis clickhouse - ${reset}" - echo type value: $installation_type - exit 0 -} - -# Defaults to minimum installation -installation_type=1 -type() { - case "$1" in - small) installation_type=1 ;; - medium) installation_type=1.5 ;; - ideal) installation_type=2 ;; - *) - echo -e ${red}${bold}'ERROR!!!\nwrong value for `type`'${reset} - usage ;; - esac -} - -function app(){ - case $1 in - nginx) - # Resetting the redirection rule - sed -i 's/.* return 301 .*/ # return 301 https:\/\/$host$request_uri;/g' nginx-ingress/nginx-ingress/templates/configmap.yaml - [[ NGINX_REDIRECT_HTTPS -eq 1 ]] && { - sed -i "s/# return 301/return 301/g" nginx-ingress/nginx-ingress/templates/configmap.yaml - } - ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type --tags nginx -v - exit 0 - ;; - postgresql|redis|clickhouse) - ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type -e db_name=$1 --tags template --tags db -v - exit 0 - ;; - frontend) - ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type --tags frontend -v - exit 0 - ;; - *) - ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type -e app_name=$1 --tags app -v - exit 0 - ;; - esac -} - -enterprise=0 -function enterprise(){ - enterprise=1 - sed -i "s#enterprise_edition_license.*#enterprise_edition_license: \"${1}\"#g" vars.yaml - # Updating image version to be ee - sed 's/\(image_tag.*[0-9]\)\(-pr\)\?"$/\1\2-ee"/' vars.yaml - echo "Importing enterprise code..." - cp -rf ../../ee/scripts/* ../ -} -monitoring(){ - if [[ enterprise -eq 0 ]]; then - echo -e "${red}Monitoring is supported only for enterprise edition.\n bash ./${script_name} -e <key> --monitoring ${reset}" - exit 1 - fi - sed -i "s#enable_monitoring.*#enable_monitoring: \"true\"#g" vars.yaml -} - -# Parsing command line args. -PARSED_ARGUMENTS=$(color getopt -a -n openreplay-cli -o vht:a:e:m --long verbose,help,type:,app:,enterprise:,monitoring -- "$@") -VALID_ARGUMENTS=$? -if [[ "$VALID_ARGUMENTS" != "0" ]]; then - usage -fi - -eval set -- "$PARSED_ARGUMENTS" -while : -do - case "$1" in - -v | --verbose) VERBOSE=1 ; shift ;; - -h | --help) usage ; shift ;; - -t | --type) type $2 ; shift 2 ;; - -a | --app) app $2 ; shift 2 ;; - -e | --enterprise) enterprise $2 ; shift 2 ;; - -m | --monitoring) monitoring ; shift ;; - # -- means the end of the arguments; drop this, and break out of the while loop - --) shift; break ;; - # If invalid options were passed, then getopt should have reported an error, - # which we checked as VALID_ARGUMENTS when getopt was called... - *) echo "Unexpected option: $1 - this should not happen." - usage ;; - esac -done - -[[ $VERBOSE -eq 1 ]] && set -x - -{ - ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type --tags pre-check -v -} || exit $? -{ - ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type --skip-tags pre-check -v -} || exit $? - - - - diff --git a/scripts/helm/local_run.md b/scripts/helm/local_run.md deleted file mode 100644 index 3c2ed9751..000000000 --- a/scripts/helm/local_run.md +++ /dev/null @@ -1,56 +0,0 @@ -## How to build and run an application from local - -### For workers - -Workers are the application which handle core functionalities. - -- List of workers are - - alerts - - assets - - db - - ender - - http - - integrations - - sink - - storage - -- Build: - ``` - cd openreplay/backend - # IMAGE_TAG=<version of openreplay, check in vars.yaml> DOCKER_REPO=rg.fr-par.scw.cloud/foss bash build.sh <worker_name> - # For example, - IMAGE_TAG=v1.0.0 DOCKER_REPO=rg.fr-par.scw.cloud/foss bash build.sh assets - ``` -- Deploy: - ``` - cd openreplay/scripts/helm - bash openreplay-cli --install <worker_name> - ``` -## For api - -All apis are handled by application called, chalice, which is a python3 application. - -- Build: - ``` - cd openreplay/api/ - # IMAGE_TAG=<version of openreplay, check in vars.yaml> DOCKER_REPO=rg.fr-par.scw.cloud/foss bash build.sh - # For example, - IMAGE_TAG=v1.0.0 DOCKER_REPO=rg.fr-par.scw.cloud/foss bash build.sh - ``` -- Deploy: - ``` - cd openreplay/scripts/helm - bash openreplay-cli --install chalice - ``` - -## For frontend - -Frontend is mainly JS components. When we're installing it, it's built and then installed. So you don't have to run a separate build for frontend. - -Note: if you want to see how it gets build, please refer, `openreplay/frontend/build.sh` - -- Build and Deploy: - ``` - cd openreplay/scripts/helm - bash openreplay-cli --install frontend - ``` diff --git a/scripts/helm/longhorn/README.md b/scripts/helm/longhorn/README.md deleted file mode 100644 index 43799453d..000000000 --- a/scripts/helm/longhorn/README.md +++ /dev/null @@ -1 +0,0 @@ -helm install longhorn ./ --namespace longhorn-system --create-namespace diff --git a/scripts/helm/longhorn/longhorn/.helmignore b/scripts/helm/longhorn/longhorn/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/scripts/helm/longhorn/longhorn/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/scripts/helm/longhorn/longhorn/Chart.yaml b/scripts/helm/longhorn/longhorn/Chart.yaml deleted file mode 100644 index ce617fecd..000000000 --- a/scripts/helm/longhorn/longhorn/Chart.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: v1 -name: longhorn -version: 1.0.2 -appVersion: v1.0.2 -kubeVersion: ">=v1.14.0-r0" -description: Longhorn is a distributed block storage system for Kubernetes. -keywords: -- longhorn -- storage -- distributed -- block -- device -- iscsi -home: https://github.com/longhorn/longhorn -sources: -- https://github.com/longhorn/longhorn -- https://github.com/longhorn/longhorn-engine -- https://github.com/longhorn/longhorn-instance-manager -- https://github.com/longhorn/longhorn-manager -- https://github.com/longhorn/longhorn-ui -- https://github.com/longhorn/longhorn-tests -maintainers: -- name: Longhorn maintainers - email: maintainers@longhorn.io -- name: Sheng Yang - email: sheng@yasker.org -icon: https://raw.githubusercontent.com/cncf/artwork/master/projects/longhorn/icon/color/longhorn-icon-color.svg?sanitize=true diff --git a/scripts/helm/longhorn/longhorn/README.md b/scripts/helm/longhorn/longhorn/README.md deleted file mode 100644 index 13e6312e8..000000000 --- a/scripts/helm/longhorn/longhorn/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Longhorn Chart - -> **Important**: Please install the Longhorn chart in the `longhorn-system` namespace only. - -> **Warning**: Longhorn doesn't support downgrading from a higher version to a lower version. - -## Source Code - -Longhorn is 100% open source software. Project source code is spread across a number of repos: - -1. Longhorn Engine -- Core controller/replica logic https://github.com/longhorn/longhorn-engine -2. Longhorn Instance Manager -- Controller/replica instance lifecycle management https://github.com/longhorn/longhorn-instance-manager -3. Longhorn Manager -- Longhorn orchestration, includes CSI driver for Kubernetes https://github.com/longhorn/longhorn-manager -4. Longhorn UI -- Dashboard https://github.com/longhorn/longhorn-ui - -## Prerequisites - -1. Docker v1.13+ -2. Kubernetes v1.15+ -3. Make sure `curl`, `findmnt`, `grep`, `awk` and `blkid` has been installed in all nodes of the Kubernetes cluster. -4. Make sure `open-iscsi` has been installed in all nodes of the Kubernetes cluster. For GKE, recommended Ubuntu as guest OS image since it contains `open-iscsi` already. - -## Installation -1. Add Longhorn chart repository. -``` -helm repo add longhorn https://charts.longhorn.io -``` - -2. Update local Longhorn chart information from chart repository. -``` -helm repo update -``` - -3. Install Longhorn chart. -- With Helm 2, the following command will create the `longhorn-system` namespace and install the Longhorn chart together. -``` -helm install longhorn/longhorn --name longhorn --namespace longhorn-system -``` -- With Helm 3, the following commands will create the `longhorn-system` namespace first, then install the Longhorn chart. - -``` -kubectl create namespace longhorn-system -helm install longhorn longhorn/longhorn --namespace longhorn-system -``` - -## Uninstallation - -With Helm 2 to uninstall Longhorn. -``` -helm delete longhorn --purge -``` - -With Helm 3 to uninstall Longhorn. -``` -helm uninstall longhorn -n longhorn-system -kubectl delete namespace longhorn-system -``` - ---- -Please see [link](https://github.com/longhorn/longhorn) for more information. diff --git a/scripts/helm/longhorn/longhorn/app-readme.md b/scripts/helm/longhorn/longhorn/app-readme.md deleted file mode 100644 index cb23135ca..000000000 --- a/scripts/helm/longhorn/longhorn/app-readme.md +++ /dev/null @@ -1,11 +0,0 @@ -# Longhorn - -Longhorn is a lightweight, reliable and easy to use distributed block storage system for Kubernetes. Once deployed, users can leverage persistent volumes provided by Longhorn. - -Longhorn creates a dedicated storage controller for each volume and synchronously replicates the volume across multiple replicas stored on multiple nodes. The storage controller and replicas are themselves orchestrated using Kubernetes. Longhorn supports snapshots, backups and even allows you to schedule recurring snapshots and backups! - -**Important**: Please install Longhorn chart in `longhorn-system` namespace only. - -**Warning**: Longhorn doesn't support downgrading from a higher version to a lower version. - -[Chart Documentation](https://github.com/longhorn/longhorn/blob/master/chart/README.md) diff --git a/scripts/helm/longhorn/longhorn/questions.yml b/scripts/helm/longhorn/longhorn/questions.yml deleted file mode 100644 index cf95ba54e..000000000 --- a/scripts/helm/longhorn/longhorn/questions.yml +++ /dev/null @@ -1,375 +0,0 @@ -categories: -- storage -namespace: longhorn-system -questions: -- variable: image.defaultImage - default: "true" - description: "Use default Longhorn images" - label: Use Default Images - type: boolean - show_subquestion_if: false - group: "Longhorn Images" - subquestions: - - variable: image.longhorn.manager.repository - default: longhornio/longhorn-manager - description: "Specify Longhorn Manager Image Repository" - type: string - label: Longhorn Manager Image Repository - group: "Longhorn Images Settings" - - variable: image.longhorn.manager.tag - default: v1.0.2 - description: "Specify Longhorn Manager Image Tag" - type: string - label: Longhorn Manager Image Tag - group: "Longhorn Images Settings" - - variable: image.longhorn.engine.repository - default: longhornio/longhorn-engine - description: "Specify Longhorn Engine Image Repository" - type: string - label: Longhorn Engine Image Repository - group: "Longhorn Images Settings" - - variable: image.longhorn.engine.tag - default: v1.0.2 - description: "Specify Longhorn Engine Image Tag" - type: string - label: Longhorn Engine Image Tag - group: "Longhorn Images Settings" - - variable: image.longhorn.ui.repository - default: longhornio/longhorn-ui - description: "Specify Longhorn UI Image Repository" - type: string - label: Longhorn UI Image Repository - group: "Longhorn Images Settings" - - variable: image.longhorn.ui.tag - default: v1.0.2 - description: "Specify Longhorn UI Image Tag" - type: string - label: Longhorn UI Image Tag - group: "Longhorn Images Settings" - - variable: image.longhorn.instanceManager.repository - default: longhornio/longhorn-instance-manager - description: "Specify Longhorn Instance Manager Image Repository" - type: string - label: Longhorn Instance Manager Image Repository - group: "Longhorn Images Settings" - - variable: image.longhorn.instanceManager.tag - default: v1_20200514 - description: "Specify Longhorn Instance Manager Image Tag" - type: string - label: Longhorn Instance Manager Image Tag - group: "Longhorn Images Settings" - - variable: image.csi.attacher.repository - default: longhornio/csi-attacher - description: "Specify CSI attacher image repository. Leave blank to autodetect." - type: string - label: Longhorn CSI Attacher Image Repository - group: "Longhorn CSI Driver Images" - - variable: image.csi.attacher.tag - default: v2.0.0 - description: "Specify CSI attacher image tag. Leave blank to autodetect." - type: string - label: Longhorn CSI Attacher Image Tag - group: "Longhorn CSI Driver Images" - - variable: image.csi.provisioner.repository - default: longhornio/csi-provisioner - description: "Specify CSI provisioner image repository. Leave blank to autodetect." - type: string - label: Longhorn CSI Provisioner Image Repository - group: "Longhorn CSI Driver Images" - - variable: image.csi.provisioner.tag - default: v1.4.0 - description: "Specify CSI provisioner image tag. Leave blank to autodetect." - type: string - label: Longhorn CSI Provisioner Image Tag - group: "Longhorn CSI Driver Images" - - variable: image.csi.nodeDriverRegistrar.repository - default: longhornio/csi-node-driver-registrar - description: "Specify CSI Node Driver Registrar image repository. Leave blank to autodetect." - type: string - label: Longhorn CSI Node Driver Registrar Image Repository - group: "Longhorn CSI Driver Images" - - variable: image.csi.nodeDriverRegistrar.tag - default: v1.2.0 - description: "Specify CSI Node Driver Registrar image tag. Leave blank to autodetect." - type: string - label: Longhorn CSI Node Driver Registrar Image Tag - group: "Longhorn CSI Driver Images" - - variable: image.csi.resizer.repository - default: longhornio/csi-resizer - description: "Specify CSI Driver Resizer image repository. Leave blank to autodetect." - type: string - label: Longhorn CSI Driver Resizer Image Repository - group: "Longhorn CSI Driver Images" - - variable: image.csi.resizer.tag - default: v0.3.0 - description: "Specify CSI Driver Resizer image tag. Leave blank to autodetect." - type: string - label: Longhorn CSI Driver Resizer Image Tag - group: "Longhorn CSI Driver Images" - - variable: image.csi.snapshotter.tag - default: v2.1.1 - description: "Specify CSI Driver Snapshotter image tag. Leave blank to autodetect." - type: string - label: Longhorn CSI Driver Snapshotter Image Tag - group: "Longhorn CSI Driver Images" -- variable: privateRegistry.registryUrl - label: Private registry URL - description: "URL of private registry. Leave blank to apply system default registry." - group: "Private Registry Settings" - type: string - default: "" -- variable: privateRegistry.registryUser - label: Private registry user - description: "User used to authenticate to private registry" - group: "Private Registry Settings" - type: string - default: "" -- variable: privateRegistry.registryPasswd - label: Private registry password - description: "Password used to authenticate to private registry" - group: "Private Registry Settings" - type: password - default: "" -- variable: longhorn.default_setting - default: "false" - description: "Customize the default settings before installing Longhorn for the first time. This option will only work if the cluster hasn't installed Longhorn." - label: "Customize Default Settings" - type: boolean - show_subquestion_if: true - group: "Longhorn Default Settings" - subquestions: - - variable: defaultSettings.registrySecret - label: Private registry secret - description: "The Kubernetes Secret name" - group: "Longhorn Default Settings" - type: string - default: "" - - variable: csi.kubeletRootDir - default: - description: "Specify kubelet root-dir. Leave blank to autodetect." - type: string - label: Kubelet Root Directory - group: "Longhorn CSI Driver Settings" - - variable: csi.attacherReplicaCount - type: int - default: - min: 1 - max: 10 - description: "Specify replica count of CSI Attacher. By default 3." - label: Longhorn CSI Attacher replica count - group: "Longhorn CSI Driver Settings" - - variable: csi.provisionerReplicaCount - type: int - default: - min: 1 - max: 10 - description: "Specify replica count of CSI Provisioner. By default 3." - label: Longhorn CSI Provisioner replica count - group: "Longhorn CSI Driver Settings" - - variable: csi.resizerReplicaCount - type: int - default: - min: 1 - max: 10 - description: "Specify replica count of CSI Resizer. By default 3." - label: Longhorn CSI Resizer replica count - group: "Longhorn CSI Driver Settings" - - variable: csi.snapshotterReplicaCount - type: int - default: - min: 1 - max: 10 - description: "Specify replica count of CSI Snapshotter. By default 3." - label: Longhorn CSI Snapshotter replica count - group: "Longhorn CSI Driver Settings" - - variable: persistence.defaultClass - default: "true" - description: "Set as default StorageClass" - group: "Longhorn CSI Driver Settings" - type: boolean - required: true - label: Default Storage Class - - variable: persistence.reclaimPolicy - default: "Delete" - description: "Define reclaim policy (Retain or Delete)" - group: "Longhorn CSI Driver Settings" - type: string - required: true - label: Storage Class Retain Policy - - variable: persistence.defaultClassReplicaCount - description: "Set replica count for default StorageClass" - group: "Longhorn CSI Driver Settings" - type: int - default: 3 - min: 1 - max: 10 - label: Default Storage Class Replica Count - - variable: defaultSettings.backupTarget - label: Backup Target - description: "The endpoint used to access the backupstore. NFS and S3 are supported." - group: "Longhorn Default Settings" - type: string - default: - - variable: defaultSettings.backupTargetCredentialSecret - label: Backup Target Credential Secret - description: "The name of the Kubernetes secret associated with the backup target." - group: "Longhorn Default Settings" - type: string - default: - - variable: defaultSettings.createDefaultDiskLabeledNodes - label: Create Default Disk on Labeled Nodes - description: 'Create default Disk automatically only on Nodes with the label "node.longhorn.io/create-default-disk=true" if no other disks exist. If disabled, the default disk will be created on all new nodes when each node is first added.' - group: "Longhorn Default Settings" - type: boolean - default: "false" - - variable: defaultSettings.defaultDataPath - label: Default Data Path - description: 'Default path to use for storing data on a host. By default "/var/lib/longhorn/"' - group: "Longhorn Default Settings" - type: string - default: "/var/lib/longhorn/" - - variable: defaultSettings.replicaSoftAntiAffinity - label: Replica Node Level Soft Anti-Affinity - description: 'Allow scheduling on nodes with existing healthy replicas of the same volume. By default false.' - group: "Longhorn Default Settings" - type: boolean - default: "false" - - variable: defaultSettings.storageOverProvisioningPercentage - label: Storage Over Provisioning Percentage - description: "The over-provisioning percentage defines how much storage can be allocated relative to the hard drive's capacity. By default 200." - group: "Longhorn Default Settings" - type: int - min: 0 - default: 200 - - variable: defaultSettings.storageMinimalAvailablePercentage - label: Storage Minimal Available Percentage - description: "If the minimum available disk capacity exceeds the actual percentage of available disk capacity, the disk becomes unschedulable until more space is freed up. By default 25." - group: "Longhorn Default Settings" - type: int - min: 0 - max: 100 - default: 25 - - variable: defaultSettings.upgradeChecker - label: Enable Upgrade Checker - description: 'Upgrade Checker will check for new Longhorn version periodically. When there is a new version available, a notification will appear in the UI. By default true.' - group: "Longhorn Default Settings" - type: boolean - default: "true" - - variable: defaultSettings.defaultReplicaCount - label: Default Replica Count - description: "The default number of replicas when a volume is created from the Longhorn UI. For Kubernetes configuration, update the `numberOfReplicas` in the StorageClass. By default 3." - group: "Longhorn Default Settings" - type: int - min: 1 - max: 20 - default: 3 - - variable: defaultSettings.guaranteedEngineCPU - label: Guaranteed Engine CPU - description: 'Allow Longhorn Instance Managers to have guaranteed CPU allocation. The value is how many CPUs should be reserved for each Engine/Replica Instance Manager Pod created by Longhorn. For example, 0.1 means one-tenth of a CPU. This will help maintain engine stability during high node workload. It only applies to the Engine/Replica Manager Pods created after the setting took effect. -WARNING: After this setting is changed, all the instance managers on all the nodes will be automatically restarted. -WARNING: DO NOT CHANGE THIS SETTING WITH ATTACHED VOLUMES. -By default 0.25.' - group: "Longhorn Default Settings" - type: float - default: 0.25 - - variable: defaultSettings.defaultLonghornStaticStorageClass - label: Default Longhorn Static StorageClass Name - description: "The 'storageClassName' is given to PVs and PVCs that are created for an existing Longhorn volume. The StorageClass name can also be used as a label, so it is possible to use a Longhorn StorageClass to bind a workload to an existing PV without creating a Kubernetes StorageClass object. By default 'longhorn-static'." - group: "Longhorn Default Settings" - type: string - default: "longhorn-static" - - variable: defaultSettings.backupstorePollInterval - label: Backupstore Poll Interval - description: "In seconds. The backupstore poll interval determines how often Longhorn checks the backupstore for new backups. Set to 0 to disable the polling. By default 300." - group: "Longhorn Default Settings" - type: int - min: 0 - default: 300 - - variable: defaultSettings.taintToleration - label: Kubernetes Taint Toleration - description: 'To dedicate nodes to store Longhorn replicas and reject other general workloads, set tolerations for Longhorn and add taints for the storage nodes. All Longhorn volumes should be detached before modifying toleration settings. We recommend setting tolerations during Longhorn deployment because the Longhorn system cannot be operated during the update. Multiple tolerations can be set here, and these tolerations are separated by semicolon. For example, `key1=value1:NoSchedule; key2:NoExecute`. Because `kubernetes.io` is used as the key of all Kubernetes default tolerations, it should not be used in the toleration settings. -WARNING: DO NOT CHANGE THIS SETTING WITH ATTACHED VOLUMES.' - group: "Longhorn Default Settings" - type: string - default: "" - - variable: defaultSettings.priorityClass - label: Priority Class - description: "The name of the Priority Class to set on the Longhorn workloads. This can help prevent Longhorn workloads from being evicted under Node Pressure. WARNING: DO NOT CHANGE THIS SETTING WITH ATTACHED VOLUMES." - group: "Longhorn Default Settings" - type: string - default: "" - - variable: defaultSettings.autoSalvage - label: Automatic salvage - description: "If enabled, volumes will be automatically salvaged when all the replicas become faulty e.g. due to network disconnection. Longhorn will try to figure out which replica(s) are usable, then use them for the volume. By default true." - group: "Longhorn Default Settings" - type: boolean - default: "true" - - variable: defaultSettings.disableSchedulingOnCordonedNode - label: Disable Scheduling On Cordoned Node - description: "Disable Longhorn manager to schedule replica on Kubernetes cordoned node. By default true." - group: "Longhorn Default Settings" - type: boolean - default: "true" - - variable: defaultSettings.replicaZoneSoftAntiAffinity - label: Replica Zone Level Soft Anti-Affinity - description: "Allow scheduling new Replicas of Volume to the Nodes in the same Zone as existing healthy Replicas. Nodes don't belong to any Zone will be treated as in the same Zone. By default true." - group: "Longhorn Default Settings" - type: boolean - default: "true" - - variable: defaultSettings.volumeAttachmentRecoveryPolicy - label: Volume Attachment Recovery Policy - description: "Defines the Longhorn action when a Volume is stuck with a Deployment Pod on a failed node. `wait` leads to the deletion of the volume attachment as soon as the pods deletion time has passed. `never` is the default Kubernetes behavior of never deleting volume attachments on terminating pods. `immediate` leads to the deletion of the volume attachment as soon as all workload pods are pending. By default wait." - group: "Longhorn Default Settings" - type: enum - options: - - "wait" - - "never" - - "immediate" - default: "wait" - - variable: defaultSettings.mkfsExt4Parameters - label: Custom mkfs.ext4 parameters - description: "Allows setting additional filesystem creation parameters for ext4. For older host kernels it might be necessary to disable the optional ext4 metadata_csum feature by specifying `-O ^64bit,^metadata_csum`." - group: "Longhorn Default Settings" - type: string -- variable: ingress.enabled - default: "false" - description: "Expose app using Layer 7 Load Balancer - ingress" - type: boolean - group: "Services and Load Balancing" - label: Expose app using Layer 7 Load Balancer - show_subquestion_if: true - subquestions: - - variable: ingress.host - default: "xip.io" - description: "layer 7 Load Balancer hostname" - type: hostname - required: true - label: Layer 7 Load Balancer Hostname -- variable: service.ui.type - default: "Rancher-Proxy" - description: "Define Longhorn UI service type" - type: enum - options: - - "ClusterIP" - - "NodePort" - - "LoadBalancer" - - "Rancher-Proxy" - label: Longhorn UI Service - show_if: "ingress.enabled=false" - group: "Services and Load Balancing" - show_subquestion_if: "NodePort" - subquestions: - - variable: service.ui.nodePort - default: "" - description: "NodePort port number(to set explicitly, choose port between 30000-32767)" - type: int - min: 30000 - max: 32767 - show_if: "service.ui.type=NodePort||service.ui.type=LoadBalancer" - label: UI Service NodePort number -- variable: enablePSP - default: "true" - description: "Setup a pod security policy for Longhorn workloads." - label: Pod Security Policy - type: boolean - group: "Other Settings" \ No newline at end of file diff --git a/scripts/helm/longhorn/longhorn/templates/NOTES.txt b/scripts/helm/longhorn/longhorn/templates/NOTES.txt deleted file mode 100644 index cca7cd77b..000000000 --- a/scripts/helm/longhorn/longhorn/templates/NOTES.txt +++ /dev/null @@ -1,5 +0,0 @@ -Longhorn is now installed on the cluster! - -Please wait a few minutes for other Longhorn components such as CSI deployments, Engine Images, and Instance Managers to be initialized. - -Visit our documentation at https://longhorn.io/docs/ diff --git a/scripts/helm/longhorn/longhorn/templates/_helpers.tpl b/scripts/helm/longhorn/longhorn/templates/_helpers.tpl deleted file mode 100644 index 9c6c892ba..000000000 --- a/scripts/helm/longhorn/longhorn/templates/_helpers.tpl +++ /dev/null @@ -1,55 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "longhorn.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "longhorn.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - - -{{- define "longhorn.managerIP" -}} -{{- $fullname := (include "longhorn.fullname" .) -}} -{{- printf "http://%s-backend:9500" $fullname | trunc 63 | trimSuffix "-" -}} -{{- end -}} - - -{{- define "secret" }} -{{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\"}}}" .Values.privateRegistry.registryUrl (printf "%s:%s" .Values.privateRegistry.registryUser .Values.privateRegistry.registryPasswd | b64enc) | b64enc }} -{{- end }} - -{{- /* -longhorn.labels generates the standard Helm labels. -*/ -}} -{{- define "longhorn.labels" -}} -app.kubernetes.io/name: {{ template "longhorn.name" . }} -helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -app.kubernetes.io/instance: {{ .Release.Name }} -app.kubernetes.io/version: {{ .Chart.AppVersion }} -{{- end -}} - - -{{- define "system_default_registry" -}} -{{- if .Values.global.cattle.systemDefaultRegistry -}} -{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} -{{- else -}} -{{- "" -}} -{{- end -}} -{{- end -}} - -{{- define "registry_url" -}} -{{- if .Values.privateRegistry.registryUrl -}} -{{- printf "%s/" .Values.privateRegistry.registryUrl -}} -{{- else -}} -{{ include "system_default_registry" . }} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/longhorn/longhorn/templates/clusterrole.yaml b/scripts/helm/longhorn/longhorn/templates/clusterrole.yaml deleted file mode 100644 index 34a46d9f2..000000000 --- a/scripts/helm/longhorn/longhorn/templates/clusterrole.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: longhorn-role - labels: {{- include "longhorn.labels" . | nindent 4 }} -rules: -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - "*" -- apiGroups: [""] - resources: ["pods", "events", "persistentvolumes", "persistentvolumeclaims","persistentvolumeclaims/status", "nodes", "proxy/nodes", "pods/log", "secrets", "services", "endpoints", "configmaps"] - verbs: ["*"] -- apiGroups: [""] - resources: ["namespaces"] - verbs: ["get", "list"] -- apiGroups: ["apps"] - resources: ["daemonsets", "statefulsets", "deployments"] - verbs: ["*"] -- apiGroups: ["batch"] - resources: ["jobs", "cronjobs"] - verbs: ["*"] -- apiGroups: ["scheduling.k8s.io"] - resources: ["priorityclasses"] - verbs: ["watch", "list"] -- apiGroups: ["storage.k8s.io"] - resources: ["storageclasses", "volumeattachments", "csinodes", "csidrivers"] - verbs: ["*"] -- apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["*"] -- apiGroups: ["longhorn.io"] - resources: ["volumes", "volumes/status", "engines", "engines/status", "replicas", "replicas/status", "settings", - "engineimages", "engineimages/status", "nodes", "nodes/status", "instancemanagers", "instancemanagers/status"] - verbs: ["*"] diff --git a/scripts/helm/longhorn/longhorn/templates/clusterrolebinding.yaml b/scripts/helm/longhorn/longhorn/templates/clusterrolebinding.yaml deleted file mode 100644 index 30c7fa78c..000000000 --- a/scripts/helm/longhorn/longhorn/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: longhorn-bind - labels: {{- include "longhorn.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: longhorn-role -subjects: -- kind: ServiceAccount - name: longhorn-service-account - namespace: {{ .Release.Namespace }} diff --git a/scripts/helm/longhorn/longhorn/templates/crds.yaml b/scripts/helm/longhorn/longhorn/templates/crds.yaml deleted file mode 100644 index 61544aa52..000000000 --- a/scripts/helm/longhorn/longhorn/templates/crds.yaml +++ /dev/null @@ -1,151 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - longhorn-manager: Engine - annotations: - helm.sh/resource-policy: keep - name: engines.longhorn.io -spec: - group: longhorn.io - names: - kind: Engine - listKind: EngineList - plural: engines - shortNames: - - lhe - singular: engine - scope: Namespaced - version: v1beta1 - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - longhorn-manager: Replica - annotations: - helm.sh/resource-policy: keep - name: replicas.longhorn.io -spec: - group: longhorn.io - names: - kind: Replica - listKind: ReplicaList - plural: replicas - shortNames: - - lhr - singular: replica - scope: Namespaced - version: v1beta1 - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - longhorn-manager: Setting - annotations: - helm.sh/resource-policy: keep - name: settings.longhorn.io -spec: - group: longhorn.io - names: - kind: Setting - listKind: SettingList - plural: settings - shortNames: - - lhs - singular: setting - scope: Namespaced - version: v1beta1 ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - longhorn-manager: Volume - annotations: - helm.sh/resource-policy: keep - name: volumes.longhorn.io -spec: - group: longhorn.io - names: - kind: Volume - listKind: VolumeList - plural: volumes - shortNames: - - lhv - singular: volume - scope: Namespaced - version: v1beta1 - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - longhorn-manager: EngineImage - annotations: - helm.sh/resource-policy: keep - name: engineimages.longhorn.io -spec: - group: longhorn.io - names: - kind: EngineImage - listKind: EngineImageList - plural: engineimages - shortNames: - - lhei - singular: engineimage - scope: Namespaced - version: v1beta1 - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - longhorn-manager: Node - annotations: - helm.sh/resource-policy: keep - name: nodes.longhorn.io -spec: - group: longhorn.io - names: - kind: Node - listKind: NodeList - plural: nodes - shortNames: - - lhn - singular: node - scope: Namespaced - version: v1beta1 - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - longhorn-manager: InstanceManager - annotations: - helm.sh/resource-policy: keep - name: instancemanagers.longhorn.io -spec: - group: longhorn.io - names: - kind: InstanceManager - listKind: InstanceManagerList - plural: instancemanagers - shortNames: - - lhim - singular: instancemanager - scope: Namespaced - version: v1beta1 - subresources: - status: {} diff --git a/scripts/helm/longhorn/longhorn/templates/daemonset-sa.yaml b/scripts/helm/longhorn/longhorn/templates/daemonset-sa.yaml deleted file mode 100644 index 1870aa0fb..000000000 --- a/scripts/helm/longhorn/longhorn/templates/daemonset-sa.yaml +++ /dev/null @@ -1,112 +0,0 @@ -apiVersion: apps/v1 -kind: DaemonSet -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - app: longhorn-manager - name: longhorn-manager - namespace: {{ .Release.Namespace }} -spec: - selector: - matchLabels: - app: longhorn-manager - template: - metadata: - labels: {{- include "longhorn.labels" . | nindent 8 }} - app: longhorn-manager - spec: - containers: - - name: longhorn-manager - image: {{ template "registry_url" . }}{{ .Values.image.longhorn.manager.repository }}:{{ .Values.image.longhorn.manager.tag }} - imagePullPolicy: IfNotPresent - securityContext: - privileged: true - command: - - longhorn-manager - - -d - - daemon - - --engine-image - - "{{ template "registry_url" . }}{{ .Values.image.longhorn.engine.repository }}:{{ .Values.image.longhorn.engine.tag }}" - - --instance-manager-image - - "{{ template "registry_url" . }}{{ .Values.image.longhorn.instanceManager.repository }}:{{ .Values.image.longhorn.instanceManager.tag }}" - - --manager-image - - "{{ template "registry_url" . }}{{ .Values.image.longhorn.manager.repository }}:{{ .Values.image.longhorn.manager.tag }}" - - --service-account - - longhorn-service-account - ports: - - containerPort: 9500 - name: manager - readinessProbe: - tcpSocket: - port: 9500 - volumeMounts: - - name: dev - mountPath: /host/dev/ - - name: proc - mountPath: /host/proc/ - - name: varrun - mountPath: /var/run/ - mountPropagation: Bidirectional - - name: longhorn - mountPath: /var/lib/longhorn/ - mountPropagation: Bidirectional - - name: longhorn-default-setting - mountPath: /var/lib/longhorn-setting/ - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - - name: DEFAULT_SETTING_PATH - value: /var/lib/longhorn-setting/default-setting.yaml - volumes: - - name: dev - hostPath: - path: /dev/ - - name: proc - hostPath: - path: /proc/ - - name: varrun - hostPath: - path: /var/run/ - - name: longhorn - hostPath: - path: /var/lib/longhorn/ - - name: longhorn-default-setting - configMap: - name: longhorn-default-setting - {{- if .Values.defaultSettings.registrySecret }} - imagePullSecrets: - - name: {{ .Values.defaultSettings.registrySecret }} - {{- end }} - serviceAccountName: longhorn-service-account - updateStrategy: - rollingUpdate: - maxUnavailable: "100%" ---- -apiVersion: v1 -kind: Service -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - app: longhorn-manager - name: longhorn-backend - namespace: {{ .Release.Namespace }} -spec: - type: {{ .Values.service.manager.type }} - sessionAffinity: ClientIP - selector: - app: longhorn-manager - ports: - - name: manager - port: 9500 - targetPort: manager - {{- if .Values.service.manager.nodePort }} - nodePort: {{ .Values.service.manager.nodePort }} - {{- end }} diff --git a/scripts/helm/longhorn/longhorn/templates/default-setting.yaml b/scripts/helm/longhorn/longhorn/templates/default-setting.yaml deleted file mode 100644 index 2eb10b4dc..000000000 --- a/scripts/helm/longhorn/longhorn/templates/default-setting.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: longhorn-default-setting - namespace: {{ .Release.Namespace }} - labels: {{- include "longhorn.labels" . | nindent 4 }} -data: - default-setting.yaml: |- - backup-target: {{ .Values.defaultSettings.backupTarget }} - backup-target-credential-secret: {{ .Values.defaultSettings.backupTargetCredentialSecret }} - create-default-disk-labeled-nodes: {{ .Values.defaultSettings.createDefaultDiskLabeledNodes }} - default-data-path: {{ .Values.defaultSettings.defaultDataPath }} - replica-soft-anti-affinity: {{ .Values.defaultSettings.replicaSoftAntiAffinity }} - storage-over-provisioning-percentage: {{ .Values.defaultSettings.storageOverProvisioningPercentage }} - storage-minimal-available-percentage: {{ .Values.defaultSettings.storageMinimalAvailablePercentage }} - upgrade-checker: {{ .Values.defaultSettings.upgradeChecker }} - default-replica-count: {{ .Values.defaultSettings.defaultReplicaCount }} - guaranteed-engine-cpu: {{ .Values.defaultSettings.guaranteedEngineCPU }} - default-longhorn-static-storage-class: {{ .Values.defaultSettings.defaultLonghornStaticStorageClass }} - backupstore-poll-interval: {{ .Values.defaultSettings.backupstorePollInterval }} - taint-toleration: {{ .Values.defaultSettings.taintToleration }} - priority-class: {{ .Values.defaultSettings.priorityClass }} - registry-secret: {{ .Values.defaultSettings.registrySecret }} - auto-salvage: {{ .Values.defaultSettings.autoSalvage }} - disable-scheduling-on-cordoned-node: {{ .Values.defaultSettings.disableSchedulingOnCordonedNode }} - replica-zone-soft-anti-affinity: {{ .Values.defaultSettings.replicaZoneSoftAntiAffinity }} - volume-attachment-recovery-policy: {{ .Values.defaultSettings.volumeAttachmentRecoveryPolicy }} - mkfs-ext4-parameters: {{ .Values.defaultSettings.mkfsExt4Parameters }} diff --git a/scripts/helm/longhorn/longhorn/templates/deployment-driver.yaml b/scripts/helm/longhorn/longhorn/templates/deployment-driver.yaml deleted file mode 100644 index ec3a867c8..000000000 --- a/scripts/helm/longhorn/longhorn/templates/deployment-driver.yaml +++ /dev/null @@ -1,93 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: longhorn-driver-deployer - namespace: {{ .Release.Namespace }} - labels: {{- include "longhorn.labels" . | nindent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - app: longhorn-driver-deployer - template: - metadata: - labels: {{- include "longhorn.labels" . | nindent 8 }} - app: longhorn-driver-deployer - spec: - initContainers: - - name: wait-longhorn-manager - image: {{ template "registry_url" . }}{{ .Values.image.longhorn.manager.repository }}:{{ .Values.image.longhorn.manager.tag }} - command: ['sh', '-c', 'while [ $(curl -m 1 -s -o /dev/null -w "%{http_code}" http://longhorn-backend:9500/v1) != "200" ]; do echo waiting; sleep 2; done'] - containers: - - name: longhorn-driver-deployer - image: {{ template "registry_url" . }}{{ .Values.image.longhorn.manager.repository }}:{{ .Values.image.longhorn.manager.tag }} - imagePullPolicy: IfNotPresent - command: - - longhorn-manager - - -d - - deploy-driver - - --manager-image - - "{{ template "registry_url" . }}{{ .Values.image.longhorn.manager.repository }}:{{ .Values.image.longhorn.manager.tag }}" - - --manager-url - - http://longhorn-backend:9500/v1 - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - {{- if .Values.csi.kubeletRootDir }} - - name: KUBELET_ROOT_DIR - value: {{ .Values.csi.kubeletRootDir }} - {{- end }} - {{- if and .Values.image.csi.attacher.repository .Values.image.csi.attacher.tag }} - - name: CSI_ATTACHER_IMAGE - value: "{{ template "registry_url" . }}{{ .Values.image.csi.attacher.repository }}:{{ .Values.image.csi.attacher.tag }}" - {{- end }} - {{- if and .Values.image.csi.provisioner.repository .Values.image.csi.provisioner.tag }} - - name: CSI_PROVISIONER_IMAGE - value: "{{ template "registry_url" . }}{{ .Values.image.csi.provisioner.repository }}:{{ .Values.image.csi.provisioner.tag }}" - {{- end }} - {{- if and .Values.image.csi.nodeDriverRegistrar.repository .Values.image.csi.nodeDriverRegistrar.tag }} - - name: CSI_NODE_DRIVER_REGISTRAR_IMAGE - value: "{{ template "registry_url" . }}{{ .Values.image.csi.nodeDriverRegistrar.repository }}:{{ .Values.image.csi.nodeDriverRegistrar.tag }}" - {{- end }} - {{- if and .Values.image.csi.resizer.repository .Values.image.csi.resizer.tag }} - - name: CSI_RESIZER_IMAGE - value: "{{ template "registry_url" . }}{{ .Values.image.csi.resizer.repository }}:{{ .Values.image.csi.resizer.tag }}" - {{- end }} - {{- if and .Values.image.csi.snapshotter.repository .Values.image.csi.snapshotter.tag }} - - name: CSI_SNAPSHOTTER_IMAGE - value: "{{ template "registry_url" . }}{{ .Values.image.csi.snapshotter.repository }}:{{ .Values.image.csi.snapshotter.tag }}" - {{- end }} - {{- if .Values.csi.attacherReplicaCount }} - - name: CSI_ATTACHER_REPLICA_COUNT - value: {{ .Values.csi.attacherReplicaCount | quote }} - {{- end }} - {{- if .Values.csi.provisionerReplicaCount }} - - name: CSI_PROVISIONER_REPLICA_COUNT - value: {{ .Values.csi.provisionerReplicaCount | quote }} - {{- end }} - {{- if .Values.csi.resizerReplicaCount }} - - name: CSI_RESIZER_REPLICA_COUNT - value: {{ .Values.csi.resizerReplicaCount | quote }} - {{- end }} - {{- if .Values.csi.snapshotterReplicaCount }} - - name: CSI_SNAPSHOTTER_REPLICA_COUNT - value: {{ .Values.csi.snapshotterReplicaCount | quote }} - {{- end }} - - {{- if .Values.defaultSettings.registrySecret }} - imagePullSecrets: - - name: {{ .Values.defaultSettings.registrySecret }} - {{- end }} - serviceAccountName: longhorn-service-account - securityContext: - runAsUser: 0 diff --git a/scripts/helm/longhorn/longhorn/templates/deployment-ui.yaml b/scripts/helm/longhorn/longhorn/templates/deployment-ui.yaml deleted file mode 100644 index 1921dbdc1..000000000 --- a/scripts/helm/longhorn/longhorn/templates/deployment-ui.yaml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - app: longhorn-ui - name: longhorn-ui - namespace: {{ .Release.Namespace }} -spec: - replicas: 1 - selector: - matchLabels: - app: longhorn-ui - template: - metadata: - labels: {{- include "longhorn.labels" . | nindent 8 }} - app: longhorn-ui - spec: - containers: - - name: longhorn-ui - image: {{ template "registry_url" . }}{{ .Values.image.longhorn.ui.repository }}:{{ .Values.image.longhorn.ui.tag }} - imagePullPolicy: IfNotPresent - securityContext: - runAsUser: 0 - ports: - - containerPort: 8000 - name: http - env: - - name: LONGHORN_MANAGER_IP - value: "http://longhorn-backend:9500" - {{- if .Values.defaultSettings.registrySecret }} - imagePullSecrets: - - name: {{ .Values.defaultSettings.registrySecret }} - {{- end }} ---- -kind: Service -apiVersion: v1 -metadata: - labels: {{- include "longhorn.labels" . | nindent 4 }} - app: longhorn-ui - {{- if eq .Values.service.ui.type "Rancher-Proxy" }} - kubernetes.io/cluster-service: "true" - {{- end }} - name: longhorn-frontend - namespace: {{ .Release.Namespace }} -spec: - {{- if eq .Values.service.ui.type "Rancher-Proxy" }} - type: ClusterIP - {{- else }} - type: {{ .Values.service.ui.type }} - {{- end }} - selector: - app: longhorn-ui - ports: - - name: http - port: 80 - targetPort: http - {{- if .Values.service.ui.nodePort }} - nodePort: {{ .Values.service.ui.nodePort }} - {{- else }} - nodePort: null - {{- end }} diff --git a/scripts/helm/longhorn/longhorn/templates/ingress.yaml b/scripts/helm/longhorn/longhorn/templates/ingress.yaml deleted file mode 100644 index e3e9e3eea..000000000 --- a/scripts/helm/longhorn/longhorn/templates/ingress.yaml +++ /dev/null @@ -1,30 +0,0 @@ -{{- if .Values.ingress.enabled }} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: longhorn-ingress - labels: {{- include "longhorn.labels" . | nindent 4 }} - app: longhorn-ingress - annotations: - {{- if .Values.ingress.tls }} - ingress.kubernetes.io/secure-backends: "true" - {{- end }} - {{- range $key, $value := .Values.ingress.annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - rules: - - host: {{ .Values.ingress.host }} - http: - paths: - - path: {{ default "" .Values.ingress.path }} - backend: - serviceName: longhorn-frontend - servicePort: 80 -{{- if .Values.ingress.tls }} - tls: - - hosts: - - {{ .Values.ingress.host }} - secretName: {{ .Values.ingress.tlsSecret }} -{{- end }} -{{- end }} diff --git a/scripts/helm/longhorn/longhorn/templates/postupgrade-job.yaml b/scripts/helm/longhorn/longhorn/templates/postupgrade-job.yaml deleted file mode 100644 index f493617f0..000000000 --- a/scripts/helm/longhorn/longhorn/templates/postupgrade-job.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - annotations: - "helm.sh/hook": post-upgrade - "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation - name: longhorn-post-upgrade - namespace: {{ .Release.Namespace }} - labels: {{- include "longhorn.labels" . | nindent 4 }} -spec: - activeDeadlineSeconds: 900 - backoffLimit: 1 - template: - metadata: - name: longhorn-post-upgrade - labels: {{- include "longhorn.labels" . | nindent 8 }} - spec: - containers: - - name: longhorn-post-upgrade - image: {{ template "registry_url" . }}{{ .Values.image.longhorn.manager.repository }}:{{ .Values.image.longhorn.manager.tag }} - imagePullPolicy: Always - command: - - longhorn-manager - - post-upgrade - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - restartPolicy: OnFailure - {{- if .Values.defaultSettings.registrySecret }} - imagePullSecrets: - - name: {{ .Values.defaultSettings.registrySecret }} - {{- end }} - serviceAccountName: longhorn-service-account diff --git a/scripts/helm/longhorn/longhorn/templates/psp.yaml b/scripts/helm/longhorn/longhorn/templates/psp.yaml deleted file mode 100644 index 66479b4fa..000000000 --- a/scripts/helm/longhorn/longhorn/templates/psp.yaml +++ /dev/null @@ -1,66 +0,0 @@ -{{- if .Values.enablePSP }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: longhorn-psp - labels: {{- include "longhorn.labels" . | nindent 4 }} -spec: - privileged: true - allowPrivilegeEscalation: true - requiredDropCapabilities: - - NET_RAW - allowedCapabilities: - - SYS_ADMIN - hostNetwork: false - hostIPC: false - hostPID: true - runAsUser: - rule: RunAsAny - seLinux: - rule: RunAsAny - fsGroup: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - volumes: - - configMap - - downwardAPI - - emptyDir - - secret - - projected - - hostPath ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: longhorn-psp-role - labels: {{- include "longhorn.labels" . | nindent 4 }} - namespace: {{ .Release.Namespace }} -rules: -- apiGroups: - - policy - resources: - - podsecuritypolicies - verbs: - - use - resourceNames: - - longhorn-psp ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: longhorn-psp-binding - labels: {{- include "longhorn.labels" . | nindent 4 }} - namespace: {{ .Release.Namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: longhorn-psp-role -subjects: -- kind: ServiceAccount - name: longhorn-service-account - namespace: {{ .Release.Namespace }} -- kind: ServiceAccount - name: default - namespace: {{ .Release.Namespace }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/longhorn/longhorn/templates/registry-secret.yml b/scripts/helm/longhorn/longhorn/templates/registry-secret.yml deleted file mode 100644 index eeb9a8f4a..000000000 --- a/scripts/helm/longhorn/longhorn/templates/registry-secret.yml +++ /dev/null @@ -1,10 +0,0 @@ -{{- if .Values.defaultSettings.registrySecret }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Values.defaultSettings.registrySecret }} - labels: {{- include "longhorn.labels" . | nindent 4 }} -type: kubernetes.io/dockerconfigjson -data: - .dockerconfigjson: {{ template "secret" . }} -{{- end }} diff --git a/scripts/helm/longhorn/longhorn/templates/serviceaccount.yaml b/scripts/helm/longhorn/longhorn/templates/serviceaccount.yaml deleted file mode 100644 index a2280b44f..000000000 --- a/scripts/helm/longhorn/longhorn/templates/serviceaccount.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: longhorn-service-account - namespace: {{ .Release.Namespace }} - labels: {{- include "longhorn.labels" . | nindent 4 }} diff --git a/scripts/helm/longhorn/longhorn/templates/storageclass.yaml b/scripts/helm/longhorn/longhorn/templates/storageclass.yaml deleted file mode 100644 index 6a80d00de..000000000 --- a/scripts/helm/longhorn/longhorn/templates/storageclass.yaml +++ /dev/null @@ -1,18 +0,0 @@ -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: longhorn - annotations: - storageclass.kubernetes.io/is-default-class: {{ .Values.persistence.defaultClass | quote }} - labels: {{- include "longhorn.labels" . | nindent 4 }} -provisioner: driver.longhorn.io -allowVolumeExpansion: true -reclaimPolicy: "{{ .Values.persistence.reclaimPolicy }}" -parameters: - numberOfReplicas: "{{ .Values.persistence.defaultClassReplicaCount }}" - staleReplicaTimeout: "30" - fromBackup: "" - baseImage: "" - {{- if .Values.recurringJobs.enable }} - recurringJobs: '{{ .Values.recurringJobs.jobsList | toPrettyJson | indent 2 | trim }}' - {{- end }} diff --git a/scripts/helm/longhorn/longhorn/templates/tls-secrets.yaml b/scripts/helm/longhorn/longhorn/templates/tls-secrets.yaml deleted file mode 100644 index 7a75df09c..000000000 --- a/scripts/helm/longhorn/longhorn/templates/tls-secrets.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.ingress.enabled }} -{{- range .Values.ingress.secrets }} -apiVersion: v1 -kind: Secret -metadata: - name: longhorn - labels: {{- include "longhorn.labels" . | nindent 4 }} - app: longhorn -type: kubernetes.io/tls -data: - tls.crt: {{ .certificate | b64enc }} - tls.key: {{ .key | b64enc }} ---- -{{- end }} -{{- end }} diff --git a/scripts/helm/longhorn/longhorn/templates/uninstall-job.yaml b/scripts/helm/longhorn/longhorn/templates/uninstall-job.yaml deleted file mode 100644 index 4dde54bc0..000000000 --- a/scripts/helm/longhorn/longhorn/templates/uninstall-job.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - annotations: - "helm.sh/hook": pre-delete - "helm.sh/hook-delete-policy": hook-succeeded - name: longhorn-uninstall - namespace: {{ .Release.Namespace }} - labels: {{- include "longhorn.labels" . | nindent 4 }} -spec: - activeDeadlineSeconds: 900 - backoffLimit: 1 - template: - metadata: - name: longhorn-uninstall - labels: {{- include "longhorn.labels" . | nindent 8 }} - spec: - containers: - - name: longhorn-uninstall - image: {{ template "registry_url" . }}{{ .Values.image.longhorn.manager.repository }}:{{ .Values.image.longhorn.manager.tag }} - imagePullPolicy: Always - command: - - longhorn-manager - - uninstall - - --force - env: - - name: LONGHORN_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - restartPolicy: OnFailure - {{- if .Values.defaultSettings.registrySecret }} - imagePullSecrets: - - name: {{ .Values.defaultSettings.registrySecret }} - {{- end }} - serviceAccountName: longhorn-service-account diff --git a/scripts/helm/longhorn/longhorn/values.yaml b/scripts/helm/longhorn/longhorn/values.yaml deleted file mode 100644 index ea46554b4..000000000 --- a/scripts/helm/longhorn/longhorn/values.yaml +++ /dev/null @@ -1,149 +0,0 @@ -# Default values for longhorn. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -global: - cattle: - systemDefaultRegistry: "" - -image: - longhorn: - engine: - repository: longhornio/longhorn-engine - tag: v1.0.2 - manager: - repository: longhornio/longhorn-manager - tag: v1.0.2 - ui: - repository: longhornio/longhorn-ui - tag: v1.0.2 - instanceManager: - repository: longhornio/longhorn-instance-manager - tag: v1_20200514 - csi: - attacher: - repository: longhornio/csi-attacher - tag: v2.0.0 - provisioner: - repository: longhornio/csi-provisioner - tag: v1.4.0 - nodeDriverRegistrar: - repository: longhornio/csi-node-driver-registrar - tag: v1.2.0 - resizer: - repository: longhornio/csi-resizer - tag: v0.3.0 - snapshotter: - repository: longhornio/csi-snapshotter - tag: v2.1.1 - pullPolicy: IfNotPresent - -service: - ui: - type: ClusterIP - nodePort: null - manager: - type: ClusterIP - nodePort: "" - -persistence: - defaultClass: true - defaultClassReplicaCount: 3 - reclaimPolicy: Delete - -recurringJobs: - enable: false - jobsList: [] - # - name: snap - # task: snapshot - # cron: '*/1 * * * *' - # retain: 1 - -csi: - kubeletRootDir: ~ - attacherReplicaCount: ~ - provisionerReplicaCount: ~ - resizerReplicaCount: ~ - snapshotterReplicaCount: ~ - -defaultSettings: - backupTarget: ~ - backupTargetCredentialSecret: ~ - createDefaultDiskLabeledNodes: ~ - defaultDataPath: ~ - replicaSoftAntiAffinity: ~ - storageOverProvisioningPercentage: ~ - storageMinimalAvailablePercentage: ~ - upgradeChecker: ~ - defaultReplicaCount: ~ - guaranteedEngineCPU: ~ - defaultLonghornStaticStorageClass: ~ - backupstorePollInterval: ~ - taintToleration: ~ - priorityClass: ~ - registrySecret: ~ - autoSalvage: ~ - disableSchedulingOnCordonedNode: ~ - replicaZoneSoftAntiAffinity: ~ - volumeAttachmentRecoveryPolicy: ~ - mkfsExt4Parameters: ~ - -privateRegistry: - registryUrl: ~ - registryUser: ~ - registryPasswd: ~ - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - # - -ingress: - ## Set to true to enable ingress record generation - enabled: false - - - host: xip.io - - ## Set this to true in order to enable TLS on the ingress record - ## A side effect of this will be that the backend service will be connected at port 443 - tls: false - - ## If TLS is set to true, you must declare what secret will store the key/certificate for TLS - tlsSecret: longhorn.local-tls - - ## Ingress annotations done as key:value pairs - ## If you're using kube-lego, you will want to add: - ## kubernetes.io/tls-acme: true - ## - ## For a full list of possible ingress annotations, please see - ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/annotations.md - ## - ## If tls is set to true, annotation ingress.kubernetes.io/secure-backends: "true" will automatically be set - annotations: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: true - - secrets: - ## If you're providing your own certificates, please use this to add the certificates as secrets - ## key and certificate should start with -----BEGIN CERTIFICATE----- or - ## -----BEGIN RSA PRIVATE KEY----- - ## - ## name should line up with a tlsSecret set further up - ## If you're using kube-lego, this is unneeded, as it will create the secret for you if it is not set - ## - ## It is also possible to create and manage the certificates outside of this helm chart - ## Please see README.md for more information - # - name: longhorn.local-tls - # key: - # certificate: - -# Configure a pod security policy in the Longhorn namespace to allow privileged pods -enablePSP: true diff --git a/scripts/helm/management/ecr_cron.yaml b/scripts/helm/management/ecr_cron.yaml deleted file mode 100644 index fdc559979..000000000 --- a/scripts/helm/management/ecr_cron.yaml +++ /dev/null @@ -1,76 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: ecr-update-sa ---- -kind: Role -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - namespace: app - name: ecr-update-role -rules: -- apiGroups: [""] - resources: ["secrets"] - # resourceNames: ["aws-registry"] - verbs: ['create','delete'] ---- -# This role binding allows "jane" to read pods in the "default" namespace. -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: ecr-update-role - namespace: app -subjects: -- kind: ServiceAccount - name: ecr-update-sa # Name is case sensitive - namespace: app -roleRef: - kind: Role #this must be Role or ClusterRole - name: ecr-update-role # this must match the name of the Role or ClusterRole you wish to bind to - apiGroup: rbac.authorization.k8s.io ---- -apiVersion: batch/v1beta1 -kind: CronJob -metadata: - name: ecr-update - namespace: app -spec: - schedule: "* */8 * * *" - successfulJobsHistoryLimit: 1 - suspend: false - jobTemplate: - spec: - template: - spec: - serviceAccountName: ecr-update-sa - restartPolicy: OnFailure - containers: - - name: update-ecr - image: amazon/aws-cli:2.0.6 - env: - - name: AWS_DEFAULT_REGION - value: eu-central-1 - - name: AWS_SECRET_ACCESS_KEY - value: QWERTYQWERTYQWERTY - - name: AWS_ACCESS_KEY_ID - value: QWERTYQWERTYQWERTY - command: - - /bin/bash - - -c - - |- - # Installing kubectl - curl -SsL https://dl.k8s.io/release/v1.20.0/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl ; chmod +x /usr/local/bin/kubectl - ACCOUNT=998611063711 # custom script | your aws account id - REGION=eu-central-1 # custom script | your aws account region of choice - SECRET_NAME=aws-registry # custom script | name of secret - EMAIL=anymail.doesnt.matter@email.com # custom script | any email address - TOKEN=$(aws ecr get-login-password --region ${REGION}) # custom script | this will call AWS ECr to gewt login password and store it in TOKEN - echo "ENV variables setup done." - kubectl delete secret --ignore-not-found $SECRET_NAME # custom script | delte previous secret if any - kubectl create secret docker-registry $SECRET_NAME \ - --docker-server=https://${ACCOUNT}.dkr.ecr.${REGION}.amazonaws.com \ - --docker-username=AWS \ - --docker-password="${TOKEN}" \ - --docker-email="${EMAIL}" - echo "Secret created by name. $SECRET_NAME" - echo "All done." diff --git a/scripts/helm/management/kubenav b/scripts/helm/management/kubenav deleted file mode 160000 index 98ca62adc..000000000 --- a/scripts/helm/management/kubenav +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 98ca62adc259b29b8a99936d7365a7a19668476c diff --git a/scripts/helm/management/rancher.yaml b/scripts/helm/management/rancher.yaml deleted file mode 100644 index d6f05cda6..000000000 --- a/scripts/helm/management/rancher.yaml +++ /dev/null @@ -1,82 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: cattle-system ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: rancher - namespace: cattle-system - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - # "namespace" omitted since ClusterRoles are not namespaced - name: rancher -rules: -- apiGroups: ["*"] - resources: ["*"] - verbs: ["*"] - ---- -apiVersion: rbac.authorization.k8s.io/v1 -# This role binding allows "jane" to read pods in the "default" namespace. -kind: ClusterRoleBinding -metadata: - name: rancher -subjects: -- kind: ServiceAccount - name: rancher - namespace: cattle-system - apiGroup: "" -roleRef: - kind: ClusterRole #this must be Role or ClusterRole - name: rancher - apiGroup: "" ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: rancher - namespace: cattle-system -spec: - replicas: 1 - selector: - matchLabels: - app: rancher - template: - metadata: - labels: - app: rancher - spec: - serviceAccountName: rancher - containers: - - name: name - image: rancher/rancher - args: - - --features - - fleet=false - env: - - name: CATTLE_FEATURES - value: "fleet=false" - resources: - requests: - cpu: 100m - memory: 200Mi - ports: - - containerPort: 443 ---- -apiVersion: v1 -kind: Service -metadata: - name: rancher - namespace: cattle-system -spec: - type: LoadBalancer - ports: - - port: 8443 - targetPort: 443 - selector: - app: rancher diff --git a/scripts/helm/management/rancher/.helmignore b/scripts/helm/management/rancher/.helmignore deleted file mode 100755 index 2b29f2764..000000000 --- a/scripts/helm/management/rancher/.helmignore +++ /dev/null @@ -1 +0,0 @@ -tests diff --git a/scripts/helm/management/rancher/Chart.yaml b/scripts/helm/management/rancher/Chart.yaml deleted file mode 100755 index 4444c3ea1..000000000 --- a/scripts/helm/management/rancher/Chart.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -appVersion: v2.5.3 -description: Install Rancher Server to manage Kubernetes clusters across providers. -home: https://rancher.com -icon: https://github.com/rancher/ui/blob/master/public/assets/images/logos/welcome-cow.svg -keywords: -- rancher -maintainers: -- email: charts@rancher.com - name: Rancher Labs -name: rancher -sources: -- https://github.com/rancher/rancher -- https://github.com/rancher/server-chart -version: 2.5.3 diff --git a/scripts/helm/management/rancher/README.md b/scripts/helm/management/rancher/README.md deleted file mode 100755 index 1808b8f32..000000000 --- a/scripts/helm/management/rancher/README.md +++ /dev/null @@ -1,211 +0,0 @@ -# Rancher - -***Rancher*** is open source software that combines everything an organization needs to adopt and run containers in production. Built on Kubernetes, Rancher makes it easy for DevOps teams to test, deploy and manage their applications. - -### Introduction - -This chart bootstraps a [Rancher Server](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/) on a Kubernetes cluster using the [Helm](https://helm.sh/) package manager. For a Rancher Supported Deployment please follow our [HA install instructions](https://rancher.com/docs/rancher/v2.x/en/installation/how-ha-works/). - - -### Prerequisites Details - -*For installations covered under [Rancher Support SLA](https://rancher.com/support-maintenance-terms/) the target cluster must be **[RKE](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/kubernetes-rke/)** or **[K3s](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/kubernetes-rke/)**.* - -Make sure the node(s) for the Rancher server fulfill the following requirements: - -[Operating Systems and Docker Requirements](https://rancher.com/docs/rancher/v2.x/en/installation/requirements#operating-systems-and-docker-requirements) -[Hardware Requirements](https://rancher.com/docs/rancher/v2.x/en/installation/requirements/#hardware-requirements) - -- [CPU and Memory](https://rancher.com/docs/rancher/v2.x/en/installation/requirements/#cpu-and-memory) -- [CPU and Memory for Rancher prior to v2.4.0](https://rancher.com/docs/rancher/v2.x/en/installation/requirements/#cpu-and-memory-for-rancher-prior-to-v2-4-0) -- [Disks](https://rancher.com/docs/rancher/v2.x/en/installation/requirements/#disks) - -[Networking Requirements](https://rancher.com/docs/rancher/v2.x/en/installation/requirements/#networking-requirements) -- [Node IP Addresses](https://rancher.com/docs/rancher/v2.x/en/installation/requirements/#node-ip-addresses) -- [Port Requirements](https://rancher.com/docs/rancher/v2.x/en/installation/requirements/#port-requirements) - -[Install the Required CLI Tools](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/#1-install-the-required-cli-tools) - -- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl) - Kubernetes command-line tool. -- [helm](https://docs.helm.sh/using_helm/#installing-helm) - Package management for Kubernetes. Refer to the [Helm version requirements](https://rancher.com/docs/rancher/v2.x/en/installation/options/helm-version) to choose a version of Helm to install Rancher. - -For a list of best practices that we recommend for running the Rancher server in production, refer to the [best practices section](https://rancher.com/docs/rancher/v2.x/en/best-practices/deployment-types/). - -## Installing Rancher - -For production environments, we recommend installing Rancher in a [high-availability Kubernetes installation](https://rancher.com/docs/rancher/v2.x/en/installation/how-ha-works/) so that your user base can always access Rancher Server. When installed in a Kubernetes cluster, Rancher will integrate with the cluster’s etcd database and take advantage of Kubernetes scheduling for high-availability. - -Optional: Installing Rancher on a [Single-node](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/#optional-installing-rancher-on-a-single-node-kubernetes-cluster) Kubernetes Cluster - -#### Add the Helm Chart Repository - -Use [helm repo add](https://helm.sh/docs/helm/helm_repo_add/) command to add the Helm chart repository that contains charts to install Rancher. For more information about the repository choices and which is best for your use case, see Choosing a Version of Rancher. - -```bash -helm repo add rancher-latest https://releases.rancher.com/server-charts/latest -``` - -#### Create a Namespace for Rancher - -We’ll need to define a Kubernetes namespace where the resources created by the Chart should be installed. This should always be cattle-system: - -```bash -kubectl create namespace cattle-system -``` - -#### Choose your SSL Configuration - -The Rancher management server is designed to be secure by default and requires SSL/TLS configuration. - -There are three recommended options for the source of the certificate used for TLS termination at the Rancher server: - -- [Rancher-generated TLS certificate](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/#4-choose-your-ssl-configuration) -- [Let’s Encrypt](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/#4-choose-your-ssl-configuration) -- [Bring your own certificate](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/#4-choose-your-ssl-configuration) - -#### Install cert-manager - -This step is only required to use certificates issued by Rancher’s generated CA **`(ingress.tls.source=rancher)`** or to request Let’s Encrypt issued certificates **`(ingress.tls.source=letsEncrypt)`**. - -[These instructions are adapted from the official cert-manager documentation.](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/#5-install-cert-manager) - -#### Install Rancher with Helm and Your Chosen Certificate Option - -- [Rancher to generated certificates](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/#6-install-rancher-with-helm-and-your-chosen-certificate-option) -```bash -helm install rancher rancher-latest/rancher \ - --namespace cattle-system \ - --set hostname=rancher.my.org - -# Wait for Rancher to be rolled out -kubectl -n cattle-system rollout status deploy/rancher -Waiting for deployment "rancher" rollout to finish: 0 of 3 updated replicas are available... -deployment "rancher" successfully rolled out -``` - -- [Let’s Encrypt](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/#6-install-rancher-with-helm-and-your-chosen-certificate-option) - -```bash -helm install rancher rancher-latest/rancher \ - --namespace cattle-system \ - --set hostname=rancher.my.org \ - --set ingress.tls.source=letsEncrypt \ - --set letsEncrypt.email=me@example.org - -# Wait for Rancher to be rolled out -kubectl -n cattle-system rollout status deploy/rancher -Waiting for deployment "rancher" rollout to finish: 0 of 3 updated replicas are available... -deployment "rancher" successfully rolled out -``` - -- [Certificates from Files](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/#6-install-rancher-with-helm-and-your-chosen-certificate-option) - -```bash -helm install rancher rancher-latest/rancher \ - --namespace cattle-system \ - --set hostname=rancher.my.org \ - --set ingress.tls.source=secret -``` - -*If you are using a Private CA signed certificate , add **--set privateCA=true** to the command:`* - -```bash -helm install rancher rancher-latest/rancher \ - --namespace cattle-system \ - --set hostname=rancher.my.org \ - --set ingress.tls.source=secret \ - --set privateCA=true - -# Wait for Rancher to be rolled out -kubectl -n cattle-system rollout status deploy/rancher -Waiting for deployment "rancher" rollout to finish: 0 of 3 updated replicas are available... -deployment "rancher" successfully rolled out -``` - -#### Verify that the Rancher Server is Successfully Deployed - -After adding the secrets, check if Rancher was rolled out successfully: - -```bash -kubectl -n cattle-system rollout status deploy/rancher -Waiting for deployment "rancher" rollout to finish: 0 of 3 updated replicas are available... -deployment "rancher" successfully rolled out -``` - -If you see the following **`error: error: deployment "rancher" exceeded its progress deadline`**, you can check the status of the deployment by running the following command: - -```bash -kubectl -n cattle-system get deploy rancher -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -rancher 3 3 3 3 3m -``` - -It should show the same count for **`DESIRED`** and **`AVAILABLE`**. - -#### Save Your Options - -Make sure you save the **`--set`** options you used. You will need to use the same options when you upgrade Rancher to new versions with Helm. - -#### Finishing Up - -That’s it. You should have a functional Rancher server. - -In a web browser, go to the DNS name that forwards traffic to your load balancer. Then you should be greeted by the colorful login page. - -Doesn’t work? Take a look at the [Troubleshooting Page](https://rancher.com/docs/rancher/v2.x/en/installation/options/troubleshooting/) - -***All of these instructions are defined in detailed in the [Rancher Documentation](https://rancher.com/docs/rancher/v2.x/en/installation/k8s-install/helm-rancher/).*** - -### Helm Chart Options for Kubernetes Installations - -The full [Helm Chart Options](https://rancher.com/docs/rancher/v2.x/en/installation/options/chart-options/) can be found here. - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. - -#### Common Options - -| Parameter | Default Value | Description | -| ------------------------- | ------------- | -------------------------------------------------------------------------------------------- | -| `hostname` | " " | ***string*** - the Fully Qualified Domain Name for your Rancher Server | -| `ingress.tls.source` | "rancher" | ***string*** - Where to get the cert for the ingress. - "***rancher, letsEncrypt, secret***" | -| `letsEncrypt.email` | " " | ***string*** - Your email address | -| `letsEncrypt.environment` | "production" | ***string*** - Valid options: "***staging, production***" | -| `privateCA` | false | ***bool*** - Set to true if your cert is signed by a private CA | - -#### Advanced Options - -| Parameter | Default Value | Description | -| ------------------------------ | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `additionalTrustedCAs` | false | ***bool*** - [See Additional Trusted CAs Server](https://rancher.com/docs/rancher/v2.x/en/installation/options/chart-options/#additional-trusted-cas) | -| `addLocal` | "true" | ***string*** - As of Rancher v2.5.0 this flag is deprecated and must be set to "true"| -| `antiAffinity` | "preferred" | ***string*** - AntiAffinity rule for Rancher pods - *"preferred, required"* | -| `replicas` | 3 | ***int*** - Number of replicas of Rancher pods | -| `auditLog.destination` | "sidecar" | ***string*** - Stream to sidecar container console or hostPath volume - *"sidecar, hostPath"* | -| `auditLog.hostPath` | "/var/log/rancher/audit" | ***string*** - log file destination on host (only applies when **auditLog.destination** is set to **hostPath**) | -| `auditLog.level` | 0 | ***int*** - set the [API Audit Log level](https://rancher.com/docs/rancher/v2.x/en/installation/api-auditing). 0 is off. [0-3] | -| `auditLog.maxAge` | 1 | ***int*** - maximum number of days to retain old audit log files (only applies when **auditLog.destination** is set to **hostPath**) | -| `auditLog.maxBackups` | 1 | int - maximum number of audit log files to retain (only applies when **auditLog.destination** is set to **hostPath**) | -| `auditLog.maxSize` | 100 | ***int*** - maximum size in megabytes of the audit log file before it gets rotated (only applies when **auditLog.destination** is set to **hostPath**) | -| `busyboxImage` | "busybox" | ***string*** - Image location for busybox image used to collect audit logs *Note: Available as of v2.2.0* | -| `debug` | false | ***bool*** - set debug flag on rancher server | -| `certmanager.version` | " " | ***string*** - set cert-manager compatibility | -| `extraEnv` | [] | ***list*** - set additional environment variables for Rancher Note: *Available as of v2.2.0* | -| `imagePullSecrets` | [] | ***list*** - list of names of Secret resource containing private registry credentials | -| `ingress.extraAnnotations` | {} | ***map*** - additional annotations to customize the ingress | -| `ingress.configurationSnippet` | " " | ***string*** - Add additional Nginx configuration. Can be used for proxy configuration. Note: *Available as of v2.0.15, v2.1.10 and v2.2.4* | -| `letsEncrypt.ingress.class` | " " | ***string*** - optional ingress class for the cert-manager acmesolver ingress that responds to the Let’s *Encrypt ACME challenges* | -| `proxy` | " " | ***string** - HTTP[S] proxy server for Rancher | -| `noProxy` | "127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" | ***string*** - comma separated list of hostnames or ip address not to use the proxy | -| `resources` | {} | ***map*** - rancher pod resource requests & limits | -| `rancherImage` | "rancher/rancher" | ***string*** - rancher image source | -| `rancherImageTag` | same as chart version | ***string*** - rancher/rancher image tag | -| `rancherImagePullPolicy` | "IfNotPresent" | ***string*** - Override imagePullPolicy for rancher server images - *"Always", "Never", "IfNotPresent"* | -| `tls` | "ingress" | ***string*** - See External TLS Termination for details. - *"ingress, external"* | -| `systemDefaultRegistry` | "" | ***string*** - private registry to be used for all system Docker images, e.g., [http://registry.example.com/] *Available as of v2.3.0* | -| `useBundledSystemChart` | false | ***bool*** - select to use the system-charts packaged with Rancher server. This option is used for air gapped installations. *Available as of v2.3.0* | -| `customLogos.enabled` | false | ***bool*** - Enabled [Rancher custom logos](https://github.com/rancher/ui/tree/master/public/assets/images/logos) persistence volume| -| `customLogos.volumeKind` | "persistentVolumeClaim" | ***string*** - Use persistentVolumeClaim or configMap for custom logos persistence| -| `customLogos.volumeName` | "" | ***string*** - Use an existing volume. Custom logos should be copied to the volume by the user. Optional for persistentVolumeClaim, required for configMap| -| `customLogos.storageClass` | "" | ***string*** - Set custom logos persistentVolumeClaim storage class. Required for dynamic pv| -| `customLogos.accessMode` | "ReadWriteOnce" | ***string*** - Set custom persistentVolumeClaim access mode| -| `customLogos.size` | "1Gi" | ***string*** - Set custom persistentVolumeClaim size| diff --git a/scripts/helm/management/rancher/templates/NOTES.txt b/scripts/helm/management/rancher/templates/NOTES.txt deleted file mode 100755 index b3e2617f2..000000000 --- a/scripts/helm/management/rancher/templates/NOTES.txt +++ /dev/null @@ -1,9 +0,0 @@ -Rancher Server has been installed. - -NOTE: Rancher may take several minutes to fully initialize. Please standby while Certificates are being issued and Ingress comes up. - -Check out our docs at https://rancher.com/docs/rancher/v2.x/en/ - -Browse to https://{{ .Values.hostname }} - -Happy Containering! diff --git a/scripts/helm/management/rancher/templates/_helpers.tpl b/scripts/helm/management/rancher/templates/_helpers.tpl deleted file mode 100755 index 00043e27a..000000000 --- a/scripts/helm/management/rancher/templates/_helpers.tpl +++ /dev/null @@ -1,25 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "rancher.name" -}} - {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "rancher.fullname" -}} - {{- $name := default .Chart.Name .Values.nameOverride -}} - {{- if contains $name .Release.Name -}} - {{- .Release.Name | trunc 63 | trimSuffix "-" -}} - {{- else -}} - {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} - {{- end -}} -{{- end -}} - -# Render Values in configurationSnippet -{{- define "configurationSnippet" -}} - {{- tpl (.Values.ingress.configurationSnippet) . | nindent 6 -}} -{{- end -}} diff --git a/scripts/helm/management/rancher/templates/clusterRoleBinding.yaml b/scripts/helm/management/rancher/templates/clusterRoleBinding.yaml deleted file mode 100755 index 50a60cbd5..000000000 --- a/scripts/helm/management/rancher/templates/clusterRoleBinding.yaml +++ /dev/null @@ -1,17 +0,0 @@ -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "rancher.fullname" . }} - labels: - app: {{ template "rancher.fullname" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -subjects: -- kind: ServiceAccount - name: {{ template "rancher.fullname" . }} - namespace: {{ .Release.Namespace }} -roleRef: - kind: ClusterRole - name: cluster-admin - apiGroup: rbac.authorization.k8s.io diff --git a/scripts/helm/management/rancher/templates/deployment.yaml b/scripts/helm/management/rancher/templates/deployment.yaml deleted file mode 100755 index a6df55506..000000000 --- a/scripts/helm/management/rancher/templates/deployment.yaml +++ /dev/null @@ -1,198 +0,0 @@ -kind: Deployment -apiVersion: apps/v1 -metadata: - name: {{ template "rancher.fullname" . }} - labels: - app: {{ template "rancher.fullname" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - replicas: {{ .Values.replicas }} - selector: - matchLabels: - app: {{ template "rancher.fullname" . }} - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 1 - type: RollingUpdate - template: - metadata: - labels: - app: {{ template "rancher.fullname" . }} - release: {{ .Release.Name }} - spec: - serviceAccountName: {{ template "rancher.fullname" . }} -{{- if .Values.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.imagePullSecrets | indent 6 }} -{{- end }} - affinity: - podAntiAffinity: -{{- if eq .Values.antiAffinity "required" }} - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - {{ template "rancher.fullname" . }} - topologyKey: kubernetes.io/hostname -{{- else }} - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - {{ template "rancher.fullname" . }} - topologyKey: kubernetes.io/hostname -{{- end }} - containers: - - image: {{ .Values.rancherImage }}:{{ default .Chart.AppVersion .Values.rancherImageTag }} - imagePullPolicy: {{ default "IfNotPresent" .Values.rancherImagePullPolicy }} - name: {{ template "rancher.name" . }} - ports: - - containerPort: 80 - protocol: TCP - args: -{{- if .Values.debug }} - - "--debug" -{{- end }} -{{- if .Values.privateCA }} - # Private CA - don't clear ca certs -{{- else if and (eq .Values.tls "ingress") (eq .Values.ingress.tls.source "rancher") }} - # Rancher self-signed - don't clear ca certs -{{- else }} - # Public trusted CA - clear ca certs - - "--no-cacerts" -{{- end }} - - "--http-listen-port=80" - - "--https-listen-port=443" - - "--add-local={{ .Values.addLocal }}" - env: - - name: CATTLE_NAMESPACE - value: {{ .Release.Namespace }} - - name: CATTLE_PEER_SERVICE - value: {{ template "rancher.fullname" . }} -{{- if gt (int .Values.auditLog.level) 0 }} - - name: AUDIT_LEVEL - value: {{ .Values.auditLog.level | quote }} - - name: AUDIT_LOG_MAXAGE - value: {{ .Values.auditLog.maxAge | quote }} - - name: AUDIT_LOG_MAXBACKUP - value: {{ .Values.auditLog.maxBackup | quote }} - - name: AUDIT_LOG_MAXSIZE - value: {{ .Values.auditLog.maxSize | quote }} -{{- end }} -{{- if .Values.proxy }} - - name: HTTP_PROXY - value: {{ .Values.proxy }} - - name: HTTPS_PROXY - value: {{ .Values.proxy }} - - name: NO_PROXY - value: {{ .Values.noProxy }} -{{- end }} -{{- if .Values.systemDefaultRegistry }} - - name: CATTLE_SYSTEM_DEFAULT_REGISTRY - value: {{ .Values.systemDefaultRegistry }} -{{- end }} -{{- if .Values.useBundledSystemChart }} - - name: CATTLE_SYSTEM_CATALOG - value: bundled -{{- end }} -{{- if .Values.restrictedAdmin }} - - name: CATTLE_RESTRICTED_DEFAULT_ADMIN - value: "true" -{{- end}} -{{- if .Values.extraEnv }} -{{ toYaml .Values.extraEnv | indent 8}} -{{- end }} - livenessProbe: - httpGet: - path: /healthz - port: 80 - initialDelaySeconds: 60 - periodSeconds: 30 - readinessProbe: - httpGet: - path: /healthz - port: 80 - initialDelaySeconds: 5 - periodSeconds: 30 - resources: -{{ toYaml .Values.resources | indent 10 }} - volumeMounts: -{{- if .Values.additionalTrustedCAs }} - - mountPath: /etc/ssl/certs/ca-additional.pem - name: tls-ca-additional-volume - subPath: ca-additional.pem - readOnly: true - - mountPath: /etc/rancher/ssl/ca-additional.pem - name: tls-ca-additional-volume - subPath: ca-additional.pem - readOnly: true -{{- end }} -{{- if .Values.privateCA }} - # Pass CA cert into rancher for private CA - - mountPath: /etc/rancher/ssl/cacerts.pem - name: tls-ca-volume - subPath: cacerts.pem - readOnly: true -{{- end }} -{{- if and .Values.customLogos.enabled (or (eq .Values.customLogos.volumeKind "persistentVolumeClaim") (and (eq .Values.customLogos.volumeKind "configMap") (.Values.customLogos.volumeName))) }} - # Mount rancher custom-logos volume - - mountPath: /usr/share/rancher/ui/assets/images/logos - name: custom-logos -{{- end }} -{{- if gt (int .Values.auditLog.level) 0 }} - - mountPath: /var/log/auditlog - name: audit-log -{{- end }} -{{- if gt (int .Values.auditLog.level) 0 }} - # Make audit logs available for Rancher log collector tools. - - image: {{ .Values.busyboxImage }} - name: {{ template "rancher.name" . }}-audit-log - command: ["tail"] - args: ["-F", "/var/log/auditlog/rancher-api-audit.log"] - volumeMounts: - - mountPath: /var/log/auditlog - name: audit-log -{{- end }} - volumes: -{{- if .Values.additionalTrustedCAs }} - - name: tls-ca-additional-volume - secret: - defaultMode: 0400 - secretName: tls-ca-additional -{{- end }} -{{- if .Values.privateCA }} - - name: tls-ca-volume - secret: - defaultMode: 0400 - secretName: tls-ca -{{- end }} -{{- if gt (int .Values.auditLog.level) 0 }} - {{- if eq .Values.auditLog.destination "hostPath" }} - - name: audit-log - hostPath: - path: {{ .Values.auditLog.hostPath }} - type: DirectoryOrCreate - {{- else }} - - name: audit-log - emptyDir: {} - {{- end }} -{{- end }} -{{- if and .Values.customLogos.enabled (or (eq .Values.customLogos.volumeKind "persistentVolumeClaim") (and (eq .Values.customLogos.volumeKind "configMap") (.Values.customLogos.volumeName))) }} - - name: custom-logos - {{- if (eq .Values.customLogos.volumeKind "persistentVolumeClaim") }} - persistentVolumeClaim: - claimName: {{ .Values.customLogos.volumeName | default (printf "%s-custom-logos" (include "rancher.fullname" .)) }} - {{- else if (eq .Values.customLogos.volumeKind "configMap") }} - configMap: - name: {{ .Values.customLogos.volumeName }} - {{- end }} -{{- end }} diff --git a/scripts/helm/management/rancher/templates/ingress.yaml b/scripts/helm/management/rancher/templates/ingress.yaml deleted file mode 100755 index 1dc581d41..000000000 --- a/scripts/helm/management/rancher/templates/ingress.yaml +++ /dev/null @@ -1,44 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "rancher.fullname" . }} - labels: - app: {{ template "rancher.fullname" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - annotations: -{{- if .Values.ingress.configurationSnippet }} - nginx.ingress.kubernetes.io/configuration-snippet: | - {{- template "configurationSnippet" . }} -{{- end }} -{{- if eq .Values.tls "external" }} - nginx.ingress.kubernetes.io/ssl-redirect: "false" # turn off ssl redirect for external. -{{- else }} - {{- if ne .Values.ingress.tls.source "secret" }} - {{- $certmanagerVer := split "." .Values.certmanager.version -}} - {{- if or (.Capabilities.APIVersions.Has "certmanager.k8s.io/v1alpha1") (and (gt (len $certmanagerVer._0) 0) (eq (int $certmanagerVer._0) 0) (lt (int $certmanagerVer._1) 11)) }} - certmanager.k8s.io/issuer: {{ template "rancher.fullname" . }} - {{- else }} - cert-manager.io/issuer: {{ template "rancher.fullname" . }} - cert-manager.io/issuer-kind: Issuer - {{- end }} - {{- end }} -{{- end }} -{{- if .Values.ingress.extraAnnotations }} -{{ toYaml .Values.ingress.extraAnnotations | indent 4 }} -{{- end }} -spec: - rules: - - host: {{ .Values.hostname }} # hostname to access rancher server - http: - paths: - - backend: - serviceName: {{ template "rancher.fullname" . }} - servicePort: 80 -{{- if eq .Values.tls "ingress" }} - tls: - - hosts: - - {{ .Values.hostname }} - secretName: tls-rancher-ingress -{{- end }} diff --git a/scripts/helm/management/rancher/templates/issuer-letsEncrypt.yaml b/scripts/helm/management/rancher/templates/issuer-letsEncrypt.yaml deleted file mode 100755 index 9bc425246..000000000 --- a/scripts/helm/management/rancher/templates/issuer-letsEncrypt.yaml +++ /dev/null @@ -1,40 +0,0 @@ -{{- if eq .Values.tls "ingress" -}} - {{- if eq .Values.ingress.tls.source "letsEncrypt" -}} - {{- $certmanagerVer := split "." .Values.certmanager.version -}} - {{- if or (.Capabilities.APIVersions.Has "cert-manager.io/v1beta1") (and (gt (len $certmanagerVer._0) 0) (eq (int $certmanagerVer._0) 0) (ge (int $certmanagerVer._1) 16)) }} -apiVersion: cert-manager.io/v1beta1 - {{- else if or (.Capabilities.APIVersions.Has "cert-manager.io/v1alpha2") (and (gt (len $certmanagerVer._0) 0) (eq (int $certmanagerVer._0) 0) (ge (int $certmanagerVer._1) 11)) }} -apiVersion: cert-manager.io/v1alpha2 - {{- else if or (.Capabilities.APIVersions.Has "certmanager.k8s.io/v1alpha1") (and (gt (len $certmanagerVer._0) 0) (eq (int $certmanagerVer._0) 0) (lt (int $certmanagerVer._1) 11)) }} -apiVersion: certmanager.k8s.io/v1alpha1 - {{- else }} -apiVersion: cert-manager.io/v1 - {{- end }} -kind: Issuer -metadata: - name: {{ template "rancher.fullname" . }} - labels: - app: {{ template "rancher.fullname" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - acme: - {{- if eq .Values.letsEncrypt.environment "production" }} - server: https://acme-v02.api.letsencrypt.org/directory - {{- else }} - server: https://acme-staging-v02.api.letsencrypt.org/directory - {{- end }} - email: {{ .Values.letsEncrypt.email }} - privateKeySecretRef: - name: letsencrypt-{{ .Values.letsEncrypt.environment }} - {{- if or (.Capabilities.APIVersions.Has "certmanager.k8s.io/v1alpha1") (and (gt (len $certmanagerVer._0) 0) (eq (int $certmanagerVer._0) 0) (lt (int $certmanagerVer._1) 11)) }} - http01: {} - {{- else }} - solvers: - - http01: - ingress: - class: {{ .Values.letsEncrypt.ingress.class }} - {{- end }} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/management/rancher/templates/issuer-rancher.yaml b/scripts/helm/management/rancher/templates/issuer-rancher.yaml deleted file mode 100755 index ebadb12ed..000000000 --- a/scripts/helm/management/rancher/templates/issuer-rancher.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if eq .Values.tls "ingress" -}} - {{- if eq .Values.ingress.tls.source "rancher" -}} - {{- $certmanagerVer := split "." .Values.certmanager.version -}} - {{- if or (.Capabilities.APIVersions.Has "cert-manager.io/v1beta1") (and (gt (len $certmanagerVer._0) 0) (eq (int $certmanagerVer._0) 0) (ge (int $certmanagerVer._1) 16)) }} -apiVersion: cert-manager.io/v1beta1 - {{- else if or (.Capabilities.APIVersions.Has "cert-manager.io/v1alpha2") (and (gt (len $certmanagerVer._0) 0) (eq (int $certmanagerVer._0) 0) (ge (int $certmanagerVer._1) 11)) }} -apiVersion: cert-manager.io/v1alpha2 - {{- else if or (.Capabilities.APIVersions.Has "certmanager.k8s.io/v1alpha1") (and (gt (len $certmanagerVer._0) 0) (eq (int $certmanagerVer._0) 0) (lt (int $certmanagerVer._1) 11)) }} -apiVersion: certmanager.k8s.io/v1alpha1 - {{- else }} -apiVersion: cert-manager.io/v1 - {{- end }} -kind: Issuer -metadata: - name: {{ template "rancher.fullname" . }} - labels: - app: {{ template "rancher.fullname" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - ca: - secretName: tls-rancher - {{- end -}} -{{- end -}} diff --git a/scripts/helm/management/rancher/templates/pvc.yaml b/scripts/helm/management/rancher/templates/pvc.yaml deleted file mode 100755 index 45e644f50..000000000 --- a/scripts/helm/management/rancher/templates/pvc.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if and (.Values.customLogos.enabled) (eq .Values.customLogos.volumeKind "persistentVolumeClaim") (not .Values.customLogos.volumeName) }} -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: {{ template "rancher.fullname" . }}-custom-logos -spec: - accessModes: - - {{ .Values.customLogos.accessMode | quote }} - resources: - requests: - storage: {{ .Values.customLogos.size | quote }} - storageClassName: {{ if .Values.customLogos.storageClass }} - {{- if (eq "-" .Values.customLogos.storageClass) -}} - "" - {{- else }} - {{- .Values.customLogos.storageClass }} - {{- end -}} - {{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/management/rancher/templates/service.yaml b/scripts/helm/management/rancher/templates/service.yaml deleted file mode 100755 index 84b6f047a..000000000 --- a/scripts/helm/management/rancher/templates/service.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "rancher.fullname" . }} - labels: - app: {{ template "rancher.fullname" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - ports: - - port: 80 - targetPort: 80 - protocol: TCP - name: http - - port: 443 - targetPort: 444 - protocol: TCP - name: https-internal - selector: - app: {{ template "rancher.fullname" . }} diff --git a/scripts/helm/management/rancher/templates/serviceAccount.yaml b/scripts/helm/management/rancher/templates/serviceAccount.yaml deleted file mode 100755 index 475641d54..000000000 --- a/scripts/helm/management/rancher/templates/serviceAccount.yaml +++ /dev/null @@ -1,9 +0,0 @@ -kind: ServiceAccount -apiVersion: v1 -metadata: - name: {{ template "rancher.fullname" . }} - labels: - app: {{ template "rancher.fullname" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} diff --git a/scripts/helm/management/rancher/values.yaml b/scripts/helm/management/rancher/values.yaml deleted file mode 100755 index ae941c1fc..000000000 --- a/scripts/helm/management/rancher/values.yaml +++ /dev/null @@ -1,126 +0,0 @@ -# Additional Trusted CAs. -# Enable this flag and add your CA certs as a secret named tls-ca-additional in the namespace. -# See README.md for details. -additionalTrustedCAs: false - -antiAffinity: preferred - -# Audit Logs https://rancher.com/docs/rancher/v2.x/en/installation/api-auditing/ -# The audit log is piped to the console of the rancher-audit-log container in the rancher pod. -# https://rancher.com/docs/rancher/v2.x/en/installation/api-auditing/ -# destination stream to sidecar container console or hostPath volume -# level: Verbosity of logs, 0 to 3. 0 is off 3 is a lot. -auditLog: - destination: sidecar - hostPath: /var/log/rancher/audit/ - level: 0 - maxAge: 1 - maxBackup: 1 - maxSize: 100 - -# As of Rancher v2.5.0 this flag is deprecated and must be set to 'true' in order for Rancher to start -addLocal: "true" - -# Image for collecting rancher audit logs. -# Important: update pkg/image/export/main.go when this default image is changed, so that it's reflected accordingly in rancher-images.txt generated for air-gapped setups. -busyboxImage: busybox - -# Add debug flag to Rancher server -debug: false - -# When starting Rancher for the first time, bootstrap the admin as restricted-admin -restrictedAdmin: false - -# Extra environment variables passed to the rancher pods. -# extraEnv: -# - name: CATTLE_TLS_MIN_VERSION -# value: "1.0" - -# Fully qualified name to reach your Rancher server -# hostname: rancher.my.org - -## Optional array of imagePullSecrets containing private registry credentials -## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ -imagePullSecrets: [] -# - name: secretName - -### ingress ### -# Readme for details and instruction on adding tls secrets. -ingress: - extraAnnotations: - nginx.ingress.kubernetes.io/proxy-connect-timeout: "30" - nginx.ingress.kubernetes.io/proxy-read-timeout: "1800" - nginx.ingress.kubernetes.io/proxy-send-timeout: "1800" - - # configurationSnippet - Add additional Nginx configuration. This example statically sets a header on the ingress. - # configurationSnippet: | - # more_set_input_headers "X-Forwarded-Host: {{ .Values.hostname }}"; - - tls: - # options: rancher, letsEncrypt, secret - source: rancher - -### LetsEncrypt config ### -# ProTip: The production environment only allows you to register a name 5 times a week. -# Use staging until you have your config right. -letsEncrypt: - # email: none@example.com - environment: production - ingress: - # options: traefik, nginx - class: "" -# If you are using certs signed by a private CA set to 'true' and set the 'tls-ca' -# in the 'rancher-system' namespace. See the README.md for details -privateCA: false - -# http[s] proxy server passed into rancher server. -# proxy: http://<username>@<password>:<url>:<port> - -# comma separated list of domains or ip addresses that will not use the proxy -noProxy: 127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.svc,.cluster.local - -# Override rancher image location for Air Gap installs -rancherImage: rancher/rancher -# rancher/rancher image tag. https://hub.docker.com/r/rancher/rancher/tags/ -# Defaults to .Chart.appVersion -# rancherImageTag: v2.0.7 - -# Override imagePullPolicy for rancher server images -# options: Always, Never, IfNotPresent -# Defaults to IfNotPresent -# rancherImagePullPolicy: <pullPolicy> - -# Number of Rancher server replicas. -replicas: 3 - -# Set pod resource requests/limits for Rancher. -resources: {} - -# -# tls -# Where to offload the TLS/SSL encryption -# - ingress (default) -# - external -tls: ingress - -systemDefaultRegistry: "" - -# Set to use the packaged system charts -useBundledSystemChart: false - -# Certmanager version compatibility -certmanager: - version: "" - -# Rancher custom logos persistence -customLogos: - enabled: false - ## Volume kind to use for persistence: persistentVolumeClaim, configMap - volumeKind: persistentVolumeClaim - ## Use an existing volume. Custom logos should be copied to the volume by the user - # volumeName: custom-logos - ## Just for volumeKind: persistentVolumeClaim - ## To disables dynamic provisioning, set storageClass: "" or storageClass: "-" - # storageClass: "-" - accessMode: ReadWriteOnce - size: 1Gi diff --git a/scripts/helm/migration.yaml b/scripts/helm/migration.yaml deleted file mode 100644 index abd4e571a..000000000 --- a/scripts/helm/migration.yaml +++ /dev/null @@ -1,50 +0,0 @@ ---- -- hosts: localhost - gather_facts: false - environment: - KUBECONFIG: "{{ kubeconfig_path }}" - vars: - db_path: [] - tasks: - - debug: - var: migration_versions - - block: - - name: generating migration db paths - set_fact: - db_path: "{{ db_path }} + [ '{{playbook_dir}}/db/init_dbs/postgresql/{{ item }}/*.sql' ]" - with_items: "{{ migration_versions.split(',') }}" - - name: Migrate postgresql - shell: | - file="{{ item|basename }}" - kubectl exec -n db postgresql-postgresql-0 -- /bin/bash -c "rm -rf /tmp/$file" - kubectl cp -n db {{ item }} postgresql-postgresql-0:/tmp/ - kubectl exec -n db postgresql-postgresql-0 -- /bin/bash -c "PGPASSWORD=asayerPostgres psql -U postgres -f /tmp/$file" &> "{{ playbook_dir }}"/postgresql_init.log - args: - chdir: db/init_dbs/postgresql - with_fileglob: "{{ db_path }}" - tags: - - postgresql - - block: - - name: Resetting the db path - set_fact: - db_path: [] - - name: generating migration db paths - set_fact: - db_path: "{{ db_path }} + [ '{{playbook_dir}}/db/init_dbs/clickhouse/{{ item }}/*.sql' ]" - with_items: "{{ migration_versions.split(',') }}" - - name: Restoring clickhouse data - shell: | - file="{{ item|basename }}" - kubectl exec -n db clickhouse-0 -- /bin/bash -c "rm -rf /tmp/$file" - kubectl cp -n db {{ item }} clickhouse-0:/tmp/ - kubectl exec -n db clickhouse-0 -- /bin/bash -c "clickhouse-client < /tmp/$file" 2>&1 | tee -a "{{ playbook_dir }}"/clickhouse_init.log - args: - chdir: db/init_dbs/clickhouse/ - with_fileglob: "{{ db_path }}" - retries: 3 - delay: 60 - register: result - until: result.rc == 0 - tags: - - clickhouse - when: enterprise_edition_license|length > 0 diff --git a/scripts/helm/monitoring/kube-prometheus-stack/.helmignore b/scripts/helm/monitoring/kube-prometheus-stack/.helmignore deleted file mode 100644 index 93bf1ec02..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/.helmignore +++ /dev/null @@ -1,26 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj -# helm/charts -OWNERS -hack/ -ci/ -kube-prometheus-*.tgz diff --git a/scripts/helm/monitoring/kube-prometheus-stack/CONTRIBUTING.md b/scripts/helm/monitoring/kube-prometheus-stack/CONTRIBUTING.md deleted file mode 100644 index f6ce2a323..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/CONTRIBUTING.md +++ /dev/null @@ -1,12 +0,0 @@ -# Contributing Guidelines - -## How to contribute to this chart - -1. Fork this repository, develop and test your Chart. -1. Bump the chart version for every change. -1. Ensure PR title has the prefix `[kube-prometheus-stack]` -1. When making changes to rules or dashboards, see the README.md section on how to sync data from upstream repositories -1. Check the `hack/minikube` folder has scripts to set up minikube and components of this chart that will allow all components to be scraped. You can use this configuration when validating your changes. -1. Check for changes of RBAC rules. -1. Check for changes in CRD specs. -1. PR must pass the linter (`helm lint`) diff --git a/scripts/helm/monitoring/kube-prometheus-stack/Chart.lock b/scripts/helm/monitoring/kube-prometheus-stack/Chart.lock deleted file mode 100644 index 895a34d61..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/Chart.lock +++ /dev/null @@ -1,12 +0,0 @@ -dependencies: -- name: kube-state-metrics - repository: https://charts.helm.sh/stable - version: 2.9.4 -- name: prometheus-node-exporter - repository: https://prometheus-community.github.io/helm-charts - version: 1.12.0 -- name: grafana - repository: https://grafana.github.io/helm-charts - version: 5.8.16 -digest: sha256:75b1d23f315cc1b1d9b1f1d5e139559d680297c731b59641d72c5c38ac4a3a88 -generated: "2021-01-01T06:51:19.99073726Z" diff --git a/scripts/helm/monitoring/kube-prometheus-stack/Chart.yaml b/scripts/helm/monitoring/kube-prometheus-stack/Chart.yaml deleted file mode 100644 index 795280b8a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/Chart.yaml +++ /dev/null @@ -1,50 +0,0 @@ -annotations: - artifacthub.io/links: | - - name: Chart Source - url: https://github.com/prometheus-community/helm-charts - - name: Upstream Project - url: https://github.com/prometheus-operator/kube-prometheus - artifacthub.io/operator: "true" -apiVersion: v2 -appVersion: 0.44.0 -dependencies: -- condition: kubeStateMetrics.enabled - name: kube-state-metrics - repository: https://charts.helm.sh/stable - version: 2.9.* -- condition: nodeExporter.enabled - name: prometheus-node-exporter - repository: https://prometheus-community.github.io/helm-charts - version: 1.12.* -- condition: grafana.enabled - name: grafana - repository: https://grafana.github.io/helm-charts - version: 5.8.* -description: kube-prometheus-stack collects Kubernetes manifests, Grafana dashboards, - and Prometheus rules combined with documentation and scripts to provide easy to - operate end-to-end Kubernetes cluster monitoring with Prometheus using the Prometheus - Operator. -home: https://github.com/prometheus-operator/kube-prometheus -icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png -keywords: -- operator -- prometheus -- kube-prometheus -kubeVersion: '>=1.16.0-0' -maintainers: -- name: vsliouniaev -- name: bismarck -- email: gianrubio@gmail.com - name: gianrubio -- email: github.gkarthiks@gmail.com - name: gkarthiks -- email: scott@r6by.com - name: scottrigby -- email: miroslav.hadzhiev@gmail.com - name: Xtigyro -name: kube-prometheus-stack -sources: -- https://github.com/prometheus-community/helm-charts -- https://github.com/prometheus-operator/kube-prometheus -type: application -version: 12.9.1 diff --git a/scripts/helm/monitoring/kube-prometheus-stack/README.md b/scripts/helm/monitoring/kube-prometheus-stack/README.md deleted file mode 100644 index 37794b149..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/README.md +++ /dev/null @@ -1,396 +0,0 @@ -# kube-prometheus-stack - -Installs the [kube-prometheus stack](https://github.com/prometheus-operator/kube-prometheus), a collection of Kubernetes manifests, [Grafana](http://grafana.com/) dashboards, and [Prometheus rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/) combined with documentation and scripts to provide easy to operate end-to-end Kubernetes cluster monitoring with [Prometheus](https://prometheus.io/) using the [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator). - -See the [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus) README for details about components, dashboards, and alerts. - -_Note: This chart was formerly named `prometheus-operator` chart, now renamed to more clearly reflect that it installs the `kube-prometheus` project stack, within which Prometheus Operator is only one component._ - -## Prerequisites - -- Kubernetes 1.16+ -- Helm 3+ - -## Get Repo Info - -```console -helm repo add prometheus-community https://prometheus-community.github.io/helm-charts -helm repo add stable https://charts.helm.sh/stable -helm repo update -``` - -_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ - -## Install Chart - -```console -# Helm -$ helm install [RELEASE_NAME] prometheus-community/kube-prometheus-stack -``` - -_See [configuration](#configuration) below._ - -_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ - -## Dependencies - -By default this chart installs additional, dependent charts: - -- [stable/kube-state-metrics](https://github.com/helm/charts/tree/master/stable/kube-state-metrics) -- [prometheus-community/prometheus-node-exporter](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-node-exporter) -- [grafana/grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana) - -To disable dependencies during installation, see [multiple releases](#multiple-releases) below. - -_See [helm dependency](https://helm.sh/docs/helm/helm_dependency/) for command documentation._ - -## Uninstall Chart - -```console -# Helm -$ helm uninstall [RELEASE_NAME] -``` - -This removes all the Kubernetes components associated with the chart and deletes the release. - -_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ - -CRDs created by this chart are not removed by default and should be manually cleaned up: - -```console -kubectl delete crd alertmanagerconfigs.monitoring.coreos.com -kubectl delete crd alertmanagers.monitoring.coreos.com -kubectl delete crd podmonitors.monitoring.coreos.com -kubectl delete crd probes.monitoring.coreos.com -kubectl delete crd prometheuses.monitoring.coreos.com -kubectl delete crd prometheusrules.monitoring.coreos.com -kubectl delete crd servicemonitors.monitoring.coreos.com -kubectl delete crd thanosrulers.monitoring.coreos.com -``` - -## Upgrading Chart - -```console -# Helm -$ helm upgrade [RELEASE_NAME] prometheus-community/kube-prometheus-stack -``` - -With Helm v3, CRDs created by this chart are not updated by default and should be manually updated. -Consult also the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions). - -_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ - -### Upgrading an existing Release to a new major version - -A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an incompatible breaking change needing manual actions. - -### From 11.x to 12.x - -The chart was migrated to support only helm v3 and later. - -### From 10.x to 11.x - -Version 11 upgrades prometheus-operator from 0.42.x to 0.43.x. Starting with 0.43.x an additional `AlertmanagerConfigs` CRD is introduced. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRD manually before updating: - -```console -kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/release-0.43/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml -``` - -Version 11 removes the deprecated tlsProxy via ghostunnel in favor of native TLS support the prometheus-operator gained with v0.39.0. - -### From 9.x to 10.x - -Version 10 upgrades prometheus-operator from 0.38.x to 0.42.x. Starting with 0.40.x an additional `Probes` CRD is introduced. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRD manually before updating: - -```console -kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/release-0.42/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml -``` - -### From 8.x to 9.x - -Version 9 of the helm chart removes the existing `additionalScrapeConfigsExternal` in favour of `additionalScrapeConfigsSecret`. This change lets users specify the secret name and secret key to use for the additional scrape configuration of prometheus. This is useful for users that have prometheus-operator as a subchart and also have a template that creates the additional scrape configuration. - -### From 7.x to 8.x - -Due to new template functions being used in the rules in version 8.x.x of the chart, an upgrade to Prometheus Operator and Prometheus is necessary in order to support them. First, upgrade to the latest version of 7.x.x - -```console -helm upgrade [RELEASE_NAME] prometheus-community/kube-prometheus-stack --version 7.5.0 -``` - -Then upgrade to 8.x.x - -```console -helm upgrade [RELEASE_NAME] prometheus-community/kube-prometheus-stack --version [8.x.x] -``` - -Minimal recommended Prometheus version for this chart release is `2.12.x` - -### From 6.x to 7.x - -Due to a change in grafana subchart, version 7.x.x now requires Helm >= 2.12.0. - -### From 5.x to 6.x - -Due to a change in deployment labels of kube-state-metrics, the upgrade requires `helm upgrade --force` in order to re-create the deployment. If this is not done an error will occur indicating that the deployment cannot be modified: - -```console -invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app.kubernetes.io/name":"kube-state-metrics"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable -``` - -If this error has already been encountered, a `helm history` command can be used to determine which release has worked, then `helm rollback` to the release, then `helm upgrade --force` to this new one - -## Configuration - -See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments: - -```console -helm show values prometheus-community/kube-prometheus-stack -``` - -You may also `helm show values` on this chart's [dependencies](#dependencies) for additional options. - -### Multiple releases - -The same chart can be used to run multiple Prometheus instances in the same cluster if required. To achieve this, it is necessary to run only one instance of prometheus-operator and a pair of alertmanager pods for an HA configuration, while all other components need to be disabled. To disable a dependency during installation, set `kubeStateMetrics.enabled`, `nodeExporter.enabled` and `grafana.enabled` to `false`. - -## Work-Arounds for Known Issues - -### Running on private GKE clusters - -When Google configure the control plane for private clusters, they automatically configure VPC peering between your Kubernetes cluster’s network and a separate Google managed project. In order to restrict what Google are able to access within your cluster, the firewall rules configured restrict access to your Kubernetes pods. This means that in order to use the webhook component with a GKE private cluster, you must configure an additional firewall rule to allow the GKE control plane access to your webhook pod. - -You can read more information on how to add firewall rules for the GKE control plane nodes in the [GKE docs](https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters#add_firewall_rules) - -Alternatively, you can disable the hooks by setting `prometheusOperator.admissionWebhooks.enabled=false`. - -## PrometheusRules Admission Webhooks - -With Prometheus Operator version 0.30+, the core Prometheus Operator pod exposes an endpoint that will integrate with the `validatingwebhookconfiguration` Kubernetes feature to prevent malformed rules from being added to the cluster. - -### How the Chart Configures the Hooks - -A validating and mutating webhook configuration requires the endpoint to which the request is sent to use TLS. It is possible to set up custom certificates to do this, but in most cases, a self-signed certificate is enough. The setup of this component requires some more complex orchestration when using helm. The steps are created to be idempotent and to allow turning the feature on and off without running into helm quirks. - -1. A pre-install hook provisions a certificate into the same namespace using a format compatible with provisioning using end-user certificates. If the certificate already exists, the hook exits. -2. The prometheus operator pod is configured to use a TLS proxy container, which will load that certificate. -3. Validating and Mutating webhook configurations are created in the cluster, with their failure mode set to Ignore. This allows rules to be created by the same chart at the same time, even though the webhook has not yet been fully set up - it does not have the correct CA field set. -4. A post-install hook reads the CA from the secret created by step 1 and patches the Validating and Mutating webhook configurations. This process will allow a custom CA provisioned by some other process to also be patched into the webhook configurations. The chosen failure policy is also patched into the webhook configurations - -### Alternatives - -It should be possible to use [jetstack/cert-manager](https://github.com/jetstack/cert-manager) if a more complete solution is required, but it has not been tested. - -### Limitations - -Because the operator can only run as a single pod, there is potential for this component failure to cause rule deployment failure. Because this risk is outweighed by the benefit of having validation, the feature is enabled by default. - -## Developing Prometheus Rules and Grafana Dashboards - -This chart Grafana Dashboards and Prometheus Rules are just a copy from [prometheus-operator/prometheus-operator](https://github.com/prometheus-operator/prometheus-operator) and other sources, synced (with alterations) by scripts in [hack](hack) folder. In order to introduce any changes you need to first [add them to the original repo](https://github.com/prometheus-operator/kube-prometheus/blob/master/docs/developing-prometheus-rules-and-grafana-dashboards.md) and then sync there by scripts. - -## Further Information - -For more in-depth documentation of configuration options meanings, please see - -- [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator) -- [Prometheus](https://prometheus.io/docs/introduction/overview/) -- [Grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana#grafana-helm-chart) - -## prometheus.io/scrape - -The prometheus operator does not support annotation-based discovery of services, using the `PodMonitor` or `ServiceMonitor` CRD in its place as they provide far more configuration options. -For information on how to use PodMonitors/ServiceMonitors, please see the documentation on the `prometheus-operator/prometheus-operator` documentation here: - -- [ServiceMonitors](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md#include-servicemonitors) -- [PodMonitors](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md#include-podmonitors) -- [Running Exporters](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/running-exporters.md) - -By default, Prometheus discovers PodMonitors and ServiceMonitors within its namespace, that are labeled with the same release tag as the prometheus-operator release. -Sometimes, you may need to discover custom PodMonitors/ServiceMonitors, for example used to scrape data from third-party applications. -An easy way of doing this, without compromising the default PodMonitors/ServiceMonitors discovery, is allowing Prometheus to discover all PodMonitors/ServiceMonitors within its namespace, without applying label filtering. -To do so, you can set `prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues` and `prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues` to `false`. - -## Migrating from stable/prometheus-operator chart - -## Zero downtime - -Since `kube-prometheus-stack` is fully compatible with the `stable/prometheus-operator` chart, a migration without downtime can be achieved. -However, the old name prefix needs to be kept. If you want the new name please follow the step by step guide below (with downtime). - -You can override the name to achieve this: - -```console -helm upgrade prometheus-operator prometheus-community/kube-prometheus-stack -n monitoring --reuse-values --set nameOverride=prometheus-operator -``` - -**Note**: It is recommended to run this first with `--dry-run --debug`. - -## Redeploy with new name (downtime) - -If the **prometheus-operator** values are compatible with the new **kube-prometheus-stack** chart, please follow the below steps for migration: - -> The guide presumes that chart is deployed in `monitoring` namespace and the deployments are running there. If in other namespace, please replace the `monitoring` to the deployed namespace. - -1. Patch the PersistenceVolume created/used by the prometheus-operator chart to `Retain` claim policy: - - ```console - kubectl patch pv/<PersistentVolume name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' - ``` - - **Note:** To execute the above command, the user must have a cluster wide permission. Please refer [Kubernetes RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) - -2. Uninstall the **prometheus-operator** release and delete the existing PersistentVolumeClaim, and verify PV become Released. - - ```console - helm uninstall prometheus-operator -n monitoring - kubectl delete pvc/<PersistenceVolumeClaim name> -n monitoring - ``` - - Additionally, you have to manually remove the remaining `prometheus-operator-kubelet` service. - - ```console - kubectl delete service/prometheus-operator-kubelet -n kube-system - ``` - - You can choose to remove all your existing CRDs (ServiceMonitors, Podmonitors, etc.) if you want to. - -3. Remove current `spec.claimRef` values to change the PV's status from Released to Available. - - ```console - kubectl patch pv/<PersistentVolume name> --type json -p='[{"op": "remove", "path": "/spec/claimRef"}]' -n monitoring - ``` - -**Note:** To execute the above command, the user must have a cluster wide permission. Please refer to [Kubernetes RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) - -After these steps, proceed to a fresh **kube-prometheus-stack** installation and make sure the current release of **kube-prometheus-stack** matching the `volumeClaimTemplate` values in the `values.yaml`. - -The binding is done via matching a specific amount of storage requested and with certain access modes. - -For example, if you had storage specified as this with **prometheus-operator**: - -```yaml -volumeClaimTemplate: - spec: - storageClassName: gp2 - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 50Gi -``` - -You have to specify matching `volumeClaimTemplate` with 50Gi storage and `ReadWriteOnce` access mode. - -Additionally, you should check the current AZ of your legacy installation's PV, and configure the fresh release to use the same AZ as the old one. If the pods are in a different AZ than the PV, the release will fail to bind the existing one, hence creating a new PV. - -This can be achieved either by specifying the labels through `values.yaml`, e.g. setting `prometheus.prometheusSpec.nodeSelector` to: - -```yaml -nodeSelector: - failure-domain.beta.kubernetes.io/zone: east-west-1a -``` - -or passing these values as `--set` overrides during installation. - -The new release should now re-attach your previously released PV with its content. - -## Migrating from coreos/prometheus-operator chart - -The multiple charts have been combined into a single chart that installs prometheus operator, prometheus, alertmanager, grafana as well as the multitude of exporters necessary to monitor a cluster. - -There is no simple and direct migration path between the charts as the changes are extensive and intended to make the chart easier to support. - -The capabilities of the old chart are all available in the new chart, including the ability to run multiple prometheus instances on a single cluster - you will need to disable the parts of the chart you do not wish to deploy. - -You can check out the tickets for this change [here](https://github.com/prometheus-operator/prometheus-operator/issues/592) and [here](https://github.com/helm/charts/pull/6765). - -### High-level overview of Changes - -#### Added dependencies - -The chart has added 3 [dependencies](#dependencies). - -- Node-Exporter, Kube-State-Metrics: These components are loaded as dependencies into the chart, and are relatively simple components -- Grafana: The Grafana chart is more feature-rich than this chart - it contains a sidecar that is able to load data sources and dashboards from configmaps deployed into the same cluster. For more information check out the [documentation for the chart](https://github.com/helm/charts/tree/master/stable/grafana) - -#### Kubelet Service - -Because the kubelet service has a new name in the chart, make sure to clean up the old kubelet service in the `kube-system` namespace to prevent counting container metrics twice. - -#### Persistent Volumes - -If you would like to keep the data of the current persistent volumes, it should be possible to attach existing volumes to new PVCs and PVs that are created using the conventions in the new chart. For example, in order to use an existing Azure disk for a helm release called `prometheus-migration` the following resources can be created: - -```yaml -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pvc-prometheus-migration-prometheus-0 -spec: - accessModes: - - ReadWriteOnce - azureDisk: - cachingMode: None - diskName: pvc-prometheus-migration-prometheus-0 - diskURI: /subscriptions/f5125d82-2622-4c50-8d25-3f7ba3e9ac4b/resourceGroups/sample-migration-resource-group/providers/Microsoft.Compute/disks/pvc-prometheus-migration-prometheus-0 - fsType: "" - kind: Managed - readOnly: false - capacity: - storage: 1Gi - persistentVolumeReclaimPolicy: Delete - storageClassName: prometheus - volumeMode: Filesystem -``` - -```yaml -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - app: prometheus - prometheus: prometheus-migration-prometheus - name: prometheus-prometheus-migration-prometheus-db-prometheus-prometheus-migration-prometheus-0 - namespace: monitoring -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - storageClassName: prometheus - volumeMode: Filesystem - volumeName: pvc-prometheus-migration-prometheus-0 -``` - -The PVC will take ownership of the PV and when you create a release using a persistent volume claim template it will use the existing PVCs as they match the naming convention used by the chart. For other cloud providers similar approaches can be used. - -#### KubeProxy - -The metrics bind address of kube-proxy is default to `127.0.0.1:10249` that prometheus instances **cannot** access to. You should expose metrics by changing `metricsBindAddress` field value to `0.0.0.0:10249` if you want to collect them. - -Depending on the cluster, the relevant part `config.conf` will be in ConfigMap `kube-system/kube-proxy` or `kube-system/kube-proxy-config`. For example: - -```console -kubectl -n kube-system edit cm kube-proxy -``` - -```yaml -apiVersion: v1 -data: - config.conf: |- - apiVersion: kubeproxy.config.k8s.io/v1alpha1 - kind: KubeProxyConfiguration - # ... - # metricsBindAddress: 127.0.0.1:10249 - metricsBindAddress: 0.0.0.0:10249 - # ... - kubeconfig.conf: |- - # ... -kind: ConfigMap -metadata: - labels: - app: kube-proxy - name: kube-proxy - namespace: kube-system -``` diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/.helmignore b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/.helmignore deleted file mode 100644 index 8cade1318..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.vscode -.project -.idea/ -*.tmproj -OWNERS diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/Chart.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/Chart.yaml deleted file mode 100644 index 2f6e0761a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/Chart.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -appVersion: 7.2.1 -description: The leading tool for querying and visualizing time series and metrics. -home: https://grafana.net -icon: https://raw.githubusercontent.com/grafana/grafana/master/public/img/logo_transparent_400x.png -kubeVersion: ^1.8.0-0 -maintainers: -- email: zanhsieh@gmail.com - name: zanhsieh -- email: rluckie@cisco.com - name: rtluckie -- email: maor.friedman@redhat.com - name: maorfr -- email: miroslav.hadzhiev@gmail.com - name: Xtigyro -name: grafana -sources: -- https://github.com/grafana/grafana -version: 5.8.16 diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/README.md b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/README.md deleted file mode 100644 index 2dc1822ec..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/README.md +++ /dev/null @@ -1,499 +0,0 @@ -# Grafana Helm Chart - -* Installs the web dashboarding system [Grafana](http://grafana.org/) - -## Get Repo Info - -```console -helm repo add grafana https://grafana.github.io/helm-charts -helm repo update -``` - -_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -helm install --name my-release grafana/grafana -``` - -## Uninstalling the Chart - -To uninstall/delete the my-release deployment: - -```console -helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Upgrading an existing Release to a new major version - -A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an -incompatible breaking change needing manual actions. - -### To 4.0.0 (And 3.12.1) - -This version requires Helm >= 2.12.0. - -### To 5.0.0 - -You have to add --force to your helm upgrade command as the labels of the chart have changed. - -## Configuration - -| Parameter | Description | Default | -|-------------------------------------------|-----------------------------------------------|---------------------------------------------------------| -| `replicas` | Number of nodes | `1` | -| `podDisruptionBudget.minAvailable` | Pod disruption minimum available | `nil` | -| `podDisruptionBudget.maxUnavailable` | Pod disruption maximum unavailable | `nil` | -| `deploymentStrategy` | Deployment strategy | `{ "type": "RollingUpdate" }` | -| `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }` | -| `readinessProbe` | Readiness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } }`| -| `securityContext` | Deployment securityContext | `{"runAsUser": 472, "runAsGroup": 472, "fsGroup": 472}` | -| `priorityClassName` | Name of Priority Class to assign pods | `nil` | -| `image.repository` | Image repository | `grafana/grafana` | -| `image.tag` | Image tag (`Must be >= 5.0.0`) | `7.0.3` | -| `image.sha` | Image sha (optional) | `17cbd08b9515fda889ca959e9d72ee6f3327c8f1844a3336dfd952134f38e2fe` | -| `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Image pull secrets | `{}` | -| `service.type` | Kubernetes service type | `ClusterIP` | -| `service.port` | Kubernetes port where service is exposed | `80` | -| `service.portName` | Name of the port on the service | `service` | -| `service.targetPort` | Internal service is port | `3000` | -| `service.nodePort` | Kubernetes service nodePort | `nil` | -| `service.annotations` | Service annotations | `{}` | -| `service.labels` | Custom labels | `{}` | -| `service.clusterIP` | internal cluster service IP | `nil` | -| `service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `nil` | -| `service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to lb (if supported) | `[]` | -| `service.externalIPs` | service external IP addresses | `[]` | -| `extraExposePorts` | Additional service ports for sidecar containers| `[]` | -| `hostAliases` | adds rules to the pod's /etc/hosts | `[]` | -| `ingress.enabled` | Enables Ingress | `false` | -| `ingress.annotations` | Ingress annotations (values are templated) | `{}` | -| `ingress.labels` | Custom labels | `{}` | -| `ingress.path` | Ingress accepted path | `/` | -| `ingress.hosts` | Ingress accepted hostnames | `["chart-example.local"]` | -| `ingress.extraPaths` | Ingress extra paths to prepend to every host configuration. Useful when configuring [custom actions with AWS ALB Ingress Controller](https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/ingress/annotation/#actions). | `[]` | -| `ingress.tls` | Ingress TLS configuration | `[]` | -| `resources` | CPU/Memory resource requests/limits | `{}` | -| `nodeSelector` | Node labels for pod assignment | `{}` | -| `tolerations` | Toleration labels for pod assignment | `[]` | -| `affinity` | Affinity settings for pod assignment | `{}` | -| `extraInitContainers` | Init containers to add to the grafana pod | `{}` | -| `extraContainers` | Sidecar containers to add to the grafana pod | `{}` | -| `extraContainerVolumes` | Volumes that can be mounted in sidecar containers | `[]` | -| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | -| `persistence.enabled` | Use persistent volume to store data | `false` | -| `persistence.type` | Type of persistence (`pvc` or `statefulset`) | `pvc` | -| `persistence.size` | Size of persistent volume claim | `10Gi` | -| `persistence.existingClaim` | Use an existing PVC to persist data | `nil` | -| `persistence.storageClassName` | Type of persistent volume claim | `nil` | -| `persistence.accessModes` | Persistence access modes | `[ReadWriteOnce]` | -| `persistence.annotations` | PersistentVolumeClaim annotations | `{}` | -| `persistence.finalizers` | PersistentVolumeClaim finalizers | `[ "kubernetes.io/pvc-protection" ]` | -| `persistence.subPath` | Mount a sub dir of the persistent volume | `nil` | -| `initChownData.enabled` | If false, don't reset data ownership at startup | true | -| `initChownData.image.repository` | init-chown-data container image repository | `busybox` | -| `initChownData.image.tag` | init-chown-data container image tag | `1.31.1` | -| `initChownData.image.sha` | init-chown-data container image sha (optional)| `""` | -| `initChownData.image.pullPolicy` | init-chown-data container image pull policy | `IfNotPresent` | -| `initChownData.resources` | init-chown-data pod resource requests & limits | `{}` | -| `schedulerName` | Alternate scheduler name | `nil` | -| `env` | Extra environment variables passed to pods | `{}` | -| `envValueFrom` | Environment variables from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. | `{}` | -| `envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | -| `envRenderSecret` | Sensible environment variables passed to pods and stored as secret | `{}` | -| `extraSecretMounts` | Additional grafana server secret mounts | `[]` | -| `extraVolumeMounts` | Additional grafana server volume mounts | `[]` | -| `extraConfigmapMounts` | Additional grafana server configMap volume mounts | `[]` | -| `extraEmptyDirMounts` | Additional grafana server emptyDir volume mounts | `[]` | -| `plugins` | Plugins to be loaded along with Grafana | `[]` | -| `datasources` | Configure grafana datasources (passed through tpl) | `{}` | -| `notifiers` | Configure grafana notifiers | `{}` | -| `dashboardProviders` | Configure grafana dashboard providers | `{}` | -| `dashboards` | Dashboards to import | `{}` | -| `dashboardsConfigMaps` | ConfigMaps reference that contains dashboards | `{}` | -| `grafana.ini` | Grafana's primary configuration | `{}` | -| `ldap.enabled` | Enable LDAP authentication | `false` | -| `ldap.existingSecret` | The name of an existing secret containing the `ldap.toml` file, this must have the key `ldap-toml`. | `""` | -| `ldap.config` | Grafana's LDAP configuration | `""` | -| `annotations` | Deployment annotations | `{}` | -| `labels` | Deployment labels | `{}` | -| `podAnnotations` | Pod annotations | `{}` | -| `podLabels` | Pod labels | `{}` | -| `podPortName` | Name of the grafana port on the pod | `grafana` | -| `sidecar.image.repository` | Sidecar image repository | `kiwigrid/k8s-sidecar` | -| `sidecar.image.tag` | Sidecar image tag | `1.1.0` | -| `sidecar.image.sha` | Sidecar image sha (optional) | `""` | -| `sidecar.imagePullPolicy` | Sidecar image pull policy | `IfNotPresent` | -| `sidecar.resources` | Sidecar resources | `{}` | -| `sidecar.enableUniqueFilenames` | Sets the kiwigrid/k8s-sidecar UNIQUE_FILENAMES environment variable | `false` | -| `sidecar.dashboards.enabled` | Enables the cluster wide search for dashboards and adds/updates/deletes them in grafana | `false` | -| `sidecar.dashboards.SCProvider` | Enables creation of sidecar provider | `true` | -| `sidecar.dashboards.provider.name` | Unique name of the grafana provider | `sidecarProvider` | -| `sidecar.dashboards.provider.orgid` | Id of the organisation, to which the dashboards should be added | `1` | -| `sidecar.dashboards.provider.folder` | Logical folder in which grafana groups dashboards | `""` | -| `sidecar.dashboards.provider.disableDelete` | Activate to avoid the deletion of imported dashboards | `false` | -| `sidecar.dashboards.provider.allowUiUpdates` | Allow updating provisioned dashboards from the UI | `false` | -| `sidecar.dashboards.provider.type` | Provider type | `file` | -| `sidecar.dashboards.provider.foldersFromFilesStructure` | Allow Grafana to replicate dashboard structure from filesystem. | `false` | -| `sidecar.dashboards.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` | -| `sidecar.skipTlsVerify` | Set to true to skip tls verification for kube api calls | `nil` | -| `sidecar.dashboards.label` | Label that config maps with dashboards should have to be added | `grafana_dashboard` | -| `sidecar.dashboards.folder` | Folder in the pod that should hold the collected dashboards (unless `sidecar.dashboards.defaultFolderName` is set). This path will be mounted. | `/tmp/dashboards` | -| `sidecar.dashboards.folderAnnotation` | The annotation the sidecar will look for in configmaps to override the destination folder for files | `nil` | -| `sidecar.dashboards.defaultFolderName` | The default folder name, it will create a subfolder under the `sidecar.dashboards.folder` and put dashboards in there instead | `nil` | -| `sidecar.dashboards.searchNamespace` | If specified, the sidecar will search for dashboard config-maps inside this namespace. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces | `nil` | -| `sidecar.datasources.enabled` | Enables the cluster wide search for datasources and adds/updates/deletes them in grafana |`false` | -| `sidecar.datasources.label` | Label that config maps with datasources should have to be added | `grafana_datasource` | -| `sidecar.datasources.searchNamespace` | If specified, the sidecar will search for datasources config-maps inside this namespace. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces | `nil` | -| `sidecar.notifiers.enabled` | Enables the cluster wide search for notifiers and adds/updates/deletes them in grafana |`false` | -| `sidecar.notifiers.label` | Label that config maps with notifiers should have to be added | `grafana_notifier` | -| `sidecar.notifiers.searchNamespace` | If specified, the sidecar will search for notifiers config-maps (or secrets) inside this namespace. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces | `nil` | -| `smtp.existingSecret` | The name of an existing secret containing the SMTP credentials. | `""` | -| `smtp.userKey` | The key in the existing SMTP secret containing the username. | `"user"` | -| `smtp.passwordKey` | The key in the existing SMTP secret containing the password. | `"password"` | -| `admin.existingSecret` | The name of an existing secret containing the admin credentials. | `""` | -| `admin.userKey` | The key in the existing admin secret containing the username. | `"admin-user"` | -| `admin.passwordKey` | The key in the existing admin secret containing the password. | `"admin-password"` | -| `serviceAccount.annotations` | ServiceAccount annotations | | -| `serviceAccount.create` | Create service account | `true` | -| `serviceAccount.name` | Service account name to use, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `` | -| `serviceAccount.nameTest` | Service account name to use for test, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `nil` | -| `rbac.create` | Create and use RBAC resources | `true` | -| `rbac.namespaced` | Creates Role and Rolebinding instead of the default ClusterRole and ClusteRoleBindings for the grafana instance | `false` | -| `rbac.useExistingRole` | Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here. | `nil` | -| `rbac.pspEnabled` | Create PodSecurityPolicy (with `rbac.create`, grant roles permissions as well) | `true` | -| `rbac.pspUseAppArmor` | Enforce AppArmor in created PodSecurityPolicy (requires `rbac.pspEnabled`) | `true` | -| `rbac.extraRoleRules` | Additional rules to add to the Role | [] | -| `rbac.extraClusterRoleRules` | Additional rules to add to the ClusterRole | [] | -| `command` | Define command to be executed by grafana container at startup | `nil` | -| `testFramework.enabled` | Whether to create test-related resources | `true` | -| `testFramework.image` | `test-framework` image repository. | `bats/bats` | -| `testFramework.tag` | `test-framework` image tag. | `v1.1.0` | -| `testFramework.imagePullPolicy` | `test-framework` image pull policy. | `IfNotPresent` | -| `testFramework.securityContext` | `test-framework` securityContext | `{}` | -| `downloadDashboards.env` | Environment variables to be passed to the `download-dashboards` container | `{}` | -| `downloadDashboards.resources` | Resources of `download-dashboards` container | `{}` | -| `downloadDashboardsImage.repository` | Curl docker image repo | `curlimages/curl` | -| `downloadDashboardsImage.tag` | Curl docker image tag | `7.73.0` | -| `downloadDashboardsImage.sha` | Curl docker image sha (optional) | `""` | -| `downloadDashboardsImage.pullPolicy` | Curl docker image pull policy | `IfNotPresent` | -| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) | -| `serviceMonitor.enabled` | Use servicemonitor from prometheus operator | `false` | -| `serviceMonitor.namespace` | Namespace this servicemonitor is installed in | | -| `serviceMonitor.interval` | How frequently Prometheus should scrape | `1m` | -| `serviceMonitor.path` | Path to scrape | `/metrics` | -| `serviceMonitor.labels` | Labels for the servicemonitor passed to Prometheus Operator | `{}` | -| `serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `30s` | -| `serviceMonitor.relabelings` | MetricRelabelConfigs to apply to samples before ingestion. | `[]` | -| `revisionHistoryLimit` | Number of old ReplicaSets to retain | `10` | -| `imageRenderer.enabled` | Enable the image-renderer deployment & service | `false` | -| `imageRenderer.image.repository` | image-renderer Image repository | `grafana/grafana-image-renderer` | -| `imageRenderer.image.tag` | image-renderer Image tag | `latest` | -| `imageRenderer.image.sha` | image-renderer Image sha (optional) | `""` | -| `imageRenderer.image.pullPolicy` | image-renderer ImagePullPolicy | `Always` | -| `imageRenderer.env` | extra env-vars for image-renderer | `{}` | -| `imageRenderer.securityContext` | image-renderer deployment securityContext | `{}` | -| `imageRenderer.hostAliases` | image-renderer deployment Host Aliases | `[]` | -| `imageRenderer.priorityClassName` | image-renderer deployment priority class | `''` | -| `imageRenderer.service.portName` | image-renderer service port name | `'http'` | -| `imageRenderer.service.port` | image-renderer service port used by both service and deployment | `8081` | -| `imageRenderer.podPortName` | name of the image-renderer port on the pod | `http` | -| `imageRenderer.revisionHistoryLimit` | number of image-renderer replica sets to keep | `10` | -| `imageRenderer.networkPolicy.limitIngress` | Enable a NetworkPolicy to limit inbound traffic from only the created grafana pods | `true` | -| `imageRenderer.networkPolicy.limitEgress` | Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods | `false` | -| `imageRenderer.resources` | Set resource limits for image-renderer pdos | `{}` | - -### Example ingress with path - -With grafana 6.3 and above -```yaml -grafana.ini: - server: - domain: monitoring.example.com - root_url: "%(protocol)s://%(domain)s/grafana" - serve_from_sub_path: true -ingress: - enabled: true - hosts: - - "monitoring.example.com" - path: "/grafana" -``` - -### Example of extraVolumeMounts - -```yaml -- extraVolumeMounts: - - name: plugins - mountPath: /var/lib/grafana/plugins - subPath: configs/grafana/plugins - existingClaim: existing-grafana-claim - readOnly: false -``` - -## Import dashboards - -There are a few methods to import dashboards to Grafana. Below are some examples and explanations as to how to use each method: - -```yaml -dashboards: - default: - some-dashboard: - json: | - { - "annotations": - - ... - # Complete json file here - ... - - "title": "Some Dashboard", - "uid": "abcd1234", - "version": 1 - } - custom-dashboard: - # This is a path to a file inside the dashboards directory inside the chart directory - file: dashboards/custom-dashboard.json - prometheus-stats: - # Ref: https://grafana.com/dashboards/2 - gnetId: 2 - revision: 2 - datasource: Prometheus - local-dashboard: - url: https://raw.githubusercontent.com/user/repository/master/dashboards/dashboard.json -``` - -## BASE64 dashboards - -Dashboards could be stored on a server that does not return JSON directly and instead of it returns a Base64 encoded file (e.g. Gerrit) -A new parameter has been added to the url use case so if you specify a b64content value equals to true after the url entry a Base64 decoding is applied before save the file to disk. -If this entry is not set or is equals to false not decoding is applied to the file before saving it to disk. - -### Gerrit use case - -Gerrit API for download files has the following schema: <https://yourgerritserver/a/{project-name}/branches/{branch-id}/files/{file-id}/content> where {project-name} and -{file-id} usually has '/' in their values and so they MUST be replaced by %2F so if project-name is user/repo, branch-id is master and file-id is equals to dir1/dir2/dashboard -the url value is <https://yourgerritserver/a/user%2Frepo/branches/master/files/dir1%2Fdir2%2Fdashboard/content> - -## Sidecar for dashboards - -If the parameter `sidecar.dashboards.enabled` is set, a sidecar container is deployed in the grafana -pod. This container watches all configmaps (or secrets) in the cluster and filters out the ones with -a label as defined in `sidecar.dashboards.label`. The files defined in those configmaps are written -to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported -dashboards are deleted/updated. - -A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside -one configmap is currently not properly mirrored in grafana. - -Example dashboard config: - -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: sample-grafana-dashboard - labels: - grafana_dashboard: "1" -data: - k8s-dashboard.json: |- - [...] -``` - -## Sidecar for datasources - -If the parameter `sidecar.datasources.enabled` is set, an init container is deployed in the grafana -pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and -filters out the ones with a label as defined in `sidecar.datasources.label`. The files defined in -those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, -the data sources in grafana can be imported. The secrets must be created before `helm install` so -that the datasources init container can list the secrets. - -Secrets are recommended over configmaps for this usecase because datasources usually contain private -data like usernames and passwords. Secrets are the more appropriate cluster resource to manage those. - -Example datasource config adapted from [Grafana](http://docs.grafana.org/administration/provisioning/#example-datasource-config-file): - -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: sample-grafana-datasource - labels: - grafana_datasource: "1" -type: Opaque -stringData: - datasource.yaml: |- - # config file version - apiVersion: 1 - - # list of datasources that should be deleted from the database - deleteDatasources: - - name: Graphite - orgId: 1 - - # list of datasources to insert/update depending - # whats available in the database - datasources: - # <string, required> name of the datasource. Required - - name: Graphite - # <string, required> datasource type. Required - type: graphite - # <string, required> access mode. proxy or direct (Server or Browser in the UI). Required - access: proxy - # <int> org id. will default to orgId 1 if not specified - orgId: 1 - # <string> url - url: http://localhost:8080 - # <string> database password, if used - password: - # <string> database user, if used - user: - # <string> database name, if used - database: - # <bool> enable/disable basic auth - basicAuth: - # <string> basic auth username - basicAuthUser: - # <string> basic auth password - basicAuthPassword: - # <bool> enable/disable with credentials headers - withCredentials: - # <bool> mark as default datasource. Max one per org - isDefault: - # <map> fields that will be converted to json and stored in json_data - jsonData: - graphiteVersion: "1.1" - tlsAuth: true - tlsAuthWithCACert: true - # <string> json object of data that will be encrypted. - secureJsonData: - tlsCACert: "..." - tlsClientCert: "..." - tlsClientKey: "..." - version: 1 - # <bool> allow users to edit datasources from the UI. - editable: false - -``` - -## Sidecar for notifiers - -If the parameter `sidecar.notifiers.enabled` is set, an init container is deployed in the grafana -pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and -filters out the ones with a label as defined in `sidecar.notifiers.label`. The files defined in -those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, -the notification channels in grafana can be imported. The secrets must be created before -`helm install` so that the notifiers init container can list the secrets. - -Secrets are recommended over configmaps for this usecase because alert notification channels usually contain -private data like SMTP usernames and passwords. Secrets are the more appropriate cluster resource to manage those. - -Example datasource config adapted from [Grafana](https://grafana.com/docs/grafana/latest/administration/provisioning/#alert-notification-channels): - -```yaml -notifiers: - - name: notification-channel-1 - type: slack - uid: notifier1 - # either - org_id: 2 - # or - org_name: Main Org. - is_default: true - send_reminder: true - frequency: 1h - disable_resolve_message: false - # See `Supported Settings` section for settings supporter for each - # alert notification type. - settings: - recipient: 'XXX' - token: 'xoxb' - uploadImage: true - url: https://slack.com - -delete_notifiers: - - name: notification-channel-1 - uid: notifier1 - org_id: 2 - - name: notification-channel-2 - # default org_id: 1 -``` - -## How to serve Grafana with a path prefix (/grafana) - -In order to serve Grafana with a prefix (e.g., <http://example.com/grafana>), add the following to your values.yaml. - -```yaml -ingress: - enabled: true - annotations: - kubernetes.io/ingress.class: "nginx" - nginx.ingress.kubernetes.io/rewrite-target: /$1 - nginx.ingress.kubernetes.io/use-regex: "true" - - path: /grafana/?(.*) - hosts: - - k8s.example.dev - -grafana.ini: - server: - root_url: http://localhost:3000/grafana # this host can be localhost -``` - -## How to securely reference secrets in grafana.ini - -This example uses Grafana uses [file providers](https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider) for secret values and the `extraSecretMounts` configuration flag (Additional grafana server secret mounts) to mount the secrets. - -In grafana.ini: - -```yaml -grafana.ini: - [auth.generic_oauth] - enabled = true - client_id = $__file{/etc/secrets/auth_generic_oauth/client_id} - client_secret = $__file{/etc/secrets/auth_generic_oauth/client_secret} -``` - -Existing secret, or created along with helm: - -```yaml ---- -apiVersion: v1 -kind: Secret -metadata: - name: auth-generic-oauth-secret -type: Opaque -stringData: - client_id: <value> - client_secret: <value> -``` - -Include in the `extraSecretMounts` configuration flag: - -```yaml -- extraSecretMounts: - - name: auth-generic-oauth-secret-mount - secretName: auth-generic-oauth-secret - defaultMode: 0440 - mountPath: /etc/secrets/auth_generic_oauth - readOnly: true -``` - -## Image Renderer Plug-In - -This chart supports enabling [remote image rendering](https://github.com/grafana/grafana-image-renderer/blob/master/docs/remote_rendering_using_docker.md) - -```yaml -imageRenderer: - enabled: true -``` - -### Image Renderer NetworkPolicy - -By default the image-renderer pods will have a network policy which only allows ingress traffic from the created grafana instance diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/default-values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/default-values.yaml deleted file mode 100644 index fc2ba605a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/default-values.yaml +++ /dev/null @@ -1 +0,0 @@ -# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml. diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-dashboard-json-values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-dashboard-json-values.yaml deleted file mode 100644 index e0c4e4168..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-dashboard-json-values.yaml +++ /dev/null @@ -1,53 +0,0 @@ -dashboards: - my-provider: - my-awesome-dashboard: - # An empty but valid dashboard - json: | - { - "__inputs": [], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "6.3.5" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": null, - "links": [], - "panels": [], - "schemaVersion": 19, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": ["5s"] - }, - "timezone": "", - "title": "Dummy Dashboard", - "uid": "IdcYQooWk", - "version": 1 - } - datasource: Prometheus diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-dashboard-values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-dashboard-values.yaml deleted file mode 100644 index 7b662c5fd..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-dashboard-values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -dashboards: - my-provider: - my-awesome-dashboard: - gnetId: 10000 - revision: 1 - datasource: Prometheus -dashboardProviders: - dashboardproviders.yaml: - apiVersion: 1 - providers: - - name: 'my-provider' - orgId: 1 - folder: '' - type: file - updateIntervalSeconds: 10 - disableDeletion: true - editable: true - options: - path: /var/lib/grafana/dashboards/my-provider diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-image-renderer-values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-image-renderer-values.yaml deleted file mode 100644 index 32f307434..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/ci/with-image-renderer-values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -podLabels: - customLableA: Aaaaa -imageRenderer: - enabled: true - env: - RENDERING_ARGS: --disable-gpu,--window-size=1280x758 - RENDERING_MODE: clustered - podLabels: - customLableB: Bbbbb - networkPolicy: - limitIngress: true - limitEgress: true - resources: - limits: - cpu: 1000m - memory: 1000Mi - requests: - cpu: 500m - memory: 50Mi diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/dashboards/custom-dashboard.json b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/dashboards/custom-dashboard.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/dashboards/custom-dashboard.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/NOTES.txt b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/NOTES.txt deleted file mode 100644 index 1fc8436d9..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/NOTES.txt +++ /dev/null @@ -1,54 +0,0 @@ -1. Get your '{{ .Values.adminUser }}' user password by running: - - kubectl get secret --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath="{.data.admin-password}" | base64 --decode ; echo - -2. The Grafana server can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: - - {{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}.svc.cluster.local -{{ if .Values.ingress.enabled }} - If you bind grafana to 80, please update values in values.yaml and reinstall: - ``` - securityContext: - runAsUser: 0 - runAsGroup: 0 - fsGroup: 0 - - command: - - "setcap" - - "'cap_net_bind_service=+ep'" - - "/usr/sbin/grafana-server &&" - - "sh" - - "/run.sh" - ``` - Details refer to https://grafana.com/docs/installation/configuration/#http-port. - Or grafana would always crash. - - From outside the cluster, the server URL(s) are: -{{- range .Values.ingress.hosts }} - http://{{ . }} -{{- end }} -{{ else }} - Get the Grafana URL to visit by running these commands in the same shell: -{{ if contains "NodePort" .Values.service.type -}} - export NODE_PORT=$(kubectl get --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "grafana.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{ else if contains "LoadBalancer" .Values.service.type -}} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc --namespace {{ template "grafana.namespace" . }} -w {{ template "grafana.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - http://$SERVICE_IP:{{ .Values.service.port -}} -{{ else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ template "grafana.namespace" . }} -l "app.kubernetes.io/name={{ template "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - kubectl --namespace {{ template "grafana.namespace" . }} port-forward $POD_NAME 3000 -{{- end }} -{{- end }} - -3. Login with the password from step 1 and the username: {{ .Values.adminUser }} - -{{- if not .Values.persistence.enabled }} -################################################################################# -###### WARNING: Persistence is disabled!!! You will lose your data when ##### -###### the Grafana pod is terminated. ##### -################################################################################# -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/_helpers.tpl b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/_helpers.tpl deleted file mode 100644 index 4dd88345b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/_helpers.tpl +++ /dev/null @@ -1,102 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "grafana.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "grafana.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "grafana.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create the name of the service account -*/}} -{{- define "grafana.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (include "grafana.fullname" .) .Values.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{- define "grafana.serviceAccountNameTest" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (print (include "grafana.fullname" .) "-test") .Values.serviceAccount.nameTest }} -{{- else -}} - {{ default "default" .Values.serviceAccount.nameTest }} -{{- end -}} -{{- end -}} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "grafana.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "grafana.labels" -}} -helm.sh/chart: {{ include "grafana.chart" . }} -{{ include "grafana.selectorLabels" . }} -{{- if or .Chart.AppVersion .Values.image.tag }} -app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Selector labels -*/}} -{{- define "grafana.selectorLabels" -}} -app.kubernetes.io/name: {{ include "grafana.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "grafana.imageRenderer.labels" -}} -helm.sh/chart: {{ include "grafana.chart" . }} -{{ include "grafana.imageRenderer.selectorLabels" . }} -{{- if or .Chart.AppVersion .Values.image.tag }} -app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Selector labels ImageRenderer -*/}} -{{- define "grafana.imageRenderer.selectorLabels" -}} -app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/_pod.tpl b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/_pod.tpl deleted file mode 100644 index a9e471ca5..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/_pod.tpl +++ /dev/null @@ -1,464 +0,0 @@ - -{{- define "grafana.pod" -}} -{{- if .Values.schedulerName }} -schedulerName: "{{ .Values.schedulerName }}" -{{- end }} -serviceAccountName: {{ template "grafana.serviceAccountName" . }} -{{- if .Values.securityContext }} -securityContext: -{{ toYaml .Values.securityContext | indent 2 }} -{{- end }} -{{- if .Values.hostAliases }} -hostAliases: -{{ toYaml .Values.hostAliases | indent 2 }} -{{- end }} -{{- if .Values.priorityClassName }} -priorityClassName: {{ .Values.priorityClassName }} -{{- end }} -{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.sidecar.datasources.enabled .Values.sidecar.notifiers.enabled .Values.extraInitContainers) }} -initContainers: -{{- end }} -{{- if ( and .Values.persistence.enabled .Values.initChownData.enabled ) }} - - name: init-chown-data - {{- if .Values.initChownData.image.sha }} - image: "{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" - {{- else }} - image: "{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.initChownData.image.pullPolicy }} - securityContext: - runAsNonRoot: false - runAsUser: 0 - command: ["chown", "-R", "{{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }}", "/var/lib/grafana"] - resources: -{{ toYaml .Values.initChownData.resources | indent 6 }} - volumeMounts: - - name: storage - mountPath: "/var/lib/grafana" -{{- if .Values.persistence.subPath }} - subPath: {{ .Values.persistence.subPath }} -{{- end }} -{{- end }} -{{- if .Values.dashboards }} - - name: download-dashboards - {{- if .Values.downloadDashboardsImage.sha }} - image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" - {{- else }} - image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.downloadDashboardsImage.pullPolicy }} - command: ["/bin/sh"] - args: [ "-c", "mkdir -p /var/lib/grafana/dashboards/default && /bin/sh /etc/grafana/download_dashboards.sh" ] - resources: -{{ toYaml .Values.downloadDashboards.resources | indent 6 }} - env: -{{- range $key, $value := .Values.downloadDashboards.env }} - - name: "{{ $key }}" - value: "{{ $value }}" -{{- end }} - volumeMounts: - - name: config - mountPath: "/etc/grafana/download_dashboards.sh" - subPath: download_dashboards.sh - - name: storage - mountPath: "/var/lib/grafana" -{{- if .Values.persistence.subPath }} - subPath: {{ .Values.persistence.subPath }} -{{- end }} - {{- range .Values.extraSecretMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - readOnly: {{ .readOnly }} - {{- end }} -{{- end }} -{{- if .Values.sidecar.datasources.enabled }} - - name: {{ template "grafana.name" . }}-sc-datasources - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - - name: METHOD - value: LIST - - name: LABEL - value: "{{ .Values.sidecar.datasources.label }}" - - name: FOLDER - value: "/etc/grafana/provisioning/datasources" - - name: RESOURCE - value: "both" - {{- if .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" - {{- end }} - {{- if .Values.sidecar.datasources.searchNamespace }} - - name: NAMESPACE - value: "{{ .Values.sidecar.datasources.searchNamespace }}" - {{- end }} - {{- if .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" - {{- end }} - resources: -{{ toYaml .Values.sidecar.resources | indent 6 }} - volumeMounts: - - name: sc-datasources-volume - mountPath: "/etc/grafana/provisioning/datasources" -{{- end}} -{{- if .Values.sidecar.notifiers.enabled }} - - name: {{ template "grafana.name" . }}-sc-notifiers - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - - name: METHOD - value: LIST - - name: LABEL - value: "{{ .Values.sidecar.notifiers.label }}" - - name: FOLDER - value: "/etc/grafana/provisioning/notifiers" - - name: RESOURCE - value: "both" - {{- if .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" - {{- end }} - {{- if .Values.sidecar.notifiers.searchNamespace }} - - name: NAMESPACE - value: "{{ .Values.sidecar.notifiers.searchNamespace }}" - {{- end }} - {{- if .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" - {{- end }} - resources: -{{ toYaml .Values.sidecar.resources | indent 6 }} - volumeMounts: - - name: sc-notifiers-volume - mountPath: "/etc/grafana/provisioning/notifiers" -{{- end}} -{{- if .Values.extraInitContainers }} -{{ toYaml .Values.extraInitContainers | indent 2 }} -{{- end }} -{{- if .Values.image.pullSecrets }} -imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end}} -{{- end }} -containers: -{{- if .Values.sidecar.dashboards.enabled }} - - name: {{ template "grafana.name" . }}-sc-dashboard - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - - name: METHOD - value: {{ .Values.sidecar.dashboards.watchMethod }} - - name: LABEL - value: "{{ .Values.sidecar.dashboards.label }}" - - name: FOLDER - value: "{{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }}" - - name: RESOURCE - value: "both" - {{- if .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" - {{- end }} - {{- if .Values.sidecar.dashboards.searchNamespace }} - - name: NAMESPACE - value: "{{ .Values.sidecar.dashboards.searchNamespace }}" - {{- end }} - {{- if .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" - {{- end }} - {{- if .Values.sidecar.dashboards.folderAnnotation }} - - name: FOLDER_ANNOTATION - value: "{{ .Values.sidecar.dashboards.folderAnnotation }}" - {{- end }} - resources: -{{ toYaml .Values.sidecar.resources | indent 6 }} - volumeMounts: - - name: sc-dashboard-volume - mountPath: {{ .Values.sidecar.dashboards.folder | quote }} -{{- end}} - - name: {{ .Chart.Name }} - {{- if .Values.image.sha }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}@sha256:{{ .Values.image.sha }}" - {{- else }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.image.pullPolicy }} - {{- if .Values.command }} - command: - {{- range .Values.command }} - - {{ . }} - {{- end }} - {{- end}} - volumeMounts: - - name: config - mountPath: "/etc/grafana/grafana.ini" - subPath: grafana.ini - {{- if .Values.ldap.enabled }} - - name: ldap - mountPath: "/etc/grafana/ldap.toml" - subPath: ldap.toml - {{- end }} - {{- range .Values.extraConfigmapMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - subPath: {{ .subPath | default "" }} - readOnly: {{ .readOnly }} - {{- end }} - - name: storage - mountPath: "/var/lib/grafana" -{{- if .Values.persistence.subPath }} - subPath: {{ .Values.persistence.subPath }} -{{- end }} -{{- if .Values.dashboards }} -{{- range $provider, $dashboards := .Values.dashboards }} -{{- range $key, $value := $dashboards }} -{{- if (or (hasKey $value "json") (hasKey $value "file")) }} - - name: dashboards-{{ $provider }} - mountPath: "/var/lib/grafana/dashboards/{{ $provider }}/{{ $key }}.json" - subPath: "{{ $key }}.json" -{{- end }} -{{- end }} -{{- end }} -{{- end -}} -{{- if .Values.dashboardsConfigMaps }} -{{- range (keys .Values.dashboardsConfigMaps | sortAlpha) }} - - name: dashboards-{{ . }} - mountPath: "/var/lib/grafana/dashboards/{{ . }}" -{{- end }} -{{- end }} -{{- if .Values.datasources }} - - name: config - mountPath: "/etc/grafana/provisioning/datasources/datasources.yaml" - subPath: datasources.yaml -{{- end }} -{{- if .Values.notifiers }} - - name: config - mountPath: "/etc/grafana/provisioning/notifiers/notifiers.yaml" - subPath: notifiers.yaml -{{- end }} -{{- if .Values.dashboardProviders }} - - name: config - mountPath: "/etc/grafana/provisioning/dashboards/dashboardproviders.yaml" - subPath: dashboardproviders.yaml -{{- end }} -{{- if .Values.sidecar.dashboards.enabled }} - - name: sc-dashboard-volume - mountPath: {{ .Values.sidecar.dashboards.folder | quote }} -{{ if .Values.sidecar.dashboards.SCProvider }} - - name: sc-dashboard-provider - mountPath: "/etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml" - subPath: provider.yaml -{{- end}} -{{- end}} -{{- if .Values.sidecar.datasources.enabled }} - - name: sc-datasources-volume - mountPath: "/etc/grafana/provisioning/datasources" -{{- end}} -{{- if .Values.sidecar.notifiers.enabled }} - - name: sc-notifiers-volume - mountPath: "/etc/grafana/provisioning/notifiers" -{{- end}} - {{- range .Values.extraSecretMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - readOnly: {{ .readOnly }} - subPath: {{ .subPath | default "" }} - {{- end }} - {{- range .Values.extraVolumeMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - subPath: {{ .subPath | default "" }} - readOnly: {{ .readOnly }} - {{- end }} - {{- range .Values.extraEmptyDirMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - {{- end }} - ports: - - name: {{ .Values.service.portName }} - containerPort: {{ .Values.service.port }} - protocol: TCP - - name: {{ .Values.podPortName }} - containerPort: 3000 - protocol: TCP - env: - {{- if not .Values.env.GF_SECURITY_ADMIN_USER }} - - name: GF_SECURITY_ADMIN_USER - valueFrom: - secretKeyRef: - name: {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.userKey | default "admin-user" }} - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) }} - - name: GF_SECURITY_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.passwordKey | default "admin-password" }} - {{- end }} - {{- if .Values.plugins }} - - name: GF_INSTALL_PLUGINS - valueFrom: - configMapKeyRef: - name: {{ template "grafana.fullname" . }} - key: plugins - {{- end }} - {{- if .Values.smtp.existingSecret }} - - name: GF_SMTP_USER - valueFrom: - secretKeyRef: - name: {{ .Values.smtp.existingSecret }} - key: {{ .Values.smtp.userKey | default "user" }} - - name: GF_SMTP_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.smtp.existingSecret }} - key: {{ .Values.smtp.passwordKey | default "password" }} - {{- end }} - {{ if .Values.imageRenderer.enabled }} - - name: GF_RENDERING_SERVER_URL - value: http://{{ template "grafana.fullname" . }}-image-renderer.{{ template "grafana.namespace" . }}:{{ .Values.imageRenderer.service.port }}/render - - name: GF_RENDERING_CALLBACK_URL - value: http://{{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}:{{ .Values.service.port }}/ - {{ end }} - {{- range $key, $value := .Values.envValueFrom }} - - name: {{ $key | quote }} - valueFrom: -{{ toYaml $value | indent 10 }} - {{- end }} -{{- range $key, $value := .Values.env }} - - name: "{{ tpl $key $ }}" - value: "{{ tpl (print $value) $ }}" -{{- end }} - {{- if .Values.envFromSecret }} - envFrom: - - secretRef: - name: {{ tpl .Values.envFromSecret . }} - {{- end }} - {{- if .Values.envRenderSecret }} - envFrom: - - secretRef: - name: {{ template "grafana.fullname" . }}-env - {{- end }} - livenessProbe: -{{ toYaml .Values.livenessProbe | indent 6 }} - readinessProbe: -{{ toYaml .Values.readinessProbe | indent 6 }} - resources: -{{ toYaml .Values.resources | indent 6 }} -{{- with .Values.extraContainers }} -{{ tpl . $ | indent 2 }} -{{- end }} -{{- with .Values.nodeSelector }} -nodeSelector: -{{ toYaml . | indent 2 }} -{{- end }} -{{- with .Values.affinity }} -affinity: -{{ toYaml . | indent 2 }} -{{- end }} -{{- with .Values.tolerations }} -tolerations: -{{ toYaml . | indent 2 }} -{{- end }} -volumes: - - name: config - configMap: - name: {{ template "grafana.fullname" . }} -{{- range .Values.extraConfigmapMounts }} - - name: {{ .name }} - configMap: - name: {{ .configMap }} -{{- end }} - {{- if .Values.dashboards }} - {{- range (keys .Values.dashboards | sortAlpha) }} - - name: dashboards-{{ . }} - configMap: - name: {{ template "grafana.fullname" $ }}-dashboards-{{ . }} - {{- end }} - {{- end }} - {{- if .Values.dashboardsConfigMaps }} - {{ $root := . }} - {{- range $provider, $name := .Values.dashboardsConfigMaps }} - - name: dashboards-{{ $provider }} - configMap: - name: {{ tpl $name $root }} - {{- end }} - {{- end }} - {{- if .Values.ldap.enabled }} - - name: ldap - secret: - {{- if .Values.ldap.existingSecret }} - secretName: {{ .Values.ldap.existingSecret }} - {{- else }} - secretName: {{ template "grafana.fullname" . }} - {{- end }} - items: - - key: ldap-toml - path: ldap.toml - {{- end }} -{{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} - - name: storage - persistentVolumeClaim: - claimName: {{ .Values.persistence.existingClaim | default (include "grafana.fullname" .) }} -{{- else if and .Values.persistence.enabled (eq .Values.persistence.type "statefulset") }} -# nothing -{{- else }} - - name: storage - emptyDir: {} -{{- end -}} -{{- if .Values.sidecar.dashboards.enabled }} - - name: sc-dashboard-volume - emptyDir: {} -{{- if .Values.sidecar.dashboards.SCProvider }} - - name: sc-dashboard-provider - configMap: - name: {{ template "grafana.fullname" . }}-config-dashboards -{{- end }} -{{- end }} -{{- if .Values.sidecar.datasources.enabled }} - - name: sc-datasources-volume - emptyDir: {} -{{- end -}} -{{- if .Values.sidecar.notifiers.enabled }} - - name: sc-notifiers-volume - emptyDir: {} -{{- end -}} -{{- range .Values.extraSecretMounts }} -{{- if .secretName }} - - name: {{ .name }} - secret: - secretName: {{ .secretName }} - defaultMode: {{ .defaultMode }} -{{- else if .projected }} - - name: {{ .name }} - projected: {{- toYaml .projected | nindent 6 }} -{{- end }} -{{- end }} -{{- range .Values.extraVolumeMounts }} - - name: {{ .name }} - persistentVolumeClaim: - claimName: {{ .existingClaim }} -{{- end }} -{{- range .Values.extraEmptyDirMounts }} - - name: {{ .name }} - emptyDir: {} -{{- end -}} -{{- if .Values.extraContainerVolumes }} -{{ toYaml .Values.extraContainerVolumes | indent 2 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/clusterrole.yaml deleted file mode 100644 index f09e06563..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/clusterrole.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if and .Values.rbac.create (not .Values.rbac.namespaced) (not .Values.rbac.useExistingRole) }} -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} - name: {{ template "grafana.fullname" . }}-clusterrole -{{- if or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.rbac.extraClusterRoleRules) }} -rules: -{{- if or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled }} -- apiGroups: [""] # "" indicates the core API group - resources: ["configmaps", "secrets"] - verbs: ["get", "watch", "list"] -{{- end}} -{{- with .Values.rbac.extraClusterRoleRules }} -{{ toYaml . | indent 0 }} -{{- end}} -{{- else }} -rules: [] -{{- end}} -{{- end}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/clusterrolebinding.yaml deleted file mode 100644 index 4accbfac0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if and .Values.rbac.create (not .Values.rbac.namespaced) }} -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "grafana.fullname" . }}-clusterrolebinding - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -subjects: - - kind: ServiceAccount - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} -roleRef: - kind: ClusterRole -{{- if (not .Values.rbac.useExistingRole) }} - name: {{ template "grafana.fullname" . }}-clusterrole -{{- else }} - name: {{ .Values.rbac.useExistingRole }} -{{- end }} - apiGroup: rbac.authorization.k8s.io -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/configmap-dashboard-provider.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/configmap-dashboard-provider.yaml deleted file mode 100644 index 8bb05670c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/configmap-dashboard-provider.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.sidecar.dashboards.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} - name: {{ template "grafana.fullname" . }}-config-dashboards - namespace: {{ template "grafana.namespace" . }} -data: - provider.yaml: |- - apiVersion: 1 - providers: - - name: '{{ .Values.sidecar.dashboards.provider.name }}' - orgId: {{ .Values.sidecar.dashboards.provider.orgid }} - folder: '{{ .Values.sidecar.dashboards.provider.folder }}' - type: {{ .Values.sidecar.dashboards.provider.type }} - disableDeletion: {{ .Values.sidecar.dashboards.provider.disableDelete }} - allowUiUpdates: {{ .Values.sidecar.dashboards.provider.allowUiUpdates }} - options: - foldersFromFilesStructure: {{ .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} - path: {{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }} -{{- end}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/configmap.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/configmap.yaml deleted file mode 100644 index a9fdc3a8f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/configmap.yaml +++ /dev/null @@ -1,69 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -data: -{{- if .Values.plugins }} - plugins: {{ join "," .Values.plugins }} -{{- end }} - grafana.ini: | -{{- range $key, $value := index .Values "grafana.ini" }} - [{{ $key }}] - {{- range $elem, $elemVal := $value }} - {{ $elem }} = {{ $elemVal }} - {{- end }} -{{- end }} - -{{- if .Values.datasources }} -{{ $root := . }} - {{- range $key, $value := .Values.datasources }} - {{ $key }}: | -{{ tpl (toYaml $value | indent 4) $root }} - {{- end -}} -{{- end -}} - -{{- if .Values.notifiers }} - {{- range $key, $value := .Values.notifiers }} - {{ $key }}: | -{{ toYaml $value | indent 4 }} - {{- end -}} -{{- end -}} - -{{- if .Values.dashboardProviders }} - {{- range $key, $value := .Values.dashboardProviders }} - {{ $key }}: | -{{ toYaml $value | indent 4 }} - {{- end -}} -{{- end -}} - -{{- if .Values.dashboards }} - download_dashboards.sh: | - #!/usr/bin/env sh - set -euf - {{- if .Values.dashboardProviders }} - {{- range $key, $value := .Values.dashboardProviders }} - {{- range $value.providers }} - mkdir -p {{ .options.path }} - {{- end }} - {{- end }} - {{- end }} - - {{- range $provider, $dashboards := .Values.dashboards }} - {{- range $key, $value := $dashboards }} - {{- if (or (hasKey $value "gnetId") (hasKey $value "url")) }} - curl -skf \ - --connect-timeout 60 \ - --max-time 60 \ - {{- if not $value.b64content }} - -H "Accept: application/json" \ - -H "Content-Type: application/json;charset=UTF-8" \ - {{ end }} - {{- if $value.url -}}"{{ $value.url }}"{{- else -}}"https://grafana.com/api/dashboards/{{ $value.gnetId }}/revisions/{{- if $value.revision -}}{{ $value.revision }}{{- else -}}1{{- end -}}/download"{{- end -}}{{ if $value.datasource }} | sed '/-- .* --/! s/"datasource":.*,/"datasource": "{{ $value.datasource }}",/g'{{ end }}{{- if $value.b64content -}} | base64 -d {{- end -}} \ - > "/var/lib/grafana/dashboards/{{ $provider }}/{{ $key }}.json" - {{- end -}} - {{- end }} - {{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/dashboards-json-configmap.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/dashboards-json-configmap.yaml deleted file mode 100644 index 59e0be641..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/dashboards-json-configmap.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- if .Values.dashboards }} -{{ $files := .Files }} -{{- range $provider, $dashboards := .Values.dashboards }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "grafana.fullname" $ }}-dashboards-{{ $provider }} - namespace: {{ template "grafana.namespace" $ }} - labels: - {{- include "grafana.labels" $ | nindent 4 }} - dashboard-provider: {{ $provider }} -{{- if $dashboards }} -data: -{{- $dashboardFound := false }} -{{- range $key, $value := $dashboards }} -{{- if (or (hasKey $value "json") (hasKey $value "file")) }} -{{- $dashboardFound = true }} -{{ print $key | indent 2 }}.json: -{{- if hasKey $value "json" }} - |- -{{ $value.json | indent 6 }} -{{- end }} -{{- if hasKey $value "file" }} -{{ toYaml ( $files.Get $value.file ) | indent 4}} -{{- end }} -{{- end }} -{{- end }} -{{- if not $dashboardFound }} - {} -{{- end }} -{{- end }} ---- -{{- end }} - -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/deployment.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/deployment.yaml deleted file mode 100644 index 4d77794cd..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/deployment.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{ if (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc")) }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.labels }} -{{ toYaml .Values.labels | indent 4 }} -{{- end }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - replicas: {{ .Values.replicas }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} -{{- with .Values.deploymentStrategy }} - strategy: -{{ toYaml . | trim | indent 4 }} -{{- end }} - template: - metadata: - labels: - {{- include "grafana.selectorLabels" . | nindent 8 }} -{{- with .Values.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} - checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} -{{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} - checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} -{{- end }} -{{- if .Values.envRenderSecret }} - checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }} -{{- end }} -{{- with .Values.podAnnotations }} -{{ toYaml . | indent 8 }} -{{- end }} - spec: - {{- include "grafana.pod" . | nindent 6 }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/headless-service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/headless-service.yaml deleted file mode 100644 index 2fa816e04..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/headless-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset")}} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "grafana.fullname" . }}-headless - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - clusterIP: None - selector: - {{- include "grafana.selectorLabels" . | nindent 4 }} - type: ClusterIP -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-deployment.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-deployment.yaml deleted file mode 100644 index 1f60ffb43..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-deployment.yaml +++ /dev/null @@ -1,112 +0,0 @@ -{{ if .Values.imageRenderer.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "grafana.fullname" . }}-image-renderer - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.imageRenderer.labels" . | nindent 4 }} -{{- if .Values.imageRenderer.labels }} -{{ toYaml .Values.imageRenderer.labels | indent 4 }} -{{- end }} -{{- with .Values.imageRenderer.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - replicas: {{ .Values.imageRenderer.replicas }} - revisionHistoryLimit: {{ .Values.imageRenderer.revisionHistoryLimit }} - selector: - matchLabels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} -{{- with .Values.imageRenderer.deploymentStrategy }} - strategy: -{{ toYaml . | trim | indent 4 }} -{{- end }} - template: - metadata: - labels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 8 }} -{{- with .Values.imageRenderer.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} -{{- with .Values.imageRenderer.podAnnotations }} -{{ toYaml . | indent 8 }} -{{- end }} - spec: - - {{- if .Values.imageRenderer.schedulerName }} - schedulerName: "{{ .Values.imageRenderer.schedulerName }}" - {{- end }} - {{- if .Values.imageRenderer.securityContext }} - securityContext: - {{ toYaml .Values.imageRenderer.securityContext | indent 2 }} - {{- end }} - {{- if .Values.imageRenderer.hostAliases }} - hostAliases: - {{ toYaml .Values.imageRenderer.hostAliases | indent 2 }} - {{- end }} - {{- if .Values.imageRenderer.priorityClassName }} - priorityClassName: {{ .Values.imageRenderer.priorityClassName }} - {{- end }} - {{- if .Values.imageRenderer.image.pullSecrets }} - imagePullSecrets: - {{- range .Values.imageRenderer.image.pullSecrets }} - - name: {{ . }} - {{- end}} - {{- end }} - containers: - - name: {{ .Chart.Name }}-image-renderer - {{- if .Values.imageRenderer.image.sha }} - image: "{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" - {{- else }} - image: "{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.imageRenderer.image.pullPolicy }} - {{- if .Values.imageRenderer.command }} - command: - {{- range .Values.imageRenderer.command }} - - {{ . }} - {{- end }} - {{- end}} - ports: - - name: {{ .Values.imageRenderer.service.portName }} - containerPort: {{ .Values.imageRenderer.service.port }} - protocol: TCP - env: - - name: HTTP_PORT - value: {{ .Values.imageRenderer.service.port | quote }} - {{- range $key, $value := .Values.imageRenderer.env }} - - name: {{ $key | quote }} - value: {{ $value | quote }} - {{- end }} - securityContext: - capabilities: - drop: ['all'] - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - volumeMounts: - - mountPath: /tmp - name: image-renderer-tmpfs - {{- with .Values.imageRenderer.resources }} - resources: -{{ toYaml . | indent 12 }} - {{- end }} - {{- with .Values.imageRenderer.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.imageRenderer.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.imageRenderer.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - volumes: - - name: image-renderer-tmpfs - emptyDir: {} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-network-policy.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-network-policy.yaml deleted file mode 100644 index f8ca73aab..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-network-policy.yaml +++ /dev/null @@ -1,76 +0,0 @@ -{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitIngress) }} ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ template "grafana.fullname" . }}-image-renderer-ingress - namespace: {{ template "grafana.namespace" . }} - annotations: - comment: Limit image-renderer ingress traffic from grafana -spec: - podSelector: - matchLabels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} - {{- if .Values.imageRenderer.podLabels }} - {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} - {{- end }} - - policyTypes: - - Ingress - ingress: - - ports: - - port: {{ .Values.imageRenderer.service.port }} - protocol: TCP - from: - - namespaceSelector: - matchLabels: - name: {{ template "grafana.namespace" . }} - podSelector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 14 }} - {{- if .Values.podLabels }} - {{ toYaml .Values.podLabels | nindent 14 }} - {{- end }} -{{ end }} - -{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitEgress) }} ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ template "grafana.fullname" . }}-image-renderer-egress - namespace: {{ template "grafana.namespace" . }} - annotations: - comment: Limit image-renderer egress traffic to grafana -spec: - podSelector: - matchLabels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} - {{- if .Values.imageRenderer.podLabels }} - {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} - {{- end }} - - policyTypes: - - Egress - egress: - # allow dns resolution - - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP - # talk only to grafana - - ports: - - port: {{ .Values.service.port }} - protocol: TCP - to: - - namespaceSelector: - matchLabels: - name: {{ template "grafana.namespace" . }} - podSelector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 14 }} - {{- if .Values.podLabels }} - {{ toYaml .Values.podLabels | nindent 14 }} - {{- end }} -{{ end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-service.yaml deleted file mode 100644 index f5d3eb02f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/image-renderer-service.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{ if .Values.imageRenderer.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "grafana.fullname" . }}-image-renderer - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.imageRenderer.labels" . | nindent 4 }} -{{- if .Values.imageRenderer.service.labels }} -{{ toYaml .Values.imageRenderer.service.labels | indent 4 }} -{{- end }} -{{- with .Values.imageRenderer.service.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - type: ClusterIP - {{- if .Values.imageRenderer.service.clusterIP }} - clusterIP: {{ .Values.imageRenderer.service.clusterIP }} - {{end}} - ports: - - name: {{ .Values.imageRenderer.service.portName }} - port: {{ .Values.imageRenderer.service.port }} - protocol: TCP - targetPort: {{ .Values.imageRenderer.service.targetPort }} - selector: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 4 }} -{{ end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/ingress.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/ingress.yaml deleted file mode 100644 index 8d35662e7..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/ingress.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "grafana.fullname" . -}} -{{- $servicePort := .Values.service.port -}} -{{- $ingressPath := .Values.ingress.path -}} -{{- $extraPaths := .Values.ingress.extraPaths -}} -{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} -apiVersion: networking.k8s.io/v1beta1 -{{ else }} -apiVersion: extensions/v1beta1 -{{ end -}} -kind: Ingress -metadata: - name: {{ $fullName }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.ingress.labels }} -{{ toYaml .Values.ingress.labels | indent 4 }} -{{- end }} - {{- if .Values.ingress.annotations }} - annotations: - {{- range $key, $value := .Values.ingress.annotations }} - {{ $key }}: {{ tpl $value $ | quote }} - {{- end }} - {{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: -{{ toYaml .Values.ingress.tls | indent 4 }} -{{- end }} - rules: - {{- if .Values.ingress.hosts }} - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: -{{ if $extraPaths }} -{{ toYaml $extraPaths | indent 10 }} -{{- end }} - - path: {{ $ingressPath }} - backend: - serviceName: {{ $fullName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- else }} - - http: - paths: - - backend: - serviceName: {{ $fullName }} - servicePort: {{ $servicePort }} - {{- if $ingressPath }} - path: {{ $ingressPath }} - {{- end }} - {{- end -}} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/poddisruptionbudget.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/poddisruptionbudget.yaml deleted file mode 100644 index 61813a436..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.podDisruptionBudget }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.labels }} -{{ toYaml .Values.labels | indent 4 }} -{{- end }} -spec: -{{- if .Values.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} -{{- end }} -{{- if .Values.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} -{{- end }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/podsecuritypolicy.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/podsecuritypolicy.yaml deleted file mode 100644 index 9d50471b0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/podsecuritypolicy.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if .Values.rbac.pspEnabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - annotations: - seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' - seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - {{- if .Values.rbac.pspUseAppArmor }} - apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' - apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - {{- end }} -spec: - privileged: false - allowPrivilegeEscalation: false - requiredDropCapabilities: - # Default set from Docker, without DAC_OVERRIDE or CHOWN - - FOWNER - - FSETID - - KILL - - SETGID - - SETUID - - SETPCAP - - NET_BIND_SERVICE - - NET_RAW - - SYS_CHROOT - - MKNOD - - AUDIT_WRITE - - SETFCAP - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - rule: 'RunAsAny' - seLinux: - rule: 'RunAsAny' - supplementalGroups: - rule: 'RunAsAny' - fsGroup: - rule: 'RunAsAny' - readOnlyRootFilesystem: false -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/pvc.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/pvc.yaml deleted file mode 100644 index 4727d0aa1..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/pvc.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "pvc")}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.persistence.annotations }} - annotations: -{{ toYaml . | indent 4 }} - {{- end }} - {{- with .Values.persistence.finalizers }} - finalizers: -{{ toYaml . | indent 4 }} - {{- end }} -spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{- if .Values.persistence.storageClassName }} - storageClassName: {{ .Values.persistence.storageClassName }} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/role.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/role.yaml deleted file mode 100644 index db853559a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/role.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}} -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: Role -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if or .Values.rbac.pspEnabled (and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.rbac.extraRoleRules))) }} -rules: -{{- if .Values.rbac.pspEnabled }} -- apiGroups: ['extensions'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: [{{ template "grafana.fullname" . }}] -{{- end }} -{{- if and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled) }} -- apiGroups: [""] # "" indicates the core API group - resources: ["configmaps", "secrets"] - verbs: ["get", "watch", "list"] -{{- end }} -{{- with .Values.rbac.extraRoleRules }} -{{ toYaml . | indent 0 }} -{{- end}} -{{- else }} -rules: [] -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/rolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/rolebinding.yaml deleted file mode 100644 index 3738e580f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/rolebinding.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role -{{- if (not .Values.rbac.useExistingRole) }} - name: {{ template "grafana.fullname" . }} -{{- else }} - name: {{ .Values.rbac.useExistingRole }} -{{- end }} -subjects: -- kind: ServiceAccount - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/secret-env.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/secret-env.yaml deleted file mode 100644 index 5c09313e6..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/secret-env.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.envRenderSecret }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "grafana.fullname" . }}-env - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -type: Opaque -data: -{{- range $key, $val := .Values.envRenderSecret }} - {{ $key }}: {{ $val | b64enc | quote }} -{{- end -}} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/secret.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/secret.yaml deleted file mode 100644 index 9d2f072e0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/secret.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -type: Opaque -data: - {{- if and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) }} - admin-user: {{ .Values.adminUser | b64enc | quote }} - {{- if .Values.adminPassword }} - admin-password: {{ .Values.adminPassword | b64enc | quote }} - {{- else }} - admin-password: {{ randAlphaNum 40 | b64enc | quote }} - {{- end }} - {{- end }} - {{- if not .Values.ldap.existingSecret }} - ldap-toml: {{ .Values.ldap.config | b64enc | quote }} - {{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/service.yaml deleted file mode 100644 index 276456698..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/service.yaml +++ /dev/null @@ -1,50 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.service.labels }} -{{ toYaml .Values.service.labels | indent 4 }} -{{- end }} -{{- with .Values.service.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: -{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} - type: ClusterIP - {{- if .Values.service.clusterIP }} - clusterIP: {{ .Values.service.clusterIP }} - {{end}} -{{- else if eq .Values.service.type "LoadBalancer" }} - type: {{ .Values.service.type }} - {{- if .Values.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.service.loadBalancerIP }} - {{- end }} - {{- if .Values.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: -{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} - {{- end -}} -{{- else }} - type: {{ .Values.service.type }} -{{- end }} -{{- if .Values.service.externalIPs }} - externalIPs: -{{ toYaml .Values.service.externalIPs | indent 4 }} -{{- end }} - ports: - - name: {{ .Values.service.portName }} - port: {{ .Values.service.port }} - protocol: TCP - targetPort: {{ .Values.service.targetPort }} -{{ if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} - nodePort: {{.Values.service.nodePort}} -{{ end }} - {{- if .Values.extraExposePorts }} - {{- tpl (toYaml .Values.extraExposePorts) . | indent 4 }} - {{- end }} - selector: - {{- include "grafana.selectorLabels" . | nindent 4 }} - diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/serviceaccount.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/serviceaccount.yaml deleted file mode 100644 index 7576eeef0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/serviceaccount.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.serviceAccount.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/servicemonitor.yaml deleted file mode 100644 index 988956bcd..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/servicemonitor.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if .Values.serviceMonitor.enabled }} ---- -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "grafana.fullname" . }} - {{- if .Values.serviceMonitor.namespace }} - namespace: {{ .Values.serviceMonitor.namespace }} - {{- end }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- if .Values.serviceMonitor.labels }} - {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} - {{- end }} -spec: - endpoints: - - interval: {{ .Values.serviceMonitor.interval }} - {{- if .Values.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} - {{- end }} - honorLabels: true - port: {{ .Values.service.portName }} - path: {{ .Values.serviceMonitor.path }} - {{- if .Values.serviceMonitor.relabelings }} - relabelings: - {{- toYaml .Values.serviceMonitor.relabelings | nindent 4 }} - {{- end }} - jobLabel: "{{ .Release.Name }}" - selector: - matchLabels: - app: {{ template "grafana.name" . }} - release: "{{ .Release.Name }}" - namespaceSelector: - matchNames: - - {{ .Release.Namespace }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/statefulset.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/statefulset.yaml deleted file mode 100644 index accfa560a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/statefulset.yaml +++ /dev/null @@ -1,47 +0,0 @@ -{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset")}} -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -spec: - replicas: {{ .Values.replicas }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} - serviceName: {{ template "grafana.fullname" . }}-headless - template: - metadata: - labels: - {{- include "grafana.selectorLabels" . | nindent 8 }} -{{- with .Values.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} - checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} - {{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} - checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} -{{- end }} -{{- with .Values.podAnnotations }} -{{ toYaml . | indent 8 }} -{{- end }} - spec: - {{- include "grafana.pod" . | nindent 6 }} - volumeClaimTemplates: - - metadata: - name: storage - spec: - accessModes: {{ .Values.persistence.accessModes }} - storageClassName: {{ .Values.persistence.storageClassName }} - resources: - requests: - storage: {{ .Values.persistence.size }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-configmap.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-configmap.yaml deleted file mode 100644 index ff53aaf1b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.testFramework.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -data: - run.sh: |- - @test "Test Health" { - url="http://{{ template "grafana.fullname" . }}/api/health" - - code=$(wget --server-response --spider --timeout 10 --tries 1 ${url} 2>&1 | awk '/^ HTTP/{print $2}') - [ "$code" == "200" ] - } -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-podsecuritypolicy.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-podsecuritypolicy.yaml deleted file mode 100644 index eb5cbbcd7..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-podsecuritypolicy.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.rbac.pspEnabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -spec: - allowPrivilegeEscalation: true - privileged: false - hostNetwork: false - hostIPC: false - hostPID: false - fsGroup: - rule: RunAsAny - seLinux: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - runAsUser: - rule: RunAsAny - volumes: - - configMap - - downwardAPI - - emptyDir - - projected - - secret -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-role.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-role.yaml deleted file mode 100644 index 6b10677ae..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-role.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.rbac.pspEnabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -rules: -- apiGroups: ['policy'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: [{{ template "grafana.fullname" . }}-test] -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-rolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-rolebinding.yaml deleted file mode 100644 index 58fa5e78b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-rolebinding.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.rbac.pspEnabled -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "grafana.fullname" . }}-test -subjects: -- kind: ServiceAccount - name: {{ template "grafana.serviceAccountNameTest" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-serviceaccount.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-serviceaccount.yaml deleted file mode 100644 index 5c3350733..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test-serviceaccount.yaml +++ /dev/null @@ -1,9 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} - name: {{ template "grafana.serviceAccountNameTest" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test.yaml deleted file mode 100644 index cdc86e5f2..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/templates/tests/test.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{- if .Values.testFramework.enabled }} -apiVersion: v1 -kind: Pod -metadata: - name: {{ template "grafana.fullname" . }}-test - labels: - {{- include "grafana.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test-success - namespace: {{ template "grafana.namespace" . }} -spec: - serviceAccountName: {{ template "grafana.serviceAccountNameTest" . }} - {{- if .Values.testFramework.securityContext }} - securityContext: {{ toYaml .Values.testFramework.securityContext | nindent 4 }} - {{- end }} - {{- if .Values.image.pullSecrets }} - imagePullSecrets: - {{- range .Values.image.pullSecrets }} - - name: {{ . }} - {{- end}} - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 4 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 4 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 4 }} - {{- end }} - containers: - - name: {{ .Release.Name }}-test - image: "{{ .Values.testFramework.image}}:{{ .Values.testFramework.tag }}" - imagePullPolicy: "{{ .Values.testFramework.imagePullPolicy}}" - command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"] - volumeMounts: - - mountPath: /tests - name: tests - readOnly: true - volumes: - - name: tests - configMap: - name: {{ template "grafana.fullname" . }}-test - restartPolicy: Never -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/values.yaml deleted file mode 100644 index 1f22b9385..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/grafana/values.yaml +++ /dev/null @@ -1,648 +0,0 @@ -rbac: - create: true - ## Use an existing ClusterRole/Role (depending on rbac.namespaced false/true) - # useExistingRole: name-of-some-(cluster)role - pspEnabled: true - pspUseAppArmor: true - namespaced: false - extraRoleRules: [] - # - apiGroups: [] - # resources: [] - # verbs: [] - extraClusterRoleRules: [] - # - apiGroups: [] - # resources: [] - # verbs: [] -serviceAccount: - create: true - name: - nameTest: -# annotations: -# eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here - -replicas: 1 - -## See `kubectl explain poddisruptionbudget.spec` for more -## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ -podDisruptionBudget: {} -# minAvailable: 1 -# maxUnavailable: 1 - -## See `kubectl explain deployment.spec.strategy` for more -## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy -deploymentStrategy: - type: RollingUpdate - -readinessProbe: - httpGet: - path: /api/health - port: 3000 - -livenessProbe: - httpGet: - path: /api/health - port: 3000 - initialDelaySeconds: 60 - timeoutSeconds: 30 - failureThreshold: 10 - -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: "default-scheduler" - -image: - repository: grafana/grafana - tag: 7.2.1 - sha: "" - pullPolicy: IfNotPresent - - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # pullSecrets: - # - myRegistrKeySecretName - -testFramework: - enabled: true - image: "bats/bats" - tag: "v1.1.0" - imagePullPolicy: IfNotPresent - securityContext: {} - -securityContext: - runAsUser: 472 - runAsGroup: 472 - fsGroup: 472 - - -extraConfigmapMounts: [] - # - name: certs-configmap - # mountPath: /etc/grafana/ssl/ - # subPath: certificates.crt # (optional) - # configMap: certs-configmap - # readOnly: true - - -extraEmptyDirMounts: [] - # - name: provisioning-notifiers - # mountPath: /etc/grafana/provisioning/notifiers - - -## Assign a PriorityClassName to pods if set -# priorityClassName: - -downloadDashboardsImage: - repository: curlimages/curl - tag: 7.73.0 - sha: "" - pullPolicy: IfNotPresent - -downloadDashboards: - env: {} - resources: {} - -## Pod Annotations -# podAnnotations: {} - -## Pod Labels -# podLabels: {} - -podPortName: grafana - -## Deployment annotations -# annotations: {} - -## Expose the grafana service to be accessed from outside the cluster (LoadBalancer service). -## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. -## ref: http://kubernetes.io/docs/user-guide/services/ -## -service: - type: ClusterIP - port: 80 - targetPort: 3000 - # targetPort: 4181 To be used with a proxy extraContainer - annotations: {} - labels: {} - portName: service - -serviceMonitor: - ## If true, a ServiceMonitor CRD is created for a prometheus operator - ## https://github.com/coreos/prometheus-operator - ## - enabled: false - path: /metrics - # namespace: monitoring (defaults to use the namespace this chart is deployed to) - labels: {} - interval: 1m - scrapeTimeout: 30s - relabelings: [] - -extraExposePorts: [] - # - name: keycloak - # port: 8080 - # targetPort: 8080 - # type: ClusterIP - -# overrides pod.spec.hostAliases in the grafana deployment's pods -hostAliases: [] - # - ip: "1.2.3.4" - # hostnames: - # - "my.host.com" - -ingress: - enabled: false - # Values can be templated - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - labels: {} - path: / - hosts: - - chart-example.local - ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. - extraPaths: [] - # - path: /* - # backend: - # serviceName: ssl-redirect - # servicePort: use-annotation - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} -# limits: -# cpu: 100m -# memory: 128Mi -# requests: -# cpu: 100m -# memory: 128Mi - -## Node labels for pod assignment -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -# -nodeSelector: {} - -## Tolerations for pod assignment -## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Affinity for pod assignment -## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -extraInitContainers: [] - -## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod -extraContainers: | -# - name: proxy -# image: quay.io/gambol99/keycloak-proxy:latest -# args: -# - -provider=github -# - -client-id= -# - -client-secret= -# - -github-org=<ORG_NAME> -# - -email-domain=* -# - -cookie-secret= -# - -http-address=http://0.0.0.0:4181 -# - -upstream-url=http://127.0.0.1:3000 -# ports: -# - name: proxy-web -# containerPort: 4181 - -## Volumes that can be used in init containers that will not be mounted to deployment pods -extraContainerVolumes: [] -# - name: volume-from-secret -# secret: -# secretName: secret-to-mount -# - name: empty-dir-volume -# emptyDir: {} - -## Enable persistence using Persistent Volume Claims -## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ -## -persistence: - type: pvc - enabled: false - # storageClassName: default - accessModes: - - ReadWriteOnce - size: 10Gi - # annotations: {} - finalizers: - - kubernetes.io/pvc-protection - # subPath: "" - # existingClaim: - -initChownData: - ## If false, data ownership will not be reset at startup - ## This allows the prometheus-server to be run with an arbitrary user - ## - enabled: true - - ## initChownData container image - ## - image: - repository: busybox - tag: "1.31.1" - sha: "" - pullPolicy: IfNotPresent - - ## initChownData resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - - -# Administrator credentials when not using an existing secret (see below) -adminUser: admin -# adminPassword: strongpassword - -# Use an existing secret for the admin user. -admin: - existingSecret: "" - userKey: admin-user - passwordKey: admin-password - -## Define command to be executed at startup by grafana container -## Needed if using `vault-env` to manage secrets (ref: https://banzaicloud.com/blog/inject-secrets-into-pods-vault/) -## Default is "run.sh" as defined in grafana's Dockerfile -# command: -# - "sh" -# - "/run.sh" - -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: - -## Extra environment variables that will be pass onto deployment pods -## -## to provide grafana with access to CloudWatch on AWS EKS: -## 1. create an iam role of type "Web identity" with provider oidc.eks.* (note the provider for later) -## 2. edit the "Trust relationships" of the role, add a line inside the StringEquals clause using the -## same oidc eks provider as noted before (same as the existing line) -## also, replace NAMESPACE and prometheus-operator-grafana with the service account namespace and name -## -## "oidc.eks.us-east-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:sub": "system:serviceaccount:NAMESPACE:prometheus-operator-grafana", -## -## 3. attach a policy to the role, you can use a built in policy called CloudWatchReadOnlyAccess -## 4. use the following env: (replace 123456789000 and iam-role-name-here with your aws account number and role name) -## -## env: -## AWS_ROLE_ARN: arn:aws:iam::123456789000:role/iam-role-name-here -## AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token -## AWS_REGION: us-east-1 -## -## 5. uncomment the EKS section in extraSecretMounts: below -## 6. uncomment the annotation section in the serviceAccount: above -## make sure to replace arn:aws:iam::123456789000:role/iam-role-name-here with your role arn - -env: {} - -## "valueFrom" environment variable references that will be added to deployment pods -## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core -## Renders in container spec as: -## env: -## ... -## - name: <key> -## valueFrom: -## <value rendered as YAML> -envValueFrom: {} - -## The name of a secret in the same kubernetes namespace which contain values to be added to the environment -## This can be useful for auth tokens, etc. Value is templated. -envFromSecret: "" - -## Sensible environment variables that will be rendered as new secret object -## This can be useful for auth tokens, etc -envRenderSecret: {} - -## Additional grafana server secret mounts -# Defines additional mounts with secrets. Secrets must be manually created in the namespace. -extraSecretMounts: [] - # - name: secret-files - # mountPath: /etc/secrets - # secretName: grafana-secret-files - # readOnly: true - # subPath: "" - # - # for AWS EKS (cloudwatch) use the following (see also instruction in env: above) - # - name: aws-iam-token - # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount - # readOnly: true - # projected: - # defaultMode: 420 - # sources: - # - serviceAccountToken: - # audience: sts.amazonaws.com - # expirationSeconds: 86400 - # path: token - -## Additional grafana server volume mounts -# Defines additional volume mounts. -extraVolumeMounts: [] - # - name: extra-volume - # mountPath: /mnt/volume - # readOnly: true - # existingClaim: volume-claim - -## Pass the plugins you want installed as a list. -## -plugins: [] - # - digrich-bubblechart-panel - # - grafana-clock-panel - -## Configure grafana datasources -## ref: http://docs.grafana.org/administration/provisioning/#datasources -## -datasources: {} -# datasources.yaml: -# apiVersion: 1 -# datasources: -# - name: Prometheus -# type: prometheus -# url: http://prometheus-prometheus-server -# access: proxy -# isDefault: true -# - name: CloudWatch -# type: cloudwatch -# access: proxy -# uid: cloudwatch -# editable: false -# jsonData: -# authType: credentials -# defaultRegion: us-east-1 - -## Configure notifiers -## ref: http://docs.grafana.org/administration/provisioning/#alert-notification-channels -## -notifiers: {} -# notifiers.yaml: -# notifiers: -# - name: email-notifier -# type: email -# uid: email1 -# # either: -# org_id: 1 -# # or -# org_name: Main Org. -# is_default: true -# settings: -# addresses: an_email_address@example.com -# delete_notifiers: - -## Configure grafana dashboard providers -## ref: http://docs.grafana.org/administration/provisioning/#dashboards -## -## `path` must be /var/lib/grafana/dashboards/<provider_name> -## -dashboardProviders: {} -# dashboardproviders.yaml: -# apiVersion: 1 -# providers: -# - name: 'default' -# orgId: 1 -# folder: '' -# type: file -# disableDeletion: false -# editable: true -# options: -# path: /var/lib/grafana/dashboards/default - -## Configure grafana dashboard to import -## NOTE: To use dashboards you must also enable/configure dashboardProviders -## ref: https://grafana.com/dashboards -## -## dashboards per provider, use provider name as key. -## -dashboards: {} - # default: - # some-dashboard: - # json: | - # $RAW_JSON - # custom-dashboard: - # file: dashboards/custom-dashboard.json - # prometheus-stats: - # gnetId: 2 - # revision: 2 - # datasource: Prometheus - # local-dashboard: - # url: https://example.com/repository/test.json - # local-dashboard-base64: - # url: https://example.com/repository/test-b64.json - # b64content: true - -## Reference to external ConfigMap per provider. Use provider name as key and ConfigMap name as value. -## A provider dashboards must be defined either by external ConfigMaps or in values.yaml, not in both. -## ConfigMap data example: -## -## data: -## example-dashboard.json: | -## RAW_JSON -## -dashboardsConfigMaps: {} -# default: "" - -## Grafana's primary configuration -## NOTE: values in map will be converted to ini format -## ref: http://docs.grafana.org/installation/configuration/ -## -grafana.ini: - paths: - data: /var/lib/grafana/data - logs: /var/log/grafana - plugins: /var/lib/grafana/plugins - provisioning: /etc/grafana/provisioning - analytics: - check_for_updates: true - log: - mode: console - grafana_net: - url: https://grafana.net -## grafana Authentication can be enabled with the following values on grafana.ini - # server: - # The full public facing url you use in browser, used for redirects and emails - # root_url: - # https://grafana.com/docs/grafana/latest/auth/github/#enable-github-in-grafana - # auth.github: - # enabled: false - # allow_sign_up: false - # scopes: user:email,read:org - # auth_url: https://github.com/login/oauth/authorize - # token_url: https://github.com/login/oauth/access_token - # api_url: https://api.github.com/user - # team_ids: - # allowed_organizations: - # client_id: - # client_secret: -## LDAP Authentication can be enabled with the following values on grafana.ini -## NOTE: Grafana will fail to start if the value for ldap.toml is invalid - # auth.ldap: - # enabled: true - # allow_sign_up: true - # config_file: /etc/grafana/ldap.toml - -## Grafana's LDAP configuration -## Templated by the template in _helpers.tpl -## NOTE: To enable the grafana.ini must be configured with auth.ldap.enabled -## ref: http://docs.grafana.org/installation/configuration/#auth-ldap -## ref: http://docs.grafana.org/installation/ldap/#configuration -ldap: - enabled: false - # `existingSecret` is a reference to an existing secret containing the ldap configuration - # for Grafana in a key `ldap-toml`. - existingSecret: "" - # `config` is the content of `ldap.toml` that will be stored in the created secret - config: "" - # config: |- - # verbose_logging = true - - # [[servers]] - # host = "my-ldap-server" - # port = 636 - # use_ssl = true - # start_tls = false - # ssl_skip_verify = false - # bind_dn = "uid=%s,ou=users,dc=myorg,dc=com" - -## Grafana's SMTP configuration -## NOTE: To enable, grafana.ini must be configured with smtp.enabled -## ref: http://docs.grafana.org/installation/configuration/#smtp -smtp: - # `existingSecret` is a reference to an existing secret containing the smtp configuration - # for Grafana. - existingSecret: "" - userKey: "user" - passwordKey: "password" - -## Sidecars that collect the configmaps with specified label and stores the included files them into the respective folders -## Requires at least Grafana 5 to work and can't be used together with parameters dashboardProviders, datasources and dashboards -sidecar: - image: - repository: kiwigrid/k8s-sidecar - tag: 1.1.0 - sha: "" - imagePullPolicy: IfNotPresent - resources: {} -# limits: -# cpu: 100m -# memory: 100Mi -# requests: -# cpu: 50m -# memory: 50Mi - # skipTlsVerify Set to true to skip tls verification for kube api calls - # skipTlsVerify: true - enableUniqueFilenames: false - dashboards: - enabled: false - SCProvider: true - # label that the configmaps with dashboards are marked with - label: grafana_dashboard - # folder in the pod that should hold the collected dashboards (unless `defaultFolderName` is set) - folder: /tmp/dashboards - # The default folder name, it will create a subfolder under the `folder` and put dashboards in there instead - defaultFolderName: null - # If specified, the sidecar will search for dashboard config-maps inside this namespace. - # Otherwise the namespace in which the sidecar is running will be used. - # It's also possible to specify ALL to search in all namespaces - searchNamespace: null - # If specified, the sidecar will look for annotation with this name to create folder and put graph here. - # You can use this parameter together with `provider.foldersFromFilesStructure`to annotate configmaps and create folder structure. - folderAnnotation: null - # provider configuration that lets grafana manage the dashboards - provider: - # name of the provider, should be unique - name: sidecarProvider - # orgid as configured in grafana - orgid: 1 - # folder in which the dashboards should be imported in grafana - folder: '' - # type of the provider - type: file - # disableDelete to activate a import-only behaviour - disableDelete: false - # allow updating provisioned dashboards from the UI - allowUiUpdates: false - # allow Grafana to replicate dashboard structure from filesystem - foldersFromFilesStructure: false - datasources: - enabled: false - # label that the configmaps with datasources are marked with - label: grafana_datasource - # If specified, the sidecar will search for datasource config-maps inside this namespace. - # Otherwise the namespace in which the sidecar is running will be used. - # It's also possible to specify ALL to search in all namespaces - searchNamespace: null - notifiers: - enabled: false - # label that the configmaps with notifiers are marked with - label: grafana_notifier - # If specified, the sidecar will search for notifier config-maps inside this namespace. - # Otherwise the namespace in which the sidecar is running will be used. - # It's also possible to specify ALL to search in all namespaces - searchNamespace: null - -## Override the deployment namespace -## -namespaceOverride: "" - -## Number of old ReplicaSets to retain -## -revisionHistoryLimit: 10 - -## Add a seperate remote image renderer deployment/service -imageRenderer: - # Enable the image-renderer deployment & service - enabled: false - replicas: 1 - image: - # image-renderer Image repository - repository: grafana/grafana-image-renderer - # image-renderer Image tag - tag: latest - # image-renderer Image sha (optional) - sha: "" - # image-renderer ImagePullPolicy - pullPolicy: Always - # extra environment variables - env: {} - # RENDERING_ARGS: --disable-gpu,--window-size=1280x758 - # RENDERING_MODE: clustered - # image-renderer deployment securityContext - securityContext: {} - # image-renderer deployment Host Aliases - hostAliases: [] - # image-renderer deployment priority class - priorityClassName: '' - service: - # image-renderer service port name - portName: 'http' - # image-renderer service port used by both service and deployment - port: 8081 - # name of the image-renderer port on the pod - podPortName: http - # number of image-renderer replica sets to keep - revisionHistoryLimit: 10 - networkPolicy: - # Enable a NetworkPolicy to limit inbound traffic to only the created grafana pods - limitIngress: true - # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods - limitEgress: false - resources: {} -# limits: -# cpu: 100m -# memory: 100Mi -# requests: -# cpu: 50m -# memory: 50Mi diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/.helmignore b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/Chart.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/Chart.yaml deleted file mode 100644 index 663499af7..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/Chart.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -appVersion: 1.9.7 -deprecated: true -description: DEPRECATED - Install kube-state-metrics to generate and expose cluster-level - metrics -home: https://github.com/kubernetes/kube-state-metrics/ -keywords: -- metric -- monitoring -- prometheus -- kubernetes -name: kube-state-metrics -sources: -- https://github.com/kubernetes/kube-state-metrics/ -version: 2.9.4 diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/README.md b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/README.md deleted file mode 100644 index 4e1178eb0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# ⚠️ Repo Archive Notice - -As of Nov 13, 2020, charts in this repo will no longer be updated. -For more information, see the Helm Charts [Deprecation and Archive Notice](https://github.com/helm/charts#%EF%B8%8F-deprecation-and-archive-notice), and [Update](https://helm.sh/blog/charts-repo-deprecation/). - -# kube-state-metrics Helm Chart - -* Installs the [kube-state-metrics agent](https://github.com/kubernetes/kube-state-metrics). - -## DEPRECATION NOTICE - -This chart is deprecated and no longer supported. - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```bash -$ helm install stable/kube-state-metrics -``` - -## Configuration - -| Parameter | Description | Default | -|:---------------------------------------------|:--------------------------------------------------------------------------------------|:-------------------------------------------| -| `image.repository` | The image repository to pull from | `quay.io/coreos/kube-state-metrics` | -| `image.tag` | The image tag to pull from | `v1.9.7` | -| `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `imagePullSecrets` | List of container registry secrets | `[]` | -| `replicas` | Number of replicas | `1` | -| `autosharding.enabled` | Set to `true` to automatically shard data across `replicas` pods. EXPERIMENTAL | `false` | -| `service.port` | The port of the container | `8080` | -| `service.annotations` | Annotations to be added to the service | `{}` | -| `customLabels` | Custom labels to apply to service, deployment and pods | `{}` | -| `hostNetwork` | Whether or not to use the host network | `false` | -| `prometheusScrape` | Whether or not enable prom scrape | `true` | -| `rbac.create` | If true, create & use RBAC resources | `true` | -| `serviceAccount.create` | If true, create & use serviceAccount | `true` | -| `serviceAccount.name` | If not set & create is true, use template fullname | | -| `serviceAccount.imagePullSecrets` | Specify image pull secrets field | `[]` | -| `serviceAccount.annotations` | Annotations to be added to the serviceAccount | `{}` | -| `podSecurityPolicy.enabled` | If true, create & use PodSecurityPolicy resources. Note that related RBACs are created only if `rbac.enabled` is `true`. | `false` | -| `podSecurityPolicy.annotations` | Specify pod annotations in the pod security policy | `{}` | -| `podSecurityPolicy.additionalVolumes` | Specify allowed volumes in the pod security policy (`secret` is always allowed) | `[]` | -| `securityContext.enabled` | Enable security context | `true` | -| `securityContext.fsGroup` | Group ID for the filesystem | `65534` | -| `securityContext.runAsGroup` | Group ID for the container | `65534` | -| `securityContext.runAsUser` | User ID for the container | `65534` | -| `priorityClassName` | Name of Priority Class to assign pods | `nil` | -| `nodeSelector` | Node labels for pod assignment | `{}` | -| `affinity` | Affinity settings for pod assignment | `{}` | -| `tolerations` | Tolerations for pod assignment | `[]` | -| `podAnnotations` | Annotations to be added to the pod | `{}` | -| `podDisruptionBudget` | Optional PodDisruptionBudget | `{}` | -| `resources` | kube-state-metrics resource requests and limits | `{}` | -| `collectors.certificatesigningrequests` | Enable the certificatesigningrequests collector. | `true` | -| `collectors.configmaps` | Enable the configmaps collector. | `true` | -| `collectors.cronjobs` | Enable the cronjobs collector. | `true` | -| `collectors.daemonsets` | Enable the daemonsets collector. | `true` | -| `collectors.deployments` | Enable the deployments collector. | `true` | -| `collectors.endpoints` | Enable the endpoints collector. | `true` | -| `collectors.horizontalpodautoscalers` | Enable the horizontalpodautoscalers collector. | `true` | -| `collectors.ingresses` | Enable the ingresses collector. | `true` | -| `collectors.jobs` | Enable the jobs collector. | `true` | -| `collectors.limitranges` | Enable the limitranges collector. | `true` | -| `collectors.mutatingwebhookconfigurations` | Enable the mutatingwebhookconfigurations collector. | `true` | -| `collectors.namespaces` | Enable the namespaces collector. | `true` | -| `collectors.networkpolicies` | Enable the networkpolicies collector. | `true` | -| `collectors.nodes` | Enable the nodes collector. | `true` | -| `collectors.persistentvolumeclaims` | Enable the persistentvolumeclaims collector. | `true` | -| `collectors.persistentvolumes` | Enable the persistentvolumes collector. | `true` | -| `collectors.poddisruptionbudgets` | Enable the poddisruptionbudgets collector. | `true` | -| `collectors.pods` | Enable the pods collector. | `true` | -| `collectors.replicasets` | Enable the replicasets collector. | `true` | -| `collectors.replicationcontrollers` | Enable the replicationcontrollers collector. | `true` | -| `collectors.resourcequotas` | Enable the resourcequotas collector. | `true` | -| `collectors.secrets` | Enable the secrets collector. | `true` | -| `collectors.services` | Enable the services collector. | `true` | -| `collectors.statefulsets` | Enable the statefulsets collector. | `true` | -| `collectors.storageclasses` | Enable the storageclasses collector. | `true` | -| `collectors.validatingwebhookconfigurations` | Enable the validatingwebhookconfigurations collector. | `true` | -| `collectors.verticalpodautoscalers` | Enable the verticalpodautoscalers collector. | `true` | -| `collectors.volumeattachments` | Enable the volumeattachments collector. | `true` | -| `prometheus.monitor.enabled` | Set this to `true` to create ServiceMonitor for Prometheus operator | `false` | -| `prometheus.monitor.additionalLabels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` | -| `prometheus.monitor.namespace` | Namespace where servicemonitor resource should be created | `the same namespace as kube-state-metrics` | -| `prometheus.monitor.honorLabels` | Honor metric labels | `false` | -| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) | -| `kubeTargetVersionOverride` | Override the k8s version of the target cluster | `""` | -| `kubeconfig.enabled` | Adds --kubeconfig arg to container at startup | `""` | -| `kubeconfig.secret` | Base64 encoded kubeconfig file | `""` | diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/NOTES.txt b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/NOTES.txt deleted file mode 100644 index 5a646e0cc..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/NOTES.txt +++ /dev/null @@ -1,10 +0,0 @@ -kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. -The exposed metrics can be found here: -https://github.com/kubernetes/kube-state-metrics/blob/master/docs/README.md#exposed-metrics - -The metrics are exported on the HTTP endpoint /metrics on the listening port. -In your case, {{ template "kube-state-metrics.fullname" . }}.{{ template "kube-state-metrics.namespace" . }}.svc.cluster.local:{{ .Values.service.port }}/metrics - -They are served either as plaintext or protobuf depending on the Accept header. -They are designed to be consumed either by Prometheus itself or by a scraper that is compatible with scraping a Prometheus client endpoint. - diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/_helpers.tpl b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/_helpers.tpl deleted file mode 100644 index 6ae0e647f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/_helpers.tpl +++ /dev/null @@ -1,47 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "kube-state-metrics.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "kube-state-metrics.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create the name of the service account to use -*/}} -{{- define "kube-state-metrics.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (include "kube-state-metrics.fullname" .) .Values.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "kube-state-metrics.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/clusterrole.yaml deleted file mode 100644 index a9198b823..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/clusterrole.yaml +++ /dev/null @@ -1,180 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} - name: {{ template "kube-state-metrics.fullname" . }} -rules: -{{ if .Values.collectors.certificatesigningrequests }} -- apiGroups: ["certificates.k8s.io"] - resources: - - certificatesigningrequests - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.configmaps }} -- apiGroups: [""] - resources: - - configmaps - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.cronjobs }} -- apiGroups: ["batch"] - resources: - - cronjobs - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.daemonsets }} -- apiGroups: ["extensions", "apps"] - resources: - - daemonsets - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.deployments }} -- apiGroups: ["extensions", "apps"] - resources: - - deployments - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.endpoints }} -- apiGroups: [""] - resources: - - endpoints - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.horizontalpodautoscalers }} -- apiGroups: ["autoscaling"] - resources: - - horizontalpodautoscalers - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.ingresses }} -- apiGroups: ["extensions", "networking.k8s.io"] - resources: - - ingresses - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.jobs }} -- apiGroups: ["batch"] - resources: - - jobs - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.limitranges }} -- apiGroups: [""] - resources: - - limitranges - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.mutatingwebhookconfigurations }} -- apiGroups: ["admissionregistration.k8s.io"] - resources: - - mutatingwebhookconfigurations - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.namespaces }} -- apiGroups: [""] - resources: - - namespaces - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.networkpolicies }} -- apiGroups: ["networking.k8s.io"] - resources: - - networkpolicies - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.nodes }} -- apiGroups: [""] - resources: - - nodes - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.persistentvolumeclaims }} -- apiGroups: [""] - resources: - - persistentvolumeclaims - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.persistentvolumes }} -- apiGroups: [""] - resources: - - persistentvolumes - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.poddisruptionbudgets }} -- apiGroups: ["policy"] - resources: - - poddisruptionbudgets - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.pods }} -- apiGroups: [""] - resources: - - pods - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.replicasets }} -- apiGroups: ["extensions", "apps"] - resources: - - replicasets - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.replicationcontrollers }} -- apiGroups: [""] - resources: - - replicationcontrollers - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.resourcequotas }} -- apiGroups: [""] - resources: - - resourcequotas - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.secrets }} -- apiGroups: [""] - resources: - - secrets - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.services }} -- apiGroups: [""] - resources: - - services - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.statefulsets }} -- apiGroups: ["apps"] - resources: - - statefulsets - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.storageclasses }} -- apiGroups: ["storage.k8s.io"] - resources: - - storageclasses - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.validatingwebhookconfigurations }} -- apiGroups: ["admissionregistration.k8s.io"] - resources: - - validatingwebhookconfigurations - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.volumeattachments }} -- apiGroups: ["storage.k8s.io"] - resources: - - volumeattachments - verbs: ["list", "watch"] -{{ end -}} -{{ if .Values.collectors.verticalpodautoscalers }} -- apiGroups: ["autoscaling.k8s.io"] - resources: - - verticalpodautoscalers - verbs: ["list", "watch"] -{{ end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/clusterrolebinding.yaml deleted file mode 100644 index 160db8bd1..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} - name: {{ template "kube-state-metrics.fullname" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "kube-state-metrics.fullname" . }} -subjects: -- kind: ServiceAccount - name: {{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/deployment.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/deployment.yaml deleted file mode 100644 index 8f491ec5d..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/deployment.yaml +++ /dev/null @@ -1,206 +0,0 @@ -apiVersion: apps/v1 -{{- if .Values.autosharding.enabled }} -kind: StatefulSet -{{- else }} -kind: Deployment -{{- end }} -metadata: - name: {{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - app.kubernetes.io/instance: "{{ .Release.Name }}" - app.kubernetes.io/managed-by: "{{ .Release.Service }}" -{{- if .Values.customLabels }} -{{ toYaml .Values.customLabels | indent 4 }} -{{- end }} -spec: - selector: - matchLabels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - replicas: {{ .Values.replicas }} -{{- if .Values.autosharding.enabled }} - serviceName: {{ template "kube-state-metrics.fullname" . }} - volumeClaimTemplates: [] -{{- end }} - template: - metadata: - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - app.kubernetes.io/instance: "{{ .Release.Name }}" -{{- if .Values.customLabels }} -{{ toYaml .Values.customLabels | indent 8 }} -{{- end }} -{{- if .Values.podAnnotations }} - annotations: -{{ toYaml .Values.podAnnotations | indent 8 }} -{{- end }} - spec: - hostNetwork: {{ .Values.hostNetwork }} - serviceAccountName: {{ template "kube-state-metrics.serviceAccountName" . }} - {{- if .Values.securityContext.enabled }} - securityContext: - fsGroup: {{ .Values.securityContext.fsGroup }} - runAsGroup: {{ .Values.securityContext.runAsGroup }} - runAsUser: {{ .Values.securityContext.runAsUser }} - {{- end }} - {{- if .Values.priorityClassName }} - priorityClassName: {{ .Values.priorityClassName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} -{{- if .Values.autosharding.enabled }} - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace -{{- end }} - args: -{{ if .Values.collectors.certificatesigningrequests }} - - --collectors=certificatesigningrequests -{{ end }} -{{ if .Values.collectors.configmaps }} - - --collectors=configmaps -{{ end }} -{{ if .Values.collectors.cronjobs }} - - --collectors=cronjobs -{{ end }} -{{ if .Values.collectors.daemonsets }} - - --collectors=daemonsets -{{ end }} -{{ if .Values.collectors.deployments }} - - --collectors=deployments -{{ end }} -{{ if .Values.collectors.endpoints }} - - --collectors=endpoints -{{ end }} -{{ if .Values.collectors.horizontalpodautoscalers }} - - --collectors=horizontalpodautoscalers -{{ end }} -{{ if .Values.collectors.ingresses }} - - --collectors=ingresses -{{ end }} -{{ if .Values.collectors.jobs }} - - --collectors=jobs -{{ end }} -{{ if .Values.collectors.limitranges }} - - --collectors=limitranges -{{ end }} -{{ if .Values.collectors.mutatingwebhookconfigurations }} - - --collectors=mutatingwebhookconfigurations -{{ end }} -{{ if .Values.collectors.namespaces }} - - --collectors=namespaces -{{ end }} -{{ if .Values.collectors.networkpolicies }} - - --collectors=networkpolicies -{{ end }} -{{ if .Values.collectors.nodes }} - - --collectors=nodes -{{ end }} -{{ if .Values.collectors.persistentvolumeclaims }} - - --collectors=persistentvolumeclaims -{{ end }} -{{ if .Values.collectors.persistentvolumes }} - - --collectors=persistentvolumes -{{ end }} -{{ if .Values.collectors.poddisruptionbudgets }} - - --collectors=poddisruptionbudgets -{{ end }} -{{ if .Values.collectors.pods }} - - --collectors=pods -{{ end }} -{{ if .Values.collectors.replicasets }} - - --collectors=replicasets -{{ end }} -{{ if .Values.collectors.replicationcontrollers }} - - --collectors=replicationcontrollers -{{ end }} -{{ if .Values.collectors.resourcequotas }} - - --collectors=resourcequotas -{{ end }} -{{ if .Values.collectors.secrets }} - - --collectors=secrets -{{ end }} -{{ if .Values.collectors.services }} - - --collectors=services -{{ end }} -{{ if .Values.collectors.statefulsets }} - - --collectors=statefulsets -{{ end }} -{{ if .Values.collectors.storageclasses }} - - --collectors=storageclasses -{{ end }} -{{ if .Values.collectors.validatingwebhookconfigurations }} - - --collectors=validatingwebhookconfigurations -{{ end }} -{{ if .Values.collectors.verticalpodautoscalers }} - - --collectors=verticalpodautoscalers -{{ end }} -{{ if .Values.collectors.volumeattachments }} - - --collectors=volumeattachments -{{ end }} -{{ if .Values.namespace }} - - --namespace={{ .Values.namespace }} -{{ end }} -{{ if .Values.autosharding.enabled }} - - --pod=$(POD_NAME) - - --pod-namespace=$(POD_NAMESPACE) -{{ end }} -{{ if .Values.kubeconfig.enabled }} - - --kubeconfig=/opt/k8s/.kube/config -{{ end }} -{{- if .Values.kubeconfig.enabled }} - volumeMounts: - - name: kubeconfig - mountPath: /opt/k8s/.kube/ - readOnly: true -{{- end }} - imagePullPolicy: {{ .Values.image.pullPolicy }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - ports: - - containerPort: 8080 - livenessProbe: - httpGet: - path: /healthz - port: 8080 - initialDelaySeconds: 5 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: / - port: 8080 - initialDelaySeconds: 5 - timeoutSeconds: 5 -{{- if .Values.resources }} - resources: -{{ toYaml .Values.resources | indent 10 }} -{{- end }} -{{- if .Values.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.imagePullSecrets | indent 8 }} -{{- end }} -{{- if .Values.affinity }} - affinity: -{{ toYaml .Values.affinity | indent 8 }} -{{- end }} -{{- if .Values.nodeSelector }} - nodeSelector: -{{ toYaml .Values.nodeSelector | indent 8 }} -{{- end }} -{{- if .Values.tolerations }} - tolerations: -{{ toYaml .Values.tolerations | indent 8 }} -{{- end }} -{{- if .Values.kubeconfig.enabled}} - volumes: - - name: kubeconfig - secret: - secretName: {{ template "kube-state-metrics.fullname" . }}-kubeconfig -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/kubeconfig-secret.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/kubeconfig-secret.yaml deleted file mode 100644 index a7800d7ad..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/kubeconfig-secret.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.kubeconfig.enabled -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "kube-state-metrics.fullname" . }}-kubeconfig - namespace: {{ template "kube-state-metrics.namespace" . }} - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - app.kubernetes.io/instance: "{{ .Release.Name }}" - app.kubernetes.io/managed-by: "{{ .Release.Service }}" -type: Opaque -data: - config: '{{ .Values.kubeconfig.secret }}' -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/pdb.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/pdb.yaml deleted file mode 100644 index 6adb50d79..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/pdb.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.podDisruptionBudget -}} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - app.kubernetes.io/instance: "{{ .Release.Name }}" - app.kubernetes.io/managed-by: "{{ .Release.Service }}" -spec: - selector: - matchLabels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} -{{ toYaml .Values.podDisruptionBudget | indent 2 }} -{{- end -}} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/podsecuritypolicy.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/podsecuritypolicy.yaml deleted file mode 100644 index e822ba0e7..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/podsecuritypolicy.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- if .Values.podSecurityPolicy.enabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "kube-state-metrics.fullname" . }} - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} -{{- if .Values.podSecurityPolicy.annotations }} - annotations: -{{ toYaml .Values.podSecurityPolicy.annotations | indent 4 }} -{{- end }} -spec: - privileged: false - volumes: - - 'secret' -{{- if .Values.podSecurityPolicy.additionalVolumes }} -{{ toYaml .Values.podSecurityPolicy.additionalVolumes | indent 4 }} -{{- end }} - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - rule: 'MustRunAsNonRoot' - seLinux: - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 1 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 1 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/psp-clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/psp-clusterrole.yaml deleted file mode 100644 index 217abc950..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/psp-clusterrole.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if and .Values.podSecurityPolicy.enabled .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} - name: psp-{{ template "kube-state-metrics.fullname" . }} -rules: -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} -- apiGroups: ['policy'] -{{- else }} -- apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "kube-state-metrics.fullname" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml deleted file mode 100644 index feb97f228..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if and .Values.podSecurityPolicy.enabled .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} - name: psp-{{ template "kube-state-metrics.fullname" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: psp-{{ template "kube-state-metrics.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/service.yaml deleted file mode 100644 index 5dacf5217..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/service.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - app.kubernetes.io/instance: "{{ .Release.Name }}" - app.kubernetes.io/managed-by: "{{ .Release.Service }}" -{{- if .Values.customLabels }} -{{ toYaml .Values.customLabels | indent 4 }} -{{- end }} - annotations: - {{- if .Values.prometheusScrape }} - prometheus.io/scrape: '{{ .Values.prometheusScrape }}' - {{- end }} - {{- if .Values.service.annotations }} - {{- toYaml .Values.service.annotations | nindent 4 }} - {{- end }} -spec: - type: "{{ .Values.service.type }}" - ports: - - name: "http" - protocol: TCP - port: {{ .Values.service.port }} - {{- if .Values.service.nodePort }} - nodePort: {{ .Values.service.nodePort }} - {{- end }} - targetPort: 8080 -{{- if .Values.service.loadBalancerIP }} - loadBalancerIP: "{{ .Values.service.loadBalancerIP }}" -{{- end }} - selector: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/serviceaccount.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/serviceaccount.yaml deleted file mode 100644 index 2e8a1ee38..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/serviceaccount.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} - name: {{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} -{{- if .Values.serviceAccount.annotations }} - annotations: -{{ toYaml .Values.serviceAccount.annotations | indent 4 }} -{{- end }} -imagePullSecrets: -{{ toYaml .Values.serviceAccount.imagePullSecrets | indent 2 }} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/servicemonitor.yaml deleted file mode 100644 index 54cde362d..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/servicemonitor.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.prometheus.monitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - app.kubernetes.io/instance: "{{ .Release.Name }}" - app.kubernetes.io/managed-by: "{{ .Release.Service }}" - {{- if .Values.prometheus.monitor.additionalLabels }} -{{ toYaml .Values.prometheus.monitor.additionalLabels | indent 4 }} - {{- end }} -spec: - selector: - matchLabels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - endpoints: - - port: http - {{- if .Values.prometheus.monitor.honorLabels }} - honorLabels: true - {{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/stsdiscovery-role.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/stsdiscovery-role.yaml deleted file mode 100644 index 9770b0498..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/stsdiscovery-role.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if and .Values.autosharding.enabled .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} -rules: -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - apps - resourceNames: - - {{ template "kube-state-metrics.fullname" . }} - resources: - - statefulsets - verbs: - - get - - list - - watch -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml deleted file mode 100644 index 6a2e5bfe7..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.autosharding.enabled .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} - labels: - app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} - helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "kube-state-metrics.fullname" . }} - namespace: {{ template "kube-state-metrics.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/values.yaml deleted file mode 100644 index 3edd4c816..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/kube-state-metrics/values.yaml +++ /dev/null @@ -1,161 +0,0 @@ -# Default values for kube-state-metrics. -prometheusScrape: true -image: - repository: quay.io/coreos/kube-state-metrics - tag: v1.9.7 - pullPolicy: IfNotPresent - -imagePullSecrets: [] -# - name: "image-pull-secret" - -# If set to true, this will deploy kube-state-metrics as a StatefulSet and the data -# will be automatically sharded across <.Values.replicas> pods using the built-in -# autodiscovery feature: https://github.com/kubernetes/kube-state-metrics#automated-sharding -# This is an experimental feature and there are no stability guarantees. -autosharding: - enabled: false - -replicas: 1 - -service: - port: 8080 - # Default to clusterIP for backward compatibility - type: ClusterIP - nodePort: 0 - loadBalancerIP: "" - annotations: {} - -customLabels: {} - -hostNetwork: false - -rbac: - # If true, create & use RBAC resources - create: true - -serviceAccount: - # Specifies whether a ServiceAccount should be created, require rbac true - create: true - # The name of the ServiceAccount to use. - # If not set and create is true, a name is generated using the fullname template - name: - # Reference to one or more secrets to be used when pulling images - # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - imagePullSecrets: [] - # ServiceAccount annotations. - # Use case: AWS EKS IAM roles for service accounts - # ref: https://docs.aws.amazon.com/eks/latest/userguide/specify-service-account-role.html - annotations: {} - -prometheus: - monitor: - enabled: false - additionalLabels: {} - namespace: "" - honorLabels: false - -## Specify if a Pod Security Policy for kube-state-metrics must be created -## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ -## -podSecurityPolicy: - enabled: false - annotations: {} - ## Specify pod annotations - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl - ## - # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' - # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - - additionalVolumes: [] - -securityContext: - enabled: true - runAsGroup: 65534 - runAsUser: 65534 - fsGroup: 65534 - -## Node labels for pod assignment -## Ref: https://kubernetes.io/docs/user-guide/node-selection/ -nodeSelector: {} - -## Affinity settings for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ -affinity: {} - -## Tolerations for pod assignment -## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -tolerations: [] - -# Annotations to be added to the pod -podAnnotations: {} - -## Assign a PriorityClassName to pods if set -# priorityClassName: "" - -# Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ -podDisruptionBudget: {} - -# Available collectors for kube-state-metrics. By default all available -# collectors are enabled. -collectors: - certificatesigningrequests: true - configmaps: true - cronjobs: true - daemonsets: true - deployments: true - endpoints: true - horizontalpodautoscalers: true - ingresses: true - jobs: true - limitranges: true - mutatingwebhookconfigurations: true - namespaces: true - networkpolicies: true - nodes: true - persistentvolumeclaims: true - persistentvolumes: true - poddisruptionbudgets: true - pods: true - replicasets: true - replicationcontrollers: true - resourcequotas: true - secrets: true - services: true - statefulsets: true - storageclasses: true - validatingwebhookconfigurations: true - verticalpodautoscalers: false - volumeattachments: true - -# Enabling kubeconfig will pass the --kubeconfig argument to the container -kubeconfig: - enabled: false - # base64 encoded kube-config file - secret: - -# Namespace to be enabled for collecting resources. By default all namespaces are collected. -# namespace: "" - -## Override the deployment namespace -## -namespaceOverride: "" - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 64Mi - # requests: - # cpu: 10m - # memory: 32Mi - -## Provide a k8s version to define apiGroups for podSecurityPolicy Cluster Role. -## For example: kubeTargetVersionOverride: 1.14.9 -## -kubeTargetVersionOverride: "" diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/.helmignore b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/Chart.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/Chart.yaml deleted file mode 100644 index 659454766..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/Chart.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -appVersion: 1.0.1 -description: A Helm chart for prometheus node-exporter -home: https://github.com/prometheus/node_exporter/ -keywords: -- node-exporter -- prometheus -- exporter -maintainers: -- email: gianrubio@gmail.com - name: gianrubio -- name: vsliouniaev -name: prometheus-node-exporter -sources: -- https://github.com/prometheus/node_exporter/ -version: 1.12.0 diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/README.md b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/README.md deleted file mode 100644 index babde05e0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# Prometheus Node Exporter - -Prometheus exporter for hardware and OS metrics exposed by *NIX kernels, written in Go with pluggable metric collectors. - -This chart bootstraps a prometheus [Node Exporter](http://github.com/prometheus/node_exporter) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -## Get Repo Info - -```console -helm repo add prometheus-community https://prometheus-community.github.io/helm-charts -helm repo update -``` - -_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ - -## Install Chart - -```console -# Helm 3 -$ helm install [RELEASE_NAME] prometheus-community/prometheus-node-exporter - -# Helm 2 -$ helm install --name [RELEASE_NAME] prometheus-community/prometheus-node-exporter -``` - -_See [configuration](#configuration) below._ - -_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ - -## Uninstall Chart - -```console -# Helm 3 -$ helm uninstall [RELEASE_NAME] - -# Helm 2 -# helm delete --purge [RELEASE_NAME] -``` - -This removes all the Kubernetes components associated with the chart and deletes the release. - -_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ - -## Upgrading Chart - -```console -# Helm 3 or 2 -$ helm upgrade [RELEASE_NAME] [CHART] --install -``` - -_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ - -## Configuring - -See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands: - -```console -# Helm 2 -$ helm inspect values prometheus-community/prometheus-node-exporter - -# Helm 3 -$ helm show values prometheus-community/prometheus-node-exporter -``` diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/ci/port-values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/ci/port-values.yaml deleted file mode 100644 index dbfb4b67f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/ci/port-values.yaml +++ /dev/null @@ -1,3 +0,0 @@ -service: - targetPort: 9102 - port: 9102 diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/NOTES.txt b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/NOTES.txt deleted file mode 100644 index dc272fa99..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/NOTES.txt +++ /dev/null @@ -1,15 +0,0 @@ -1. Get the application URL by running these commands: -{{- if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ template "prometheus-node-exporter.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus-node-exporter.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ template "prometheus-node-exporter.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc -w {{ template "prometheus-node-exporter.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ template "prometheus-node-exporter.namespace" . }} {{ template "prometheus-node-exporter.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - echo http://$SERVICE_IP:{{ .Values.service.port }} -{{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ template "prometheus-node-exporter.namespace" . }} -l "app={{ template "prometheus-node-exporter.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - echo "Visit http://127.0.0.1:9100 to use your application" - kubectl port-forward --namespace {{ template "prometheus-node-exporter.namespace" . }} $POD_NAME 9100 -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/_helpers.tpl b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/_helpers.tpl deleted file mode 100644 index e8260688f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/_helpers.tpl +++ /dev/null @@ -1,66 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "prometheus-node-exporter.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "prometheus-node-exporter.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* Generate basic labels */}} -{{- define "prometheus-node-exporter.labels" }} -app: {{ template "prometheus-node-exporter.name" . }} -heritage: {{.Release.Service }} -release: {{.Release.Name }} -chart: {{ template "prometheus-node-exporter.chart" . }} -{{- if .Values.podLabels}} -{{ toYaml .Values.podLabels }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "prometheus-node-exporter.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - - -{{/* -Create the name of the service account to use -*/}} -{{- define "prometheus-node-exporter.serviceAccountName" -}} -{{- if .Values.serviceAccount.create -}} - {{ default (include "prometheus-node-exporter.fullname" .) .Values.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "prometheus-node-exporter.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/daemonset.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/daemonset.yaml deleted file mode 100644 index 2787daea9..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/daemonset.yaml +++ /dev/null @@ -1,159 +0,0 @@ -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: {{ template "prometheus-node-exporter.fullname" . }} - namespace: {{ template "prometheus-node-exporter.namespace" . }} - labels: {{ include "prometheus-node-exporter.labels" . | indent 4 }} -spec: - selector: - matchLabels: - app: {{ template "prometheus-node-exporter.name" . }} - release: {{ .Release.Name }} - {{- if .Values.updateStrategy }} - updateStrategy: -{{ toYaml .Values.updateStrategy | indent 4 }} - {{- end }} - template: - metadata: - labels: {{ include "prometheus-node-exporter.labels" . | indent 8 }} - {{- if .Values.podAnnotations }} - annotations: - {{- toYaml .Values.podAnnotations | nindent 8 }} - {{- end }} - spec: -{{- if and .Values.rbac.create .Values.serviceAccount.create }} - serviceAccountName: {{ template "prometheus-node-exporter.serviceAccountName" . }} -{{- end }} -{{- if .Values.securityContext }} - securityContext: -{{ toYaml .Values.securityContext | indent 8 }} -{{- end }} -{{- if .Values.priorityClassName }} - priorityClassName: {{ .Values.priorityClassName }} -{{- end }} - containers: - - name: node-exporter - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - args: - - --path.procfs=/host/proc - - --path.sysfs=/host/sys - - --path.rootfs=/host/root - - --web.listen-address=$(HOST_IP):{{ .Values.service.port }} -{{- if .Values.extraArgs }} -{{ toYaml .Values.extraArgs | indent 12 }} -{{- end }} - env: - - name: HOST_IP - {{- if .Values.service.listenOnAllInterfaces }} - value: 0.0.0.0 - {{- else }} - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - {{- end }} - ports: - - name: metrics - containerPort: {{ .Values.service.targetPort }} - protocol: TCP - livenessProbe: - httpGet: - path: / - port: {{ .Values.service.port }} - readinessProbe: - httpGet: - path: / - port: {{ .Values.service.port }} - resources: -{{ toYaml .Values.resources | indent 12 }} - volumeMounts: - - name: proc - mountPath: /host/proc - readOnly: true - - name: sys - mountPath: /host/sys - readOnly: true - - name: root - mountPath: /host/root - mountPropagation: HostToContainer - readOnly: true - {{- if .Values.extraHostVolumeMounts }} - {{- range $_, $mount := .Values.extraHostVolumeMounts }} - - name: {{ $mount.name }} - mountPath: {{ $mount.mountPath }} - readOnly: {{ $mount.readOnly }} - {{- if $mount.mountPropagation }} - mountPropagation: {{ $mount.mountPropagation }} - {{- end }} - {{- end }} - {{- end }} - {{- if .Values.sidecarVolumeMount }} - {{- range $_, $mount := .Values.sidecarVolumeMount }} - - name: {{ $mount.name }} - mountPath: {{ $mount.mountPath }} - readOnly: true - {{- end }} - {{- end }} - {{- if .Values.configmaps }} - {{- range $_, $mount := .Values.configmaps }} - - name: {{ $mount.name }} - mountPath: {{ $mount.mountPath }} - {{- end }} - {{- end }} -{{- if .Values.sidecars }} -{{ toYaml .Values.sidecars | indent 8 }} - {{- if .Values.sidecarVolumeMount }} - volumeMounts: - {{- range $_, $mount := .Values.sidecarVolumeMount }} - - name: {{ $mount.name }} - mountPath: {{ $mount.mountPath }} - readOnly: {{ $mount.readOnly }} - {{- end }} - {{- end }} -{{- end }} - hostNetwork: {{ .Values.hostNetwork }} - hostPID: true -{{- if .Values.affinity }} - affinity: -{{ toYaml .Values.affinity | indent 8 }} -{{- end }} -{{- if .Values.nodeSelector }} - nodeSelector: -{{ toYaml .Values.nodeSelector | indent 8 }} -{{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - volumes: - - name: proc - hostPath: - path: /proc - - name: sys - hostPath: - path: /sys - - name: root - hostPath: - path: / - {{- if .Values.extraHostVolumeMounts }} - {{- range $_, $mount := .Values.extraHostVolumeMounts }} - - name: {{ $mount.name }} - hostPath: - path: {{ $mount.hostPath }} - {{- end }} - {{- end }} - {{- if .Values.sidecarVolumeMount }} - {{- range $_, $mount := .Values.sidecarVolumeMount }} - - name: {{ $mount.name }} - emptyDir: - medium: Memory - {{- end }} - {{- end }} - {{- if .Values.configmaps }} - {{- range $_, $mount := .Values.configmaps }} - - name: {{ $mount.name }} - configMap: - name: {{ $mount.name }} - {{- end }} - {{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/endpoints.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/endpoints.yaml deleted file mode 100644 index 8daaeaaff..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/endpoints.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.endpoints }} -apiVersion: v1 -kind: Endpoints -metadata: - name: {{ template "prometheus-node-exporter.fullname" . }} - namespace: {{ template "prometheus-node-exporter.namespace" . }} - labels: -{{ include "prometheus-node-exporter.labels" . | indent 4 }} -subsets: - - addresses: - {{- range .Values.endpoints }} - - ip: {{ . }} - {{- end }} - ports: - - name: metrics - port: 9100 - protocol: TCP -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/monitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/monitor.yaml deleted file mode 100644 index 4e31ba363..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/monitor.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.prometheus.monitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "prometheus-node-exporter.fullname" . }} - namespace: {{ template "prometheus-node-exporter.namespace" . }} - labels: {{ include "prometheus-node-exporter.labels" . | indent 4 }} - {{- if .Values.prometheus.monitor.additionalLabels }} -{{ toYaml .Values.prometheus.monitor.additionalLabels | indent 4 }} - {{- end }} -spec: - selector: - matchLabels: - app: {{ template "prometheus-node-exporter.name" . }} - release: {{ .Release.Name }} - endpoints: - - port: metrics - {{- if .Values.prometheus.monitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.prometheus.monitor.scrapeTimeout }} - {{- end }} -{{- if .Values.prometheus.monitor.relabelings }} - relabelings: -{{ toYaml .Values.prometheus.monitor.relabelings | indent 6 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp-clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp-clusterrole.yaml deleted file mode 100644 index cb433369c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp-clusterrole.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.rbac.create }} -{{- if .Values.rbac.pspEnabled }} -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: psp-{{ template "prometheus-node-exporter.fullname" . }} - labels: {{ include "prometheus-node-exporter.labels" . | indent 4 }} -rules: -- apiGroups: ['extensions'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "prometheus-node-exporter.fullname" . }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp-clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp-clusterrolebinding.yaml deleted file mode 100644 index d36d93ecf..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp-clusterrolebinding.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.rbac.create }} -{{- if .Values.rbac.pspEnabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: psp-{{ template "prometheus-node-exporter.fullname" . }} - labels: {{ include "prometheus-node-exporter.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: psp-{{ template "prometheus-node-exporter.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "prometheus-node-exporter.fullname" . }} - namespace: {{ template "prometheus-node-exporter.namespace" . }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp.yaml deleted file mode 100644 index f00506c98..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/psp.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if .Values.rbac.create }} -{{- if .Values.rbac.pspEnabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "prometheus-node-exporter.fullname" . }} - namespace: {{ template "prometheus-node-exporter.namespace" . }} - labels: {{ include "prometheus-node-exporter.labels" . | indent 4 }} -spec: - privileged: false - # Required to prevent escalations to root. - # allowPrivilegeEscalation: false - # This is redundant with non-root + disallow privilege escalation, - # but we can provide it for defense in depth. - #requiredDropCapabilities: - # - ALL - # Allow core volume types. - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - - 'hostPath' - hostNetwork: true - hostIPC: false - hostPID: true - hostPorts: - - min: 0 - max: 65535 - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/service.yaml deleted file mode 100644 index b0a447fe3..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "prometheus-node-exporter.fullname" . }} - namespace: {{ template "prometheus-node-exporter.namespace" . }} -{{- if .Values.service.annotations }} - annotations: -{{ toYaml .Values.service.annotations | indent 4 }} -{{- end }} - labels: {{ include "prometheus-node-exporter.labels" . | indent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - {{- if ( and (eq .Values.service.type "NodePort" ) (not (empty .Values.service.nodePort)) ) }} - nodePort: {{ .Values.service.nodePort }} - {{- end }} - targetPort: {{ .Values.service.targetPort }} - protocol: TCP - name: metrics - selector: - app: {{ template "prometheus-node-exporter.name" . }} - release: {{ .Release.Name }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/serviceaccount.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/serviceaccount.yaml deleted file mode 100644 index bd1c223b4..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/templates/serviceaccount.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if .Values.rbac.create -}} -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "prometheus-node-exporter.serviceAccountName" . }} - namespace: {{ template "prometheus-node-exporter.namespace" . }} - labels: - app: {{ template "prometheus-node-exporter.name" . }} - chart: {{ template "prometheus-node-exporter.chart" . }} - release: "{{ .Release.Name }}" - heritage: "{{ .Release.Service }}" -imagePullSecrets: -{{ toYaml .Values.serviceAccount.imagePullSecrets | indent 2 }} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/values.yaml deleted file mode 100644 index 7edd8936a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/charts/prometheus-node-exporter/values.yaml +++ /dev/null @@ -1,141 +0,0 @@ -# Default values for prometheus-node-exporter. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -image: - repository: quay.io/prometheus/node-exporter - tag: v1.0.1 - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 9100 - targetPort: 9100 - nodePort: - listenOnAllInterfaces: true - annotations: - prometheus.io/scrape: "true" - -prometheus: - monitor: - enabled: false - additionalLabels: {} - namespace: "" - - relabelings: [] - scrapeTimeout: 10s - -## Customize the updateStrategy if set -updateStrategy: - type: RollingUpdate - rollingUpdate: - maxUnavailable: 1 - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 200m - # memory: 50Mi - # requests: - # cpu: 100m - # memory: 30Mi - -serviceAccount: - # Specifies whether a ServiceAccount should be created - create: true - # The name of the ServiceAccount to use. - # If not set and create is true, a name is generated using the fullname template - name: - imagePullSecrets: [] - -securityContext: - fsGroup: 65534 - runAsGroup: 65534 - runAsNonRoot: true - runAsUser: 65534 - -rbac: - ## If true, create & use RBAC resources - ## - create: true - ## If true, create & use Pod Security Policy resources - ## https://kubernetes.io/docs/concepts/policy/pod-security-policy/ - pspEnabled: true - -# for deployments that have node_exporter deployed outside of the cluster, list -# their addresses here -endpoints: [] - -# Expose the service to the host network -hostNetwork: true - -## Assign a group of affinity scheduling rules -## -affinity: {} -# nodeAffinity: -# requiredDuringSchedulingIgnoredDuringExecution: -# nodeSelectorTerms: -# - matchFields: -# - key: metadata.name -# operator: In -# values: -# - target-host-name - -# Annotations to be added to node exporter pods -podAnnotations: {} - -# Extra labels to be added to node exporter pods -podLabels: {} - -## Assign a nodeSelector if operating a hybrid cluster -## -nodeSelector: {} -# beta.kubernetes.io/arch: amd64 -# beta.kubernetes.io/os: linux - -tolerations: - - effect: NoSchedule - operator: Exists - -## Assign a PriorityClassName to pods if set -# priorityClassName: "" - -## Additional container arguments -## -extraArgs: [] -# - --collector.diskstats.ignored-devices=^(ram|loop|fd|(h|s|v)d[a-z]|nvme\\d+n\\d+p)\\d+$ -# - --collector.textfile.directory=/run/prometheus - -## Additional mounts from the host -## -extraHostVolumeMounts: [] -# - name: <mountName> -# hostPath: <hostPath> -# mountPath: <mountPath> -# readOnly: true|false -# mountPropagation: None|HostToContainer|Bidirectional - -## Additional configmaps to be mounted. -## -configmaps: [] -# - name: <configMapName> -# mountPath: <mountPath> - -## Override the deployment namespace -## -namespaceOverride: "" - -## Additional containers for export metrics to text file -## -sidecars: [] -## - name: nvidia-dcgm-exporter -## image: nvidia/dcgm-exporter:1.4.3 - -## Volume for sidecar containers -## -sidecarVolumeMount: [] -## - name: collector-textfiles -## mountPath: /run/prometheus -## readOnly: false diff --git a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-alertmanagerconfigs.yaml b/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-alertmanagerconfigs.yaml deleted file mode 100644 index fb1ad5f31..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-alertmanagerconfigs.yaml +++ /dev/null @@ -1,1854 +0,0 @@ -# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.44.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: alertmanagerconfigs.monitoring.coreos.com -spec: - group: monitoring.coreos.com - names: - kind: AlertmanagerConfig - listKind: AlertmanagerConfigList - plural: alertmanagerconfigs - singular: alertmanagerconfig - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: AlertmanagerConfig defines a namespaced AlertmanagerConfig to be aggregated across multiple namespaces configuring one Alertmanager cluster. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - spec: - description: AlertmanagerConfigSpec is a specification of the desired behavior of the Alertmanager configuration. By definition, the Alertmanager configuration only applies to alerts for which the `namespace` label is equal to the namespace of the AlertmanagerConfig resource. - properties: - inhibitRules: - description: List of inhibition rules. The rules will only apply to alerts matching the resource’s namespace. - items: - description: InhibitRule defines an inhibition rule that allows to mute alerts when other alerts are already firing. See https://prometheus.io/docs/alerting/latest/configuration/#inhibit_rule - properties: - equal: - description: Labels that must have an equal value in the source and target alert for the inhibition to take effect. - items: - type: string - type: array - sourceMatch: - description: Matchers for which one or more alerts have to exist for the inhibition to take effect. The operator enforces that the alert matches the resource’s namespace. - items: - description: Matcher defines how to match on alert's labels. - properties: - name: - description: Label to match. - type: string - regex: - description: Whether to match on equality (false) or regular-expression (true). - type: boolean - value: - description: Label value to match. - type: string - required: - - name - - value - type: object - type: array - targetMatch: - description: Matchers that have to be fulfilled in the alerts to be muted. The operator enforces that the alert matches the resource’s namespace. - items: - description: Matcher defines how to match on alert's labels. - properties: - name: - description: Label to match. - type: string - regex: - description: Whether to match on equality (false) or regular-expression (true). - type: boolean - value: - description: Label value to match. - type: string - required: - - name - - value - type: object - type: array - type: object - type: array - receivers: - description: List of receivers. - items: - description: Receiver defines one or more notification integrations. - properties: - emailConfigs: - description: List of Email configurations. - items: - description: EmailConfig configures notifications via Email. - properties: - authIdentity: - type: string - authPassword: - description: SecretKeySelector selects a key of a Secret. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - authSecret: - description: SecretKeySelector selects a key of a Secret. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - authUsername: - description: SMTP authentication information. - type: string - from: - description: The sender address. - type: string - headers: - description: Further headers email header key/value pairs. Overrides any headers previously set by the notification implementation. - items: - description: KeyValue defines a (key, value) tuple. - properties: - key: - description: Key of the tuple. - type: string - value: - description: Value of the tuple. - type: string - required: - - key - - value - type: object - type: array - hello: - description: The hostname to identify to the SMTP server. - type: string - html: - description: The HTML body of the email notification. - type: string - requireTLS: - description: The SMTP TLS requirement. Note that Go does not support unencrypted connections to remote SMTP endpoints. - type: boolean - sendResolved: - description: Whether or not to notify about resolved alerts. - type: boolean - smarthost: - description: The SMTP host through which emails are sent. - type: string - text: - description: The text body of the email notification. - type: string - tlsConfig: - description: TLS configuration - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - to: - description: The email address to send notifications to. - type: string - type: object - type: array - name: - description: Name of the receiver. Must be unique across all items from the list. - type: string - opsgenieConfigs: - description: List of OpsGenie configurations. - items: - description: OpsGenieConfig configures notifications via OpsGenie. See https://prometheus.io/docs/alerting/latest/configuration/#opsgenie_config - properties: - apiKey: - description: The secret's key that contains the OpsGenie API key. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - apiURL: - description: The URL to send OpsGenie API requests to. - type: string - description: - description: Description of the incident. - type: string - details: - description: A set of arbitrary key/value pairs that provide further detail about the incident. - items: - description: KeyValue defines a (key, value) tuple. - properties: - key: - description: Key of the tuple. - type: string - value: - description: Value of the tuple. - type: string - required: - - key - - value - type: object - type: array - httpConfig: - description: HTTP client configuration. - properties: - basicAuth: - description: BasicAuth for the client. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenSecret: - description: The secret's key that contains the bearer token to be used by the client for authentication. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - proxyURL: - description: Optional proxy URL. - type: string - tlsConfig: - description: TLS configuration for the client. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - message: - description: Alert text limited to 130 characters. - type: string - note: - description: Additional alert note. - type: string - priority: - description: Priority level of alert. Possible values are P1, P2, P3, P4, and P5. - type: string - responders: - description: List of responders responsible for notifications. - items: - description: OpsGenieConfigResponder defines a responder to an incident. One of id, name or username has to be defined. - properties: - id: - description: ID of the responder. - type: string - name: - description: Name of the responder. - type: string - type: - description: Type of responder. - type: string - username: - description: Username of the responder. - type: string - type: object - type: array - sendResolved: - description: Whether or not to notify about resolved alerts. - type: boolean - source: - description: Backlink to the sender of the notification. - type: string - tags: - description: Comma separated list of tags attached to the notifications. - type: string - type: object - type: array - pagerdutyConfigs: - description: List of PagerDuty configurations. - items: - description: PagerDutyConfig configures notifications via PagerDuty. See https://prometheus.io/docs/alerting/latest/configuration/#pagerduty_config - properties: - class: - description: The class/type of the event. - type: string - client: - description: Client identification. - type: string - clientURL: - description: Backlink to the sender of notification. - type: string - component: - description: The part or component of the affected system that is broken. - type: string - description: - description: Description of the incident. - type: string - details: - description: Arbitrary key/value pairs that provide further detail about the incident. - items: - description: KeyValue defines a (key, value) tuple. - properties: - key: - description: Key of the tuple. - type: string - value: - description: Value of the tuple. - type: string - required: - - key - - value - type: object - type: array - group: - description: A cluster or grouping of sources. - type: string - httpConfig: - description: HTTP client configuration. - properties: - basicAuth: - description: BasicAuth for the client. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenSecret: - description: The secret's key that contains the bearer token to be used by the client for authentication. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - proxyURL: - description: Optional proxy URL. - type: string - tlsConfig: - description: TLS configuration for the client. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - routingKey: - description: The secret's key that contains the PagerDuty integration key (when using Events API v2). Either this field or `serviceKey` needs to be defined. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - sendResolved: - description: Whether or not to notify about resolved alerts. - type: boolean - serviceKey: - description: The secret's key that contains the PagerDuty service key (when using integration type "Prometheus"). Either this field or `routingKey` needs to be defined. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - severity: - description: Severity of the incident. - type: string - url: - description: The URL to send requests to. - type: string - type: object - type: array - pushoverConfigs: - description: List of Pushover configurations. - items: - description: PushoverConfig configures notifications via Pushover. See https://prometheus.io/docs/alerting/latest/configuration/#pushover_config - properties: - expire: - description: How long your notification will continue to be retried for, unless the user acknowledges the notification. - type: string - html: - description: Whether notification message is HTML or plain text. - type: boolean - httpConfig: - description: HTTP client configuration. - properties: - basicAuth: - description: BasicAuth for the client. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenSecret: - description: The secret's key that contains the bearer token to be used by the client for authentication. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - proxyURL: - description: Optional proxy URL. - type: string - tlsConfig: - description: TLS configuration for the client. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - message: - description: Notification message. - type: string - priority: - description: Priority, see https://pushover.net/api#priority - type: string - retry: - description: How often the Pushover servers will send the same notification to the user. Must be at least 30 seconds. - type: string - sendResolved: - description: Whether or not to notify about resolved alerts. - type: boolean - sound: - description: The name of one of the sounds supported by device clients to override the user's default sound choice - type: string - title: - description: Notification title. - type: string - token: - description: Your registered application’s API token, see https://pushover.net/apps - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - url: - description: A supplementary URL shown alongside the message. - type: string - urlTitle: - description: A title for supplementary URL, otherwise just the URL is shown - type: string - userKey: - description: The recipient user’s user key. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - type: array - slackConfigs: - description: List of Slack configurations. - items: - description: SlackConfig configures notifications via Slack. See https://prometheus.io/docs/alerting/latest/configuration/#slack_config - properties: - actions: - description: A list of Slack actions that are sent with each notification. - items: - description: SlackAction configures a single Slack action that is sent with each notification. See https://api.slack.com/docs/message-attachments#action_fields and https://api.slack.com/docs/message-buttons for more information. - properties: - confirm: - description: SlackConfirmationField protect users from destructive actions or particularly distinguished decisions by asking them to confirm their button click one more time. See https://api.slack.com/docs/interactive-message-field-guide#confirmation_fields for more information. - properties: - dismissText: - type: string - okText: - type: string - text: - type: string - title: - type: string - required: - - text - type: object - name: - type: string - style: - type: string - text: - type: string - type: - type: string - url: - type: string - value: - type: string - required: - - text - - type - type: object - type: array - apiURL: - description: The secret's key that contains the Slack webhook URL. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - callbackId: - type: string - channel: - description: The channel or user to send notifications to. - type: string - color: - type: string - fallback: - type: string - fields: - description: A list of Slack fields that are sent with each notification. - items: - description: SlackField configures a single Slack field that is sent with each notification. Each field must contain a title, value, and optionally, a boolean value to indicate if the field is short enough to be displayed next to other fields designated as short. See https://api.slack.com/docs/message-attachments#fields for more information. - properties: - short: - type: boolean - title: - type: string - value: - type: string - required: - - title - - value - type: object - type: array - footer: - type: string - httpConfig: - description: HTTP client configuration. - properties: - basicAuth: - description: BasicAuth for the client. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenSecret: - description: The secret's key that contains the bearer token to be used by the client for authentication. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - proxyURL: - description: Optional proxy URL. - type: string - tlsConfig: - description: TLS configuration for the client. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - iconEmoji: - type: string - iconURL: - type: string - imageURL: - type: string - linkNames: - type: boolean - mrkdwnIn: - items: - type: string - type: array - pretext: - type: string - sendResolved: - description: Whether or not to notify about resolved alerts. - type: boolean - shortFields: - type: boolean - text: - type: string - thumbURL: - type: string - title: - type: string - titleLink: - type: string - username: - type: string - type: object - type: array - victoropsConfigs: - description: List of VictorOps configurations. - items: - description: VictorOpsConfig configures notifications via VictorOps. See https://prometheus.io/docs/alerting/latest/configuration/#victorops_config - properties: - apiKey: - description: The API key to use when talking to the VictorOps API. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - apiUrl: - description: The VictorOps API URL. - type: string - customFields: - description: Additional custom fields for notification. - items: - description: KeyValue defines a (key, value) tuple. - properties: - key: - description: Key of the tuple. - type: string - value: - description: Value of the tuple. - type: string - required: - - key - - value - type: object - type: array - entityDisplayName: - description: Contains summary of the alerted problem. - type: string - httpConfig: - description: The HTTP client's configuration. - properties: - basicAuth: - description: BasicAuth for the client. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenSecret: - description: The secret's key that contains the bearer token to be used by the client for authentication. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - proxyURL: - description: Optional proxy URL. - type: string - tlsConfig: - description: TLS configuration for the client. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - messageType: - description: Describes the behavior of the alert (CRITICAL, WARNING, INFO). - type: string - monitoringTool: - description: The monitoring tool the state message is from. - type: string - routingKey: - description: A key used to map the alert to a team. - type: string - sendResolved: - description: Whether or not to notify about resolved alerts. - type: boolean - stateMessage: - description: Contains long explanation of the alerted problem. - type: string - required: - - routingKey - type: object - type: array - webhookConfigs: - description: List of webhook configurations. - items: - description: WebhookConfig configures notifications via a generic receiver supporting the webhook payload. See https://prometheus.io/docs/alerting/latest/configuration/#webhook_config - properties: - httpConfig: - description: HTTP client configuration. - properties: - basicAuth: - description: BasicAuth for the client. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenSecret: - description: The secret's key that contains the bearer token to be used by the client for authentication. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - proxyURL: - description: Optional proxy URL. - type: string - tlsConfig: - description: TLS configuration for the client. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - maxAlerts: - description: Maximum number of alerts to be sent per webhook message. - format: int32 - type: integer - sendResolved: - description: Whether or not to notify about resolved alerts. - type: boolean - url: - description: The URL to send HTTP POST requests to. `urlSecret` takes precedence over `url`. One of `urlSecret` and `url` should be defined. - type: string - urlSecret: - description: The secret's key that contains the webhook URL to send HTTP requests to. `urlSecret` takes precedence over `url`. One of `urlSecret` and `url` should be defined. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - type: array - wechatConfigs: - description: List of WeChat configurations. - items: - description: WeChatConfig configures notifications via WeChat. See https://prometheus.io/docs/alerting/latest/configuration/#wechat_config - properties: - agentID: - type: string - apiSecret: - description: The secret's key that contains the WeChat API key. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - apiURL: - description: The WeChat API URL. - type: string - corpID: - description: The corp id for authentication. - type: string - httpConfig: - description: HTTP client configuration. - properties: - basicAuth: - description: BasicAuth for the client. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenSecret: - description: The secret's key that contains the bearer token to be used by the client for authentication. The secret needs to be in the same namespace as the AlertmanagerConfig object and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - proxyURL: - description: Optional proxy URL. - type: string - tlsConfig: - description: TLS configuration for the client. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - message: - description: API request data as defined by the WeChat API. - type: string - messageType: - type: string - sendResolved: - description: Whether or not to notify about resolved alerts. - type: boolean - toParty: - type: string - toTag: - type: string - toUser: - type: string - type: object - type: array - required: - - name - type: object - type: array - route: - description: The Alertmanager route definition for alerts matching the resource’s namespace. It will be added to the generated Alertmanager configuration as a first-level route. - properties: - continue: - description: Boolean indicating whether an alert should continue matching subsequent sibling nodes. It will always be overridden to true for the first-level route by the Prometheus operator. - type: boolean - groupBy: - description: List of labels to group by. - items: - type: string - type: array - groupInterval: - description: How long to wait before sending an updated notification. Must match the regular expression `[0-9]+(ms|s|m|h)` (milliseconds seconds minutes hours). - type: string - groupWait: - description: How long to wait before sending the initial notification. Must match the regular expression `[0-9]+(ms|s|m|h)` (milliseconds seconds minutes hours). - type: string - matchers: - description: 'List of matchers that the alert’s labels should match. For the first level route, the operator removes any existing equality and regexp matcher on the `namespace` label and adds a `namespace: <object namespace>` matcher.' - items: - description: Matcher defines how to match on alert's labels. - properties: - name: - description: Label to match. - type: string - regex: - description: Whether to match on equality (false) or regular-expression (true). - type: boolean - value: - description: Label value to match. - type: string - required: - - name - - value - type: object - type: array - receiver: - description: Name of the receiver for this route. If present, it should be listed in the `receivers` field. The field can be omitted only for nested routes otherwise it is mandatory. - type: string - repeatInterval: - description: How long to wait before repeating the last notification. Must match the regular expression `[0-9]+(ms|s|m|h)` (milliseconds seconds minutes hours). - type: string - routes: - description: Child routes. - items: - x-kubernetes-preserve-unknown-fields: true - type: array - type: object - type: object - required: - - spec - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-alertmanagers.yaml b/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-alertmanagers.yaml deleted file mode 100644 index 86a6b980e..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-alertmanagers.yaml +++ /dev/null @@ -1,3216 +0,0 @@ -# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.44.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: alertmanagers.monitoring.coreos.com -spec: - group: monitoring.coreos.com - names: - kind: Alertmanager - listKind: AlertmanagerList - plural: alertmanagers - singular: alertmanager - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The version of Alertmanager - jsonPath: .spec.version - name: Version - type: string - - description: The desired replicas number of Alertmanagers - jsonPath: .spec.replicas - name: Replicas - type: integer - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: Alertmanager describes an Alertmanager cluster. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - spec: - description: 'Specification of the desired behavior of the Alertmanager cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' - properties: - additionalPeers: - description: AdditionalPeers allows injecting a set of additional Alertmanagers to peer with to form a highly available cluster. - items: - type: string - type: array - affinity: - description: If specified, the pod's scheduling constraints. - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. - items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements by node's fields. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. The terms are ORed. - items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements by node's fields. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key <topologyKey> matches that of any node on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key <topologyKey> matches that of any node on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - alertmanagerConfigNamespaceSelector: - description: Namespaces to be selected for AlertmanagerConfig discovery. If nil, only check own namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - alertmanagerConfigSelector: - description: AlertmanagerConfigs to be selected for to merge and configure Alertmanager with. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - baseImage: - description: 'Base image that is used to deploy pods, without tag. Deprecated: use ''image'' instead' - type: string - clusterAdvertiseAddress: - description: 'ClusterAdvertiseAddress is the explicit address to advertise in cluster. Needs to be provided for non RFC1918 [1] (public) addresses. [1] RFC1918: https://tools.ietf.org/html/rfc1918' - type: string - clusterGossipInterval: - description: Interval between gossip attempts. - type: string - clusterPeerTimeout: - description: Timeout for cluster peering. - type: string - clusterPushpullInterval: - description: Interval between pushpull attempts. - type: string - configMaps: - description: ConfigMaps is a list of ConfigMaps in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. The ConfigMaps are mounted into /etc/alertmanager/configmaps/<configmap-name>. - items: - type: string - type: array - configSecret: - description: ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains configuration for this Alertmanager instance. Defaults to 'alertmanager-<alertmanager-name>' The secret is mounted into /etc/alertmanager/config. - type: string - containers: - description: 'Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to an Alertmanager pod. Containers described here modify an operator generated container if they share the same name and modifications are done via a strategic merge patch. The current container names are: `alertmanager` and `config-reloader`. Overriding containers is entirely outside the scope of what the maintainers will support and by doing so, you accept that this behaviour may break at any time without notice.' - items: - description: A single application container that you want to run within a pod. - properties: - args: - description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - command: - description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - env: - description: List of environment variables to set in the container. Cannot be updated. - items: - description: EnvVar represents an environment variable present in a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: Source for the environment variable's value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. - items: - description: EnvFromSource represents the source of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap must be defined - type: boolean - type: object - prefix: - description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret must be defined - type: boolean - type: object - type: object - type: array - image: - description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' - type: string - imagePullPolicy: - description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' - type: string - lifecycle: - description: Actions that the management system should take in response to container lifecycle events. Cannot be updated. - properties: - postStart: - description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: 'Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - name: - description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. - type: string - ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. - items: - description: ContainerPort represents a network port in a single container. - properties: - containerPort: - description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port to. - type: string - hostPort: - description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. - format: int32 - type: integer - name: - description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. - type: string - protocol: - default: TCP - description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: 'Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - resources: - description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - securityContext: - description: 'Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' - properties: - allowPrivilegeEscalation: - description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' - type: boolean - capabilities: - description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - type: object - privileged: - description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. - type: boolean - procMount: - description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. - type: string - readOnlyRootFilesystem: - description: Whether this container has a read-only root filesystem. Default is false. - type: boolean - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: 'StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod''s lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - stdin: - description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. - type: boolean - stdinOnce: - description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false - type: boolean - terminationMessagePath: - description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' - type: string - terminationMessagePolicy: - description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. - type: string - tty: - description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices to be used by the container. - items: - description: volumeDevice describes a mapping of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of the container that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: Pod volumes to mount into the container's filesystem. Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume within a container. - properties: - mountPath: - description: Path within the container at which the volume should be mounted. Must not contain ':'. - type: string - mountPropagation: - description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - type: boolean - subPath: - description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. - type: string - required: - - name - type: object - type: array - externalUrl: - description: The external URL the Alertmanager instances will be available under. This is necessary to generate correct URLs. This is necessary if Alertmanager is not served from root of a DNS name. - type: string - forceEnableClusterMode: - description: ForceEnableClusterMode ensures Alertmanager does not deactivate the cluster mode when running with a single replica. Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each. - type: boolean - image: - description: Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary to ensure the Prometheus Operator knows what version of Alertmanager is being configured. - type: string - imagePullSecrets: - description: An optional list of references to secrets in the same namespace to use for pulling prometheus and alertmanager images from registries see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod - items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. - properties: - name: - description: '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?' - type: string - type: object - type: array - initContainers: - description: 'InitContainers allows adding initContainers to the pod definition. Those can be used to e.g. fetch secrets for injection into the Alertmanager configuration from external sources. Any errors during the execution of an initContainer will lead to a restart of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ Using initContainers for any use case other then secret fetching is entirely outside the scope of what the maintainers will support and by doing so, you accept that this behaviour may break at any time without notice.' - items: - description: A single application container that you want to run within a pod. - properties: - args: - description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - command: - description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - env: - description: List of environment variables to set in the container. Cannot be updated. - items: - description: EnvVar represents an environment variable present in a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: Source for the environment variable's value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. - items: - description: EnvFromSource represents the source of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap must be defined - type: boolean - type: object - prefix: - description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret must be defined - type: boolean - type: object - type: object - type: array - image: - description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' - type: string - imagePullPolicy: - description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' - type: string - lifecycle: - description: Actions that the management system should take in response to container lifecycle events. Cannot be updated. - properties: - postStart: - description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: 'Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - name: - description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. - type: string - ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. - items: - description: ContainerPort represents a network port in a single container. - properties: - containerPort: - description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port to. - type: string - hostPort: - description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. - format: int32 - type: integer - name: - description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. - type: string - protocol: - default: TCP - description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: 'Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - resources: - description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - securityContext: - description: 'Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' - properties: - allowPrivilegeEscalation: - description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' - type: boolean - capabilities: - description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - type: object - privileged: - description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. - type: boolean - procMount: - description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. - type: string - readOnlyRootFilesystem: - description: Whether this container has a read-only root filesystem. Default is false. - type: boolean - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: 'StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod''s lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - stdin: - description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. - type: boolean - stdinOnce: - description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false - type: boolean - terminationMessagePath: - description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' - type: string - terminationMessagePolicy: - description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. - type: string - tty: - description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices to be used by the container. - items: - description: volumeDevice describes a mapping of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of the container that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: Pod volumes to mount into the container's filesystem. Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume within a container. - properties: - mountPath: - description: Path within the container at which the volume should be mounted. Must not contain ':'. - type: string - mountPropagation: - description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - type: boolean - subPath: - description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. - type: string - required: - - name - type: object - type: array - listenLocal: - description: ListenLocal makes the Alertmanager server listen on loopback, so that it does not bind against the Pod IP. Note this is only for the Alertmanager UI, not the gossip communication. - type: boolean - logFormat: - description: Log format for Alertmanager to be configured with. - type: string - logLevel: - description: Log level for Alertmanager to be configured with. - type: string - nodeSelector: - additionalProperties: - type: string - description: Define which Nodes the Pods are scheduled on. - type: object - paused: - description: If set to true all actions on the underlying managed objects are not goint to be performed, except for delete actions. - type: boolean - podMetadata: - description: PodMetadata configures Labels and Annotations which are propagated to the alertmanager pods. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' - type: object - name: - description: 'Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' - type: string - type: object - portName: - description: Port name used for the pods and governing service. This defaults to web - type: string - priorityClassName: - description: Priority class assigned to the Pods - type: string - replicas: - description: Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the running cluster equal to the expected size. - format: int32 - type: integer - resources: - description: Define resources requests and limits for single Pods. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - retention: - description: Time duration Alertmanager shall retain data for. Default is '120h', and must match the regular expression `[0-9]+(ms|s|m|h)` (milliseconds seconds minutes hours). - type: string - routePrefix: - description: The route prefix Alertmanager registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, but the server serves requests under a different route prefix. For example for use with `kubectl proxy`. - type: string - secrets: - description: Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/<secret-name>. - items: - type: string - type: array - securityContext: - description: SecurityContext holds pod-level security attributes and common container settings. This defaults to the default PodSecurityContext. - properties: - fsGroup: - description: "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: \n 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- \n If unset, the Kubelet will not modify the ownership and permissions of any volume." - format: int64 - type: integer - fsGroupChangePolicy: - description: 'fsGroupChangePolicy defines behavior of changing ownership and permission of the volume before being exposed inside Pod. This field will only apply to volume types which support fsGroup based ownership(and permissions). It will have no effect on ephemeral volume types such as: secret, configmaps and emptydir. Valid values are "OnRootMismatch" and "Always". If not specified defaults to "Always".' - type: string - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - supplementalGroups: - description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. - items: - format: int64 - type: integer - type: array - sysctls: - description: Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: ServiceAccountName is the name of the ServiceAccount to use to run the Prometheus Pods. - type: string - sha: - description: 'SHA of Alertmanager container image to be deployed. Defaults to the value of `version`. Similar to a tag, but the SHA explicitly deploys an immutable container image. Version and Tag are ignored if SHA is set. Deprecated: use ''image'' instead. The image digest can be specified as part of the image URL.' - type: string - storage: - description: Storage is the definition of how storage will be used by the Alertmanager instances. - properties: - disableMountSubPath: - description: 'Deprecated: subPath usage will be disabled by default in a future release, this option will become unnecessary. DisableMountSubPath allows to remove any subPath usage in volume mounts.' - type: boolean - emptyDir: - description: 'EmptyDirVolumeSource to be used by the Prometheus StatefulSets. If specified, used in place of any volumeClaimTemplate. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir' - properties: - medium: - description: 'What type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: 'Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - volumeClaimTemplate: - description: A PVC spec to be used by the Prometheus StatefulSets. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - description: EmbeddedMetadata contains metadata relevant to an EmbeddedResource. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' - type: object - name: - description: 'Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' - type: string - type: object - spec: - description: 'Spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - accessModes: - description: 'AccessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' - items: - type: string - type: array - dataSource: - description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot - Beta) * An existing PVC (PersistentVolumeClaim) * An existing custom resource/object that implements data population (Alpha) In order to use VolumeSnapshot object types, the appropriate feature gate must be enabled (VolumeSnapshotDataSource or AnyVolumeDataSource) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the specified data source is not supported, the volume will not be created and the failure will be reported as an event. In the future, we plan to support more data source types and the behavior of the provisioner may change.' - properties: - apiGroup: - description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - resources: - description: 'Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - selector: - description: A label query over volumes to consider for binding. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - storageClassName: - description: 'Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' - type: string - volumeMode: - description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: VolumeName is the binding reference to the PersistentVolume backing this claim. - type: string - type: object - status: - description: 'Status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - accessModes: - description: 'AccessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' - items: - type: string - type: array - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying volume. - type: object - conditions: - description: Current Condition of persistent volume claim. If underlying persistent volume is being resized then the Condition will be set to 'ResizeStarted'. - items: - description: PersistentVolumeClaimCondition contails details about state of pvc - properties: - lastProbeTime: - description: Last time we probed the condition. - format: date-time - type: string - lastTransitionTime: - description: Last time the condition transitioned from one status to another. - format: date-time - type: string - message: - description: Human-readable message indicating details about last transition. - type: string - reason: - description: Unique, this should be a short, machine understandable string that gives the reason for condition's last transition. If it reports "ResizeStarted" that means the underlying persistent volume is being resized. - type: string - status: - type: string - type: - description: PersistentVolumeClaimConditionType is a valid value of PersistentVolumeClaimCondition.Type - type: string - required: - - status - - type - type: object - type: array - phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - type: object - type: object - type: object - tag: - description: 'Tag of Alertmanager container image to be deployed. Defaults to the value of `version`. Version is ignored if Tag is set. Deprecated: use ''image'' instead. The image tag can be specified as part of the image URL.' - type: string - tolerations: - description: If specified, the pod's tolerations. - items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple <key,value,effect> using the matching operator <operator>. - properties: - effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: If specified, the pod's topology spread constraints. - items: - description: TopologySpreadConstraint specifies how to spread matching pods among the given topology. - properties: - labelSelector: - description: LabelSelector is used to find matching pods. Pods that match this label selector are counted to determine the number of pods in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - maxSkew: - description: 'MaxSkew describes the degree to which pods may be unevenly distributed. It''s the maximum permitted difference between the number of matching pods in any two topology domains of a given topology type. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 1/1/0: | zone1 | zone2 | zone3 | | P | P | | - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 1/1/1; scheduling it onto zone1(zone2) would make the ActualSkew(2-0) on zone1(zone2) violate MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled onto any zone. It''s a required field. Default value is 1 and 0 is not allowed.' - format: int32 - type: integer - topologyKey: - description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each <key, value> as a "bucket", and try to put balanced number of pods into each bucket. It's a required field. - type: string - whenUnsatisfiable: - description: 'WhenUnsatisfiable indicates how to deal with a pod if it doesn''t satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it - ScheduleAnyway tells the scheduler to still schedule it It''s considered as "Unsatisfiable" if and only if placing incoming pod on any topology violates "MaxSkew". For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler won''t make it *more* imbalanced. It''s a required field.' - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - version: - description: Version the cluster should be on. - type: string - volumeMounts: - description: VolumeMounts allows configuration of additional VolumeMounts on the output StatefulSet definition. VolumeMounts specified will be appended to other VolumeMounts in the alertmanager container, that are generated as a result of StorageSpec objects. - items: - description: VolumeMount describes a mounting of a Volume within a container. - properties: - mountPath: - description: Path within the container at which the volume should be mounted. Must not contain ':'. - type: string - mountPropagation: - description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - type: boolean - subPath: - description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - volumes: - description: Volumes allows configuration of additional volumes on the output StatefulSet definition. Volumes specified will be appended to other volumes that are generated as a result of StorageSpec objects. - items: - description: Volume represents a named volume in a pod that may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - partition: - description: 'The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as "1". Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty).' - format: int32 - type: integer - readOnly: - description: 'Specify "true" to force and set the ReadOnly property in VolumeMounts to "true". If omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - type: boolean - volumeID: - description: 'Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - type: string - required: - - volumeID - type: object - azureDisk: - description: AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. - properties: - cachingMode: - description: 'Host Caching mode: None, Read Only, Read Write.' - type: string - diskName: - description: The Name of the data disk in the blob storage - type: string - diskURI: - description: The URI the data disk in the blob storage - type: string - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'Expected values Shared: multiple blob disks per storage account Dedicated: single blob disk per storage account Managed: azure managed data disk (only in managed availability set). defaults to shared' - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: AzureFile represents an Azure File Service mount on the host and bind mount to the pod. - properties: - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: the name of secret that contains Azure Storage Account Name and Key - type: string - shareName: - description: Share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: CephFS represents a Ceph FS mount on the host that shares a pod's lifetime - properties: - monitors: - description: 'Required: Monitors is a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - items: - type: string - type: array - path: - description: 'Optional: Used as the mounted root, rather than the full Ceph tree, default is /' - type: string - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: boolean - secretFile: - description: 'Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: string - secretRef: - description: 'Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - properties: - name: - description: '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?' - type: string - type: object - user: - description: 'Optional: User is the rados user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: string - required: - - monitors - type: object - cinder: - description: 'Cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - properties: - fsType: - description: 'Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: string - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: boolean - secretRef: - description: 'Optional: points to a secret object containing parameters used to connect to OpenStack.' - properties: - name: - description: '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?' - type: string - type: object - volumeID: - description: 'volume id used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: string - required: - - volumeID - type: object - configMap: - description: ConfigMap represents a configMap that should populate this volume - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its keys must be defined - type: boolean - type: object - csi: - description: CSI (Container Storage Interface) represents storage that is handled by an external CSI driver (Alpha feature). - properties: - driver: - description: Driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: Filesystem type to mount. Ex. "ext4", "xfs", "ntfs". If not provided, the empty value is passed to the associated CSI driver which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: NodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. This field is optional, and may be empty if no secret is required. If the secret object contains more than one secret, all secret references are passed. - properties: - name: - description: '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?' - type: string - type: object - readOnly: - description: Specifies a read-only configuration for the volume. Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: VolumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: DownwardAPI represents downward API about the pod that should populate this volume - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: Items is a list of downward API volume file - items: - description: DownwardAPIVolumeFile represents information to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: 'Required: Path is the relative path name of the file to be created. Must not be absolute or contain the ''..'' path. Must be utf-8 encoded. The first item of the relative path must not start with ''..''' - type: string - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - emptyDir: - description: 'EmptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - properties: - medium: - description: 'What type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: 'Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - fc: - description: FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. - properties: - fsType: - description: 'Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - lun: - description: 'Optional: FC target lun number' - format: int32 - type: integer - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.' - type: boolean - targetWWNs: - description: 'Optional: FC target worldwide names (WWNs)' - items: - type: string - type: array - wwids: - description: 'Optional: FC volume world wide identifiers (wwids) Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously.' - items: - type: string - type: array - type: object - flexVolume: - description: FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. - properties: - driver: - description: Driver is the name of the driver to use for this volume. - type: string - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'Optional: Extra command options if any.' - type: object - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.' - type: boolean - secretRef: - description: 'Optional: SecretRef is reference to the secret object containing sensitive information to pass to the plugin scripts. This may be empty if no secret object is specified. If the secret object contains more than one secret, all secrets are passed to the plugin scripts.' - properties: - name: - description: '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?' - type: string - type: object - required: - - driver - type: object - flocker: - description: Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running - properties: - datasetName: - description: Name of the dataset stored as metadata -> name on the dataset for Flocker should be considered as deprecated - type: string - datasetUUID: - description: UUID of the dataset. This is unique identifier of a Flocker dataset - type: string - type: object - gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - partition: - description: 'The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as "1". Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - format: int32 - type: integer - pdName: - description: 'Unique name of the PD resource in GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - type: string - readOnly: - description: 'ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - type: boolean - required: - - pdName - type: object - gitRepo: - description: 'GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod''s container.' - properties: - directory: - description: Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name. - type: string - repository: - description: Repository URL - type: string - revision: - description: Commit hash for the specified revision. - type: string - required: - - repository - type: object - glusterfs: - description: 'Glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' - properties: - endpoints: - description: 'EndpointsName is the endpoint name that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: string - path: - description: 'Path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: string - readOnly: - description: 'ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: 'HostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath --- TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not mount host directories as read/write.' - properties: - path: - description: 'Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' - type: string - type: - description: 'Type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' - type: string - required: - - path - type: object - iscsi: - description: 'ISCSI represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' - properties: - chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: whether support iSCSI Session CHAP authentication - type: boolean - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection. - type: string - iqn: - description: Target iSCSI Qualified Name. - type: string - iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). - type: string - lun: - description: iSCSI Target Lun number. - format: int32 - type: integer - portals: - description: iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - readOnly: - description: ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. - type: boolean - secretRef: - description: CHAP Secret for iSCSI target and initiator authentication - properties: - name: - description: '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?' - type: string - type: object - targetPortal: - description: iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: 'Volume''s name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - nfs: - description: 'NFS represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - properties: - path: - description: 'Path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: string - readOnly: - description: 'ReadOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: boolean - server: - description: 'Server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - type: string - readOnly: - description: Will force the ReadOnly setting in VolumeMounts. Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: ID that identifies Photon Controller persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: PortworxVolume represents a portworx volume attached and mounted on kubelets host machine - properties: - fsType: - description: FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: VolumeID uniquely identifies a Portworx volume - type: string - required: - - volumeID - type: object - projected: - description: Items for all in one resources secrets, configmaps, and downward API - properties: - defaultMode: - description: Mode bits to use on created files by default. Must be a value between 0 and 0777. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: list of volume projections - items: - description: Projection that may be projected along with other supported volume types - properties: - configMap: - description: information about the configMap data to project - properties: - items: - description: If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its keys must be defined - type: boolean - type: object - downwardAPI: - description: information about the downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume file - items: - description: DownwardAPIVolumeFile represents information to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: 'Required: Path is the relative path name of the file to be created. Must not be absolute or contain the ''..'' path. Must be utf-8 encoded. The first item of the relative path must not start with ''..''' - type: string - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - secret: - description: information about the secret data to project - properties: - items: - description: If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - type: object - serviceAccountToken: - description: information about the serviceAccountToken data to project - properties: - audience: - description: Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver. - type: string - expirationSeconds: - description: ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes. - format: int64 - type: integer - path: - description: Path is the path relative to the mount point of the file to project the token into. - type: string - required: - - path - type: object - type: object - type: array - required: - - sources - type: object - quobyte: - description: Quobyte represents a Quobyte mount on the host that shares a pod's lifetime - properties: - group: - description: Group to map volume access to Default is no group - type: string - readOnly: - description: ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. - type: boolean - registry: - description: Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes - type: string - tenant: - description: Tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: User to map volume access to Defaults to serivceaccount user - type: string - volume: - description: Volume is a string that references an already created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: 'RBD represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - keyring: - description: 'Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - monitors: - description: 'A collection of Ceph monitors. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - items: - type: string - type: array - pool: - description: 'The rados pool name. Default is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - readOnly: - description: 'ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: boolean - secretRef: - description: 'SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - properties: - name: - description: '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?' - type: string - type: object - user: - description: 'The rados user name. Default is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - required: - - image - - monitors - type: object - scaleIO: - description: ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". - type: string - gateway: - description: The host address of the ScaleIO API Gateway. - type: string - protectionDomain: - description: The name of the ScaleIO Protection Domain for the configured storage. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. - properties: - name: - description: '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?' - type: string - type: object - sslEnabled: - description: Flag to enable/disable SSL communication with Gateway, default false - type: boolean - storageMode: - description: Indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. - type: string - storagePool: - description: The ScaleIO Storage Pool associated with the protection domain. - type: string - system: - description: The name of the storage system as configured in ScaleIO. - type: string - volumeName: - description: The name of a volume already created in the ScaleIO system that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: 'Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - optional: - description: Specify whether the Secret or its keys must be defined - type: boolean - secretName: - description: 'Name of the secret in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' - type: string - type: object - storageos: - description: StorageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: SecretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. - properties: - name: - description: '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?' - type: string - type: object - volumeName: - description: VolumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. - type: string - volumeNamespace: - description: VolumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping to be mirrored within StorageOS for tighter integration. Set VolumeName to any name to override the default behaviour. Set to "default" if you are not using namespaces within StorageOS. Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: Storage Policy Based Management (SPBM) profile ID associated with the StoragePolicyName. - type: string - storagePolicyName: - description: Storage Policy Based Management (SPBM) profile name. - type: string - volumePath: - description: Path that identifies vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - type: object - status: - description: 'Most recent observed status of the Alertmanager cluster. Read-only. Not included when requesting from the apiserver, only from the Prometheus Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' - properties: - availableReplicas: - description: Total number of available pods (ready for at least minReadySeconds) targeted by this Alertmanager cluster. - format: int32 - type: integer - paused: - description: Represents whether any actions on the underlying managed objects are being performed. Only delete actions will be performed. - type: boolean - replicas: - description: Total number of non-terminated pods targeted by this Alertmanager cluster (their labels match the selector). - format: int32 - type: integer - unavailableReplicas: - description: Total number of unavailable pods targeted by this Alertmanager cluster. - format: int32 - type: integer - updatedReplicas: - description: Total number of non-terminated pods targeted by this Alertmanager cluster that have the desired version spec. - format: int32 - type: integer - required: - - availableReplicas - - paused - - replicas - - unavailableReplicas - - updatedReplicas - type: object - required: - - spec - type: object - served: true - storage: true - subresources: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-podmonitors.yaml b/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-podmonitors.yaml deleted file mode 100644 index 630465b80..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-podmonitors.yaml +++ /dev/null @@ -1,356 +0,0 @@ -# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.44.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: podmonitors.monitoring.coreos.com -spec: - group: monitoring.coreos.com - names: - kind: PodMonitor - listKind: PodMonitorList - plural: podmonitors - singular: podmonitor - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: PodMonitor defines monitoring for a set of pods. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - spec: - description: Specification of desired Pod selection for target discovery by Prometheus. - properties: - jobLabel: - description: The label to use to retrieve the job name from. - type: string - namespaceSelector: - description: Selector to select which namespaces the Endpoints objects are discovered from. - properties: - any: - description: Boolean describing whether all namespaces are selected in contrast to a list restricting them. - type: boolean - matchNames: - description: List of namespace names. - items: - type: string - type: array - type: object - podMetricsEndpoints: - description: A list of endpoints allowed as part of this PodMonitor. - items: - description: PodMetricsEndpoint defines a scrapeable endpoint of a Kubernetes Pod serving Prometheus metrics. - properties: - basicAuth: - description: 'BasicAuth allow an endpoint to authenticate over basic authentication. More info: https://prometheus.io/docs/operating/configuration/#endpoint' - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenSecret: - description: Secret to mount to read bearer token for scraping targets. The secret needs to be in the same namespace as the pod monitor and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - honorLabels: - description: HonorLabels chooses the metric's labels on collisions with target labels. - type: boolean - honorTimestamps: - description: HonorTimestamps controls whether Prometheus respects the timestamps present in scraped data. - type: boolean - interval: - description: Interval at which metrics should be scraped - type: string - metricRelabelings: - description: MetricRelabelConfigs to apply to samples before ingestion. - items: - description: 'RelabelConfig allows dynamic rewriting of the label set, being applied to samples before ingestion. It defines `<metric_relabel_configs>`-section of Prometheus configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' - properties: - action: - description: Action to perform based on regex matching. Default is 'replace' - type: string - modulus: - description: Modulus to take of the hash of the source label values. - format: int64 - type: integer - regex: - description: Regular expression against which the extracted value is matched. Default is '(.*)' - type: string - replacement: - description: Replacement value against which a regex replace is performed if the regular expression matches. Regex capture groups are available. Default is '$1' - type: string - separator: - description: Separator placed between concatenated source label values. default is ';'. - type: string - sourceLabels: - description: The source labels select values from existing labels. Their content is concatenated using the configured separator and matched against the configured regular expression for the replace, keep, and drop actions. - items: - type: string - type: array - targetLabel: - description: Label to which the resulting value is written in a replace action. It is mandatory for replace actions. Regex capture groups are available. - type: string - type: object - type: array - params: - additionalProperties: - items: - type: string - type: array - description: Optional HTTP URL parameters - type: object - path: - description: HTTP path to scrape for metrics. - type: string - port: - description: Name of the pod port this endpoint refers to. Mutually exclusive with targetPort. - type: string - proxyUrl: - description: ProxyURL eg http://proxyserver:2195 Directs scrapes to proxy through this endpoint. - type: string - relabelings: - description: 'RelabelConfigs to apply to samples before ingestion. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' - items: - description: 'RelabelConfig allows dynamic rewriting of the label set, being applied to samples before ingestion. It defines `<metric_relabel_configs>`-section of Prometheus configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' - properties: - action: - description: Action to perform based on regex matching. Default is 'replace' - type: string - modulus: - description: Modulus to take of the hash of the source label values. - format: int64 - type: integer - regex: - description: Regular expression against which the extracted value is matched. Default is '(.*)' - type: string - replacement: - description: Replacement value against which a regex replace is performed if the regular expression matches. Regex capture groups are available. Default is '$1' - type: string - separator: - description: Separator placed between concatenated source label values. default is ';'. - type: string - sourceLabels: - description: The source labels select values from existing labels. Their content is concatenated using the configured separator and matched against the configured regular expression for the replace, keep, and drop actions. - items: - type: string - type: array - targetLabel: - description: Label to which the resulting value is written in a replace action. It is mandatory for replace actions. Regex capture groups are available. - type: string - type: object - type: array - scheme: - description: HTTP scheme to use for scraping. - type: string - scrapeTimeout: - description: Timeout after which the scrape is ended - type: string - targetPort: - anyOf: - - type: integer - - type: string - description: 'Deprecated: Use ''port'' instead.' - x-kubernetes-int-or-string: true - tlsConfig: - description: TLS configuration to use when scraping the endpoint. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - type: array - podTargetLabels: - description: PodTargetLabels transfers labels on the Kubernetes Pod onto the target. - items: - type: string - type: array - sampleLimit: - description: SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. - format: int64 - type: integer - selector: - description: Selector to select Pod objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - targetLimit: - description: TargetLimit defines a limit on the number of scraped targets that will be accepted. - format: int64 - type: integer - required: - - podMetricsEndpoints - - selector - type: object - required: - - spec - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-probes.yaml b/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-probes.yaml deleted file mode 100644 index 41a1b6ff2..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-probes.yaml +++ /dev/null @@ -1,169 +0,0 @@ -# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.44.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: probes.monitoring.coreos.com -spec: - group: monitoring.coreos.com - names: - kind: Probe - listKind: ProbeList - plural: probes - singular: probe - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: Probe defines monitoring for a set of static targets or ingresses. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - spec: - description: Specification of desired Ingress selection for target discovery by Prometheus. - properties: - interval: - description: Interval at which targets are probed using the configured prober. If not specified Prometheus' global scrape interval is used. - type: string - jobName: - description: The job name assigned to scraped metrics by default. - type: string - module: - description: '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' - type: string - prober: - description: Specification for the prober to use for probing targets. The prober.URL parameter is required. Targets cannot be probed if left empty. - properties: - path: - description: Path to collect metrics from. Defaults to `/probe`. - type: string - scheme: - description: HTTP scheme to use for scraping. Defaults to `http`. - type: string - url: - description: Mandatory URL of the prober. - type: string - required: - - url - type: object - scrapeTimeout: - description: Timeout for scraping metrics from the Prometheus exporter. - type: string - targets: - description: Targets defines a set of static and/or dynamically discovered targets to be probed using the prober. - properties: - ingress: - description: Ingress defines the set of dynamically discovered ingress objects which hosts are considered for probing. - properties: - namespaceSelector: - description: Select Ingress objects by namespace. - properties: - any: - description: Boolean describing whether all namespaces are selected in contrast to a list restricting them. - type: boolean - matchNames: - description: List of namespace names. - items: - type: string - type: array - type: object - relabelingConfigs: - description: 'RelabelConfigs to apply to samples before ingestion. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' - items: - description: 'RelabelConfig allows dynamic rewriting of the label set, being applied to samples before ingestion. It defines `<metric_relabel_configs>`-section of Prometheus configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' - properties: - action: - description: Action to perform based on regex matching. Default is 'replace' - type: string - modulus: - description: Modulus to take of the hash of the source label values. - format: int64 - type: integer - regex: - description: Regular expression against which the extracted value is matched. Default is '(.*)' - type: string - replacement: - description: Replacement value against which a regex replace is performed if the regular expression matches. Regex capture groups are available. Default is '$1' - type: string - separator: - description: Separator placed between concatenated source label values. default is ';'. - type: string - sourceLabels: - description: The source labels select values from existing labels. Their content is concatenated using the configured separator and matched against the configured regular expression for the replace, keep, and drop actions. - items: - type: string - type: array - targetLabel: - description: Label to which the resulting value is written in a replace action. It is mandatory for replace actions. Regex capture groups are available. - type: string - type: object - type: array - selector: - description: Select Ingress objects by labels. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - type: object - staticConfig: - description: 'StaticConfig defines static targets which are considers for probing. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config.' - properties: - labels: - additionalProperties: - type: string - description: Labels assigned to all metrics scraped from the targets. - type: object - static: - description: Targets is a list of URLs to probe using the configured prober. - items: - type: string - type: array - type: object - type: object - type: object - required: - - spec - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-prometheuses.yaml b/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-prometheuses.yaml deleted file mode 100644 index fd43ebcab..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-prometheuses.yaml +++ /dev/null @@ -1,4422 +0,0 @@ -# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.44.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: prometheuses.monitoring.coreos.com -spec: - group: monitoring.coreos.com - names: - kind: Prometheus - listKind: PrometheusList - plural: prometheuses - singular: prometheus - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The version of Prometheus - jsonPath: .spec.version - name: Version - type: string - - description: The desired replicas number of Prometheuses - jsonPath: .spec.replicas - name: Replicas - type: integer - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: Prometheus defines a Prometheus deployment. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - spec: - description: 'Specification of the desired behavior of the Prometheus cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' - properties: - additionalAlertManagerConfigs: - description: 'AdditionalAlertManagerConfigs allows specifying a key of a Secret containing additional Prometheus AlertManager configurations. AlertManager configurations specified are appended to the configurations generated by the Prometheus Operator. Job configurations specified must have the form as specified in the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alertmanager_config. As AlertManager configs are appended, the user is responsible to make sure it is valid. Note that using this feature may expose the possibility to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible AlertManager configs are going to break Prometheus after the upgrade.' - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - additionalAlertRelabelConfigs: - description: 'AdditionalAlertRelabelConfigs allows specifying a key of a Secret containing additional Prometheus alert relabel configurations. Alert relabel configurations specified are appended to the configurations generated by the Prometheus Operator. Alert relabel configurations specified must have the form as specified in the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs. As alert relabel configs are appended, the user is responsible to make sure it is valid. Note that using this feature may expose the possibility to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible alert relabel configs are going to break Prometheus after the upgrade.' - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - additionalScrapeConfigs: - description: 'AdditionalScrapeConfigs allows specifying a key of a Secret containing additional Prometheus scrape configurations. Scrape configurations specified are appended to the configurations generated by the Prometheus Operator. Job configurations specified must have the form as specified in the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config. As scrape configs are appended, the user is responsible to make sure it is valid. Note that using this feature may expose the possibility to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible scrape configs are going to break Prometheus after the upgrade.' - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - affinity: - description: If specified, the pod's scheduling constraints. - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. - items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements by node's fields. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. The terms are ORed. - items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements by node's fields. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key <topologyKey> matches that of any node on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key <topologyKey> matches that of any node on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - alerting: - description: Define details regarding alerting. - properties: - alertmanagers: - description: AlertmanagerEndpoints Prometheus should fire alerts against. - items: - description: AlertmanagerEndpoints defines a selection of a single Endpoints object containing alertmanager IPs to fire alerts against. - properties: - apiVersion: - description: Version of the Alertmanager API that Prometheus uses to send alerts. It can be "v1" or "v2". - type: string - bearerTokenFile: - description: BearerTokenFile to read from filesystem to use when authenticating to Alertmanager. - type: string - name: - description: Name of Endpoints object in Namespace. - type: string - namespace: - description: Namespace of Endpoints object. - type: string - pathPrefix: - description: Prefix for the HTTP path alerts are pushed to. - type: string - port: - anyOf: - - type: integer - - type: string - description: Port the Alertmanager API is exposed on. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use when firing alerts. - type: string - timeout: - description: Timeout is a per-target Alertmanager timeout when pushing alerts. - type: string - tlsConfig: - description: TLS Config to use for alertmanager connection. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - caFile: - description: Path to the CA cert in the Prometheus container to use for the targets. - type: string - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - certFile: - description: Path to the client cert file in the Prometheus container for the targets. - type: string - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keyFile: - description: Path to the client key file in the Prometheus container for the targets. - type: string - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - required: - - name - - namespace - - port - type: object - type: array - required: - - alertmanagers - type: object - allowOverlappingBlocks: - description: AllowOverlappingBlocks enables vertical compaction and vertical query merge in Prometheus. This is still experimental in Prometheus so it may change in any upcoming release. - type: boolean - apiserverConfig: - description: APIServerConfig allows specifying a host and auth methods to access apiserver. If left empty, Prometheus is assumed to run inside of the cluster and will discover API servers automatically and use the pod's CA certificate and bearer token file at /var/run/secrets/kubernetes.io/serviceaccount/. - properties: - basicAuth: - description: BasicAuth allow an endpoint to authenticate over basic authentication - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerToken: - description: Bearer token for accessing apiserver. - type: string - bearerTokenFile: - description: File to read bearer token for accessing apiserver. - type: string - host: - description: Host of apiserver. A valid string consisting of a hostname or IP followed by an optional port number - type: string - tlsConfig: - description: TLS Config to use for accessing apiserver. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - caFile: - description: Path to the CA cert in the Prometheus container to use for the targets. - type: string - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - certFile: - description: Path to the client cert file in the Prometheus container for the targets. - type: string - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keyFile: - description: Path to the client key file in the Prometheus container for the targets. - type: string - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - required: - - host - type: object - arbitraryFSAccessThroughSMs: - description: ArbitraryFSAccessThroughSMs configures whether configuration based on a service monitor can access arbitrary files on the file system of the Prometheus container e.g. bearer token files. - properties: - deny: - type: boolean - type: object - baseImage: - description: 'Base image to use for a Prometheus deployment. Deprecated: use ''image'' instead' - type: string - configMaps: - description: ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. The ConfigMaps are mounted into /etc/prometheus/configmaps/<configmap-name>. - items: - type: string - type: array - containers: - description: 'Containers allows injecting additional containers or modifying operator generated containers. This can be used to allow adding an authentication proxy to a Prometheus pod or to change the behavior of an operator generated container. Containers described here modify an operator generated container if they share the same name and modifications are done via a strategic merge patch. The current container names are: `prometheus`, `config-reloader`, and `thanos-sidecar`. Overriding containers is entirely outside the scope of what the maintainers will support and by doing so, you accept that this behaviour may break at any time without notice.' - items: - description: A single application container that you want to run within a pod. - properties: - args: - description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - command: - description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - env: - description: List of environment variables to set in the container. Cannot be updated. - items: - description: EnvVar represents an environment variable present in a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: Source for the environment variable's value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. - items: - description: EnvFromSource represents the source of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap must be defined - type: boolean - type: object - prefix: - description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret must be defined - type: boolean - type: object - type: object - type: array - image: - description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' - type: string - imagePullPolicy: - description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' - type: string - lifecycle: - description: Actions that the management system should take in response to container lifecycle events. Cannot be updated. - properties: - postStart: - description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: 'Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - name: - description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. - type: string - ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. - items: - description: ContainerPort represents a network port in a single container. - properties: - containerPort: - description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port to. - type: string - hostPort: - description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. - format: int32 - type: integer - name: - description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. - type: string - protocol: - default: TCP - description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: 'Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - resources: - description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - securityContext: - description: 'Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' - properties: - allowPrivilegeEscalation: - description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' - type: boolean - capabilities: - description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - type: object - privileged: - description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. - type: boolean - procMount: - description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. - type: string - readOnlyRootFilesystem: - description: Whether this container has a read-only root filesystem. Default is false. - type: boolean - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: 'StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod''s lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - stdin: - description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. - type: boolean - stdinOnce: - description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false - type: boolean - terminationMessagePath: - description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' - type: string - terminationMessagePolicy: - description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. - type: string - tty: - description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices to be used by the container. - items: - description: volumeDevice describes a mapping of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of the container that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: Pod volumes to mount into the container's filesystem. Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume within a container. - properties: - mountPath: - description: Path within the container at which the volume should be mounted. Must not contain ':'. - type: string - mountPropagation: - description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - type: boolean - subPath: - description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. - type: string - required: - - name - type: object - type: array - disableCompaction: - description: Disable prometheus compaction. - type: boolean - enableAdminAPI: - description: 'Enable access to prometheus web admin API. Defaults to the value of `false`. WARNING: Enabling the admin APIs enables mutating endpoints, to delete data, shutdown Prometheus, and more. Enabling this should be done with care and the user is advised to add additional authentication authorization via a proxy to ensure only clients authorized to perform these actions can do so. For more information see https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis' - type: boolean - enforcedNamespaceLabel: - description: EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. The label value will always be the namespace of the object that is being created. - type: string - enforcedSampleLimit: - description: EnforcedSampleLimit defines global limit on number of scraped samples that will be accepted. This overrides any SampleLimit set per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the SampleLimit to keep overall number of samples/series under the desired limit. Note that if SampleLimit is lower that value will be taken instead. - format: int64 - type: integer - enforcedTargetLimit: - description: EnforcedTargetLimit defines a global limit on the number of scraped targets. This overrides any TargetLimit set per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the TargetLimit to keep overall number of targets under the desired limit. Note that if TargetLimit is higher that value will be taken instead. - format: int64 - type: integer - evaluationInterval: - description: Interval between consecutive evaluations. - type: string - externalLabels: - additionalProperties: - type: string - description: The labels to add to any time series or alerts when communicating with external systems (federation, remote storage, Alertmanager). - type: object - externalUrl: - description: The external URL the Prometheus instances will be available under. This is necessary to generate correct URLs. This is necessary if Prometheus is not served from root of a DNS name. - type: string - ignoreNamespaceSelectors: - description: IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector settings from the podmonitor and servicemonitor configs, and they will only discover endpoints within their current namespace. Defaults to false. - type: boolean - image: - description: Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary to ensure the Prometheus Operator knows what version of Prometheus is being configured. - type: string - imagePullSecrets: - description: An optional list of references to secrets in the same namespace to use for pulling prometheus and alertmanager images from registries see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod - items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. - properties: - name: - description: '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?' - type: string - type: object - type: array - initContainers: - description: 'InitContainers allows adding initContainers to the pod definition. Those can be used to e.g. fetch secrets for injection into the Prometheus configuration from external sources. Any errors during the execution of an initContainer will lead to a restart of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ Using initContainers for any use case other then secret fetching is entirely outside the scope of what the maintainers will support and by doing so, you accept that this behaviour may break at any time without notice.' - items: - description: A single application container that you want to run within a pod. - properties: - args: - description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - command: - description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - env: - description: List of environment variables to set in the container. Cannot be updated. - items: - description: EnvVar represents an environment variable present in a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: Source for the environment variable's value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. - items: - description: EnvFromSource represents the source of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap must be defined - type: boolean - type: object - prefix: - description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret must be defined - type: boolean - type: object - type: object - type: array - image: - description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' - type: string - imagePullPolicy: - description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' - type: string - lifecycle: - description: Actions that the management system should take in response to container lifecycle events. Cannot be updated. - properties: - postStart: - description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: 'Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - name: - description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. - type: string - ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. - items: - description: ContainerPort represents a network port in a single container. - properties: - containerPort: - description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port to. - type: string - hostPort: - description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. - format: int32 - type: integer - name: - description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. - type: string - protocol: - default: TCP - description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: 'Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - resources: - description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - securityContext: - description: 'Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' - properties: - allowPrivilegeEscalation: - description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' - type: boolean - capabilities: - description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - type: object - privileged: - description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. - type: boolean - procMount: - description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. - type: string - readOnlyRootFilesystem: - description: Whether this container has a read-only root filesystem. Default is false. - type: boolean - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: 'StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod''s lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - stdin: - description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. - type: boolean - stdinOnce: - description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false - type: boolean - terminationMessagePath: - description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' - type: string - terminationMessagePolicy: - description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. - type: string - tty: - description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices to be used by the container. - items: - description: volumeDevice describes a mapping of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of the container that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: Pod volumes to mount into the container's filesystem. Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume within a container. - properties: - mountPath: - description: Path within the container at which the volume should be mounted. Must not contain ':'. - type: string - mountPropagation: - description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - type: boolean - subPath: - description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. - type: string - required: - - name - type: object - type: array - listenLocal: - description: ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. - type: boolean - logFormat: - description: Log format for Prometheus to be configured with. - type: string - logLevel: - description: Log level for Prometheus to be configured with. - type: string - nodeSelector: - additionalProperties: - type: string - description: Define which Nodes the Pods are scheduled on. - type: object - overrideHonorLabels: - description: OverrideHonorLabels if set to true overrides all user configured honor_labels. If HonorLabels is set in ServiceMonitor or PodMonitor to true, this overrides honor_labels to false. - type: boolean - overrideHonorTimestamps: - description: OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. - type: boolean - paused: - description: When a Prometheus deployment is paused, no actions except for deletion will be performed on the underlying objects. - type: boolean - podMetadata: - description: PodMetadata configures Labels and Annotations which are propagated to the prometheus pods. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' - type: object - name: - description: 'Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' - type: string - type: object - podMonitorNamespaceSelector: - description: Namespaces to be selected for PodMonitor discovery. If nil, only check own namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - podMonitorSelector: - description: '*Experimental* PodMonitors to be selected for target discovery. *Deprecated:* if neither this nor serviceMonitorSelector are specified, configuration is unmanaged.' - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - portName: - description: Port name used for the pods and governing service. This defaults to web - type: string - priorityClassName: - description: Priority class assigned to the Pods - type: string - probeNamespaceSelector: - description: '*Experimental* Namespaces to be selected for Probe discovery. If nil, only check own namespace.' - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - probeSelector: - description: '*Experimental* Probes to be selected for target discovery.' - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - prometheusExternalLabelName: - description: Name of Prometheus external label used to denote Prometheus instance name. Defaults to the value of `prometheus`. External label will _not_ be added when value is set to empty string (`""`). - type: string - prometheusRulesExcludedFromEnforce: - description: PrometheusRulesExcludedFromEnforce - list of prometheus rules to be excluded from enforcing of adding namespace labels. Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair - items: - description: PrometheusRuleExcludeConfig enables users to configure excluded PrometheusRule names and their namespaces to be ignored while enforcing namespace label for alerts and metrics. - properties: - ruleName: - description: RuleNamespace - name of excluded rule - type: string - ruleNamespace: - description: RuleNamespace - namespace of excluded rule - type: string - required: - - ruleName - - ruleNamespace - type: object - type: array - query: - description: QuerySpec defines the query command line flags when starting Prometheus. - properties: - lookbackDelta: - description: The delta difference allowed for retrieving metrics during expression evaluations. - type: string - maxConcurrency: - description: Number of concurrent queries that can be run at once. - format: int32 - type: integer - maxSamples: - description: Maximum number of samples a single query can load into memory. Note that queries will fail if they would load more samples than this into memory, so this also limits the number of samples a query can return. - format: int32 - type: integer - timeout: - description: Maximum time a query may take before being aborted. - type: string - type: object - queryLogFile: - description: QueryLogFile specifies the file to which PromQL queries are logged. Note that this location must be writable, and can be persisted using an attached volume. Alternatively, the location can be set to a stdout location such as `/dev/stdout` to log querie information to the default Prometheus log stream. This is only available in versions of Prometheus >= 2.16.0. For more details, see the Prometheus docs (https://prometheus.io/docs/guides/query-log/) - type: string - remoteRead: - description: If specified, the remote_read spec. This is an experimental feature, it may change in any upcoming release in a breaking way. - items: - description: RemoteReadSpec defines the remote_read configuration for prometheus. - properties: - basicAuth: - description: BasicAuth for the URL. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerToken: - description: bearer token for remote read. - type: string - bearerTokenFile: - description: File to read bearer token for remote read. - type: string - name: - description: The name of the remote read queue, must be unique if specified. The name is used in metrics and logging in order to differentiate read configurations. Only valid in Prometheus versions 2.15.0 and newer. - type: string - proxyUrl: - description: Optional ProxyURL - type: string - readRecent: - description: Whether reads should be made for queries for time ranges that the local storage should have complete data for. - type: boolean - remoteTimeout: - description: Timeout for requests to the remote read endpoint. - type: string - requiredMatchers: - additionalProperties: - type: string - description: An optional list of equality matchers which have to be present in a selector to query the remote read endpoint. - type: object - tlsConfig: - description: TLS Config to use for remote read. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - caFile: - description: Path to the CA cert in the Prometheus container to use for the targets. - type: string - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - certFile: - description: Path to the client cert file in the Prometheus container for the targets. - type: string - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keyFile: - description: Path to the client key file in the Prometheus container for the targets. - type: string - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - url: - description: The URL of the endpoint to send samples to. - type: string - required: - - url - type: object - type: array - remoteWrite: - description: If specified, the remote_write spec. This is an experimental feature, it may change in any upcoming release in a breaking way. - items: - description: RemoteWriteSpec defines the remote_write configuration for prometheus. - properties: - basicAuth: - description: BasicAuth for the URL. - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerToken: - description: File to read bearer token for remote write. - type: string - bearerTokenFile: - description: File to read bearer token for remote write. - type: string - name: - description: The name of the remote write queue, must be unique if specified. The name is used in metrics and logging in order to differentiate queues. Only valid in Prometheus versions 2.15.0 and newer. - type: string - proxyUrl: - description: Optional ProxyURL - type: string - queueConfig: - description: QueueConfig allows tuning of the remote write queue parameters. - properties: - batchSendDeadline: - description: BatchSendDeadline is the maximum time a sample will wait in buffer. - type: string - capacity: - description: Capacity is the number of samples to buffer per shard before we start dropping them. - type: integer - maxBackoff: - description: MaxBackoff is the maximum retry delay. - type: string - maxRetries: - description: MaxRetries is the maximum number of times to retry a batch on recoverable errors. - type: integer - maxSamplesPerSend: - description: MaxSamplesPerSend is the maximum number of samples per send. - type: integer - maxShards: - description: MaxShards is the maximum number of shards, i.e. amount of concurrency. - type: integer - minBackoff: - description: MinBackoff is the initial retry delay. Gets doubled for every retry. - type: string - minShards: - description: MinShards is the minimum number of shards, i.e. amount of concurrency. - type: integer - type: object - remoteTimeout: - description: Timeout for requests to the remote write endpoint. - type: string - tlsConfig: - description: TLS Config to use for remote write. - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - caFile: - description: Path to the CA cert in the Prometheus container to use for the targets. - type: string - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - certFile: - description: Path to the client cert file in the Prometheus container for the targets. - type: string - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keyFile: - description: Path to the client key file in the Prometheus container for the targets. - type: string - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - url: - description: The URL of the endpoint to send samples to. - type: string - writeRelabelConfigs: - description: The list of remote write relabel configurations. - items: - description: 'RelabelConfig allows dynamic rewriting of the label set, being applied to samples before ingestion. It defines `<metric_relabel_configs>`-section of Prometheus configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' - properties: - action: - description: Action to perform based on regex matching. Default is 'replace' - type: string - modulus: - description: Modulus to take of the hash of the source label values. - format: int64 - type: integer - regex: - description: Regular expression against which the extracted value is matched. Default is '(.*)' - type: string - replacement: - description: Replacement value against which a regex replace is performed if the regular expression matches. Regex capture groups are available. Default is '$1' - type: string - separator: - description: Separator placed between concatenated source label values. default is ';'. - type: string - sourceLabels: - description: The source labels select values from existing labels. Their content is concatenated using the configured separator and matched against the configured regular expression for the replace, keep, and drop actions. - items: - type: string - type: array - targetLabel: - description: Label to which the resulting value is written in a replace action. It is mandatory for replace actions. Regex capture groups are available. - type: string - type: object - type: array - required: - - url - type: object - type: array - replicaExternalLabelName: - description: Name of Prometheus external label used to denote replica name. Defaults to the value of `prometheus_replica`. External label will _not_ be added when value is set to empty string (`""`). - type: string - replicas: - description: Number of replicas of each shard to deploy for a Prometheus deployment. Number of replicas multiplied by shards is the total number of Pods created. - format: int32 - type: integer - resources: - description: Define resources requests and limits for single Pods. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - retention: - description: Time duration Prometheus shall retain data for. Default is '24h', and must match the regular expression `[0-9]+(ms|s|m|h|d|w|y)` (milliseconds seconds minutes hours days weeks years). - type: string - retentionSize: - description: Maximum amount of disk space used by blocks. - type: string - routePrefix: - description: The route prefix Prometheus registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, but the server serves requests under a different route prefix. For example for use with `kubectl proxy`. - type: string - ruleNamespaceSelector: - description: Namespaces to be selected for PrometheusRules discovery. If unspecified, only the same namespace as the Prometheus object is in is used. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - ruleSelector: - description: A selector to select which PrometheusRules to mount for loading alerting/recording rules from. Until (excluding) Prometheus Operator v0.24.0 Prometheus Operator will migrate any legacy rule ConfigMaps to PrometheusRule custom resources selected by RuleSelector. Make sure it does not match any config maps that you do not want to be migrated. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - rules: - description: /--rules.*/ command-line arguments. - properties: - alert: - description: /--rules.alert.*/ command-line arguments - properties: - forGracePeriod: - description: Minimum duration between alert and restored 'for' state. This is maintained only for alerts with configured 'for' time greater than grace period. - type: string - forOutageTolerance: - description: Max time to tolerate prometheus outage for restoring 'for' state of alert. - type: string - resendDelay: - description: Minimum amount of time to wait before resending an alert to Alertmanager. - type: string - type: object - type: object - scrapeInterval: - description: Interval between consecutive scrapes. - type: string - scrapeTimeout: - description: Number of seconds to wait for target to respond before erroring. - type: string - secrets: - description: Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. The Secrets are mounted into /etc/prometheus/secrets/<secret-name>. - items: - type: string - type: array - securityContext: - description: SecurityContext holds pod-level security attributes and common container settings. This defaults to the default PodSecurityContext. - properties: - fsGroup: - description: "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: \n 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- \n If unset, the Kubelet will not modify the ownership and permissions of any volume." - format: int64 - type: integer - fsGroupChangePolicy: - description: 'fsGroupChangePolicy defines behavior of changing ownership and permission of the volume before being exposed inside Pod. This field will only apply to volume types which support fsGroup based ownership(and permissions). It will have no effect on ephemeral volume types such as: secret, configmaps and emptydir. Valid values are "OnRootMismatch" and "Always". If not specified defaults to "Always".' - type: string - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - supplementalGroups: - description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. - items: - format: int64 - type: integer - type: array - sysctls: - description: Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: ServiceAccountName is the name of the ServiceAccount to use to run the Prometheus Pods. - type: string - serviceMonitorNamespaceSelector: - description: Namespaces to be selected for ServiceMonitor discovery. If nil, only check own namespace. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - serviceMonitorSelector: - description: ServiceMonitors to be selected for target discovery. *Deprecated:* if neither this nor podMonitorSelector are specified, configuration is unmanaged. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - sha: - description: 'SHA of Prometheus container image to be deployed. Defaults to the value of `version`. Similar to a tag, but the SHA explicitly deploys an immutable container image. Version and Tag are ignored if SHA is set. Deprecated: use ''image'' instead. The image digest can be specified as part of the image URL.' - type: string - shards: - description: 'EXPERIMENTAL: Number of shards to distribute targets onto. Number of replicas multiplied by shards is the total number of Pods created. Note that scaling down shards will not reshard data onto remaining instances, it must be manually moved. Increasing shards will not reshard data either but it will continue to be available from the same instances. To query globally use Thanos sidecar and Thanos querier or remote write data to a central location. Sharding is done on the content of the `__address__` target meta-label.' - format: int32 - type: integer - storage: - description: Storage spec to specify how storage shall be used. - properties: - disableMountSubPath: - description: 'Deprecated: subPath usage will be disabled by default in a future release, this option will become unnecessary. DisableMountSubPath allows to remove any subPath usage in volume mounts.' - type: boolean - emptyDir: - description: 'EmptyDirVolumeSource to be used by the Prometheus StatefulSets. If specified, used in place of any volumeClaimTemplate. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir' - properties: - medium: - description: 'What type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: 'Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - volumeClaimTemplate: - description: A PVC spec to be used by the Prometheus StatefulSets. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - description: EmbeddedMetadata contains metadata relevant to an EmbeddedResource. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' - type: object - name: - description: 'Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' - type: string - type: object - spec: - description: 'Spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - accessModes: - description: 'AccessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' - items: - type: string - type: array - dataSource: - description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot - Beta) * An existing PVC (PersistentVolumeClaim) * An existing custom resource/object that implements data population (Alpha) In order to use VolumeSnapshot object types, the appropriate feature gate must be enabled (VolumeSnapshotDataSource or AnyVolumeDataSource) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the specified data source is not supported, the volume will not be created and the failure will be reported as an event. In the future, we plan to support more data source types and the behavior of the provisioner may change.' - properties: - apiGroup: - description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - resources: - description: 'Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - selector: - description: A label query over volumes to consider for binding. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - storageClassName: - description: 'Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' - type: string - volumeMode: - description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: VolumeName is the binding reference to the PersistentVolume backing this claim. - type: string - type: object - status: - description: 'Status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - accessModes: - description: 'AccessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' - items: - type: string - type: array - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying volume. - type: object - conditions: - description: Current Condition of persistent volume claim. If underlying persistent volume is being resized then the Condition will be set to 'ResizeStarted'. - items: - description: PersistentVolumeClaimCondition contails details about state of pvc - properties: - lastProbeTime: - description: Last time we probed the condition. - format: date-time - type: string - lastTransitionTime: - description: Last time the condition transitioned from one status to another. - format: date-time - type: string - message: - description: Human-readable message indicating details about last transition. - type: string - reason: - description: Unique, this should be a short, machine understandable string that gives the reason for condition's last transition. If it reports "ResizeStarted" that means the underlying persistent volume is being resized. - type: string - status: - type: string - type: - description: PersistentVolumeClaimConditionType is a valid value of PersistentVolumeClaimCondition.Type - type: string - required: - - status - - type - type: object - type: array - phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - type: object - type: object - type: object - tag: - description: 'Tag of Prometheus container image to be deployed. Defaults to the value of `version`. Version is ignored if Tag is set. Deprecated: use ''image'' instead. The image tag can be specified as part of the image URL.' - type: string - thanos: - description: "Thanos configuration allows configuring various aspects of a Prometheus server in a Thanos environment. \n This section is experimental, it may change significantly without deprecation notice in any release. \n This is experimental and may change significantly without backward compatibility in any release." - properties: - baseImage: - description: 'Thanos base image if other than default. Deprecated: use ''image'' instead' - type: string - grpcServerTlsConfig: - description: 'GRPCServerTLSConfig configures the gRPC server from which Thanos Querier reads recorded rule data. Note: Currently only the CAFile, CertFile, and KeyFile fields are supported. Maps to the ''--grpc-server-tls-*'' CLI args.' - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - caFile: - description: Path to the CA cert in the Prometheus container to use for the targets. - type: string - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - certFile: - description: Path to the client cert file in the Prometheus container for the targets. - type: string - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keyFile: - description: Path to the client key file in the Prometheus container for the targets. - type: string - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - image: - description: Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary to ensure the Prometheus Operator knows what version of Thanos is being configured. - type: string - listenLocal: - description: ListenLocal makes the Thanos sidecar listen on loopback, so that it does not bind against the Pod IP. - type: boolean - logFormat: - description: LogFormat for Thanos sidecar to be configured with. - type: string - logLevel: - description: LogLevel for Thanos sidecar to be configured with. - type: string - minTime: - description: MinTime for Thanos sidecar to be configured with. Option can be a constant time in RFC3339 format or time duration relative to current time, such as -1d or 2h45m. Valid duration units are ms, s, m, h, d, w, y. - type: string - objectStorageConfig: - description: ObjectStorageConfig configures object storage in Thanos. Alternative to ObjectStorageConfigFile, and lower order priority. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - objectStorageConfigFile: - description: ObjectStorageConfigFile specifies the path of the object storage configuration file. When used alongside with ObjectStorageConfig, ObjectStorageConfigFile takes precedence. - type: string - resources: - description: Resources defines the resource requirements for the Thanos sidecar. If not provided, no requests/limits will be set - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - sha: - description: 'SHA of Thanos container image to be deployed. Defaults to the value of `version`. Similar to a tag, but the SHA explicitly deploys an immutable container image. Version and Tag are ignored if SHA is set. Deprecated: use ''image'' instead. The image digest can be specified as part of the image URL.' - type: string - tag: - description: 'Tag of Thanos sidecar container image to be deployed. Defaults to the value of `version`. Version is ignored if Tag is set. Deprecated: use ''image'' instead. The image tag can be specified as part of the image URL.' - type: string - tracingConfig: - description: TracingConfig configures tracing in Thanos. This is an experimental feature, it may change in any upcoming release in a breaking way. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - version: - description: Version describes the version of Thanos to use. - type: string - type: object - tolerations: - description: If specified, the pod's tolerations. - items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple <key,value,effect> using the matching operator <operator>. - properties: - effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: If specified, the pod's topology spread constraints. - items: - description: TopologySpreadConstraint specifies how to spread matching pods among the given topology. - properties: - labelSelector: - description: LabelSelector is used to find matching pods. Pods that match this label selector are counted to determine the number of pods in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - maxSkew: - description: 'MaxSkew describes the degree to which pods may be unevenly distributed. It''s the maximum permitted difference between the number of matching pods in any two topology domains of a given topology type. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 1/1/0: | zone1 | zone2 | zone3 | | P | P | | - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 1/1/1; scheduling it onto zone1(zone2) would make the ActualSkew(2-0) on zone1(zone2) violate MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled onto any zone. It''s a required field. Default value is 1 and 0 is not allowed.' - format: int32 - type: integer - topologyKey: - description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each <key, value> as a "bucket", and try to put balanced number of pods into each bucket. It's a required field. - type: string - whenUnsatisfiable: - description: 'WhenUnsatisfiable indicates how to deal with a pod if it doesn''t satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it - ScheduleAnyway tells the scheduler to still schedule it It''s considered as "Unsatisfiable" if and only if placing incoming pod on any topology violates "MaxSkew". For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler won''t make it *more* imbalanced. It''s a required field.' - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - version: - description: Version of Prometheus to be deployed. - type: string - volumeMounts: - description: VolumeMounts allows configuration of additional VolumeMounts on the output StatefulSet definition. VolumeMounts specified will be appended to other VolumeMounts in the prometheus container, that are generated as a result of StorageSpec objects. - items: - description: VolumeMount describes a mounting of a Volume within a container. - properties: - mountPath: - description: Path within the container at which the volume should be mounted. Must not contain ':'. - type: string - mountPropagation: - description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - type: boolean - subPath: - description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - volumes: - description: Volumes allows configuration of additional volumes on the output StatefulSet definition. Volumes specified will be appended to other volumes that are generated as a result of StorageSpec objects. - items: - description: Volume represents a named volume in a pod that may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - partition: - description: 'The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as "1". Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty).' - format: int32 - type: integer - readOnly: - description: 'Specify "true" to force and set the ReadOnly property in VolumeMounts to "true". If omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - type: boolean - volumeID: - description: 'Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - type: string - required: - - volumeID - type: object - azureDisk: - description: AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. - properties: - cachingMode: - description: 'Host Caching mode: None, Read Only, Read Write.' - type: string - diskName: - description: The Name of the data disk in the blob storage - type: string - diskURI: - description: The URI the data disk in the blob storage - type: string - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'Expected values Shared: multiple blob disks per storage account Dedicated: single blob disk per storage account Managed: azure managed data disk (only in managed availability set). defaults to shared' - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: AzureFile represents an Azure File Service mount on the host and bind mount to the pod. - properties: - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: the name of secret that contains Azure Storage Account Name and Key - type: string - shareName: - description: Share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: CephFS represents a Ceph FS mount on the host that shares a pod's lifetime - properties: - monitors: - description: 'Required: Monitors is a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - items: - type: string - type: array - path: - description: 'Optional: Used as the mounted root, rather than the full Ceph tree, default is /' - type: string - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: boolean - secretFile: - description: 'Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: string - secretRef: - description: 'Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - properties: - name: - description: '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?' - type: string - type: object - user: - description: 'Optional: User is the rados user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: string - required: - - monitors - type: object - cinder: - description: 'Cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - properties: - fsType: - description: 'Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: string - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: boolean - secretRef: - description: 'Optional: points to a secret object containing parameters used to connect to OpenStack.' - properties: - name: - description: '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?' - type: string - type: object - volumeID: - description: 'volume id used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: string - required: - - volumeID - type: object - configMap: - description: ConfigMap represents a configMap that should populate this volume - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its keys must be defined - type: boolean - type: object - csi: - description: CSI (Container Storage Interface) represents storage that is handled by an external CSI driver (Alpha feature). - properties: - driver: - description: Driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: Filesystem type to mount. Ex. "ext4", "xfs", "ntfs". If not provided, the empty value is passed to the associated CSI driver which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: NodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. This field is optional, and may be empty if no secret is required. If the secret object contains more than one secret, all secret references are passed. - properties: - name: - description: '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?' - type: string - type: object - readOnly: - description: Specifies a read-only configuration for the volume. Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: VolumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: DownwardAPI represents downward API about the pod that should populate this volume - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: Items is a list of downward API volume file - items: - description: DownwardAPIVolumeFile represents information to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: 'Required: Path is the relative path name of the file to be created. Must not be absolute or contain the ''..'' path. Must be utf-8 encoded. The first item of the relative path must not start with ''..''' - type: string - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - emptyDir: - description: 'EmptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - properties: - medium: - description: 'What type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: 'Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - fc: - description: FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. - properties: - fsType: - description: 'Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - lun: - description: 'Optional: FC target lun number' - format: int32 - type: integer - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.' - type: boolean - targetWWNs: - description: 'Optional: FC target worldwide names (WWNs)' - items: - type: string - type: array - wwids: - description: 'Optional: FC volume world wide identifiers (wwids) Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously.' - items: - type: string - type: array - type: object - flexVolume: - description: FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. - properties: - driver: - description: Driver is the name of the driver to use for this volume. - type: string - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'Optional: Extra command options if any.' - type: object - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.' - type: boolean - secretRef: - description: 'Optional: SecretRef is reference to the secret object containing sensitive information to pass to the plugin scripts. This may be empty if no secret object is specified. If the secret object contains more than one secret, all secrets are passed to the plugin scripts.' - properties: - name: - description: '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?' - type: string - type: object - required: - - driver - type: object - flocker: - description: Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running - properties: - datasetName: - description: Name of the dataset stored as metadata -> name on the dataset for Flocker should be considered as deprecated - type: string - datasetUUID: - description: UUID of the dataset. This is unique identifier of a Flocker dataset - type: string - type: object - gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - partition: - description: 'The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as "1". Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - format: int32 - type: integer - pdName: - description: 'Unique name of the PD resource in GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - type: string - readOnly: - description: 'ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - type: boolean - required: - - pdName - type: object - gitRepo: - description: 'GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod''s container.' - properties: - directory: - description: Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name. - type: string - repository: - description: Repository URL - type: string - revision: - description: Commit hash for the specified revision. - type: string - required: - - repository - type: object - glusterfs: - description: 'Glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' - properties: - endpoints: - description: 'EndpointsName is the endpoint name that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: string - path: - description: 'Path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: string - readOnly: - description: 'ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: 'HostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath --- TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not mount host directories as read/write.' - properties: - path: - description: 'Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' - type: string - type: - description: 'Type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' - type: string - required: - - path - type: object - iscsi: - description: 'ISCSI represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' - properties: - chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: whether support iSCSI Session CHAP authentication - type: boolean - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection. - type: string - iqn: - description: Target iSCSI Qualified Name. - type: string - iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). - type: string - lun: - description: iSCSI Target Lun number. - format: int32 - type: integer - portals: - description: iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - readOnly: - description: ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. - type: boolean - secretRef: - description: CHAP Secret for iSCSI target and initiator authentication - properties: - name: - description: '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?' - type: string - type: object - targetPortal: - description: iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: 'Volume''s name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - nfs: - description: 'NFS represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - properties: - path: - description: 'Path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: string - readOnly: - description: 'ReadOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: boolean - server: - description: 'Server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - type: string - readOnly: - description: Will force the ReadOnly setting in VolumeMounts. Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: ID that identifies Photon Controller persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: PortworxVolume represents a portworx volume attached and mounted on kubelets host machine - properties: - fsType: - description: FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: VolumeID uniquely identifies a Portworx volume - type: string - required: - - volumeID - type: object - projected: - description: Items for all in one resources secrets, configmaps, and downward API - properties: - defaultMode: - description: Mode bits to use on created files by default. Must be a value between 0 and 0777. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: list of volume projections - items: - description: Projection that may be projected along with other supported volume types - properties: - configMap: - description: information about the configMap data to project - properties: - items: - description: If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its keys must be defined - type: boolean - type: object - downwardAPI: - description: information about the downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume file - items: - description: DownwardAPIVolumeFile represents information to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: 'Required: Path is the relative path name of the file to be created. Must not be absolute or contain the ''..'' path. Must be utf-8 encoded. The first item of the relative path must not start with ''..''' - type: string - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - secret: - description: information about the secret data to project - properties: - items: - description: If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - type: object - serviceAccountToken: - description: information about the serviceAccountToken data to project - properties: - audience: - description: Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver. - type: string - expirationSeconds: - description: ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes. - format: int64 - type: integer - path: - description: Path is the path relative to the mount point of the file to project the token into. - type: string - required: - - path - type: object - type: object - type: array - required: - - sources - type: object - quobyte: - description: Quobyte represents a Quobyte mount on the host that shares a pod's lifetime - properties: - group: - description: Group to map volume access to Default is no group - type: string - readOnly: - description: ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. - type: boolean - registry: - description: Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes - type: string - tenant: - description: Tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: User to map volume access to Defaults to serivceaccount user - type: string - volume: - description: Volume is a string that references an already created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: 'RBD represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - keyring: - description: 'Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - monitors: - description: 'A collection of Ceph monitors. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - items: - type: string - type: array - pool: - description: 'The rados pool name. Default is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - readOnly: - description: 'ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: boolean - secretRef: - description: 'SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - properties: - name: - description: '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?' - type: string - type: object - user: - description: 'The rados user name. Default is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - required: - - image - - monitors - type: object - scaleIO: - description: ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". - type: string - gateway: - description: The host address of the ScaleIO API Gateway. - type: string - protectionDomain: - description: The name of the ScaleIO Protection Domain for the configured storage. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. - properties: - name: - description: '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?' - type: string - type: object - sslEnabled: - description: Flag to enable/disable SSL communication with Gateway, default false - type: boolean - storageMode: - description: Indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. - type: string - storagePool: - description: The ScaleIO Storage Pool associated with the protection domain. - type: string - system: - description: The name of the storage system as configured in ScaleIO. - type: string - volumeName: - description: The name of a volume already created in the ScaleIO system that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: 'Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - optional: - description: Specify whether the Secret or its keys must be defined - type: boolean - secretName: - description: 'Name of the secret in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' - type: string - type: object - storageos: - description: StorageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: SecretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. - properties: - name: - description: '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?' - type: string - type: object - volumeName: - description: VolumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. - type: string - volumeNamespace: - description: VolumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping to be mirrored within StorageOS for tighter integration. Set VolumeName to any name to override the default behaviour. Set to "default" if you are not using namespaces within StorageOS. Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: Storage Policy Based Management (SPBM) profile ID associated with the StoragePolicyName. - type: string - storagePolicyName: - description: Storage Policy Based Management (SPBM) profile name. - type: string - volumePath: - description: Path that identifies vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - walCompression: - description: Enable compression of the write-ahead log using Snappy. This flag is only available in versions of Prometheus >= 2.11.0. - type: boolean - web: - description: WebSpec defines the web command line flags when starting Prometheus. - properties: - pageTitle: - description: The prometheus web page title - type: string - type: object - type: object - status: - description: 'Most recent observed status of the Prometheus cluster. Read-only. Not included when requesting from the apiserver, only from the Prometheus Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' - properties: - availableReplicas: - description: Total number of available pods (ready for at least minReadySeconds) targeted by this Prometheus deployment. - format: int32 - type: integer - paused: - description: Represents whether any actions on the underlying managed objects are being performed. Only delete actions will be performed. - type: boolean - replicas: - description: Total number of non-terminated pods targeted by this Prometheus deployment (their labels match the selector). - format: int32 - type: integer - unavailableReplicas: - description: Total number of unavailable pods targeted by this Prometheus deployment. - format: int32 - type: integer - updatedReplicas: - description: Total number of non-terminated pods targeted by this Prometheus deployment that have the desired version spec. - format: int32 - type: integer - required: - - availableReplicas - - paused - - replicas - - unavailableReplicas - - updatedReplicas - type: object - required: - - spec - type: object - served: true - storage: true - subresources: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-prometheusrules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-prometheusrules.yaml deleted file mode 100644 index 02759cd7d..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-prometheusrules.yaml +++ /dev/null @@ -1,90 +0,0 @@ -# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.44.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: prometheusrules.monitoring.coreos.com -spec: - group: monitoring.coreos.com - names: - kind: PrometheusRule - listKind: PrometheusRuleList - plural: prometheusrules - singular: prometheusrule - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: PrometheusRule defines recording and alerting rules for a Prometheus instance - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - spec: - description: Specification of desired alerting rule definitions for Prometheus. - properties: - groups: - description: Content of Prometheus rule file - items: - description: 'RuleGroup is a list of sequentially evaluated recording and alerting rules. Note: PartialResponseStrategy is only used by ThanosRuler and will be ignored by Prometheus instances. Valid values for this field are ''warn'' or ''abort''. More info: https://github.com/thanos-io/thanos/blob/master/docs/components/rule.md#partial-response' - properties: - interval: - type: string - name: - type: string - partial_response_strategy: - type: string - rules: - items: - description: Rule describes an alerting or recording rule. - properties: - alert: - type: string - annotations: - additionalProperties: - type: string - type: object - expr: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - for: - type: string - labels: - additionalProperties: - type: string - type: object - record: - type: string - required: - - expr - type: object - type: array - required: - - name - - rules - type: object - type: array - type: object - required: - - spec - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-servicemonitors.yaml b/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-servicemonitors.yaml deleted file mode 100644 index f5d989d7c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-servicemonitors.yaml +++ /dev/null @@ -1,373 +0,0 @@ -# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.44.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: servicemonitors.monitoring.coreos.com -spec: - group: monitoring.coreos.com - names: - kind: ServiceMonitor - listKind: ServiceMonitorList - plural: servicemonitors - singular: servicemonitor - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: ServiceMonitor defines monitoring for a set of services. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - spec: - description: Specification of desired Service selection for target discovery by Prometheus. - properties: - endpoints: - description: A list of endpoints allowed as part of this ServiceMonitor. - items: - description: Endpoint defines a scrapeable endpoint serving Prometheus metrics. - properties: - basicAuth: - description: 'BasicAuth allow an endpoint to authenticate over basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints' - properties: - password: - description: The secret in the service monitor namespace that contains the password for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - username: - description: The secret in the service monitor namespace that contains the username for authentication. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - bearerTokenFile: - description: File to read bearer token for scraping targets. - type: string - bearerTokenSecret: - description: Secret to mount to read bearer token for scraping targets. The secret needs to be in the same namespace as the service monitor and accessible by the Prometheus Operator. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - honorLabels: - description: HonorLabels chooses the metric's labels on collisions with target labels. - type: boolean - honorTimestamps: - description: HonorTimestamps controls whether Prometheus respects the timestamps present in scraped data. - type: boolean - interval: - description: Interval at which metrics should be scraped - type: string - metricRelabelings: - description: MetricRelabelConfigs to apply to samples before ingestion. - items: - description: 'RelabelConfig allows dynamic rewriting of the label set, being applied to samples before ingestion. It defines `<metric_relabel_configs>`-section of Prometheus configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' - properties: - action: - description: Action to perform based on regex matching. Default is 'replace' - type: string - modulus: - description: Modulus to take of the hash of the source label values. - format: int64 - type: integer - regex: - description: Regular expression against which the extracted value is matched. Default is '(.*)' - type: string - replacement: - description: Replacement value against which a regex replace is performed if the regular expression matches. Regex capture groups are available. Default is '$1' - type: string - separator: - description: Separator placed between concatenated source label values. default is ';'. - type: string - sourceLabels: - description: The source labels select values from existing labels. Their content is concatenated using the configured separator and matched against the configured regular expression for the replace, keep, and drop actions. - items: - type: string - type: array - targetLabel: - description: Label to which the resulting value is written in a replace action. It is mandatory for replace actions. Regex capture groups are available. - type: string - type: object - type: array - params: - additionalProperties: - items: - type: string - type: array - description: Optional HTTP URL parameters - type: object - path: - description: HTTP path to scrape for metrics. - type: string - port: - description: Name of the service port this endpoint refers to. Mutually exclusive with targetPort. - type: string - proxyUrl: - description: ProxyURL eg http://proxyserver:2195 Directs scrapes to proxy through this endpoint. - type: string - relabelings: - description: 'RelabelConfigs to apply to samples before scraping. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config' - items: - description: 'RelabelConfig allows dynamic rewriting of the label set, being applied to samples before ingestion. It defines `<metric_relabel_configs>`-section of Prometheus configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs' - properties: - action: - description: Action to perform based on regex matching. Default is 'replace' - type: string - modulus: - description: Modulus to take of the hash of the source label values. - format: int64 - type: integer - regex: - description: Regular expression against which the extracted value is matched. Default is '(.*)' - type: string - replacement: - description: Replacement value against which a regex replace is performed if the regular expression matches. Regex capture groups are available. Default is '$1' - type: string - separator: - description: Separator placed between concatenated source label values. default is ';'. - type: string - sourceLabels: - description: The source labels select values from existing labels. Their content is concatenated using the configured separator and matched against the configured regular expression for the replace, keep, and drop actions. - items: - type: string - type: array - targetLabel: - description: Label to which the resulting value is written in a replace action. It is mandatory for replace actions. Regex capture groups are available. - type: string - type: object - type: array - scheme: - description: HTTP scheme to use for scraping. - type: string - scrapeTimeout: - description: Timeout after which the scrape is ended - type: string - targetPort: - anyOf: - - type: integer - - type: string - description: Name or number of the target port of the Pod behind the Service, the port must be specified with container port property. Mutually exclusive with port. - x-kubernetes-int-or-string: true - tlsConfig: - description: TLS configuration to use when scraping the endpoint - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - caFile: - description: Path to the CA cert in the Prometheus container to use for the targets. - type: string - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - certFile: - description: Path to the client cert file in the Prometheus container for the targets. - type: string - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keyFile: - description: Path to the client key file in the Prometheus container for the targets. - type: string - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - type: object - type: array - jobLabel: - description: The label to use to retrieve the job name from. - type: string - namespaceSelector: - description: Selector to select which namespaces the Endpoints objects are discovered from. - properties: - any: - description: Boolean describing whether all namespaces are selected in contrast to a list restricting them. - type: boolean - matchNames: - description: List of namespace names. - items: - type: string - type: array - type: object - podTargetLabels: - description: PodTargetLabels transfers labels on the Kubernetes Pod onto the target. - items: - type: string - type: array - sampleLimit: - description: SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. - format: int64 - type: integer - selector: - description: Selector to select Endpoints objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - targetLabels: - description: TargetLabels transfers labels on the Kubernetes Service onto the target. - items: - type: string - type: array - targetLimit: - description: TargetLimit defines a limit on the number of scraped targets that will be accepted. - format: int64 - type: integer - required: - - endpoints - - selector - type: object - required: - - spec - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-thanosrulers.yaml b/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-thanosrulers.yaml deleted file mode 100644 index f647e7247..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/crds/crd-thanosrulers.yaml +++ /dev/null @@ -1,3340 +0,0 @@ -# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.44.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: thanosrulers.monitoring.coreos.com -spec: - group: monitoring.coreos.com - names: - kind: ThanosRuler - listKind: ThanosRulerList - plural: thanosrulers - singular: thanosruler - scope: Namespaced - versions: - - name: v1 - schema: - openAPIV3Schema: - description: ThanosRuler defines a ThanosRuler deployment. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - spec: - description: 'Specification of the desired behavior of the ThanosRuler cluster. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' - properties: - affinity: - description: If specified, the pod's scheduling constraints. - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. - items: - description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements by node's fields. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. The terms are ORed. - items: - description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements by node's labels. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements by node's fields. - items: - description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: The label key that the selector applies to. - type: string - operator: - description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: 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. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key <topologyKey> matches that of any node on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key <topologyKey> matches that of any node on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces the labelSelector applies to (matches against); null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - alertDropLabels: - description: AlertDropLabels configure the label names which should be dropped in ThanosRuler alerts. If `labels` field is not provided, `thanos_ruler_replica` will be dropped in alerts by default. - items: - type: string - type: array - alertQueryUrl: - description: The external Query URL the Thanos Ruler will set in the 'Source' field of all alerts. Maps to the '--alert.query-url' CLI arg. - type: string - alertmanagersConfig: - description: Define configuration for connecting to alertmanager. Only available with thanos v0.10.0 and higher. Maps to the `alertmanagers.config` arg. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - alertmanagersUrl: - description: 'Define URLs to send alerts to Alertmanager. For Thanos v0.10.0 and higher, AlertManagersConfig should be used instead. Note: this field will be ignored if AlertManagersConfig is specified. Maps to the `alertmanagers.url` arg.' - items: - type: string - type: array - containers: - description: 'Containers allows injecting additional containers or modifying operator generated containers. This can be used to allow adding an authentication proxy to a ThanosRuler pod or to change the behavior of an operator generated container. Containers described here modify an operator generated container if they share the same name and modifications are done via a strategic merge patch. The current container names are: `thanos-ruler` and `config-reloader`. Overriding containers is entirely outside the scope of what the maintainers will support and by doing so, you accept that this behaviour may break at any time without notice.' - items: - description: A single application container that you want to run within a pod. - properties: - args: - description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - command: - description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - env: - description: List of environment variables to set in the container. Cannot be updated. - items: - description: EnvVar represents an environment variable present in a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: Source for the environment variable's value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. - items: - description: EnvFromSource represents the source of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap must be defined - type: boolean - type: object - prefix: - description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret must be defined - type: boolean - type: object - type: object - type: array - image: - description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' - type: string - imagePullPolicy: - description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' - type: string - lifecycle: - description: Actions that the management system should take in response to container lifecycle events. Cannot be updated. - properties: - postStart: - description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: 'Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - name: - description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. - type: string - ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. - items: - description: ContainerPort represents a network port in a single container. - properties: - containerPort: - description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port to. - type: string - hostPort: - description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. - format: int32 - type: integer - name: - description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. - type: string - protocol: - default: TCP - description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: 'Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - resources: - description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - securityContext: - description: 'Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' - properties: - allowPrivilegeEscalation: - description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' - type: boolean - capabilities: - description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - type: object - privileged: - description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. - type: boolean - procMount: - description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. - type: string - readOnlyRootFilesystem: - description: Whether this container has a read-only root filesystem. Default is false. - type: boolean - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: 'StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod''s lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - stdin: - description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. - type: boolean - stdinOnce: - description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false - type: boolean - terminationMessagePath: - description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' - type: string - terminationMessagePolicy: - description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. - type: string - tty: - description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices to be used by the container. - items: - description: volumeDevice describes a mapping of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of the container that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: Pod volumes to mount into the container's filesystem. Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume within a container. - properties: - mountPath: - description: Path within the container at which the volume should be mounted. Must not contain ':'. - type: string - mountPropagation: - description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - type: boolean - subPath: - description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. - type: string - required: - - name - type: object - type: array - enforcedNamespaceLabel: - description: EnforcedNamespaceLabel enforces adding a namespace label of origin for each alert and metric that is user created. The label value will always be the namespace of the object that is being created. - type: string - evaluationInterval: - description: Interval between consecutive evaluations. - type: string - externalPrefix: - description: The external URL the Thanos Ruler instances will be available under. This is necessary to generate correct URLs. This is necessary if Thanos Ruler is not served from root of a DNS name. - type: string - grpcServerTlsConfig: - description: 'GRPCServerTLSConfig configures the gRPC server from which Thanos Querier reads recorded rule data. Note: Currently only the CAFile, CertFile, and KeyFile fields are supported. Maps to the ''--grpc-server-tls-*'' CLI args.' - properties: - ca: - description: Struct containing the CA cert to use for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - caFile: - description: Path to the CA cert in the Prometheus container to use for the targets. - type: string - cert: - description: Struct containing the client cert file for the targets. - properties: - configMap: - description: ConfigMap containing data to use for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - certFile: - description: Path to the client cert file in the Prometheus container for the targets. - type: string - insecureSkipVerify: - description: Disable target certificate validation. - type: boolean - keyFile: - description: Path to the client key file in the Prometheus container for the targets. - type: string - keySecret: - description: Secret containing the client key file for the targets. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - serverName: - description: Used to verify the hostname for the targets. - type: string - type: object - image: - description: Thanos container image URL. - type: string - imagePullSecrets: - description: An optional list of references to secrets in the same namespace to use for pulling thanos images from registries see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod - items: - description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace. - properties: - name: - description: '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?' - type: string - type: object - type: array - initContainers: - description: 'InitContainers allows adding initContainers to the pod definition. Those can be used to e.g. fetch secrets for injection into the ThanosRuler configuration from external sources. Any errors during the execution of an initContainer will lead to a restart of the Pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ Using initContainers for any use case other then secret fetching is entirely outside the scope of what the maintainers will support and by doing so, you accept that this behaviour may break at any time without notice.' - items: - description: A single application container that you want to run within a pod. - properties: - args: - description: 'Arguments to the entrypoint. The docker image''s CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - command: - description: 'Entrypoint array. Not executed within a shell. The docker image''s ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container''s environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' - items: - type: string - type: array - env: - description: List of environment variables to set in the container. Cannot be updated. - items: - description: EnvVar represents an environment variable present in a Container. - properties: - name: - description: Name of the environment variable. Must be a C_IDENTIFIER. - type: string - value: - description: 'Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: Source for the environment variable's value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - fieldRef: - description: 'Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - secretKeyRef: - description: Selects a key of a secret in the pod's namespace - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - description: List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. - items: - description: EnvFromSource represents the source of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap must be defined - type: boolean - type: object - prefix: - description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret must be defined - type: boolean - type: object - type: object - type: array - image: - description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images This field is optional to allow higher level config management to default or override container images in workload controllers like Deployments and StatefulSets.' - type: string - imagePullPolicy: - description: 'Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' - type: string - lifecycle: - description: Actions that the management system should take in response to container lifecycle events. Cannot be updated. - properties: - postStart: - description: 'PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: 'PreStop is called immediately before a container is terminated due to an API request or management event such as liveness/startup probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod''s termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod''s termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: 'Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - name: - description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. - type: string - ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. - items: - description: ContainerPort represents a network port in a single container. - properties: - containerPort: - description: Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port to. - type: string - hostPort: - description: Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. - format: int32 - type: integer - name: - description: If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. - type: string - protocol: - default: TCP - description: Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: 'Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - resources: - description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - securityContext: - description: 'Security options the pod should run with. More info: https://kubernetes.io/docs/concepts/policy/security-context/ More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' - properties: - allowPrivilegeEscalation: - description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN' - type: boolean - capabilities: - description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities type - type: string - type: array - type: object - privileged: - description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. - type: boolean - procMount: - description: procMount denotes the type of proc mount to use for the containers. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. - type: string - readOnlyRootFilesystem: - description: Whether this container has a read-only root filesystem. Default is false. - type: boolean - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: 'StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod''s lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - properties: - exec: - description: One and only one of the following should be specified. Exec specifies the action to take. - properties: - command: - description: Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - type: object - failureThreshold: - description: Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - format: int32 - type: integer - httpGet: - description: HTTPGet specifies the http request to perform. - properties: - host: - description: Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header to be used in HTTP probes - properties: - name: - description: The header field name - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: Scheme to use for connecting to the host. Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: 'Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - periodSeconds: - description: How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: 'TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook' - properties: - host: - description: 'Optional: Host name to connect to, defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' - format: int32 - type: integer - type: object - stdin: - description: Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. Default is false. - type: boolean - stdinOnce: - description: Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF. Default is false - type: boolean - terminationMessagePath: - description: 'Optional: Path at which the file to which the container''s termination message will be written is mounted into the container''s filesystem. Message written is intended to be brief final status, such as an assertion failure message. Will be truncated by the node if greater than 4096 bytes. The total message length across all containers will be limited to 12kb. Defaults to /dev/termination-log. Cannot be updated.' - type: string - terminationMessagePolicy: - description: Indicate how the termination message should be populated. File will use the contents of terminationMessagePath to populate the container status message on both success and failure. FallbackToLogsOnError will use the last chunk of container log output if the termination message file is empty and the container exited with an error. The log output is limited to 2048 bytes or 80 lines, whichever is smaller. Defaults to File. Cannot be updated. - type: string - tty: - description: Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices to be used by the container. - items: - description: volumeDevice describes a mapping of a raw block device within a container. - properties: - devicePath: - description: devicePath is the path inside of the container that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim in the pod - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - description: Pod volumes to mount into the container's filesystem. Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume within a container. - properties: - mountPath: - description: Path within the container at which the volume should be mounted. Must not contain ':'. - type: string - mountPropagation: - description: mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - type: boolean - subPath: - description: Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to "" (volume's root). SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - description: Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated. - type: string - required: - - name - type: object - type: array - labels: - additionalProperties: - type: string - description: Labels configure the external label pairs to ThanosRuler. If not provided, default replica label `thanos_ruler_replica` will be added as a label and be dropped in alerts. - type: object - listenLocal: - description: ListenLocal makes the Thanos ruler listen on loopback, so that it does not bind against the Pod IP. - type: boolean - logFormat: - description: Log format for ThanosRuler to be configured with. - type: string - logLevel: - description: Log level for ThanosRuler to be configured with. - type: string - nodeSelector: - additionalProperties: - type: string - description: Define which Nodes the Pods are scheduled on. - type: object - objectStorageConfig: - description: ObjectStorageConfig configures object storage in Thanos. Alternative to ObjectStorageConfigFile, and lower order priority. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - objectStorageConfigFile: - description: ObjectStorageConfigFile specifies the path of the object storage configuration file. When used alongside with ObjectStorageConfig, ObjectStorageConfigFile takes precedence. - type: string - paused: - description: When a ThanosRuler deployment is paused, no actions except for deletion will be performed on the underlying objects. - type: boolean - podMetadata: - description: PodMetadata contains Labels and Annotations gets propagated to the thanos ruler pods. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' - type: object - name: - description: 'Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' - type: string - type: object - portName: - description: Port name used for the pods and governing service. This defaults to web - type: string - priorityClassName: - description: Priority class assigned to the Pods - type: string - prometheusRulesExcludedFromEnforce: - description: PrometheusRulesExcludedFromEnforce - list of Prometheus rules to be excluded from enforcing of adding namespace labels. Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair - items: - description: PrometheusRuleExcludeConfig enables users to configure excluded PrometheusRule names and their namespaces to be ignored while enforcing namespace label for alerts and metrics. - properties: - ruleName: - description: RuleNamespace - name of excluded rule - type: string - ruleNamespace: - description: RuleNamespace - namespace of excluded rule - type: string - required: - - ruleName - - ruleNamespace - type: object - type: array - queryConfig: - description: Define configuration for connecting to thanos query instances. If this is defined, the QueryEndpoints field will be ignored. Maps to the `query.config` CLI argument. Only available with thanos v0.11.0 and higher. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - queryEndpoints: - description: QueryEndpoints defines Thanos querier endpoints from which to query metrics. Maps to the --query flag of thanos ruler. - items: - type: string - type: array - replicas: - description: Number of thanos ruler instances to deploy. - format: int32 - type: integer - resources: - description: Resources defines the resource requirements for single Pods. If not provided, no requests/limits will be set - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - retention: - description: Time duration ThanosRuler shall retain data for. Default is '24h', and must match the regular expression `[0-9]+(ms|s|m|h|d|w|y)` (milliseconds seconds minutes hours days weeks years). - type: string - routePrefix: - description: The route prefix ThanosRuler registers HTTP handlers for. This allows thanos UI to be served on a sub-path. - type: string - ruleNamespaceSelector: - description: Namespaces to be selected for Rules discovery. If unspecified, only the same namespace as the ThanosRuler object is in is used. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - ruleSelector: - description: A label selector to select which PrometheusRules to mount for alerting and recording. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - securityContext: - description: SecurityContext holds pod-level security attributes and common container settings. This defaults to the default PodSecurityContext. - properties: - fsGroup: - description: "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: \n 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- \n If unset, the Kubelet will not modify the ownership and permissions of any volume." - format: int64 - type: integer - fsGroupChangePolicy: - description: 'fsGroupChangePolicy defines behavior of changing ownership and permission of the volume before being exposed inside Pod. This field will only apply to volume types which support fsGroup based ownership(and permissions). It will have no effect on ephemeral volume types such as: secret, configmaps and emptydir. Valid values are "OnRootMismatch" and "Always". If not specified defaults to "Always".' - type: string - runAsGroup: - description: The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - supplementalGroups: - description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. - items: - format: int64 - type: integer - type: array - sysctls: - description: Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - description: The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: ServiceAccountName is the name of the ServiceAccount to use to run the Thanos Ruler Pods. - type: string - storage: - description: Storage spec to specify how storage shall be used. - properties: - disableMountSubPath: - description: 'Deprecated: subPath usage will be disabled by default in a future release, this option will become unnecessary. DisableMountSubPath allows to remove any subPath usage in volume mounts.' - type: boolean - emptyDir: - description: 'EmptyDirVolumeSource to be used by the Prometheus StatefulSets. If specified, used in place of any volumeClaimTemplate. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir' - properties: - medium: - description: 'What type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: 'Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - volumeClaimTemplate: - description: A PVC spec to be used by the Prometheus StatefulSets. - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - description: EmbeddedMetadata contains metadata relevant to an EmbeddedResource. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels' - type: object - name: - description: 'Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names' - type: string - type: object - spec: - description: 'Spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - accessModes: - description: 'AccessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' - items: - type: string - type: array - dataSource: - description: 'This field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot - Beta) * An existing PVC (PersistentVolumeClaim) * An existing custom resource/object that implements data population (Alpha) In order to use VolumeSnapshot object types, the appropriate feature gate must be enabled (VolumeSnapshotDataSource or AnyVolumeDataSource) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the specified data source is not supported, the volume will not be created and the failure will be reported as an event. In the future, we plan to support more data source types and the behavior of the provisioner may change.' - properties: - apiGroup: - description: APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - resources: - description: 'Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - selector: - description: A label query over volumes to consider for binding. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - storageClassName: - description: 'Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' - type: string - volumeMode: - description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: VolumeName is the binding reference to the PersistentVolume backing this claim. - type: string - type: object - status: - description: 'Status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - accessModes: - description: 'AccessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' - items: - type: string - type: array - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying volume. - type: object - conditions: - description: Current Condition of persistent volume claim. If underlying persistent volume is being resized then the Condition will be set to 'ResizeStarted'. - items: - description: PersistentVolumeClaimCondition contails details about state of pvc - properties: - lastProbeTime: - description: Last time we probed the condition. - format: date-time - type: string - lastTransitionTime: - description: Last time the condition transitioned from one status to another. - format: date-time - type: string - message: - description: Human-readable message indicating details about last transition. - type: string - reason: - description: Unique, this should be a short, machine understandable string that gives the reason for condition's last transition. If it reports "ResizeStarted" that means the underlying persistent volume is being resized. - type: string - status: - type: string - type: - description: PersistentVolumeClaimConditionType is a valid value of PersistentVolumeClaimCondition.Type - type: string - required: - - status - - type - type: object - type: array - phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - type: object - type: object - type: object - tolerations: - description: If specified, the pod's tolerations. - items: - description: The pod this Toleration is attached to tolerates any taint that matches the triple <key,value,effect> using the matching operator <operator>. - properties: - effect: - description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: - description: If specified, the pod's topology spread constraints. - items: - description: TopologySpreadConstraint specifies how to spread matching pods among the given topology. - properties: - labelSelector: - description: LabelSelector is used to find matching pods. Pods that match this label selector are counted to determine the number of pods in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. - properties: - key: - description: key is the label key that the selector applies to. - type: string - operator: - description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: 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. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: 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. - type: object - type: object - maxSkew: - description: 'MaxSkew describes the degree to which pods may be unevenly distributed. It''s the maximum permitted difference between the number of matching pods in any two topology domains of a given topology type. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 1/1/0: | zone1 | zone2 | zone3 | | P | P | | - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 1/1/1; scheduling it onto zone1(zone2) would make the ActualSkew(2-0) on zone1(zone2) violate MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled onto any zone. It''s a required field. Default value is 1 and 0 is not allowed.' - format: int32 - type: integer - topologyKey: - description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each <key, value> as a "bucket", and try to put balanced number of pods into each bucket. It's a required field. - type: string - whenUnsatisfiable: - description: 'WhenUnsatisfiable indicates how to deal with a pod if it doesn''t satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it - ScheduleAnyway tells the scheduler to still schedule it It''s considered as "Unsatisfiable" if and only if placing incoming pod on any topology violates "MaxSkew". For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler won''t make it *more* imbalanced. It''s a required field.' - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - tracingConfig: - description: TracingConfig configures tracing in Thanos. This is an experimental feature, it may change in any upcoming release in a breaking way. - properties: - key: - description: The key of the secret to select from. Must be a valid secret key. - type: string - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - required: - - key - type: object - volumes: - description: Volumes allows configuration of additional volumes on the output StatefulSet definition. Volumes specified will be appended to other volumes that are generated as a result of StorageSpec objects. - items: - description: Volume represents a named volume in a pod that may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - partition: - description: 'The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as "1". Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty).' - format: int32 - type: integer - readOnly: - description: 'Specify "true" to force and set the ReadOnly property in VolumeMounts to "true". If omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - type: boolean - volumeID: - description: 'Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' - type: string - required: - - volumeID - type: object - azureDisk: - description: AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. - properties: - cachingMode: - description: 'Host Caching mode: None, Read Only, Read Write.' - type: string - diskName: - description: The Name of the data disk in the blob storage - type: string - diskURI: - description: The URI the data disk in the blob storage - type: string - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - kind: - description: 'Expected values Shared: multiple blob disks per storage account Dedicated: single blob disk per storage account Managed: azure managed data disk (only in managed availability set). defaults to shared' - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: AzureFile represents an Azure File Service mount on the host and bind mount to the pod. - properties: - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: the name of secret that contains Azure Storage Account Name and Key - type: string - shareName: - description: Share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: CephFS represents a Ceph FS mount on the host that shares a pod's lifetime - properties: - monitors: - description: 'Required: Monitors is a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - items: - type: string - type: array - path: - description: 'Optional: Used as the mounted root, rather than the full Ceph tree, default is /' - type: string - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: boolean - secretFile: - description: 'Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: string - secretRef: - description: 'Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - properties: - name: - description: '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?' - type: string - type: object - user: - description: 'Optional: User is the rados user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' - type: string - required: - - monitors - type: object - cinder: - description: 'Cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - properties: - fsType: - description: 'Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: string - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: boolean - secretRef: - description: 'Optional: points to a secret object containing parameters used to connect to OpenStack.' - properties: - name: - description: '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?' - type: string - type: object - volumeID: - description: 'volume id used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' - type: string - required: - - volumeID - type: object - configMap: - description: ConfigMap represents a configMap that should populate this volume - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its keys must be defined - type: boolean - type: object - csi: - description: CSI (Container Storage Interface) represents storage that is handled by an external CSI driver (Alpha feature). - properties: - driver: - description: Driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. - type: string - fsType: - description: Filesystem type to mount. Ex. "ext4", "xfs", "ntfs". If not provided, the empty value is passed to the associated CSI driver which will determine the default filesystem to apply. - type: string - nodePublishSecretRef: - description: NodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. This field is optional, and may be empty if no secret is required. If the secret object contains more than one secret, all secret references are passed. - properties: - name: - description: '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?' - type: string - type: object - readOnly: - description: Specifies a read-only configuration for the volume. Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: VolumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. - type: object - required: - - driver - type: object - downwardAPI: - description: DownwardAPI represents downward API about the pod that should populate this volume - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: Items is a list of downward API volume file - items: - description: DownwardAPIVolumeFile represents information to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: 'Required: Path is the relative path name of the file to be created. Must not be absolute or contain the ''..'' path. Must be utf-8 encoded. The first item of the relative path must not start with ''..''' - type: string - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - emptyDir: - description: 'EmptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - properties: - medium: - description: 'What type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: 'Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - fc: - description: FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. - properties: - fsType: - description: 'Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - lun: - description: 'Optional: FC target lun number' - format: int32 - type: integer - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.' - type: boolean - targetWWNs: - description: 'Optional: FC target worldwide names (WWNs)' - items: - type: string - type: array - wwids: - description: 'Optional: FC volume world wide identifiers (wwids) Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously.' - items: - type: string - type: array - type: object - flexVolume: - description: FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. - properties: - driver: - description: Driver is the name of the driver to use for this volume. - type: string - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - type: string - options: - additionalProperties: - type: string - description: 'Optional: Extra command options if any.' - type: object - readOnly: - description: 'Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.' - type: boolean - secretRef: - description: 'Optional: SecretRef is reference to the secret object containing sensitive information to pass to the plugin scripts. This may be empty if no secret object is specified. If the secret object contains more than one secret, all secrets are passed to the plugin scripts.' - properties: - name: - description: '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?' - type: string - type: object - required: - - driver - type: object - flocker: - description: Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running - properties: - datasetName: - description: Name of the dataset stored as metadata -> name on the dataset for Flocker should be considered as deprecated - type: string - datasetUUID: - description: UUID of the dataset. This is unique identifier of a Flocker dataset - type: string - type: object - gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - partition: - description: 'The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as "1". Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - format: int32 - type: integer - pdName: - description: 'Unique name of the PD resource in GCE. Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - type: string - readOnly: - description: 'ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' - type: boolean - required: - - pdName - type: object - gitRepo: - description: 'GitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir into the Pod''s container.' - properties: - directory: - description: Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name. - type: string - repository: - description: Repository URL - type: string - revision: - description: Commit hash for the specified revision. - type: string - required: - - repository - type: object - glusterfs: - description: 'Glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' - properties: - endpoints: - description: 'EndpointsName is the endpoint name that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: string - path: - description: 'Path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: string - readOnly: - description: 'ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' - type: boolean - required: - - endpoints - - path - type: object - hostPath: - description: 'HostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath --- TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not mount host directories as read/write.' - properties: - path: - description: 'Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' - type: string - type: - description: 'Type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' - type: string - required: - - path - type: object - iscsi: - description: 'ISCSI represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' - properties: - chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: whether support iSCSI Session CHAP authentication - type: boolean - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface <target portal>:<volume name> will be created for the connection. - type: string - iqn: - description: Target iSCSI Qualified Name. - type: string - iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). - type: string - lun: - description: iSCSI Target Lun number. - format: int32 - type: integer - portals: - description: iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260). - items: - type: string - type: array - readOnly: - description: ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. - type: boolean - secretRef: - description: CHAP Secret for iSCSI target and initiator authentication - properties: - name: - description: '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?' - type: string - type: object - targetPortal: - description: iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260). - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: 'Volume''s name. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - nfs: - description: 'NFS represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - properties: - path: - description: 'Path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: string - readOnly: - description: 'ReadOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: boolean - server: - description: 'Server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - type: string - readOnly: - description: Will force the ReadOnly setting in VolumeMounts. Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - pdID: - description: ID that identifies Photon Controller persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: PortworxVolume represents a portworx volume attached and mounted on kubelets host machine - properties: - fsType: - description: FSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - volumeID: - description: VolumeID uniquely identifies a Portworx volume - type: string - required: - - volumeID - type: object - projected: - description: Items for all in one resources secrets, configmaps, and downward API - properties: - defaultMode: - description: Mode bits to use on created files by default. Must be a value between 0 and 0777. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - sources: - description: list of volume projections - items: - description: Projection that may be projected along with other supported volume types - properties: - configMap: - description: information about the configMap data to project - properties: - items: - description: If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the ConfigMap or its keys must be defined - type: boolean - type: object - downwardAPI: - description: information about the downwardAPI data to project - properties: - items: - description: Items is a list of DownwardAPIVolume file - items: - description: DownwardAPIVolumeFile represents information to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the specified API version. - type: string - required: - - fieldPath - type: object - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: 'Required: Path is the relative path name of the file to be created. Must not be absolute or contain the ''..'' path. Must be utf-8 encoded. The first item of the relative path must not start with ''..''' - type: string - resourceFieldRef: - description: 'Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - required: - - path - type: object - type: array - type: object - secret: - description: information about the secret data to project - properties: - items: - description: If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - name: - description: '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?' - type: string - optional: - description: Specify whether the Secret or its key must be defined - type: boolean - type: object - serviceAccountToken: - description: information about the serviceAccountToken data to project - properties: - audience: - description: Audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience of the token, and otherwise should reject the token. The audience defaults to the identifier of the apiserver. - type: string - expirationSeconds: - description: ExpirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume plugin will proactively rotate the service account token. The kubelet will start trying to rotate the token if the token is older than 80 percent of its time to live or if the token is older than 24 hours.Defaults to 1 hour and must be at least 10 minutes. - format: int64 - type: integer - path: - description: Path is the path relative to the mount point of the file to project the token into. - type: string - required: - - path - type: object - type: object - type: array - required: - - sources - type: object - quobyte: - description: Quobyte represents a Quobyte mount on the host that shares a pod's lifetime - properties: - group: - description: Group to map volume access to Default is no group - type: string - readOnly: - description: ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. - type: boolean - registry: - description: Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes - type: string - tenant: - description: Tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin - type: string - user: - description: User to map volume access to Defaults to serivceaccount user - type: string - volume: - description: Volume is a string that references an already created Quobyte volume by name. - type: string - required: - - registry - - volume - type: object - rbd: - description: 'RBD represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' - properties: - fsType: - description: 'Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' - type: string - image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - keyring: - description: 'Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - monitors: - description: 'A collection of Ceph monitors. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - items: - type: string - type: array - pool: - description: 'The rados pool name. Default is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - readOnly: - description: 'ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: boolean - secretRef: - description: 'SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - properties: - name: - description: '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?' - type: string - type: object - user: - description: 'The rados user name. Default is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' - type: string - required: - - image - - monitors - type: object - scaleIO: - description: ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". - type: string - gateway: - description: The host address of the ScaleIO API Gateway. - type: string - protectionDomain: - description: The name of the ScaleIO Protection Domain for the configured storage. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: SecretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. - properties: - name: - description: '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?' - type: string - type: object - sslEnabled: - description: Flag to enable/disable SSL communication with Gateway, default false - type: boolean - storageMode: - description: Indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. - type: string - storagePool: - description: The ScaleIO Storage Pool associated with the protection domain. - type: string - system: - description: The name of the storage system as configured in ScaleIO. - type: string - volumeName: - description: The name of a volume already created in the ScaleIO system that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: 'Secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' - properties: - defaultMode: - description: 'Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - items: - description: If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within a volume. - properties: - key: - description: The key to project. - type: string - mode: - description: 'Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.' - format: int32 - type: integer - path: - description: The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - optional: - description: Specify whether the Secret or its keys must be defined - type: boolean - secretName: - description: 'Name of the secret in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' - type: string - type: object - storageos: - description: StorageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - readOnly: - description: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: SecretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. - properties: - name: - description: '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?' - type: string - type: object - volumeName: - description: VolumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. - type: string - volumeNamespace: - description: VolumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping to be mirrored within StorageOS for tighter integration. Set VolumeName to any name to override the default behaviour. Set to "default" if you are not using namespaces within StorageOS. Namespaces that do not pre-exist within StorageOS will be created. - type: string - type: object - vsphereVolume: - description: VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine - properties: - fsType: - description: Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - type: string - storagePolicyID: - description: Storage Policy Based Management (SPBM) profile ID associated with the StoragePolicyName. - type: string - storagePolicyName: - description: Storage Policy Based Management (SPBM) profile name. - type: string - volumePath: - description: Path that identifies vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - type: object - status: - description: 'Most recent observed status of the ThanosRuler cluster. Read-only. Not included when requesting from the apiserver, only from the ThanosRuler Operator API itself. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' - properties: - availableReplicas: - description: Total number of available pods (ready for at least minReadySeconds) targeted by this ThanosRuler deployment. - format: int32 - type: integer - paused: - description: Represents whether any actions on the underlying managed objects are being performed. Only delete actions will be performed. - type: boolean - replicas: - description: Total number of non-terminated pods targeted by this ThanosRuler deployment (their labels match the selector). - format: int32 - type: integer - unavailableReplicas: - description: Total number of unavailable pods targeted by this ThanosRuler deployment. - format: int32 - type: integer - updatedReplicas: - description: Total number of non-terminated pods targeted by this ThanosRuler deployment that have the desired version spec. - format: int32 - type: integer - required: - - availableReplicas - - paused - - replicas - - unavailableReplicas - - updatedReplicas - type: object - required: - - spec - type: object - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/NOTES.txt b/scripts/helm/monitoring/kube-prometheus-stack/templates/NOTES.txt deleted file mode 100644 index 371f3ae39..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/NOTES.txt +++ /dev/null @@ -1,4 +0,0 @@ -{{ $.Chart.Name }} has been installed. Check its status by running: - kubectl --namespace {{ template "kube-prometheus-stack.namespace" . }} get pods -l "release={{ $.Release.Name }}" - -Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator. diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/_helpers.tpl b/scripts/helm/monitoring/kube-prometheus-stack/templates/_helpers.tpl deleted file mode 100644 index 8a3d1b76f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/_helpers.tpl +++ /dev/null @@ -1,93 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* Expand the name of the chart. This is suffixed with -alertmanager, which means subtract 13 from longest 63 available */}} -{{- define "kube-prometheus-stack.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 50 | trimSuffix "-" -}} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -The components in this chart create additional resources that expand the longest created name strings. -The longest name that gets created adds and extra 37 characters, so truncation should be 63-35=26. -*/}} -{{- define "kube-prometheus-stack.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 26 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 26 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 26 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* Fullname suffixed with operator */}} -{{- define "kube-prometheus-stack.operator.fullname" -}} -{{- printf "%s-operator" (include "kube-prometheus-stack.fullname" .) -}} -{{- end }} - -{{/* Fullname suffixed with prometheus */}} -{{- define "kube-prometheus-stack.prometheus.fullname" -}} -{{- printf "%s-prometheus" (include "kube-prometheus-stack.fullname" .) -}} -{{- end }} - -{{/* Fullname suffixed with alertmanager */}} -{{- define "kube-prometheus-stack.alertmanager.fullname" -}} -{{- printf "%s-alertmanager" (include "kube-prometheus-stack.fullname" .) -}} -{{- end }} - -{{/* Create chart name and version as used by the chart label. */}} -{{- define "kube-prometheus-stack.chartref" -}} -{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} -{{- end }} - -{{/* Generate basic labels */}} -{{- define "kube-prometheus-stack.labels" }} -chart: {{ template "kube-prometheus-stack.chartref" . }} -release: {{ $.Release.Name | quote }} -heritage: {{ $.Release.Service | quote }} -{{- if .Values.commonLabels}} -{{ toYaml .Values.commonLabels }} -{{- end }} -{{- end }} - -{{/* Create the name of kube-prometheus-stack service account to use */}} -{{- define "kube-prometheus-stack.operator.serviceAccountName" -}} -{{- if .Values.prometheusOperator.serviceAccount.create -}} - {{ default (include "kube-prometheus-stack.operator.fullname" .) .Values.prometheusOperator.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.prometheusOperator.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* Create the name of prometheus service account to use */}} -{{- define "kube-prometheus-stack.prometheus.serviceAccountName" -}} -{{- if .Values.prometheus.serviceAccount.create -}} - {{ default (include "kube-prometheus-stack.prometheus.fullname" .) .Values.prometheus.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.prometheus.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* Create the name of alertmanager service account to use */}} -{{- define "kube-prometheus-stack.alertmanager.serviceAccountName" -}} -{{- if .Values.alertmanager.serviceAccount.create -}} - {{ default (include "kube-prometheus-stack.alertmanager.fullname" .) .Values.alertmanager.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.alertmanager.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "kube-prometheus-stack.namespace" -}} - {{- if .Values.namespaceOverride -}} - {{- .Values.namespaceOverride -}} - {{- else -}} - {{- .Release.Namespace -}} - {{- end -}} -{{- end -}} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/alertmanager.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/alertmanager.yaml deleted file mode 100644 index 78d0f7c5b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/alertmanager.yaml +++ /dev/null @@ -1,137 +0,0 @@ -{{- if .Values.alertmanager.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: Alertmanager -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: -{{- if .Values.alertmanager.alertmanagerSpec.image }} - image: {{ .Values.alertmanager.alertmanagerSpec.image.repository }}:{{ .Values.alertmanager.alertmanagerSpec.image.tag }} - version: {{ .Values.alertmanager.alertmanagerSpec.image.tag }} - {{- if .Values.alertmanager.alertmanagerSpec.image.sha }} - sha: {{ .Values.alertmanager.alertmanagerSpec.image.sha }} - {{- end }} -{{- end }} - replicas: {{ .Values.alertmanager.alertmanagerSpec.replicas }} - listenLocal: {{ .Values.alertmanager.alertmanagerSpec.listenLocal }} - serviceAccountName: {{ template "kube-prometheus-stack.alertmanager.serviceAccountName" . }} -{{- if .Values.alertmanager.alertmanagerSpec.externalUrl }} - externalUrl: "{{ .Values.alertmanager.alertmanagerSpec.externalUrl }}" -{{- else if and .Values.alertmanager.ingress.enabled .Values.alertmanager.ingress.hosts }} - externalUrl: "http://{{ tpl (index .Values.alertmanager.ingress.hosts 0) . }}{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" -{{- else }} - externalUrl: http://{{ template "kube-prometheus-stack.fullname" . }}-alertmanager.{{ template "kube-prometheus-stack.namespace" . }}:{{ .Values.alertmanager.service.port }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.nodeSelector }} - nodeSelector: -{{ toYaml .Values.alertmanager.alertmanagerSpec.nodeSelector | indent 4 }} -{{- end }} - paused: {{ .Values.alertmanager.alertmanagerSpec.paused }} - logFormat: {{ .Values.alertmanager.alertmanagerSpec.logFormat | quote }} - logLevel: {{ .Values.alertmanager.alertmanagerSpec.logLevel | quote }} - retention: {{ .Values.alertmanager.alertmanagerSpec.retention | quote }} -{{- if .Values.alertmanager.alertmanagerSpec.secrets }} - secrets: -{{ toYaml .Values.alertmanager.alertmanagerSpec.secrets | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.configSecret }} - configSecret: {{ .Values.alertmanager.alertmanagerSpec.configSecret }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.configMaps }} - configMaps: -{{ toYaml .Values.alertmanager.alertmanagerSpec.configMaps | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector }} - alertmanagerConfigSelector: -{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfigSelector | indent 4}} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.alertmanagerConfigNamespaceSelector }} - alertmanagerConfigNamespaceSelector: -{{ toYaml .Values.alertmanager.alertmanagerSpec.alertmanagerConfigNamespaceSelector | indent 4}} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.resources }} - resources: -{{ toYaml .Values.alertmanager.alertmanagerSpec.resources | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.routePrefix }} - routePrefix: "{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.securityContext }} - securityContext: -{{ toYaml .Values.alertmanager.alertmanagerSpec.securityContext | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.storage }} - storage: -{{ toYaml .Values.alertmanager.alertmanagerSpec.storage | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.podMetadata }} - podMetadata: -{{ toYaml .Values.alertmanager.alertmanagerSpec.podMetadata | indent 4 }} -{{- end }} -{{- if or .Values.alertmanager.alertmanagerSpec.podAntiAffinity .Values.alertmanager.alertmanagerSpec.affinity }} - affinity: -{{- if .Values.alertmanager.alertmanagerSpec.affinity }} -{{ toYaml .Values.alertmanager.alertmanagerSpec.affinity | indent 4 }} -{{- end }} -{{- if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity "hard" }} - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }} - labelSelector: - matchLabels: - app: alertmanager - alertmanager: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager -{{- else if eq .Values.alertmanager.alertmanagerSpec.podAntiAffinity "soft" }} - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - topologyKey: {{ .Values.alertmanager.alertmanagerSpec.podAntiAffinityTopologyKey }} - labelSelector: - matchLabels: - app: alertmanager - alertmanager: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager -{{- end }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.tolerations }} - tolerations: -{{ toYaml .Values.alertmanager.alertmanagerSpec.tolerations | indent 4 }} -{{- end }} -{{- if .Values.global.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.global.imagePullSecrets | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.containers }} - containers: -{{ toYaml .Values.alertmanager.alertmanagerSpec.containers | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.initContainers }} - initContainers: -{{ toYaml .Values.alertmanager.alertmanagerSpec.initContainers | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.priorityClassName }} - priorityClassName: {{.Values.alertmanager.alertmanagerSpec.priorityClassName }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.additionalPeers }} - additionalPeers: -{{ toYaml .Values.alertmanager.alertmanagerSpec.additionalPeers | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.volumes }} - volumes: -{{ toYaml .Values.alertmanager.alertmanagerSpec.volumes | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.volumeMounts }} - volumeMounts: -{{ toYaml .Values.alertmanager.alertmanagerSpec.volumeMounts | indent 4 }} -{{- end }} - portName: {{ .Values.alertmanager.alertmanagerSpec.portName }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }} - clusterAdvertiseAddress: {{ .Values.alertmanager.alertmanagerSpec.clusterAdvertiseAddress }} -{{- end }} -{{- if .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }} - forceEnableClusterMode: {{ .Values.alertmanager.alertmanagerSpec.forceEnableClusterMode }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/ingress.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/ingress.yaml deleted file mode 100644 index c67be5cbc..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/ingress.yaml +++ /dev/null @@ -1,58 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled }} -{{- $serviceName := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "alertmanager" }} -{{- $servicePort := .Values.alertmanager.service.port -}} -{{- $routePrefix := list .Values.alertmanager.alertmanagerSpec.routePrefix }} -{{- $paths := .Values.alertmanager.ingress.paths | default $routePrefix -}} -{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} -apiVersion: networking.k8s.io/v1beta1 -{{ else }} -apiVersion: extensions/v1beta1 -{{ end -}} -kind: Ingress -metadata: - name: {{ $serviceName }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- if .Values.alertmanager.ingress.annotations }} - annotations: -{{ toYaml .Values.alertmanager.ingress.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{- if .Values.alertmanager.ingress.labels }} -{{ toYaml .Values.alertmanager.ingress.labels | indent 4 }} -{{- end }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - {{- if or (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1") }} - {{- if .Values.alertmanager.ingress.ingressClassName }} - ingressClassName: {{ .Values.alertmanager.ingress.ingressClassName }} - {{- end }} - {{- end }} - rules: - {{- if .Values.alertmanager.ingress.hosts }} - {{- range $host := .Values.alertmanager.ingress.hosts }} - - host: {{ tpl $host $ }} - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end -}} - {{- end -}} - {{- else }} - - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end -}} - {{- end -}} - {{- if .Values.alertmanager.ingress.tls }} - tls: -{{ toYaml .Values.alertmanager.ingress.tls | indent 4 }} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/ingressperreplica.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/ingressperreplica.yaml deleted file mode 100644 index 7689c29d9..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/ingressperreplica.yaml +++ /dev/null @@ -1,58 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.servicePerReplica.enabled .Values.alertmanager.ingressPerReplica.enabled }} -{{- $count := .Values.alertmanager.alertmanagerSpec.replicas | int -}} -{{- $servicePort := .Values.alertmanager.service.port -}} -{{- $ingressValues := .Values.alertmanager.ingressPerReplica -}} -apiVersion: v1 -kind: List -metadata: - name: {{ include "kube-prometheus-stack.fullname" $ }}-alertmanager-ingressperreplica - namespace: {{ template "kube-prometheus-stack.namespace" . }} -items: -{{ range $i, $e := until $count }} - - kind: Ingress - {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} - apiVersion: networking.k8s.io/v1beta1 - {{ else }} - apiVersion: extensions/v1beta1 - {{ end -}} - metadata: - name: {{ include "kube-prometheus-stack.fullname" $ }}-alertmanager-{{ $i }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - app: {{ include "kube-prometheus-stack.name" $ }}-alertmanager -{{ include "kube-prometheus-stack.labels" $ | indent 8 }} - {{- if $ingressValues.labels }} -{{ toYaml $ingressValues.labels | indent 8 }} - {{- end }} - {{- if $ingressValues.annotations }} - annotations: -{{ toYaml $ingressValues.annotations | indent 8 }} - {{- end }} - spec: - {{- if or ($.Capabilities.APIVersions.Has "networking.k8s.io/v1") ($.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1") }} - {{- if $ingressValues.ingressClassName }} - ingressClassName: {{ $ingressValues.ingressClassName }} - {{- end }} - {{- end }} - rules: - - host: {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }} - http: - paths: - {{- range $p := $ingressValues.paths }} - - path: {{ tpl $p $ }} - backend: - serviceName: {{ include "kube-prometheus-stack.fullname" $ }}-alertmanager-{{ $i }} - servicePort: {{ $servicePort }} - {{- end -}} - {{- if or $ingressValues.tlsSecretName $ingressValues.tlsSecretPerReplica.enabled }} - tls: - - hosts: - - {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }} - {{- if $ingressValues.tlsSecretPerReplica.enabled }} - secretName: {{ $ingressValues.tlsSecretPerReplica.prefix }}-{{ $i }} - {{- else }} - secretName: {{ $ingressValues.tlsSecretName }} - {{- end }} - {{- end }} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/podDisruptionBudget.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/podDisruptionBudget.yaml deleted file mode 100644 index 1dbe809cd..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/podDisruptionBudget.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.podDisruptionBudget.enabled }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - {{- if .Values.alertmanager.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.alertmanager.podDisruptionBudget.minAvailable }} - {{- end }} - {{- if .Values.alertmanager.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.alertmanager.podDisruptionBudget.maxUnavailable }} - {{- end }} - selector: - matchLabels: - app: alertmanager - alertmanager: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp-role.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp-role.yaml deleted file mode 100644 index d64d1f813..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp-role.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -kind: Role -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -rules: -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} -- apiGroups: ['policy'] -{{- else }} -- apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "kube-prometheus-stack.fullname" . }}-alertmanager -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp-rolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp-rolebinding.yaml deleted file mode 100644 index 9248cc8dd..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp-rolebinding.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager -subjects: - - kind: ServiceAccount - name: {{ template "kube-prometheus-stack.alertmanager.serviceAccountName" . }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp.yaml deleted file mode 100644 index 6fa445009..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/psp.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{- if .Values.global.rbac.pspAnnotations }} - annotations: -{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} -{{- end }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - privileged: false - # Required to prevent escalations to root. - # allowPrivilegeEscalation: false - # This is redundant with non-root + disallow privilege escalation, - # but we can provide it for defense in depth. - #requiredDropCapabilities: - # - ALL - # Allow core volume types. - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} - diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/secret.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/secret.yaml deleted file mode 100644 index 43c4e20b2..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/secret.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if and (.Values.alertmanager.enabled) (not .Values.alertmanager.alertmanagerSpec.useExistingSecret) }} -apiVersion: v1 -kind: Secret -metadata: - name: alertmanager-{{ template "kube-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- if .Values.alertmanager.secret.annotations }} - annotations: -{{ toYaml .Values.alertmanager.secret.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -data: -{{- if .Values.alertmanager.tplConfig }} - alertmanager.yaml: {{ tpl (toYaml .Values.alertmanager.config) . | b64enc | quote }} -{{- else }} - alertmanager.yaml: {{ toYaml .Values.alertmanager.config | b64enc | quote }} -{{- end}} -{{- range $key, $val := .Values.alertmanager.templateFiles }} - {{ $key }}: {{ $val | b64enc | quote }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/service.yaml deleted file mode 100644 index bbcc60f2b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/service.yaml +++ /dev/null @@ -1,50 +0,0 @@ -{{- if .Values.alertmanager.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager - self-monitor: {{ .Values.alertmanager.serviceMonitor.selfMonitor | quote }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.alertmanager.service.labels }} -{{ toYaml .Values.alertmanager.service.labels | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.service.annotations }} - annotations: -{{ toYaml .Values.alertmanager.service.annotations | indent 4 }} -{{- end }} -spec: -{{- if .Values.alertmanager.service.clusterIP }} - clusterIP: {{ .Values.alertmanager.service.clusterIP }} -{{- end }} -{{- if .Values.alertmanager.service.externalIPs }} - externalIPs: -{{ toYaml .Values.alertmanager.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.alertmanager.service.loadBalancerIP }} -{{- end }} -{{- if .Values.alertmanager.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.alertmanager.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} - ports: - - name: {{ .Values.alertmanager.alertmanagerSpec.portName }} - {{- if eq .Values.alertmanager.service.type "NodePort" }} - nodePort: {{ .Values.alertmanager.service.nodePort }} - {{- end }} - port: {{ .Values.alertmanager.service.port }} - targetPort: {{ .Values.alertmanager.service.targetPort }} - protocol: TCP -{{- if .Values.alertmanager.service.additionalPorts }} -{{ toYaml .Values.alertmanager.service.additionalPorts | indent 2 }} -{{- end }} - selector: - app: alertmanager - alertmanager: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - type: "{{ .Values.alertmanager.service.type }}" -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/serviceaccount.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/serviceaccount.yaml deleted file mode 100644 index c5e6e9228..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/serviceaccount.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "kube-prometheus-stack.alertmanager.serviceAccountName" . }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.alertmanager.serviceAccount.annotations }} - annotations: -{{ toYaml .Values.alertmanager.serviceAccount.annotations | indent 4 }} -{{- end }} -imagePullSecrets: -{{ toYaml .Values.global.imagePullSecrets | indent 2 }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/servicemonitor.yaml deleted file mode 100644 index a699accb8..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/servicemonitor.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.serviceMonitor.selfMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-alertmanager - release: {{ $.Release.Name | quote }} - self-monitor: "true" - namespaceSelector: - matchNames: - - {{ printf "%s" (include "kube-prometheus-stack.namespace" .) | quote }} - endpoints: - - port: {{ .Values.alertmanager.alertmanagerSpec.portName }} - {{- if .Values.alertmanager.serviceMonitor.interval }} - interval: {{ .Values.alertmanager.serviceMonitor.interval }} - {{- end }} - {{- if .Values.alertmanager.serviceMonitor.scheme }} - scheme: {{ .Values.alertmanager.serviceMonitor.scheme }} - {{- end }} - {{- if .Values.alertmanager.serviceMonitor.bearerTokenFile }} - bearerTokenFile: {{ .Values.alertmanager.serviceMonitor.bearerTokenFile }} - {{- end }} - {{- if .Values.alertmanager.serviceMonitor.tlsConfig }} - tlsConfig: {{ toYaml .Values.alertmanager.serviceMonitor.tlsConfig | nindent 6 }} - {{- end }} - path: "{{ trimSuffix "/" .Values.alertmanager.alertmanagerSpec.routePrefix }}/metrics" -{{- if .Values.alertmanager.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.alertmanager.serviceMonitor.metricRelabelings | indent 6) . }} -{{- end }} -{{- if .Values.alertmanager.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.alertmanager.serviceMonitor.relabelings | indent 6 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/serviceperreplica.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/serviceperreplica.yaml deleted file mode 100644 index 0f12ae879..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/alertmanager/serviceperreplica.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.servicePerReplica.enabled }} -{{- $count := .Values.alertmanager.alertmanagerSpec.replicas | int -}} -{{- $serviceValues := .Values.alertmanager.servicePerReplica -}} -apiVersion: v1 -kind: List -metadata: - name: {{ include "kube-prometheus-stack.fullname" $ }}-alertmanager-serviceperreplica - namespace: {{ template "kube-prometheus-stack.namespace" . }} -items: -{{- range $i, $e := until $count }} - - apiVersion: v1 - kind: Service - metadata: - name: {{ include "kube-prometheus-stack.fullname" $ }}-alertmanager-{{ $i }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - app: {{ include "kube-prometheus-stack.name" $ }}-alertmanager -{{ include "kube-prometheus-stack.labels" $ | indent 8 }} - {{- if $serviceValues.annotations }} - annotations: -{{ toYaml $serviceValues.annotations | indent 8 }} - {{- end }} - spec: - {{- if $serviceValues.clusterIP }} - clusterIP: {{ $serviceValues.clusterIP }} - {{- end }} - {{- if $serviceValues.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := $serviceValues.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} - {{- end }} - ports: - - name: {{ $.Values.alertmanager.alertmanagerSpec.portName }} - {{- if eq $serviceValues.type "NodePort" }} - nodePort: {{ $serviceValues.nodePort }} - {{- end }} - port: {{ $serviceValues.port }} - targetPort: {{ $serviceValues.targetPort }} - selector: - app: alertmanager - alertmanager: {{ template "kube-prometheus-stack.fullname" $ }}-alertmanager - statefulset.kubernetes.io/pod-name: alertmanager-{{ include "kube-prometheus-stack.fullname" $ }}-alertmanager-{{ $i }} - type: "{{ $serviceValues.type }}" -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/core-dns/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/core-dns/service.yaml deleted file mode 100644 index f77db4199..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/core-dns/service.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if .Values.coreDns.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-coredns - labels: - app: {{ template "kube-prometheus-stack.name" . }}-coredns - jobLabel: coredns -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -spec: - clusterIP: None - ports: - - name: http-metrics - port: {{ .Values.coreDns.service.port }} - protocol: TCP - targetPort: {{ .Values.coreDns.service.targetPort }} - selector: - {{- if .Values.coreDns.service.selector }} -{{ toYaml .Values.coreDns.service.selector | indent 4 }} - {{- else}} - k8s-app: kube-dns - {{- end}} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/core-dns/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/core-dns/servicemonitor.yaml deleted file mode 100644 index c398db612..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/core-dns/servicemonitor.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.coreDns.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-coredns - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-coredns -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - jobLabel: jobLabel - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-coredns - release: {{ $.Release.Name | quote }} - namespaceSelector: - matchNames: - - "kube-system" - endpoints: - - port: http-metrics - {{- if .Values.coreDns.serviceMonitor.interval}} - interval: {{ .Values.coreDns.serviceMonitor.interval }} - {{- end }} - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token -{{- if .Values.coreDns.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.coreDns.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.coreDns.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.coreDns.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-api-server/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-api-server/servicemonitor.yaml deleted file mode 100644 index 4c0290e73..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-api-server/servicemonitor.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if .Values.kubeApiServer.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-apiserver - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-apiserver -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - endpoints: - - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - {{- if .Values.kubeApiServer.serviceMonitor.interval }} - interval: {{ .Values.kubeApiServer.serviceMonitor.interval }} - {{- end }} - port: https - scheme: https -{{- if .Values.kubeApiServer.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeApiServer.serviceMonitor.metricRelabelings | indent 6) . }} -{{- end }} -{{- if .Values.kubeApiServer.relabelings }} - relabelings: -{{ toYaml .Values.kubeApiServer.relabelings | indent 6 }} -{{- end }} - tlsConfig: - caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - serverName: {{ .Values.kubeApiServer.tlsConfig.serverName }} - insecureSkipVerify: {{ .Values.kubeApiServer.tlsConfig.insecureSkipVerify }} - jobLabel: {{ .Values.kubeApiServer.serviceMonitor.jobLabel }} - namespaceSelector: - matchNames: - - default - selector: -{{ toYaml .Values.kubeApiServer.serviceMonitor.selector | indent 4 }} -{{- end}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/endpoints.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/endpoints.yaml deleted file mode 100644 index 413193028..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/endpoints.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.kubeControllerManager.enabled .Values.kubeControllerManager.endpoints }} -apiVersion: v1 -kind: Endpoints -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-controller-manager - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-controller-manager - k8s-app: kube-controller-manager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -subsets: - - addresses: - {{- range .Values.kubeControllerManager.endpoints }} - - ip: {{ . }} - {{- end }} - ports: - - name: http-metrics - port: {{ .Values.kubeControllerManager.service.port }} - protocol: TCP -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/service.yaml deleted file mode 100644 index 8b5556a89..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/service.yaml +++ /dev/null @@ -1,27 +0,0 @@ -{{- if .Values.kubeControllerManager.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-controller-manager - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-controller-manager - jobLabel: kube-controller-manager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -spec: - clusterIP: None - ports: - - name: http-metrics - port: {{ .Values.kubeControllerManager.service.port }} - protocol: TCP - targetPort: {{ .Values.kubeControllerManager.service.targetPort }} -{{- if .Values.kubeControllerManager.endpoints }}{{- else }} - selector: - {{- if .Values.kubeControllerManager.service.selector }} -{{ toYaml .Values.kubeControllerManager.service.selector | indent 4 }} - {{- else}} - component: kube-controller-manager - {{- end}} -{{- end }} - type: ClusterIP -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/servicemonitor.yaml deleted file mode 100644 index 2f30a0cc2..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-controller-manager/servicemonitor.yaml +++ /dev/null @@ -1,44 +0,0 @@ -{{- if .Values.kubeControllerManager.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-controller-manager - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-controller-manager -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - jobLabel: jobLabel - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-controller-manager - release: {{ $.Release.Name | quote }} - namespaceSelector: - matchNames: - - "kube-system" - endpoints: - - port: http-metrics - {{- if .Values.kubeControllerManager.serviceMonitor.interval }} - interval: {{ .Values.kubeControllerManager.serviceMonitor.interval }} - {{- end }} - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - {{- if .Values.kubeControllerManager.serviceMonitor.https }} - scheme: https - tlsConfig: - caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - {{- if .Values.kubeControllerManager.serviceMonitor.insecureSkipVerify }} - insecureSkipVerify: {{ .Values.kubeControllerManager.serviceMonitor.insecureSkipVerify }} - {{- end }} - {{- if .Values.kubeControllerManager.serviceMonitor.serverName }} - serverName: {{ .Values.kubeControllerManager.serviceMonitor.serverName }} - {{- end }} - {{- end }} -{{- if .Values.kubeControllerManager.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeControllerManager.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubeControllerManager.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.kubeControllerManager.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-dns/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-dns/service.yaml deleted file mode 100644 index c7bf142d5..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-dns/service.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- if .Values.kubeDns.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-dns - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-dns - jobLabel: kube-dns -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -spec: - clusterIP: None - ports: - - name: http-metrics-dnsmasq - port: {{ .Values.kubeDns.service.dnsmasq.port }} - protocol: TCP - targetPort: {{ .Values.kubeDns.service.dnsmasq.targetPort }} - - name: http-metrics-skydns - port: {{ .Values.kubeDns.service.skydns.port }} - protocol: TCP - targetPort: {{ .Values.kubeDns.service.skydns.targetPort }} - selector: - {{- if .Values.kubeDns.service.selector }} -{{ toYaml .Values.kubeDns.service.selector | indent 4 }} - {{- else}} - k8s-app: kube-dns - {{- end}} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-dns/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-dns/servicemonitor.yaml deleted file mode 100644 index 3c1a06175..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-dns/servicemonitor.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.kubeDns.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-dns - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-dns -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - jobLabel: jobLabel - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-dns - release: {{ $.Release.Name | quote }} - namespaceSelector: - matchNames: - - "kube-system" - endpoints: - - port: http-metrics-dnsmasq - {{- if .Values.kubeDns.serviceMonitor.interval }} - interval: {{ .Values.kubeDns.serviceMonitor.interval }} - {{- end }} - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token -{{- if .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeDns.serviceMonitor.dnsmasqMetricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubeDns.serviceMonitor.dnsmasqRelabelings }} - relabelings: -{{ toYaml .Values.kubeDns.serviceMonitor.dnsmasqRelabelings | indent 4 }} -{{- end }} - - port: http-metrics-skydns - {{- if .Values.kubeDns.serviceMonitor.interval }} - interval: {{ .Values.kubeDns.serviceMonitor.interval }} - {{- end }} - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token -{{- if .Values.kubeDns.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeDns.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubeDns.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.kubeDns.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/endpoints.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/endpoints.yaml deleted file mode 100644 index 8f07a5cc2..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/endpoints.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.kubeEtcd.enabled .Values.kubeEtcd.endpoints }} -apiVersion: v1 -kind: Endpoints -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-etcd - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-etcd - k8s-app: etcd-server -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -subsets: - - addresses: - {{- range .Values.kubeEtcd.endpoints }} - - ip: {{ . }} - {{- end }} - ports: - - name: http-metrics - port: {{ .Values.kubeEtcd.service.port }} - protocol: TCP -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/service.yaml deleted file mode 100644 index 957e8bbc1..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/service.yaml +++ /dev/null @@ -1,27 +0,0 @@ -{{- if .Values.kubeEtcd.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-etcd - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-etcd - jobLabel: kube-etcd -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -spec: - clusterIP: None - ports: - - name: http-metrics - port: {{ .Values.kubeEtcd.service.port }} - protocol: TCP - targetPort: {{ .Values.kubeEtcd.service.targetPort }} -{{- if .Values.kubeEtcd.endpoints }}{{- else }} - selector: - {{- if .Values.kubeEtcd.service.selector }} -{{ toYaml .Values.kubeEtcd.service.selector | indent 4 }} - {{- else}} - component: etcd - {{- end}} -{{- end }} - type: ClusterIP -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/servicemonitor.yaml deleted file mode 100644 index 17a447ad9..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-etcd/servicemonitor.yaml +++ /dev/null @@ -1,50 +0,0 @@ -{{- if .Values.kubeEtcd.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-etcd - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-etcd -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - jobLabel: jobLabel - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-etcd - release: {{ $.Release.Name | quote }} - namespaceSelector: - matchNames: - - "kube-system" - endpoints: - - port: http-metrics - {{- if .Values.kubeEtcd.serviceMonitor.interval }} - interval: {{ .Values.kubeEtcd.serviceMonitor.interval }} - {{- end }} - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - {{- if eq .Values.kubeEtcd.serviceMonitor.scheme "https" }} - scheme: https - tlsConfig: - {{- if .Values.kubeEtcd.serviceMonitor.serverName }} - serverName: {{ .Values.kubeEtcd.serviceMonitor.serverName }} - {{- end }} - {{- if .Values.kubeEtcd.serviceMonitor.caFile }} - caFile: {{ .Values.kubeEtcd.serviceMonitor.caFile }} - {{- end }} - {{- if .Values.kubeEtcd.serviceMonitor.certFile }} - certFile: {{ .Values.kubeEtcd.serviceMonitor.certFile }} - {{- end }} - {{- if .Values.kubeEtcd.serviceMonitor.keyFile }} - keyFile: {{ .Values.kubeEtcd.serviceMonitor.keyFile }} - {{- end}} - insecureSkipVerify: {{ .Values.kubeEtcd.serviceMonitor.insecureSkipVerify }} - {{- end }} -{{- if .Values.kubeEtcd.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeEtcd.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubeEtcd.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.kubeEtcd.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/endpoints.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/endpoints.yaml deleted file mode 100644 index 2cb756d15..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/endpoints.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.kubeProxy.enabled .Values.kubeProxy.endpoints }} -apiVersion: v1 -kind: Endpoints -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-proxy - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-proxy - k8s-app: kube-proxy -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -subsets: - - addresses: - {{- range .Values.kubeProxy.endpoints }} - - ip: {{ . }} - {{- end }} - ports: - - name: http-metrics - port: {{ .Values.kubeProxy.service.port }} - protocol: TCP -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/service.yaml deleted file mode 100644 index abe420600..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/service.yaml +++ /dev/null @@ -1,27 +0,0 @@ -{{- if .Values.kubeProxy.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-proxy - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-proxy - jobLabel: kube-proxy -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -spec: - clusterIP: None - ports: - - name: http-metrics - port: {{ .Values.kubeProxy.service.port }} - protocol: TCP - targetPort: {{ .Values.kubeProxy.service.targetPort }} -{{- if .Values.kubeProxy.endpoints }}{{- else }} - selector: - {{- if .Values.kubeProxy.service.selector }} -{{ toYaml .Values.kubeProxy.service.selector | indent 4 }} - {{- else}} - k8s-app: kube-proxy - {{- end}} -{{- end }} - type: ClusterIP -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/servicemonitor.yaml deleted file mode 100644 index 0ac44182b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-proxy/servicemonitor.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if .Values.kubeProxy.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-proxy - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-proxy -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - jobLabel: jobLabel - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-proxy - release: {{ $.Release.Name | quote }} - namespaceSelector: - matchNames: - - "kube-system" - endpoints: - - port: http-metrics - {{- if .Values.kubeProxy.serviceMonitor.interval }} - interval: {{ .Values.kubeProxy.serviceMonitor.interval }} - {{- end }} - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - {{- if .Values.kubeProxy.serviceMonitor.https }} - scheme: https - tlsConfig: - caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - {{- end}} -{{- if .Values.kubeProxy.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ toYaml .Values.kubeProxy.serviceMonitor.metricRelabelings | indent 4 }} -{{- end }} -{{- if .Values.kubeProxy.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.kubeProxy.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/endpoints.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/endpoints.yaml deleted file mode 100644 index f4ad60fd6..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/endpoints.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.kubeScheduler.enabled .Values.kubeScheduler.endpoints }} -apiVersion: v1 -kind: Endpoints -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-scheduler - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-scheduler - k8s-app: kube-scheduler -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -subsets: - - addresses: - {{- range .Values.kubeScheduler.endpoints }} - - ip: {{ . }} - {{- end }} - ports: - - name: http-metrics - port: {{ .Values.kubeScheduler.service.port }} - protocol: TCP -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/service.yaml deleted file mode 100644 index 15559d45a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/service.yaml +++ /dev/null @@ -1,27 +0,0 @@ -{{- if .Values.kubeScheduler.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-scheduler - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-scheduler - jobLabel: kube-scheduler -{{ include "kube-prometheus-stack.labels" . | indent 4 }} - namespace: kube-system -spec: - clusterIP: None - ports: - - name: http-metrics - port: {{ .Values.kubeScheduler.service.port}} - protocol: TCP - targetPort: {{ .Values.kubeScheduler.service.targetPort}} -{{- if .Values.kubeScheduler.endpoints }}{{- else }} - selector: - {{- if .Values.kubeScheduler.service.selector }} -{{ toYaml .Values.kubeScheduler.service.selector | indent 4 }} - {{- else}} - component: kube-scheduler - {{- end}} -{{- end }} - type: ClusterIP -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/servicemonitor.yaml deleted file mode 100644 index b565ec2b8..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-scheduler/servicemonitor.yaml +++ /dev/null @@ -1,44 +0,0 @@ -{{- if .Values.kubeScheduler.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-scheduler - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-scheduler -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - jobLabel: jobLabel - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-scheduler - release: {{ $.Release.Name | quote }} - namespaceSelector: - matchNames: - - "kube-system" - endpoints: - - port: http-metrics - {{- if .Values.kubeScheduler.serviceMonitor.interval }} - interval: {{ .Values.kubeScheduler.serviceMonitor.interval }} - {{- end }} - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - {{- if .Values.kubeScheduler.serviceMonitor.https }} - scheme: https - tlsConfig: - caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - {{- if .Values.kubeScheduler.serviceMonitor.insecureSkipVerify }} - insecureSkipVerify: {{ .Values.kubeScheduler.serviceMonitor.insecureSkipVerify }} - {{- end}} - {{- if .Values.kubeScheduler.serviceMonitor.serverName }} - serverName: {{ .Values.kubeScheduler.serviceMonitor.serverName }} - {{- end}} - {{- end}} -{{- if .Values.kubeScheduler.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeScheduler.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubeScheduler.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.kubeScheduler.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-state-metrics/serviceMonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-state-metrics/serviceMonitor.yaml deleted file mode 100644 index f09de5d2e..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kube-state-metrics/serviceMonitor.yaml +++ /dev/null @@ -1,30 +0,0 @@ -{{- if .Values.kubeStateMetrics.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kube-state-metrics - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kube-state-metrics -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - jobLabel: app.kubernetes.io/name - endpoints: - - port: http - {{- if .Values.kubeStateMetrics.serviceMonitor.interval }} - interval: {{ .Values.kubeStateMetrics.serviceMonitor.interval }} - {{- end }} - honorLabels: true -{{- if .Values.kubeStateMetrics.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubeStateMetrics.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubeStateMetrics.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.kubeStateMetrics.serviceMonitor.relabelings | indent 4 }} -{{- end }} - selector: - matchLabels: - app.kubernetes.io/name: kube-state-metrics - app.kubernetes.io/instance: "{{ $.Release.Name }}" -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kubelet/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kubelet/servicemonitor.yaml deleted file mode 100644 index 364593274..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/kubelet/servicemonitor.yaml +++ /dev/null @@ -1,151 +0,0 @@ -{{- if .Values.kubelet.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-kubelet - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-kubelet -{{- include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - endpoints: - {{- if .Values.kubelet.serviceMonitor.https }} - - port: https-metrics - scheme: https - {{- if .Values.kubelet.serviceMonitor.interval }} - interval: {{ .Values.kubelet.serviceMonitor.interval }} - {{- end }} - tlsConfig: - caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token - honorLabels: true -{{- if .Values.kubelet.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubelet.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.kubelet.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.cAdvisor }} - - port: https-metrics - scheme: https - path: /metrics/cadvisor - {{- if .Values.kubelet.serviceMonitor.interval }} - interval: {{ .Values.kubelet.serviceMonitor.interval }} - {{- end }} - {{- if .Values.kubelet.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.kubelet.serviceMonitor.scrapeTimeout }} - {{- end }} - honorLabels: true - tlsConfig: - caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token -{{- if .Values.kubelet.serviceMonitor.cAdvisorMetricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubelet.serviceMonitor.cAdvisorMetricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.cAdvisorRelabelings }} - relabelings: -{{ toYaml .Values.kubelet.serviceMonitor.cAdvisorRelabelings | indent 4 }} -{{- end }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.probes }} - - port: https-metrics - scheme: https - path: /metrics/probes - {{- if .Values.kubelet.serviceMonitor.interval }} - interval: {{ .Values.kubelet.serviceMonitor.interval }} - {{- end }} - honorLabels: true - tlsConfig: - caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token -{{- if .Values.kubelet.serviceMonitor.probesMetricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubelet.serviceMonitor.probesMetricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.probesRelabelings }} - relabelings: -{{ toYaml .Values.kubelet.serviceMonitor.probesRelabelings | indent 4 }} -{{- end }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.resource }} - - port: https-metrics - scheme: https - path: {{ .Values.kubelet.serviceMonitor.resourcePath }} - {{- if .Values.kubelet.serviceMonitor.interval }} - interval: {{ .Values.kubelet.serviceMonitor.interval }} - {{- end }} - honorLabels: true - tlsConfig: - caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token -{{- if .Values.kubelet.serviceMonitor.resourceMetricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubelet.serviceMonitor.resourceMetricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.resourceRelabelings }} - relabelings: -{{ toYaml .Values.kubelet.serviceMonitor.resourceRelabelings | indent 4 }} -{{- end }} -{{- end }} - {{- else }} - - port: http-metrics - {{- if .Values.kubelet.serviceMonitor.interval }} - interval: {{ .Values.kubelet.serviceMonitor.interval }} - {{- end }} - honorLabels: true -{{- if .Values.kubelet.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubelet.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.kubelet.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.cAdvisor }} - - port: http-metrics - path: /metrics/cadvisor - {{- if .Values.kubelet.serviceMonitor.interval }} - interval: {{ .Values.kubelet.serviceMonitor.interval }} - {{- end }} - honorLabels: true -{{- if .Values.kubelet.serviceMonitor.cAdvisorMetricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubelet.serviceMonitor.cAdvisorMetricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.cAdvisorRelabelings }} - relabelings: -{{ toYaml .Values.kubelet.serviceMonitor.cAdvisorRelabelings | indent 4 }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.resource }} - - port: http-metrics - path: {{ .Values.kubelet.serviceMonitor.resourcePath }} - {{- if .Values.kubelet.serviceMonitor.interval }} - interval: {{ .Values.kubelet.serviceMonitor.interval }} - {{- end }} - honorLabels: true -{{- if .Values.kubelet.serviceMonitor.resourceMetricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.kubelet.serviceMonitor.resourceMetricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.kubelet.serviceMonitor.resourceRelabelings }} - relabelings: -{{ toYaml .Values.kubelet.serviceMonitor.resourceRelabelings | indent 4 }} -{{- end }} -{{- end }} -{{- end }} - {{- end }} - jobLabel: k8s-app - namespaceSelector: - matchNames: - - {{ .Values.kubelet.namespace }} - selector: - matchLabels: - k8s-app: kubelet -{{- end}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/node-exporter/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/node-exporter/servicemonitor.yaml deleted file mode 100644 index 5ca5f1b75..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/exporters/node-exporter/servicemonitor.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.nodeExporter.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-node-exporter - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-node-exporter -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - jobLabel: {{ .Values.nodeExporter.jobLabel }} - selector: - matchLabels: - app: prometheus-node-exporter - release: {{ $.Release.Name }} - endpoints: - - port: metrics - {{- if .Values.nodeExporter.serviceMonitor.interval }} - interval: {{ .Values.nodeExporter.serviceMonitor.interval }} - {{- end }} - {{- if .Values.nodeExporter.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ .Values.nodeExporter.serviceMonitor.scrapeTimeout }} - {{- end }} -{{- if .Values.nodeExporter.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.nodeExporter.serviceMonitor.metricRelabelings | indent 4) . }} -{{- end }} -{{- if .Values.nodeExporter.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.nodeExporter.serviceMonitor.relabelings | indent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/configmap-dashboards.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/configmap-dashboards.yaml deleted file mode 100644 index fdd64ce6f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/configmap-dashboards.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -{{- $files := .Files.Glob "dashboards/*.json" }} -{{- if $files }} -apiVersion: v1 -kind: ConfigMapList -items: -{{- range $path, $fileContents := $files }} -{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }} -- apiVersion: v1 - kind: ConfigMap - metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) $dashboardName | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 6 }} - data: - {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }} -{{- end }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/configmaps-datasources.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/configmaps-datasources.yaml deleted file mode 100644 index de904ddbb..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/configmaps-datasources.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- if and .Values.grafana.enabled .Values.grafana.sidecar.datasources.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-grafana-datasource - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- if .Values.grafana.sidecar.datasources.annotations }} - annotations: -{{ toYaml .Values.grafana.sidecar.datasources.annotations | indent 4 }} -{{- end }} - labels: - {{ $.Values.grafana.sidecar.datasources.label }}: "1" - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - datasource.yaml: |- - apiVersion: 1 - datasources: -{{- if .Values.grafana.sidecar.datasources.defaultDatasourceEnabled }} - - name: Prometheus - type: prometheus - url: http://{{ template "kube-prometheus-stack.fullname" . }}-prometheus:{{ .Values.prometheus.service.port }}/{{ trimPrefix "/" .Values.prometheus.prometheusSpec.routePrefix }} - access: proxy - isDefault: true - jsonData: - timeInterval: {{ .Values.prometheus.prometheusSpec.scrapeInterval | default "30s" }} -{{- if .Values.grafana.sidecar.datasources.createPrometheusReplicasDatasources }} -{{- range until (int .Values.prometheus.prometheusSpec.replicas) }} - - name: Prometheus-{{ . }} - type: prometheus - url: http://prometheus-{{ template "kube-prometheus-stack.fullname" $ }}-prometheus-{{ . }}.prometheus-operated:9090/{{ trimPrefix "/" $.Values.prometheus.prometheusSpec.routePrefix }} - access: proxy - isDefault: false - jsonData: - timeInterval: {{ .Values.prometheus.prometheusSpec.scrapeInterval | default "30s" }} -{{- end }} -{{- end }} -{{- end }} -{{- if .Values.grafana.additionalDataSources }} -{{ tpl (toYaml .Values.grafana.additionalDataSources | indent 4) . }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/apiserver.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/apiserver.yaml deleted file mode 100644 index 1fa3a1935..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/apiserver.yaml +++ /dev/null @@ -1,1747 +0,0 @@ -{{- /* -Generated from 'apiserver' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.kubeApiServer.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "apiserver" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - apiserver.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "content": "The SLO (service level objective) and other metrics displayed on this dashboard are for informational purposes only.", - "datasource": null, - "description": "The SLO (service level objective) and other metrics displayed on this dashboard are for informational purposes only.", - "gridPos": { - "h": 2, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "mode": "markdown", - "span": 12, - "title": "Notice", - "type": "text" - } - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 3, - "description": "How many percent of requests (both read and write) in 30 days have been answered successfully and fast enough?", - "format": "percentunit", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "apiserver_request:availability30d{verb=\"all\", cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Availability (30d) > 99.000%", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": 3, - "description": "How much error budget is left looking at our 0.990% availability guarantees?", - "fill": 10, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 8, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "100 * (apiserver_request:availability30d{verb=\"all\", cluster=\"$cluster\"} - 0.990000)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "errorbudget", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "ErrorBudget (30d) > 99.000%", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "decimals": 3, - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "decimals": 3, - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 3, - "description": "How many percent of read requests (LIST,GET) in 30 days have been answered successfully and fast enough?", - "format": "percentunit", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "apiserver_request:availability30d{verb=\"read\", cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Read Availability (30d)", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "How many read requests (LIST,GET) per second do the apiservers get by code?", - "fill": 10, - "fillGradient": 0, - "gridPos": { - - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - { - "alias": "/2../i", - "color": "#56A64B" - }, - { - "alias": "/3../i", - "color": "#F2CC0C" - }, - { - "alias": "/4../i", - "color": "#3274D9" - }, - { - "alias": "/5../i", - "color": "#E02F44" - } - ], - "spaceLength": 10, - "span": 3, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (code) (code_resource:apiserver_request_total:rate5m{verb=\"read\", cluster=\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}} code {{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Read SLI - Requests", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "reqps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "reqps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "How many percent of read requests (LIST,GET) per second are returned with errors (5xx)?", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\"read\",code=~\"5..\", cluster=\"$cluster\"}) / sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\"read\", cluster=\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}} resource {{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Read SLI - Errors", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "How many seconds is the 99th percentile for reading (LIST|GET) a given resource?", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "cluster_quantile:apiserver_request_duration_seconds:histogram_quantile{verb=\"read\", cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}} resource {{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Read SLI - Duration", - "tooltip": { - "shared": false, - "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": "s", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 3, - "description": "How many percent of write requests (POST|PUT|PATCH|DELETE) in 30 days have been answered successfully and fast enough?", - "format": "percentunit", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 9, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "apiserver_request:availability30d{verb=\"write\", cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Write Availability (30d)", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "How many write requests (POST|PUT|PATCH|DELETE) per second do the apiservers get by code?", - "fill": 10, - "fillGradient": 0, - "gridPos": { - - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - { - "alias": "/2../i", - "color": "#56A64B" - }, - { - "alias": "/3../i", - "color": "#F2CC0C" - }, - { - "alias": "/4../i", - "color": "#3274D9" - }, - { - "alias": "/5../i", - "color": "#E02F44" - } - ], - "spaceLength": 10, - "span": 3, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (code) (code_resource:apiserver_request_total:rate5m{verb=\"write\", cluster=\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}} code {{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Write SLI - Requests", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "reqps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "reqps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "How many percent of write requests (POST|PUT|PATCH|DELETE) per second are returned with errors (5xx)?", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\"write\",code=~\"5..\", cluster=\"$cluster\"}) / sum by (resource) (code_resource:apiserver_request_total:rate5m{verb=\"write\", cluster=\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}} resource {{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Write SLI - Errors", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "How many seconds is the 99th percentile for writing (POST|PUT|PATCH|DELETE) a given resource?", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "cluster_quantile:apiserver_request_duration_seconds:histogram_quantile{verb=\"write\", cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}} resource {{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Write SLI - Duration", - "tooltip": { - "shared": false, - "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": "s", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(workqueue_adds_total{job=\"apiserver\", instance=~\"$instance\", cluster=\"$cluster\"}[5m])) by (instance, name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Work Queue Add Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 14, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(workqueue_depth{job=\"apiserver\", instance=~\"$instance\", cluster=\"$cluster\"}[5m])) by (instance, name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Work Queue Depth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 15, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(workqueue_queue_duration_seconds_bucket{job=\"apiserver\", instance=~\"$instance\", cluster=\"$cluster\"}[5m])) by (instance, name, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Work Queue Latency", - "tooltip": { - "shared": false, - "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": "s", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 16, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_resident_memory_bytes{job=\"apiserver\",instance=~\"$instance\", cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "shared": false, - "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": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 17, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{job=\"apiserver\",instance=~\"$instance\", cluster=\"$cluster\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 18, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_goroutines{job=\"apiserver\",instance=~\"$instance\", cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Goroutines", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(apiserver_request_total, cluster)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(apiserver_request_total{job=\"apiserver\", cluster=\"$cluster\"}, instance)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / API server", - "uid": "09ec8aa1e996d6ffcd6817bbaff4db1b", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/cluster-total.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/cluster-total.yaml deleted file mode 100644 index 93bf909d9..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/cluster-total.yaml +++ /dev/null @@ -1,1882 +0,0 @@ -{{- /* -Generated from 'cluster-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "cluster-total" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - cluster-total.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "columns": [ - { - "text": "Time", - "value": "Time" - }, - { - "text": "Value #A", - "value": "Value #A" - }, - { - "text": "Value #B", - "value": "Value #B" - }, - { - "text": "Value #C", - "value": "Value #C" - }, - { - "text": "Value #D", - "value": "Value #D" - }, - { - "text": "Value #E", - "value": "Value #E" - }, - { - "text": "Value #F", - "value": "Value #F" - }, - { - "text": "Value #G", - "value": "Value #G" - }, - { - "text": "Value #H", - "value": "Value #H" - }, - { - "text": "namespace", - "value": "namespace" - } - ], - "datasource": "$datasource", - "fill": 1, - "fontSize": "90%", - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null as zero", - "renderer": "flot", - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": false - }, - "spaceLength": 10, - "span": 24, - "styles": [ - { - "alias": "Time", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Time", - "thresholds": [ - - ], - "type": "hidden", - "unit": "short" - }, - { - "alias": "Current Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Average Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Average Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "d/8b7a8b326d7a6f1f04244066368c67af/kubernetes-networking-namespace-pods?orgId=1&refresh=30s&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Status", - "type": "table" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 6, - "panels": [ - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 7, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 8, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 11 - }, - "id": 9, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth History", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 12 - }, - "id": 10, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 21 - }, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 30 - }, - "id": 12, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 13, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 14, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 15, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 50 - }, - "id": 16, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 59 - }, - "id": 17, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\".+\"}[$interval:$resolution])) by (namespace))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 59 - }, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - { - "targetBlank": true, - "title": "What is TCP Retransmit?", - "url": "https://accedian.com/enterprises/blog/network-packet-loss-retransmissions-and-duplicate-acknowledgements/" - } - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(rate(node_netstat_Tcp_RetransSegs{cluster=\"$cluster\"}[$interval:$resolution]) / rate(node_netstat_Tcp_OutSegs{cluster=\"$cluster\"}[$interval:$resolution])) by (instance))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of TCP Retransmits out of all sent segments", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 59 - }, - "id": 19, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [ - { - "targetBlank": true, - "title": "Why monitor SYN retransmits?", - "url": "https://github.com/prometheus/node_exporter/issues/1023#issuecomment-408128365" - } - ], - "minSpan": 24, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(rate(node_netstat_TcpExt_TCPSynRetrans{cluster=\"$cluster\"}[$interval:$resolution]) / rate(node_netstat_Tcp_RetransSegs{cluster=\"$cluster\"}[$interval:$resolution])) by (instance))", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of TCP SYN Retransmits out of all retransmits", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Networking / Cluster", - "uid": "ff635a025bcfea7bc3dd4f508990a3e9", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/controller-manager.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/controller-manager.yaml deleted file mode 100644 index 76d561aed..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/controller-manager.yaml +++ /dev/null @@ -1,1151 +0,0 @@ -{{- /* -Generated from 'controller-manager' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.kubeControllerManager.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "controller-manager" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - controller-manager.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 2, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(up{job=\"kube-controller-manager\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Up", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(workqueue_adds_total{job=\"kube-controller-manager\", instance=~\"$instance\"}[5m])) by (instance, name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Work Queue Add Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(workqueue_depth{job=\"kube-controller-manager\", instance=~\"$instance\"}[5m])) by (instance, name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Work Queue Depth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 5, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(workqueue_queue_duration_seconds_bucket{job=\"kube-controller-manager\", instance=~\"$instance\"}[5m])) by (instance, name, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}name{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Work Queue Latency", - "tooltip": { - "shared": false, - "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": "s", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-controller-manager\", instance=~\"$instance\",code=~\"2..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "2xx", - "refId": "A" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-controller-manager\", instance=~\"$instance\",code=~\"3..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "3xx", - "refId": "B" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-controller-manager\", instance=~\"$instance\",code=~\"4..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "4xx", - "refId": "C" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-controller-manager\", instance=~\"$instance\",code=~\"5..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "5xx", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Kube API Request Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 8, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{job=\"kube-controller-manager\", instance=~\"$instance\", verb=\"POST\"}[5m])) by (verb, url, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Post Request Latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{job=\"kube-controller-manager\", instance=~\"$instance\", verb=\"GET\"}[5m])) by (verb, url, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Get Request Latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_resident_memory_bytes{job=\"kube-controller-manager\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "shared": false, - "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": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{job=\"kube-controller-manager\",instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_goroutines{job=\"kube-controller-manager\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Goroutines", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(process_cpu_seconds_total{job=\"kube-controller-manager\"}, instance)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Controller Manager", - "uid": "72e0e05bef5099e5f049b05fdc429ed4", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/etcd.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/etcd.yaml deleted file mode 100644 index 0595cb478..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/etcd.yaml +++ /dev/null @@ -1,1116 +0,0 @@ -{{- /* -Generated from 'etcd' from https://raw.githubusercontent.com/etcd-io/etcd/master/Documentation/op-guide/grafana.json -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.kubeEtcd.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "etcd" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - etcd.json: |- - { - "annotations": { - "list": [] - }, - "description": "etcd sample Grafana dashboard with Prometheus", - "editable": true, - "gnetId": null, - "hideControls": false, - "links": [], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "$datasource", - "editable": true, - "error": false, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 28, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum(etcd_server_has_leader{job=\"$cluster\"})", - "intervalFactor": 2, - "legendFormat": "", - "metric": "etcd_server_has_leader", - "refId": "A", - "step": 20 - } - ], - "thresholds": "", - "title": "Up", - "type": "singlestat", - "valueFontSize": "200%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 23, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 5, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(grpc_server_started_total{job=\"$cluster\",grpc_type=\"unary\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "RPC Rate", - "metric": "grpc_server_started_total", - "refId": "A", - "step": 2 - }, - { - "expr": "sum(rate(grpc_server_handled_total{job=\"$cluster\",grpc_type=\"unary\",grpc_code!=\"OK\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "RPC Failed Rate", - "metric": "grpc_server_handled_total", - "refId": "B", - "step": 2 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "RPC Rate", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 41, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 4, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(grpc_server_started_total{job=\"$cluster\",grpc_service=\"etcdserverpb.Watch\",grpc_type=\"bidi_stream\"}) - sum(grpc_server_handled_total{job=\"$cluster\",grpc_service=\"etcdserverpb.Watch\",grpc_type=\"bidi_stream\"})", - "intervalFactor": 2, - "legendFormat": "Watch Streams", - "metric": "grpc_server_handled_total", - "refId": "A", - "step": 4 - }, - { - "expr": "sum(grpc_server_started_total{job=\"$cluster\",grpc_service=\"etcdserverpb.Lease\",grpc_type=\"bidi_stream\"}) - sum(grpc_server_handled_total{job=\"$cluster\",grpc_service=\"etcdserverpb.Lease\",grpc_type=\"bidi_stream\"})", - "intervalFactor": 2, - "legendFormat": "Lease Streams", - "metric": "grpc_server_handled_total", - "refId": "B", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Active Streams", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "showTitle": false, - "title": "Row" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "decimals": null, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "etcd_mvcc_db_total_size_in_bytes{job=\"$cluster\"}", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} DB Size", - "metric": "", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "DB Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 4, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket{job=\"$cluster\"}[5m])) by (instance, le))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} WAL fsync", - "metric": "etcd_disk_wal_fsync_duration_seconds_bucket", - "refId": "A", - "step": 4 - }, - { - "expr": "histogram_quantile(0.99, sum(rate(etcd_disk_backend_commit_duration_seconds_bucket{job=\"$cluster\"}[5m])) by (instance, le))", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} DB fsync", - "metric": "etcd_disk_backend_commit_duration_seconds_bucket", - "refId": "B", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Sync Duration", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 29, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_resident_memory_bytes{job=\"$cluster\"}", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Resident Memory", - "metric": "process_resident_memory_bytes", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "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": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "title": "New row" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 5, - "id": 22, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 3, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "rate(etcd_network_client_grpc_received_bytes_total{job=\"$cluster\"}[5m])", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Client Traffic In", - "metric": "etcd_network_client_grpc_received_bytes_total", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Client Traffic In", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 5, - "id": 21, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 3, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "rate(etcd_network_client_grpc_sent_bytes_total{job=\"$cluster\"}[5m])", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Client Traffic Out", - "metric": "etcd_network_client_grpc_sent_bytes_total", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Client Traffic Out", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 20, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(etcd_network_peer_received_bytes_total{job=\"$cluster\"}[5m])) by (instance)", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Peer Traffic In", - "metric": "etcd_network_peer_received_bytes_total", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Peer Traffic In", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "decimals": null, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 16, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(etcd_network_peer_sent_bytes_total{job=\"$cluster\"}[5m])) by (instance)", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Peer Traffic Out", - "metric": "etcd_network_peer_sent_bytes_total", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Peer Traffic Out", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "title": "New row" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 40, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(etcd_server_proposals_failed_total{job=\"$cluster\"}[5m]))", - "intervalFactor": 2, - "legendFormat": "Proposal Failure Rate", - "metric": "etcd_server_proposals_failed_total", - "refId": "A", - "step": 2 - }, - { - "expr": "sum(etcd_server_proposals_pending{job=\"$cluster\"})", - "intervalFactor": 2, - "legendFormat": "Proposal Pending Total", - "metric": "etcd_server_proposals_pending", - "refId": "B", - "step": 2 - }, - { - "expr": "sum(rate(etcd_server_proposals_committed_total{job=\"$cluster\"}[5m]))", - "intervalFactor": 2, - "legendFormat": "Proposal Commit Rate", - "metric": "etcd_server_proposals_committed_total", - "refId": "C", - "step": 2 - }, - { - "expr": "sum(rate(etcd_server_proposals_applied_total{job=\"$cluster\"}[5m]))", - "intervalFactor": 2, - "legendFormat": "Proposal Apply Rate", - "refId": "D", - "step": 2 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Raft Proposals", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "decimals": 0, - "editable": true, - "error": false, - "fill": 0, - "id": 19, - "isNew": true, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "changes(etcd_server_leader_changes_seen_total{job=\"$cluster\"}[1d])", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Total Leader Elections Per Day", - "metric": "etcd_server_leader_changes_seen_total", - "refId": "A", - "step": 2 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Total Leader Elections Per Day", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "title": "New row" - } - ], - "schemaVersion": 13, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [], - "query": "label_values(etcd_server_has_leader, job)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "etcd", - "uid": "c2f4e12cdf69feb95caa41a5a1b423d9", - "version": 215 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-coredns.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-coredns.yaml deleted file mode 100644 index 3665b57ae..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-coredns.yaml +++ /dev/null @@ -1,1531 +0,0 @@ -{{- /* Added manually, can be changed in-place. */ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.coreDns.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-coredns" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-coredns.json: |- - { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "description": "A dashboard for the CoreDNS DNS server with updated metrics for version 1.7.0+. Based on the CoreDNS dashboard by buhay.", - "editable": true, - "gnetId": 12539, - "graphTooltip": 0, - "iteration": 1603798405693, - "links": [ - { - "icon": "external link", - "tags": [], - "targetBlank": true, - "title": "CoreDNS.io", - "type": "link", - "url": "https://coredns.io" - } - ], - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [], - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "total", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(coredns_dns_request_count_total{instance=~\"$instance\"}[5m])) by (proto) or\nsum(rate(coredns_dns_requests_total{instance=~\"$instance\"}[5m])) by (proto)", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}", - "refId": "A", - "step": 60 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Requests (total)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 0 - }, - "hiddenSeries": false, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "total", - "yaxis": 2 - }, - { - "alias": "other", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(coredns_dns_request_type_count_total{instance=~\"$instance\"}[5m])) by (type) or \nsum(rate(coredns_dns_requests_total{instance=~\"$instance\"}[5m])) by (type)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{type}}"}}", - "refId": "A", - "step": 60 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Requests (by qtype)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 0 - }, - "hiddenSeries": false, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "total", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(coredns_dns_request_count_total{instance=~\"$instance\"}[5m])) by (zone) or\nsum(rate(coredns_dns_requests_total{instance=~\"$instance\"}[5m])) by (zone)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{zone}}"}}", - "refId": "A", - "step": 60 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Requests (by zone)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 7 - }, - "hiddenSeries": false, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "total", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(coredns_dns_request_do_count_total{instance=~\"$instance\"}[5m])) or\nsum(rate(coredns_dns_do_requests_total{instance=~\"$instance\"}[5m]))", - "interval": "", - "intervalFactor": 2, - "legendFormat": "DO", - "refId": "A", - "step": 40 - }, - { - "expr": "sum(rate(coredns_dns_request_count_total{instance=~\"$instance\"}[5m])) or\nsum(rate(coredns_dns_requests_total{instance=~\"$instance\"}[5m]))", - "interval": "", - "intervalFactor": 2, - "legendFormat": "total", - "refId": "B", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Requests (DO bit)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 7 - }, - "hiddenSeries": false, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "tcp:90", - "yaxis": 2 - }, - { - "alias": "tcp:99 ", - "yaxis": 2 - }, - { - "alias": "tcp:50", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\"$instance\",proto=\"udp\"}[5m])) by (le,proto))", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:99 ", - "refId": "A", - "step": 60 - }, - { - "expr": "histogram_quantile(0.90, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\"$instance\",proto=\"udp\"}[5m])) by (le,proto))", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:90", - "refId": "B", - "step": 60 - }, - { - "expr": "histogram_quantile(0.50, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\"$instance\",proto=\"udp\"}[5m])) by (le,proto))", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:50", - "refId": "C", - "step": 60 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Requests (size, udp)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 7 - }, - "hiddenSeries": false, - "id": 12, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "tcp:90", - "yaxis": 1 - }, - { - "alias": "tcp:99 ", - "yaxis": 1 - }, - { - "alias": "tcp:50", - "yaxis": 1 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\"$instance\",proto=\"tcp\"}[5m])) by (le,proto))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:99 ", - "refId": "A", - "step": 60 - }, - { - "expr": "histogram_quantile(0.90, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\"$instance\",proto=\"tcp\"}[5m])) by (le,proto))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:90", - "refId": "B", - "step": 60 - }, - { - "expr": "histogram_quantile(0.50, sum(rate(coredns_dns_request_size_bytes_bucket{instance=~\"$instance\",proto=\"tcp\"}[5m])) by (le,proto))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:50", - "refId": "C", - "step": 60 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Requests (size,tcp)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 14 - }, - "hiddenSeries": false, - "id": 14, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(coredns_dns_response_rcode_count_total{instance=~\"$instance\"}[5m])) by (rcode) or\nsum(rate(coredns_dns_responses_total{instance=~\"$instance\"}[5m])) by (rcode)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{rcode}}"}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Responses (by rcode)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 14 - }, - "hiddenSeries": false, - "id": 32, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(coredns_dns_request_duration_seconds_bucket{instance=~\"$instance\"}[5m])) by (le, job))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "99%", - "refId": "A", - "step": 40 - }, - { - "expr": "histogram_quantile(0.90, sum(rate(coredns_dns_request_duration_seconds_bucket{instance=~\"$instance\"}[5m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "90%", - "refId": "B", - "step": 40 - }, - { - "expr": "histogram_quantile(0.50, sum(rate(coredns_dns_request_duration_seconds_bucket{instance=~\"$instance\"}[5m])) by (le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "50%", - "refId": "C", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Responses (duration)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 21 - }, - "hiddenSeries": false, - "id": 18, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "udp:50%", - "yaxis": 1 - }, - { - "alias": "tcp:50%", - "yaxis": 2 - }, - { - "alias": "tcp:90%", - "yaxis": 2 - }, - { - "alias": "tcp:99%", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\"$instance\",proto=\"udp\"}[5m])) by (le,proto)) ", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:99%", - "refId": "A", - "step": 40 - }, - { - "expr": "histogram_quantile(0.90, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\"$instance\",proto=\"udp\"}[5m])) by (le,proto)) ", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:90%", - "refId": "B", - "step": 40 - }, - { - "expr": "histogram_quantile(0.50, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\"$instance\",proto=\"udp\"}[5m])) by (le,proto)) ", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:50%", - "metric": "", - "refId": "C", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Responses (size, udp)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 21 - }, - "hiddenSeries": false, - "id": 20, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "udp:50%", - "yaxis": 1 - }, - { - "alias": "tcp:50%", - "yaxis": 1 - }, - { - "alias": "tcp:90%", - "yaxis": 1 - }, - { - "alias": "tcp:99%", - "yaxis": 1 - } - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\"$instance\",proto=\"tcp\"}[5m])) by (le,proto)) ", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:99%", - "refId": "A", - "step": 40 - }, - { - "expr": "histogram_quantile(0.90, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\"$instance\",proto=\"tcp\"}[5m])) by (le,proto)) ", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:90%", - "refId": "B", - "step": 40 - }, - { - "expr": "histogram_quantile(0.50, sum(rate(coredns_dns_response_size_bytes_bucket{instance=~\"$instance\",proto=\"tcp\"}[5m])) by (le, proto)) ", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{"{{proto}}"}}:50%", - "metric": "", - "refId": "C", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Responses (size, tcp)", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 28 - }, - "hiddenSeries": false, - "id": 22, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(coredns_cache_size{instance=~\"$instance\"}) by (type) or\nsum(coredns_cache_entries{instance=~\"$instance\"}) by (type)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{"{{type}}"}}", - "refId": "A", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Cache (size)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "decbytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fieldConfig": { - "defaults": { - "custom": {}, - "links": [] - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "grid": {}, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 28 - }, - "hiddenSeries": false, - "id": 24, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.2.0", - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "misses", - "yaxis": 2 - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(coredns_cache_hits_total{instance=~\"$instance\"}[5m])) by (type)", - "hide": false, - "intervalFactor": 2, - "legendFormat": "hits:{{"{{type}}"}}", - "refId": "A", - "step": 40 - }, - { - "expr": "sum(rate(coredns_cache_misses_total{instance=~\"$instance\"}[5m])) by (type)", - "hide": false, - "intervalFactor": 2, - "legendFormat": "misses", - "refId": "B", - "step": 40 - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Cache (hitrate)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": "10s", - "schemaVersion": 26, - "style": "dark", - "tags": [ - "dns", - "coredns" - ], - "templating": { - "list": [ - { - "current": { - "selected": true, - "text": "default", - "value": "default" - }, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "datasource", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "allValue": ".*", - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "definition": "label_values(up{job=\"coredns\"}, instance)", - "hide": 0, - "includeAll": true, - "label": "Instance", - "multi": false, - "name": "instance", - "options": [], - "query": "label_values(up{job=\"coredns\"}, instance)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 3, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "utc", - "title": "CoreDNS", - "uid": "vkQ0UHxik", - "version": 2 - } -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-cluster.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-cluster.yaml deleted file mode 100644 index b1aadb177..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-cluster.yaml +++ /dev/null @@ -1,2582 +0,0 @@ -{{- /* -Generated from 'k8s-resources-cluster' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-cluster" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-cluster.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "100px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 1, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "1 - avg(rate(node_cpu_seconds_total{mode=\"idle\", cluster=\"$cluster\"}[$__rate_interval]))", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable_cpu_cores{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Requests Commitment", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable_cpu_cores{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Limits Commitment", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "1 - sum(:node_memory_MemAvailable_bytes:sum{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable_memory_bytes{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable_memory_bytes{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Requests Commitment", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\"}) / sum(kube_node_status_allocatable_memory_bytes{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Limits Commitment", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Headlines", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workloads", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to workloads", - "linkUrl": "./d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(kube_pod_owner{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\"}) by (workload, namespace)) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", container!=\"\"}) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (w/o cache)", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workloads", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to workloads", - "linkUrl": "./d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(kube_pod_owner{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "count(avg(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\"}) by (workload, namespace)) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", container!=\"\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", container!=\"\"}) by (namespace) / sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", container!=\"\"}) by (namespace) / sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Requests by Namespace", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Requests", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 11, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Current Receive Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Transmit Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Network Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 12, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 14, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "avg(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Namespace: Received", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 15, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "avg(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Namespace: Transmitted", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 16, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 17, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 18, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 19, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=~\".+\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(node_cpu_seconds_total, cluster)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Compute Resources / Cluster", - "uid": "efa86fd1d0c121a26444b636a3f509a8", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml deleted file mode 100644 index 4694b5996..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-namespace.yaml +++ /dev/null @@ -1,2286 +0,0 @@ -{{- /* -Generated from 'k8s-resources-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-namespace" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-namespace.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "100px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation (from requests)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation (from limits)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_requests_memory_bytes{namespace=\"$namespace\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilization (from requests)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) / sum(kube_pod_container_resource_limits_memory_bytes{namespace=\"$namespace\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation (from limits)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Headlines", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "quota - requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - }, - { - "alias": "quota - limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "quota - requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - }, - { - "alias": "quota - limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (w/o cache)", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Usage (RSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Cache)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Swap)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(kube_pod_container_resource_requests_memory_bytes{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\", image!=\"\"}) by (pod) / sum(kube_pod_container_resource_limits_memory_bytes{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(container_memory_cache{cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sum(container_memory_swap{cluster=\"$cluster\", namespace=\"$namespace\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 9, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Current Receive Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Transmit Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Network Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 11, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 12, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 14, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 15, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Compute Resources / Namespace (Pods)", - "uid": "85a562078cdf77779eaa1add43ccec1e", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-node.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-node.yaml deleted file mode 100644 index b99e40ff1..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-node.yaml +++ /dev/null @@ -1,978 +0,0 @@ -{{- /* -Generated from 'k8s-resources-node' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-node" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-node.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", node=~\"$node\"}) by (pod) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", node=~\"$node\"}) by (pod) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\", container!=\"\"}) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (w/o cache)", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Usage (RSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Cache)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Swap)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod) / sum(kube_pod_container_resource_requests_memory_bytes{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_working_set_bytes{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod) / sum(kube_pod_container_resource_limits_memory_bytes{node=~\"$node\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_rss{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_cache{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_memory_swap{cluster=\"$cluster\", node=~\"$node\",container!=\"\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": true, - "name": "node", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, node)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Compute Resources / Node (Pods)", - "uid": "200ac8fdbfbb74b39aff88118e4d1c2c", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml deleted file mode 100644 index acee659c4..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-pod.yaml +++ /dev/null @@ -1,1772 +0,0 @@ -{{- /* -Generated from 'k8s-resources-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-pod" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-pod.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "requests", - "color": "#F2495C", - "fill": 0, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - }, - { - "alias": "limits", - "color": "#FF9830", - "fill": 0, - "hideTooltip": true, - "legend": true, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", cluster=\"$cluster\"}) by (container)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"})\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"})\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 2, - "legend": { - "avg": false, - "current": true, - "max": true, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(container_cpu_cfs_throttled_periods_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container!=\"\", cluster=\"$cluster\"}[5m])) by (container) /sum(increase(container_cpu_cfs_periods_total{namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container!=\"\", cluster=\"$cluster\"}[5m])) by (container)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 0.25, - "yaxis": "left" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Throttling", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Throttling", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Container", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "container", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - }, - { - "alias": "limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container!=\"\", image!=\"\"}) by (container)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"})\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"})\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Usage (RSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Cache)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Swap)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Container", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "container", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"POD\", container!=\"\", image!=\"\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", image!=\"\"}) by (container) / sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\", image!=\"\"}) by (container) / sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(container_memory_cache{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sum(container_memory_swap{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container != \"\", container != \"POD\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 11, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{namespace=~\"$namespace\", pod=~\"$pod\"}[$__rate_interval])) by (pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "pod", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\", namespace=\"$namespace\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Compute Resources / Pod", - "uid": "6581e46e4e5c7ba40a07646395ef7b23", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml deleted file mode 100644 index 0df1bea02..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-workload.yaml +++ /dev/null @@ -1,2034 +0,0 @@ -{{- /* -Generated from 'k8s-resources-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-workload" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-workload.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 5, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Current Receive Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Transmit Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Network Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(avg(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Pod: Received", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(avg(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Pod: Transmitted", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 11, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 12, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "workload", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\"}, workload)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\"}, workload_type)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Compute Resources / Workload", - "uid": "a164a7f0339f99e89cea5cb47e9be617", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml deleted file mode 100644 index 9ff5394fa..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/k8s-resources-workloads-namespace.yaml +++ /dev/null @@ -1,2195 +0,0 @@ -{{- /* -Generated from 'k8s-resources-workloads-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-workloads-namespace" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-workloads-namespace.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "quota - requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - }, - { - "alias": "quota - limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"requests.cpu\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"limits.cpu\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Running Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "./d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workload Type", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "workload_type", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}) by (workload, workload_type)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "quota - requests", - "color": "#F2495C", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - }, - { - "alias": "quota - limits", - "color": "#FF9830", - "dashes": true, - "fill": 0, - "hideTooltip": true, - "legend": false, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"requests.memory\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - requests", - "legendLink": null, - "step": 10 - }, - { - "expr": "scalar(kube_resourcequota{cluster=\"$cluster\", namespace=\"$namespace\", type=\"hard\",resource=\"limits.memory\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "quota - limits", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Running Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "./d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workload Type", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "workload_type", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}) by (workload, workload_type)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(\n container_memory_working_set_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container!=\"\", image!=\"\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n* on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=\"$namespace\", workload_type=\"$type\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 5, - "interval": "1m", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Current Receive Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Transmit Bandwidth", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTargetBlank": false, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$type", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workload Type", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "workload_type", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Network Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(avg(irate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Workload: Received", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(avg(irate(container_network_transmit_bytes_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Container Bandwidth by Workload: Transmitted", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 11, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 12, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 13, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\", namespace=~\"$namespace\"}[$__rate_interval])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\", namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "deployment", - "value": "deployment" - }, - "datasource": "$datasource", - "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\".+\"}, workload_type)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{namespace=~\"$namespace\", workload=~\".+\"}, workload_type)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Compute Resources / Namespace (Workloads)", - "uid": "a87fb0d919ec0ea5f6543124e16c42a5", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/kubelet.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/kubelet.yaml deleted file mode 100644 index 5f1b2a2f8..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/kubelet.yaml +++ /dev/null @@ -1,2533 +0,0 @@ -{{- /* -Generated from 'kubelet' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.kubelet.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "kubelet" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - kubelet.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 2, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(up{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Up", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kubelet_running_pods{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": "", - "title": "Running Pods", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 4, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kubelet_running_containers{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": "", - "title": "Running Container", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(volume_manager_total_volumes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\", state=\"actual_state_of_world\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": "", - "title": "Actual Volume Count", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 6, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(volume_manager_total_volumes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",state=\"desired_state_of_world\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": "", - "title": "Desired Volume Count", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 7, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(kubelet_node_config_error{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": "", - "title": "Config Error Count", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(kubelet_runtime_operations_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (operation_type, instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}operation_type{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Operation Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(kubelet_runtime_operations_errors_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance, operation_type)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}operation_type{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Operation Error Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 10, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(kubelet_runtime_operations_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance, operation_type, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}operation_type{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Operation duration 99th quantile", - "tooltip": { - "shared": false, - "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": "s", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(kubelet_pod_start_duration_seconds_count{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} pod", - "refId": "A" - }, - { - "expr": "sum(rate(kubelet_pod_worker_duration_seconds_count{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} worker", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Pod Start Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 12, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(kubelet_pod_start_duration_seconds_count{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} pod", - "refId": "A" - }, - { - "expr": "histogram_quantile(0.99, sum(rate(kubelet_pod_worker_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} worker", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Pod Start Duration", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 13, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(storage_operation_duration_seconds_count{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance, operation_name, volume_plugin)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}operation_name{{`}}`}} {{`{{`}}volume_plugin{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Storage Operation Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 14, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(storage_operation_errors_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance, operation_name, volume_plugin)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}operation_name{{`}}`}} {{`{{`}}volume_plugin{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Storage Operation Error Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 15, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(storage_operation_duration_seconds_bucket{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[5m])) by (instance, operation_name, volume_plugin, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}operation_name{{`}}`}} {{`{{`}}volume_plugin{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Storage Operation Duration 99th quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 16, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(kubelet_cgroup_manager_duration_seconds_count{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[5m])) by (instance, operation_type)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}operation_type{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Cgroup manager operation rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 17, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(kubelet_cgroup_manager_duration_seconds_bucket{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[5m])) by (instance, operation_type, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}operation_type{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Cgroup manager 99th quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "description": "Pod lifecycle event generator", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(kubelet_pleg_relist_duration_seconds_count{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[5m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "PLEG relist rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 19, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(kubelet_pleg_relist_interval_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "PLEG relist interval", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(kubelet_pleg_relist_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "PLEG relist duration", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 21, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",code=~\"2..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "2xx", - "refId": "A" - }, - { - "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",code=~\"3..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "3xx", - "refId": "B" - }, - { - "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",code=~\"4..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "4xx", - "refId": "C" - }, - { - "expr": "sum(rate(rest_client_requests_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\",code=~\"5..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "5xx", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "RPC Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\", instance=~\"$instance\"}[5m])) by (instance, verb, url, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Request duration 99th quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 23, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_resident_memory_bytes{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "shared": false, - "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": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 24, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 25, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_goroutines{cluster=\"$cluster\",job=\"kubelet\", metrics_path=\"/metrics\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Goroutines", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(kubelet_runtime_operations_total{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\"}, instance)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Kubelet", - "uid": "3138fa155d5915769fbded898ac09fd9", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/namespace-by-pod.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/namespace-by-pod.yaml deleted file mode 100644 index e814ba744..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/namespace-by-pod.yaml +++ /dev/null @@ -1,1464 +0,0 @@ -{{- /* -Generated from 'namespace-by-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "namespace-by-pod" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - namespace-by-pod.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 0, - "format": "time_series", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "height": 9, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "minSpan": 12, - "nullPointMode": "connected", - "nullText": null, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "max": 10000000000, - "min": 0, - "title": "$namespace", - "unit": "Bps" - }, - "mappings": [ - - ], - "override": { - - }, - "thresholds": [ - { - "color": "dark-green", - "index": 0, - "value": null - }, - { - "color": "dark-yellow", - "index": 1, - "value": 5000000000 - }, - { - "color": "dark-red", - "index": 2, - "value": 7000000000 - } - ], - "values": false - } - }, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 12, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution]))", - "format": "time_series", - "instant": null, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "type": "gauge", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 0, - "format": "time_series", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "height": 9, - "id": 4, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "minSpan": 12, - "nullPointMode": "connected", - "nullText": null, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "max": 10000000000, - "min": 0, - "title": "$namespace", - "unit": "Bps" - }, - "mappings": [ - - ], - "override": { - - }, - "thresholds": [ - { - "color": "dark-green", - "index": 0, - "value": null - }, - { - "color": "dark-yellow", - "index": 1, - "value": 5000000000 - }, - { - "color": "dark-red", - "index": 2, - "value": 7000000000 - } - ], - "values": false - } - }, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 12, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution]))", - "format": "time_series", - "instant": null, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "type": "gauge", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "columns": [ - { - "text": "Time", - "value": "Time" - }, - { - "text": "Value #A", - "value": "Value #A" - }, - { - "text": "Value #B", - "value": "Value #B" - }, - { - "text": "Value #C", - "value": "Value #C" - }, - { - "text": "Value #D", - "value": "Value #D" - }, - { - "text": "Value #E", - "value": "Value #E" - }, - { - "text": "Value #F", - "value": "Value #F" - }, - { - "text": "pod", - "value": "pod" - } - ], - "datasource": "$datasource", - "fill": 1, - "fontSize": "100%", - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null as zero", - "renderer": "flot", - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": false - }, - "spaceLength": 10, - "span": 24, - "styles": [ - { - "alias": "Time", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Time", - "thresholds": [ - - ], - "type": "hidden", - "unit": "short" - }, - { - "alias": "Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "d/7a18067ce943a40ae25454675c19ff5c/kubernetes-networking-pod?orgId=1&refresh=30s&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Status", - "type": "table" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 19 - }, - "id": 6, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 20 - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 20 - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 29 - }, - "id": 9, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 30 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 30 - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 30 - }, - "id": 12, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 40 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 40 - }, - "id": 14, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "kube-system", - "value": "kube-system" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Networking / Namespace (Pods)", - "uid": "8b7a8b326d7a6f1f04244066368c67af", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/namespace-by-workload.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/namespace-by-workload.yaml deleted file mode 100644 index a526290a7..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/namespace-by-workload.yaml +++ /dev/null @@ -1,1736 +0,0 @@ -{{- /* -Generated from 'namespace-by-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "namespace-by-workload" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - namespace-by-workload.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} workload {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} workload {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "columns": [ - { - "text": "Time", - "value": "Time" - }, - { - "text": "Value #A", - "value": "Value #A" - }, - { - "text": "Value #B", - "value": "Value #B" - }, - { - "text": "Value #C", - "value": "Value #C" - }, - { - "text": "Value #D", - "value": "Value #D" - }, - { - "text": "Value #E", - "value": "Value #E" - }, - { - "text": "Value #F", - "value": "Value #F" - }, - { - "text": "Value #G", - "value": "Value #G" - }, - { - "text": "Value #H", - "value": "Value #H" - }, - { - "text": "workload", - "value": "workload" - } - ], - "datasource": "$datasource", - "fill": 1, - "fontSize": "90%", - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null as zero", - "renderer": "flot", - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": false - }, - "spaceLength": 10, - "span": 24, - "styles": [ - { - "alias": "Time", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Time", - "thresholds": [ - - ], - "type": "hidden", - "unit": "short" - }, - { - "alias": "Current Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Current Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Average Bandwidth Received", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Average Bandwidth Transmitted", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "Bps" - }, - { - "alias": "Rate of Received Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Received Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Rate of Transmitted Packets Dropped", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "pps" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "d/728bf77cc1166d2f3133bf25846876cc/kubernetes-networking-workload?orgId=1&refresh=30s&var-namespace=$namespace&var-type=$type&var-workload=$__cell", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Status", - "type": "table" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 19 - }, - "id": 6, - "panels": [ - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 20 - }, - "id": 7, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} workload {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 20 - }, - "id": 8, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} workload {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 29 - }, - "id": 9, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth HIstory", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 38 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 38 - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 39 - }, - "id": 12, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 40 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 40 - }, - "id": 14, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 15, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 41 - }, - "id": 16, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 41 - }, - "id": 17, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\", workload_type=\"$type\"}) by (workload))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}workload{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "kube-system", - "value": "kube-system" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "deployment", - "value": "deployment" - }, - "datasource": "$datasource", - "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\"}, workload_type)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\".+\"}, workload_type)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Networking / Namespace (Workload)", - "uid": "bbb2a765a623ae38130206c7d94a160f", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/node-cluster-rsrc-use.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/node-cluster-rsrc-use.yaml deleted file mode 100644 index 82b821a7a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/node-cluster-rsrc-use.yaml +++ /dev/null @@ -1,964 +0,0 @@ -{{- /* -Generated from 'node-cluster-rsrc-use' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.nodeExporter.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "node-cluster-rsrc-use" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - node-cluster-rsrc-use.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(\n instance:node_cpu_utilisation:rate1m{job=\"node-exporter\"}\n*\n instance:node_num_cpu:sum{job=\"node-exporter\"}\n)\n/ scalar(sum(instance:node_num_cpu:sum{job=\"node-exporter\"}))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_load1_per_cpu:ratio{job=\"node-exporter\"}\n/ scalar(count(instance:node_load1_per_cpu:ratio{job=\"node-exporter\"}))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Saturation (load1 per CPU)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_memory_utilisation:ratio{job=\"node-exporter\"}\n/ scalar(count(instance:node_memory_utilisation:ratio{job=\"node-exporter\"}))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_vmstat_pgmajfault:rate1m{job=\"node-exporter\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Saturation (Major Page Faults)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "rps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "/ Receive/", - "stack": "A" - }, - { - "alias": "/ Transmit/", - "stack": "B", - "transform": "negative-Y" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_network_receive_bytes_excluding_lo:rate1m{job=\"node-exporter\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Receive", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - }, - { - "expr": "instance:node_network_transmit_bytes_excluding_lo:rate1m{job=\"node-exporter\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Transmit", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Net Utilisation (Bytes Receive/Transmit)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "/ Receive/", - "stack": "A" - }, - { - "alias": "/ Transmit/", - "stack": "B", - "transform": "negative-Y" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_network_receive_drop_excluding_lo:rate1m{job=\"node-exporter\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Receive", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - }, - { - "expr": "instance:node_network_transmit_drop_excluding_lo:rate1m{job=\"node-exporter\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Transmit", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Net Saturation (Drops Receive/Transmit)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "rps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "instance_device:node_disk_io_time_seconds:rate1m{job=\"node-exporter\"}\n/ scalar(count(instance_device:node_disk_io_time_seconds:rate1m{job=\"node-exporter\"}))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}device{{`}}`}}", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "instance_device:node_disk_io_time_weighted_seconds:rate1m{job=\"node-exporter\"}\n/ scalar(count(instance_device:node_disk_io_time_weighted_seconds:rate1m{job=\"node-exporter\"}))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} {{`{{`}}device{{`}}`}}", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Saturation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Disk IO", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum without (device) (\n max without (fstype, mountpoint) (\n node_filesystem_size_bytes{job=\"node-exporter\", fstype!=\"\"} - node_filesystem_avail_bytes{job=\"node-exporter\", fstype!=\"\"}\n )\n) \n/ scalar(sum(max without (fstype, mountpoint) (node_filesystem_size_bytes{job=\"node-exporter\", fstype!=\"\"})))\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "legendLink": "/dashboard/file/node-rsrc-use.json", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk Space Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Disk Space", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "USE Method / Cluster", - "uid": "3e97d1d02672cdd0861f4c97c64f89b2", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/node-rsrc-use.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/node-rsrc-use.yaml deleted file mode 100644 index 9cdfa645e..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/node-rsrc-use.yaml +++ /dev/null @@ -1,991 +0,0 @@ -{{- /* -Generated from 'node-rsrc-use' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.nodeExporter.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "node-rsrc-use" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - node-rsrc-use.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_cpu_utilisation:rate1m{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Utilisation", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_load1_per_cpu:ratio{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Saturation", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Saturation (Load1 per CPU)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_memory_utilisation:ratio{job=\"node-exporter\", job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Memory", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_vmstat_pgmajfault:rate1m{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Major page faults", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Saturation (Major Page Faults)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "/Receive/", - "stack": "A" - }, - { - "alias": "/Transmit/", - "stack": "B", - "transform": "negative-Y" - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_network_receive_bytes_excluding_lo:rate1m{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Receive", - "legendLink": null, - "step": 10 - }, - { - "expr": "instance:node_network_transmit_bytes_excluding_lo:rate1m{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Transmit", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Net Utilisation (Bytes Receive/Transmit)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "/Receive/", - "stack": "A" - }, - { - "alias": "/Transmit/", - "stack": "B", - "transform": "negative-Y" - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "instance:node_network_receive_drop_excluding_lo:rate1m{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Receive drops", - "legendLink": null, - "step": 10 - }, - { - "expr": "instance:node_network_transmit_drop_excluding_lo:rate1m{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Transmit drops", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Net Saturation (Drops Receive/Transmit)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "rps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Net", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "instance_device:node_disk_io_time_seconds:rate1m{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "instance_device:node_disk_io_time_weighted_seconds:rate1m{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Saturation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Disk IO", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "1 -\n(\n max without (mountpoint, fstype) (node_filesystem_avail_bytes{job=\"node-exporter\", fstype!=\"\", instance=\"$instance\"})\n/\n max without (mountpoint, fstype) (node_filesystem_size_bytes{job=\"node-exporter\", fstype!=\"\", instance=\"$instance\"})\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk Space Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Disk Space", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "instance", - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(up{job=\"node-exporter\"}, instance)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "USE Method / Node", - "uid": "fac67cfbe174d3ef53eb473d73d9212f", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/nodes.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/nodes.yaml deleted file mode 100644 index b2935aee4..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/nodes.yaml +++ /dev/null @@ -1,1001 +0,0 @@ -{{- /* -Generated from 'nodes' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "nodes" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - nodes.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 2, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(\n (1 - rate(node_cpu_seconds_total{job=\"node-exporter\", mode=\"idle\", instance=\"$instance\"}[$__interval]))\n/ ignoring(cpu) group_left\n count without (cpu)( node_cpu_seconds_total{job=\"node-exporter\", mode=\"idle\", instance=\"$instance\"})\n)\n", - "format": "time_series", - "interval": "1m", - "intervalFactor": 5, - "legendFormat": "{{`{{`}}cpu{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 0, - "fillGradient": 0, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node_load1{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "1m load average", - "refId": "A" - }, - { - "expr": "node_load5{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "5m load average", - "refId": "B" - }, - { - "expr": "node_load15{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "15m load average", - "refId": "C" - }, - { - "expr": "count(node_cpu_seconds_total{job=\"node-exporter\", instance=\"$instance\", mode=\"idle\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "logical cores", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Load Average", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(\n node_memory_MemTotal_bytes{job=\"node-exporter\", instance=\"$instance\"}\n-\n node_memory_MemFree_bytes{job=\"node-exporter\", instance=\"$instance\"}\n-\n node_memory_Buffers_bytes{job=\"node-exporter\", instance=\"$instance\"}\n-\n node_memory_Cached_bytes{job=\"node-exporter\", instance=\"$instance\"}\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "memory used", - "refId": "A" - }, - { - "expr": "node_memory_Buffers_bytes{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "refId": "B" - }, - { - "expr": "node_memory_Cached_bytes{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "memory cached", - "refId": "C" - }, - { - "expr": "node_memory_MemFree_bytes{job=\"node-exporter\", instance=\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "memory free", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "100 -\n(\n avg(node_memory_MemAvailable_bytes{job=\"node-exporter\", instance=\"$instance\"})\n/\n avg(node_memory_MemTotal_bytes{job=\"node-exporter\", instance=\"$instance\"})\n* 100\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Memory Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 0, - "fillGradient": 0, - "gridPos": { - - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - { - "alias": "/ read| written/", - "yaxis": 1 - }, - { - "alias": "/ io time/", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_disk_read_bytes_total{job=\"node-exporter\", instance=\"$instance\", device=~\"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+\"}[$__interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}} read", - "refId": "A" - }, - { - "expr": "rate(node_disk_written_bytes_total{job=\"node-exporter\", instance=\"$instance\", device=~\"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+\"}[$__interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}} written", - "refId": "B" - }, - { - "expr": "rate(node_disk_io_time_seconds_total{job=\"node-exporter\", instance=\"$instance\", device=~\"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+\"}[$__interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}} io time", - "refId": "C" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "shared": false, - "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": "s", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - { - "alias": "used", - "color": "#E0B400" - }, - { - "alias": "available", - "color": "#73BF69" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n max by (device) (\n node_filesystem_size_bytes{job=\"node-exporter\", instance=\"$instance\", fstype!=\"\"}\n -\n node_filesystem_avail_bytes{job=\"node-exporter\", instance=\"$instance\", fstype!=\"\"}\n )\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "used", - "refId": "A" - }, - { - "expr": "sum(\n max by (device) (\n node_filesystem_avail_bytes{job=\"node-exporter\", instance=\"$instance\", fstype!=\"\"}\n )\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "available", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk Space Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 0, - "fillGradient": 0, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_network_receive_bytes_total{job=\"node-exporter\", instance=\"$instance\", device!=\"lo\"}[$__interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Network Received", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 0, - "fillGradient": 0, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_network_transmit_bytes_total{job=\"node-exporter\", instance=\"$instance\", device!=\"lo\"}[$__interval])", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Network Transmitted", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(node_exporter_build_info{job=\"node-exporter\"}, instance)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Nodes", - "uid": "fa49a4706d07a042595b664c87fb33ea", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml deleted file mode 100644 index 4ac20ce6a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/persistentvolumesusage.yaml +++ /dev/null @@ -1,577 +0,0 @@ -{{- /* -Generated from 'persistentvolumesusage' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "persistentvolumesusage" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - persistentvolumesusage.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(\n sum without(instance, node) (kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n -\n sum without(instance, node) (kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n)\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used Space", - "refId": "A" - }, - { - "expr": "sum without(instance, node) (kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Free Space", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Volume Space Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(\n kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n -\n kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n)\n/\nkubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n* 100\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Volume Space Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum without(instance, node) (kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used inodes", - "refId": "A" - }, - { - "expr": "(\n sum without(instance, node) (kubelet_volume_stats_inodes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n -\n sum without(instance, node) (kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n)\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": " Free inodes", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Volume inodes Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n/\nkubelet_volume_stats_inodes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n* 100\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Volume inodes Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kubelet_volume_stats_capacity_bytes, cluster)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "PersistentVolumeClaim", - "multi": false, - "name": "volume", - "options": [ - - ], - "query": "label_values(kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", metrics_path=\"/metrics\", namespace=\"$namespace\"}, persistentvolumeclaim)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-7d", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Persistent Volumes", - "uid": "919b92a8e8041bd567af9edab12c840c", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/pod-total.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/pod-total.yaml deleted file mode 100644 index 76c2c6e08..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/pod-total.yaml +++ /dev/null @@ -1,1228 +0,0 @@ -{{- /* -Generated from 'pod-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "pod-total" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - pod-total.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 0, - "format": "time_series", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "height": 9, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "minSpan": 12, - "nullPointMode": "connected", - "nullText": null, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "max": 10000000000, - "min": 0, - "title": "$namespace: $pod", - "unit": "Bps" - }, - "mappings": [ - - ], - "override": { - - }, - "thresholds": [ - { - "color": "dark-green", - "index": 0, - "value": null - }, - { - "color": "dark-yellow", - "index": 1, - "value": 5000000000 - }, - { - "color": "dark-red", - "index": 2, - "value": 7000000000 - } - ], - "values": false - } - }, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 12, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution]))", - "format": "time_series", - "instant": null, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "type": "gauge", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "decimals": 0, - "format": "time_series", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "height": 9, - "id": 4, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "minSpan": 12, - "nullPointMode": "connected", - "nullText": null, - "options": { - "fieldOptions": { - "calcs": [ - "last" - ], - "defaults": { - "max": 10000000000, - "min": 0, - "title": "$namespace: $pod", - "unit": "Bps" - }, - "mappings": [ - - ], - "override": { - - }, - "thresholds": [ - { - "color": "dark-green", - "index": 0, - "value": null - }, - { - "color": "dark-yellow", - "index": 1, - "value": 5000000000 - }, - { - "color": "dark-red", - "index": 2, - "value": 7000000000 - } - ], - "values": false - } - }, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 12, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution]))", - "format": "time_series", - "instant": null, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "type": "gauge", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 20 - }, - "id": 8, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 21 - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 21 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 21 - }, - "id": 11, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 32 - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 32 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\", pod=~\"$pod\"}[$interval:$resolution])) by (pod)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "kube-system", - "value": "kube-system" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}, pod)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "pod", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}, pod)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Networking / Pod", - "uid": "7a18067ce943a40ae25454675c19ff5c", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml deleted file mode 100644 index 950443a15..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/prometheus-remote-write.yaml +++ /dev/null @@ -1,1670 +0,0 @@ -{{- /* -Generated from 'prometheus-remote-write' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.prometheus.prometheusSpec.remoteWriteDashboards }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "prometheus-remote-write" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - prometheus-remote-write.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 2, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(\n prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"} \n- \n ignoring(remote_name, url) group_right(instance) prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Highest Timestamp In vs. Highest Timestamp Sent", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(\n rate(prometheus_remote_storage_highest_timestamp_in_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m]) \n- \n ignoring (remote_name, url) group_right(instance) rate(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate[5m]", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Timestamps", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(\n prometheus_remote_storage_samples_in_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n- \n ignoring(remote_name, url) group_right(instance) rate(prometheus_remote_storage_succeeded_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n- \n rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate, in vs. succeeded or dropped [5m]", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Samples", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 5, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "minSpan": 6, - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Shards", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shards_max{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Max Shards", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shards_min{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Min Shards", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shards_desired{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Desired Shards", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Shards", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_shard_capacity{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Shard Capacity", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_remote_storage_pending_samples{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Pending Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Shard Details", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_tsdb_wal_segment_current{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "TSDB Current Segment", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_wal_watcher_current_segment{cluster=~\"$cluster\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}consumer{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Remote Write Current Segment", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Segments", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_remote_storage_dropped_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Dropped Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 14, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_remote_storage_failed_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Failed Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 15, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_remote_storage_retried_samples_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Retried Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 16, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_remote_storage_enqueue_retries_total{cluster=~\"$cluster\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cluster{{`}}`}}:{{`{{`}}instance{{`}}`}} {{`{{`}}remote_name{{`}}`}}:{{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Enqueue Retries", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Misc. Rates", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - - ], - "templating": { - "list": [ - { - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "value": { - "selected": true, - "text": "All", - "value": "$__all" - } - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(prometheus_build_info, instance)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "value": { - "selected": true, - "text": "All", - "value": "$__all" - } - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": true, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_container_info{image=~\".*prometheus.*\"}, cluster)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "url", - "options": [ - - ], - "query": "label_values(prometheus_remote_storage_shards{cluster=~\"$cluster\", instance=~\"$instance\"}, url)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Prometheus Remote Write", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/prometheus.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/prometheus.yaml deleted file mode 100644 index dfd3f3df0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/prometheus.yaml +++ /dev/null @@ -1,1227 +0,0 @@ -{{- /* -Generated from 'prometheus' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "prometheus" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - prometheus.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Count", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "hidden", - "unit": "short" - }, - { - "alias": "Uptime", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Instance", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "instance", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Job", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "job", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Version", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTargetBlank": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "version", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count by (job, instance, version) (prometheus_build_info{job=~\"$job\", instance=~\"$instance\"})", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "max by (job, instance) (time() - process_start_time_seconds{job=~\"$job\", instance=~\"$instance\"})", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Prometheus Stats", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Prometheus Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(prometheus_target_sync_length_seconds_sum{job=~\"$job\",instance=~\"$instance\"}[5m])) by (scrape_job) * 1e3", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}scrape_job{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Target Sync", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(prometheus_sd_discovered_targets{job=~\"$job\",instance=~\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Targets", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Targets", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Discovery", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_target_interval_length_seconds_sum{job=~\"$job\",instance=~\"$instance\"}[5m]) / rate(prometheus_target_interval_length_seconds_count{job=~\"$job\",instance=~\"$instance\"}[5m]) * 1e3", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}interval{{`}}`}} configured", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Scrape Interval Duration", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_exceeded_sample_limit_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "exceeded sample limit: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_duplicate_timestamp_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "duplicate timestamp: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_out_of_bounds_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "out of bounds: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum by (job) (rate(prometheus_target_scrapes_sample_out_of_order_total[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "out of order: {{`{{`}}job{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Scrape failures", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_tsdb_head_samples_appended_total{job=~\"$job\",instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Appended Samples", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Retrieval", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_tsdb_head_series{job=~\"$job\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head series", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Head Series", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "prometheus_tsdb_head_chunks{job=~\"$job\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}} head chunks", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Head Chunks", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "rate(prometheus_engine_query_duration_seconds_count{job=~\"$job\",instance=~\"$instance\",slice=\"inner_eval\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}job{{`}}`}} {{`{{`}}instance{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Query Rate", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "max by (slice) (prometheus_engine_query_duration_seconds{quantile=\"0.9\",job=~\"$job\",instance=~\"$instance\"}) * 1e3", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}slice{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Stage Duration", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Query", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": "job", - "multi": true, - "name": "job", - "options": [ - - ], - "query": "label_values(prometheus_build_info, job)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": "instance", - "multi": true, - "name": "instance", - "options": [ - - ], - "query": "label_values(prometheus_build_info, instance)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "utc", - "title": "Prometheus Overview", - "uid": "", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/proxy.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/proxy.yaml deleted file mode 100644 index 8c6b77c09..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/proxy.yaml +++ /dev/null @@ -1,1231 +0,0 @@ -{{- /* -Generated from 'proxy' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.kubeProxy.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "proxy" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - proxy.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 2, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(up{job=\"kube-proxy\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Up", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 5, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(kubeproxy_sync_proxy_rules_duration_seconds_count{job=\"kube-proxy\", instance=~\"$instance\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "rate", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rules Sync Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 5, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99,rate(kubeproxy_sync_proxy_rules_duration_seconds_bucket{job=\"kube-proxy\", instance=~\"$instance\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rule Sync Latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 5, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(kubeproxy_network_programming_duration_seconds_count{job=\"kube-proxy\", instance=~\"$instance\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "rate", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Network Programming Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 6, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(kubeproxy_network_programming_duration_seconds_bucket{job=\"kube-proxy\", instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Network Programming Latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-proxy\", instance=~\"$instance\",code=~\"2..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "2xx", - "refId": "A" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-proxy\", instance=~\"$instance\",code=~\"3..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "3xx", - "refId": "B" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-proxy\", instance=~\"$instance\",code=~\"4..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "4xx", - "refId": "C" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-proxy\", instance=~\"$instance\",code=~\"5..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "5xx", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Kube API Request Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 8, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{job=\"kube-proxy\",instance=~\"$instance\",verb=\"POST\"}[5m])) by (verb, url, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Post Request Latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{job=\"kube-proxy\", instance=~\"$instance\", verb=\"GET\"}[5m])) by (verb, url, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Get Request Latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_resident_memory_bytes{job=\"kube-proxy\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "shared": false, - "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": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{job=\"kube-proxy\",instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_goroutines{job=\"kube-proxy\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Goroutines", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(kubeproxy_network_programming_duration_seconds_bucket{job=\"kube-proxy\"}, instance)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Proxy", - "uid": "632e265de029684c40b21cb76bca4f94", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/scheduler.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/scheduler.yaml deleted file mode 100644 index 860fdc8bb..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/scheduler.yaml +++ /dev/null @@ -1,1074 +0,0 @@ -{{- /* -Generated from 'scheduler' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.kubeScheduler.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "scheduler" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - scheduler.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 2, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(up{job=\"kube-scheduler\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Up", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "min" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 5, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(scheduler_e2e_scheduling_duration_seconds_count{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} e2e", - "refId": "A" - }, - { - "expr": "sum(rate(scheduler_binding_duration_seconds_count{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} binding", - "refId": "B" - }, - { - "expr": "sum(rate(scheduler_scheduling_algorithm_duration_seconds_count{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} scheduling algorithm", - "refId": "C" - }, - { - "expr": "sum(rate(scheduler_volume_scheduling_duration_seconds_count{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])) by (instance)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} volume", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Scheduling Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 5, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job=\"kube-scheduler\",instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} e2e", - "refId": "A" - }, - { - "expr": "histogram_quantile(0.99, sum(rate(scheduler_binding_duration_seconds_bucket{job=\"kube-scheduler\",instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} binding", - "refId": "B" - }, - { - "expr": "histogram_quantile(0.99, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job=\"kube-scheduler\",instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} scheduling algorithm", - "refId": "C" - }, - { - "expr": "histogram_quantile(0.99, sum(rate(scheduler_volume_scheduling_duration_seconds_bucket{job=\"kube-scheduler\",instance=~\"$instance\"}[5m])) by (instance, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} volume", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Scheduling latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 5, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-scheduler\", instance=~\"$instance\",code=~\"2..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "2xx", - "refId": "A" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-scheduler\", instance=~\"$instance\",code=~\"3..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "3xx", - "refId": "B" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-scheduler\", instance=~\"$instance\",code=~\"4..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "4xx", - "refId": "C" - }, - { - "expr": "sum(rate(rest_client_requests_total{job=\"kube-scheduler\", instance=~\"$instance\",code=~\"5..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "5xx", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Kube API Request Rate", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 8, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{job=\"kube-scheduler\", instance=~\"$instance\", verb=\"POST\"}[5m])) by (verb, url, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Post Request Latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 7, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(rest_client_request_duration_seconds_bucket{job=\"kube-scheduler\", instance=~\"$instance\", verb=\"GET\"}[5m])) by (verb, url, le))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}verb{{`}}`}} {{`{{`}}url{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Get Request Latency 99th Quantile", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "s", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_resident_memory_bytes{job=\"kube-scheduler\", instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "shared": false, - "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": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(process_cpu_seconds_total{job=\"kube-scheduler\", instance=~\"$instance\"}[5m])", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_goroutines{job=\"kube-scheduler\",instance=~\"$instance\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Goroutines", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(process_cpu_seconds_total{job=\"kube-scheduler\"}, instance)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Scheduler", - "uid": "2e6b6a3b4bddf1427b3a55aa1311c656", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/statefulset.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/statefulset.yaml deleted file mode 100644 index 9b3ce7d64..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/statefulset.yaml +++ /dev/null @@ -1,928 +0,0 @@ -{{- /* -Generated from 'statefulset' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "statefulset" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - statefulset.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 2, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", container!=\"\", namespace=\"$namespace\", pod=~\"$statefulset.*\"}[3m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "CPU", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "GB", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", container!=\"\", namespace=\"$namespace\", pod=~\"$statefulset.*\"}) / 1024^3", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Memory", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 4, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "Bps", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\", pod=~\"$statefulset.*\"}[3m])) + sum(rate(container_network_receive_bytes_total{job=\"kubelet\", metrics_path=\"/metrics/cadvisor\", cluster=\"$cluster\", namespace=\"$namespace\",pod=~\"$statefulset.*\"}[3m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Network", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "height": "100px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_replicas{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Desired Replicas", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 6, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "min(kube_statefulset_status_replicas_current{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Replicas of current version", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 7, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_status_observed_generation{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Observed Generation", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 8, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_metadata_generation{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Metadata Generation", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(kube_statefulset_replicas{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "replicas specified", - "refId": "A" - }, - { - "expr": "max(kube_statefulset_status_replicas{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "replicas created", - "refId": "B" - }, - { - "expr": "min(kube_statefulset_status_replicas_ready{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "ready", - "refId": "C" - }, - { - "expr": "min(kube_statefulset_status_replicas_current{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "replicas of current version", - "refId": "D" - }, - { - "expr": "min(kube_statefulset_status_replicas_updated{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "updated", - "refId": "E" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Replicas", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_statefulset_metadata_generation, cluster)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_statefulset_metadata_generation{job=\"kube-state-metrics\", cluster=\"$cluster\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Name", - "multi": false, - "name": "statefulset", - "options": [ - - ], - "query": "label_values(kube_statefulset_metadata_generation{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\"}, statefulset)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / StatefulSets", - "uid": "a31c1f46e6f727cb37c0d731a7245005", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/workload-total.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/workload-total.yaml deleted file mode 100644 index 08d8cfdae..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards-1.14/workload-total.yaml +++ /dev/null @@ -1,1438 +0,0 @@ -{{- /* -Generated from 'workload-total' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "workload-total" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - workload-total.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "panels": [ - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 2, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Current Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} pod {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} pod {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Current Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 5, - "panels": [ - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 6, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} pod {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Received", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 7, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [ - - ], - "minSpan": 24, - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 24, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(avg(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}} pod {{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Average Rate of Bytes Transmitted", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "series", - "name": null, - "show": false, - "values": [ - "current" - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Average Bandwidth", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 11 - }, - "id": 8, - "panels": [ - - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Bandwidth HIstory", - "titleSize": "h6", - "type": "row" - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 12 - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Receive Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 12 - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_bytes_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Transmit Bandwidth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 21 - }, - "id": 11, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 22 - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 22 - }, - "id": 13, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Packets", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": true, - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 22 - }, - "id": 14, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 23 - }, - "id": 15, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_receive_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Received Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 2, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 23 - }, - "id": 16, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [ - - ], - "minSpan": 12, - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum(irate(container_network_transmit_packets_dropped_total{cluster=\"$cluster\",namespace=~\"$namespace\"}[$interval:$resolution])\n* on (namespace,pod)\ngroup_left(workload,workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\", workload_type=\"$type\"}) by (pod))\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "refId": "A", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Rate of Transmitted Packets Dropped", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "pps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Errors", - "titleSize": "h6", - "type": "row" - } - ], - "refresh": "10s", - "rows": [ - - ], - "schemaVersion": 18, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "default", - "value": "default" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "kube-system", - "value": "kube-system" - }, - "datasource": "$datasource", - "definition": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(container_network_receive_packets_total{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "", - "value": "" - }, - "datasource": "$datasource", - "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\"}, workload)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "workload", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\"}, workload)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "deployment", - "value": "deployment" - }, - "datasource": "$datasource", - "definition": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(namespace_workload_pod:kube_pod_owner:relabel{cluster=\"$cluster\",namespace=~\"$namespace\", workload=~\"$workload\"}, workload_type)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "resolution", - "options": [ - { - "selected": false, - "text": "30s", - "value": "30s" - }, - { - "selected": true, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - } - ], - "query": "30s,5m,1h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - }, - { - "allValue": null, - "auto": false, - "auto_count": 30, - "auto_min": "10s", - "current": { - "text": "5m", - "value": "5m" - }, - "datasource": "$datasource", - "hide": 2, - "includeAll": false, - "label": null, - "multi": false, - "name": "interval", - "options": [ - { - "selected": true, - "text": "4h", - "value": "4h" - } - ], - "query": "4h", - "refresh": 2, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "interval", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "UTC", - "title": "Kubernetes / Networking / Workload", - "uid": "728bf77cc1166d2f3133bf25846876cc", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/etcd.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/etcd.yaml deleted file mode 100644 index 835a69013..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/etcd.yaml +++ /dev/null @@ -1,1116 +0,0 @@ -{{- /* -Generated from 'etcd' from https://raw.githubusercontent.com/etcd-io/etcd/master/Documentation/op-guide/grafana.json -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled .Values.kubeEtcd.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "etcd" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - etcd.json: |- - { - "annotations": { - "list": [] - }, - "description": "etcd sample Grafana dashboard with Prometheus", - "editable": true, - "gnetId": null, - "hideControls": false, - "links": [], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "$datasource", - "editable": true, - "error": false, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 28, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum(etcd_server_has_leader{job=\"$cluster\"})", - "intervalFactor": 2, - "legendFormat": "", - "metric": "etcd_server_has_leader", - "refId": "A", - "step": 20 - } - ], - "thresholds": "", - "title": "Up", - "type": "singlestat", - "valueFontSize": "200%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 23, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 5, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(grpc_server_started_total{job=\"$cluster\",grpc_type=\"unary\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "RPC Rate", - "metric": "grpc_server_started_total", - "refId": "A", - "step": 2 - }, - { - "expr": "sum(rate(grpc_server_handled_total{job=\"$cluster\",grpc_type=\"unary\",grpc_code!=\"OK\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "RPC Failed Rate", - "metric": "grpc_server_handled_total", - "refId": "B", - "step": 2 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "RPC Rate", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ops", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 41, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 4, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(grpc_server_started_total{job=\"$cluster\",grpc_service=\"etcdserverpb.Watch\",grpc_type=\"bidi_stream\"}) - sum(grpc_server_handled_total{job=\"$cluster\",grpc_service=\"etcdserverpb.Watch\",grpc_type=\"bidi_stream\"})", - "intervalFactor": 2, - "legendFormat": "Watch Streams", - "metric": "grpc_server_handled_total", - "refId": "A", - "step": 4 - }, - { - "expr": "sum(grpc_server_started_total{job=\"$cluster\",grpc_service=\"etcdserverpb.Lease\",grpc_type=\"bidi_stream\"}) - sum(grpc_server_handled_total{job=\"$cluster\",grpc_service=\"etcdserverpb.Lease\",grpc_type=\"bidi_stream\"})", - "intervalFactor": 2, - "legendFormat": "Lease Streams", - "metric": "grpc_server_handled_total", - "refId": "B", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Active Streams", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "showTitle": false, - "title": "Row" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "decimals": null, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "etcd_mvcc_db_total_size_in_bytes{job=\"$cluster\"}", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} DB Size", - "metric": "", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "DB Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 4, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket{job=\"$cluster\"}[5m])) by (instance, le))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} WAL fsync", - "metric": "etcd_disk_wal_fsync_duration_seconds_bucket", - "refId": "A", - "step": 4 - }, - { - "expr": "histogram_quantile(0.99, sum(rate(etcd_disk_backend_commit_duration_seconds_bucket{job=\"$cluster\"}[5m])) by (instance, le))", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} DB fsync", - "metric": "etcd_disk_backend_commit_duration_seconds_bucket", - "refId": "B", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Sync Duration", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 29, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 4, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_resident_memory_bytes{job=\"$cluster\"}", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Resident Memory", - "metric": "process_resident_memory_bytes", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "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": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "title": "New row" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 5, - "id": 22, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 3, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "rate(etcd_network_client_grpc_received_bytes_total{job=\"$cluster\"}[5m])", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Client Traffic In", - "metric": "etcd_network_client_grpc_received_bytes_total", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Client Traffic In", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 5, - "id": 21, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 3, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "rate(etcd_network_client_grpc_sent_bytes_total{job=\"$cluster\"}[5m])", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Client Traffic Out", - "metric": "etcd_network_client_grpc_sent_bytes_total", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Client Traffic Out", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 20, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(etcd_network_peer_received_bytes_total{job=\"$cluster\"}[5m])) by (instance)", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Peer Traffic In", - "metric": "etcd_network_peer_received_bytes_total", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Peer Traffic In", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "decimals": null, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 16, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 3, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(etcd_network_peer_sent_bytes_total{job=\"$cluster\"}[5m])) by (instance)", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Peer Traffic Out", - "metric": "etcd_network_peer_sent_bytes_total", - "refId": "A", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Peer Traffic Out", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "title": "New row" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "editable": true, - "error": false, - "fill": 0, - "id": 40, - "isNew": true, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(etcd_server_proposals_failed_total{job=\"$cluster\"}[5m]))", - "intervalFactor": 2, - "legendFormat": "Proposal Failure Rate", - "metric": "etcd_server_proposals_failed_total", - "refId": "A", - "step": 2 - }, - { - "expr": "sum(etcd_server_proposals_pending{job=\"$cluster\"})", - "intervalFactor": 2, - "legendFormat": "Proposal Pending Total", - "metric": "etcd_server_proposals_pending", - "refId": "B", - "step": 2 - }, - { - "expr": "sum(rate(etcd_server_proposals_committed_total{job=\"$cluster\"}[5m]))", - "intervalFactor": 2, - "legendFormat": "Proposal Commit Rate", - "metric": "etcd_server_proposals_committed_total", - "refId": "C", - "step": 2 - }, - { - "expr": "sum(rate(etcd_server_proposals_applied_total{job=\"$cluster\"}[5m]))", - "intervalFactor": 2, - "legendFormat": "Proposal Apply Rate", - "refId": "D", - "step": 2 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Raft Proposals", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "datasource": "$datasource", - "decimals": 0, - "editable": true, - "error": false, - "fill": 0, - "id": 19, - "isNew": true, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "changes(etcd_server_leader_changes_seen_total{job=\"$cluster\"}[1d])", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}instance{{`}}`}} Total Leader Elections Per Day", - "metric": "etcd_server_leader_changes_seen_total", - "refId": "A", - "step": 2 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Total Leader Elections Per Day", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "title": "New row" - } - ], - "schemaVersion": 13, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [], - "query": "label_values(etcd_server_has_leader, job)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "etcd", - "uid": "c2f4e12cdf69feb95caa41a5a1b423d9", - "version": 215 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-cluster-rsrc-use.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-cluster-rsrc-use.yaml deleted file mode 100644 index fbe5e313b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-cluster-rsrc-use.yaml +++ /dev/null @@ -1,959 +0,0 @@ -{{- /* -Generated from 'k8s-cluster-rsrc-use' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-cluster-rsrc-use" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-cluster-rsrc-use.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node:cluster_cpu_utilisation:ratio{cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_cpu_saturation_load1:{cluster=\"$cluster\"} / scalar(sum(min(kube_pod_info{cluster=\"$cluster\"}) by (node)))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Saturation (Load1)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node:cluster_memory_utilisation:ratio{cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_memory_swap_io_bytes:sum_rate{cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Saturation (Swap I/O)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_disk_utilisation:avg_irate{cluster=\"$cluster\"} / scalar(:kube_pod_info_node_count:{cluster=\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_disk_saturation:avg_irate{cluster=\"$cluster\"} / scalar(:kube_pod_info_node_count:{cluster=\"$cluster\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Saturation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Disk", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_net_utilisation:sum_irate{cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Net Utilisation (Transmitted)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_net_saturation:sum_irate{cluster=\"$cluster\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Net Saturation (Dropped)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Network", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(max(node_filesystem_size_bytes{fstype=~\"ext[234]|btrfs|xfs|zfs\", cluster=\"$cluster\"} - node_filesystem_avail_bytes{fstype=~\"ext[234]|btrfs|xfs|zfs\", cluster=\"$cluster\"}) by (device,pod,namespace)) by (pod,namespace)\n/ scalar(sum(max(node_filesystem_size_bytes{fstype=~\"ext[234]|btrfs|xfs|zfs\", cluster=\"$cluster\"}) by (device,pod,namespace)))\n* on (namespace, pod) group_left (node) node_namespace_pod:kube_pod_info:{cluster=\"$cluster\"}\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}node{{`}}`}}", - "legendLink": "./d/4ac4f123aae0ff6dbaf4f4f66120033b/k8s-node-rsrc-use", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk Capacity", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Storage", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(:kube_pod_info_node_count:, cluster)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / USE Method / Cluster", - "uid": "a6e7d1362e1ddbb79db21d5bb40d7137", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-node-rsrc-use.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-node-rsrc-use.yaml deleted file mode 100644 index 6d0157854..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-node-rsrc-use.yaml +++ /dev/null @@ -1,986 +0,0 @@ -{{- /* -Generated from 'k8s-node-rsrc-use' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-node-rsrc-use" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-node-rsrc-use.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_cpu_utilisation:avg1m{cluster=\"$cluster\", node=\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Utilisation", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_cpu_saturation_load1:{cluster=\"$cluster\", node=\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Saturation", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Saturation (Load1)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_memory_utilisation:{cluster=\"$cluster\", node=\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Memory", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_memory_swap_io_bytes:sum_rate{cluster=\"$cluster\", node=\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Swap IO", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Saturation (Swap I/O)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_disk_utilisation:avg_irate{cluster=\"$cluster\", node=\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Utilisation", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_disk_saturation:avg_irate{cluster=\"$cluster\", node=\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Saturation", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Saturation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Disk", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_net_utilisation:sum_irate{cluster=\"$cluster\", node=\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Utilisation", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Net Utilisation (Transmitted)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_net_saturation:sum_irate{cluster=\"$cluster\", node=\"$node\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Saturation", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Net Saturation (Dropped)", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Net", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node:node_filesystem_usage:{cluster=\"$cluster\"}\n* on (namespace, pod) group_left (node) node_namespace_pod:kube_pod_info:{cluster=\"$cluster\", node=\"$node\"}\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Disk", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(:kube_pod_info_node_count:, cluster)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "node", - "multi": false, - "name": "node", - "options": [ - - ], - "query": "label_values(kube_node_info{cluster=\"$cluster\"}, node)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / USE Method / Node", - "uid": "4ac4f123aae0ff6dbaf4f4f66120033b", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-cluster.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-cluster.yaml deleted file mode 100644 index ecfbb3cbf..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-cluster.yaml +++ /dev/null @@ -1,1479 +0,0 @@ -{{- /* -Generated from 'k8s-resources-cluster' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-cluster" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-cluster.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "100px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "1 - avg(rate(node_cpu_seconds_total{mode=\"idle\", cluster=\"$cluster\"}[1m]))", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\"}) / sum(node:node_num_cpu:sum{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Requests Commitment", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\"}) / sum(node:node_num_cpu:sum{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "CPU Limits Commitment", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "1 - sum(:node_memory_MemFreeCachedBuffers_bytes:sum{cluster=\"$cluster\"}) / sum(:node_memory_MemTotal_bytes:sum{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Utilisation", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 5, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\"}) / sum(:node_memory_MemTotal_bytes:sum{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Requests Commitment", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "format": "percentunit", - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 2, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\"}) / sum(:node_memory_MemTotal_bytes:sum{cluster=\"$cluster\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "70,80", - "timeFrom": null, - "timeShift": null, - "title": "Memory Limits Commitment", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "singlestat", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Headlines", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workloads", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTooltip": "Drill down to workloads", - "linkUrl": "./d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count(mixin_pod_workload{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "count(avg(mixin_pod_workload{cluster=\"$cluster\"}) by (workload, namespace)) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\"}) by (namespace) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", container_name!=\"\"}) by (namespace)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}namespace{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (w/o cache)", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workloads", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": true, - "linkTooltip": "Drill down to workloads", - "linkUrl": "./d/a87fb0d919ec0ea5f6543124e16c42a5/k8s-resources-workloads-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell_1", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down to pods", - "linkUrl": "./d/85a562078cdf77779eaa1add43ccec1e/k8s-resources-namespace?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$__cell", - "pattern": "namespace", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count(mixin_pod_workload{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "count(avg(mixin_pod_workload{cluster=\"$cluster\"}) by (workload, namespace)) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", container_name!=\"\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", container_name!=\"\"}) by (namespace) / sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", container_name!=\"\"}) by (namespace) / sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\"}) by (namespace)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Requests by Namespace", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Requests", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(:kube_pod_info_node_count:, cluster)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / Compute Resources / Cluster", - "uid": "efa86fd1d0c121a26444b636a3f509a8", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-namespace.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-namespace.yaml deleted file mode 100644 index 64da49cb5..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-namespace.yaml +++ /dev/null @@ -1,963 +0,0 @@ -{{- /* -Generated from 'k8s-resources-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-namespace" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-namespace.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod_name{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(label_replace(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(label_replace(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(label_replace(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"}) by (pod_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod_name{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage (w/o cache)", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Usage (RSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Cache)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Swap", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(label_replace(container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\",container_name!=\"\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\",container_name!=\"\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod) / sum(kube_pod_container_resource_requests_memory_bytes{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\",container_name!=\"\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod) / sum(kube_pod_container_resource_limits_memory_bytes{namespace=\"$namespace\"}) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_rss{cluster=\"$cluster\", namespace=\"$namespace\",container_name!=\"\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_cache{cluster=\"$cluster\", namespace=\"$namespace\",container_name!=\"\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_swap{cluster=\"$cluster\", namespace=\"$namespace\",container_name!=\"\"}, \"pod\", \"$1\", \"pod_name\", \"(.*)\")) by (pod)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(:kube_pod_info_node_count:, cluster)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / Compute Resources / Namespace (Pods)", - "uid": "85a562078cdf77779eaa1add43ccec1e", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-pod.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-pod.yaml deleted file mode 100644 index 78cd0452f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-pod.yaml +++ /dev/null @@ -1,1006 +0,0 @@ -{{- /* -Generated from 'k8s-resources-pod' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-pod" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-pod.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{namespace=\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\", cluster=\"$cluster\"}) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container_name{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Container", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "container", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(label_replace(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(label_replace(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container) / sum(kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(label_replace(namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container) / sum(kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_rss{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\", container_name!=\"\"}) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container_name{{`}}`}} (RSS)", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(container_memory_cache{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\", container_name!=\"\"}) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container_name{{`}}`}} (Cache)", - "legendLink": null, - "step": 10 - }, - { - "expr": "sum(container_memory_swap{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\", container_name!=\"\"}) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}container_name{{`}}`}} (Swap)", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Usage (RSS)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Cache)", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #G", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Usage (Swap", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #H", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Container", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "container", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(label_replace(container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name!=\"POD\", container_name!=\"\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container) / sum(kube_pod_container_resource_requests_memory_bytes{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container!=\"\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name!=\"\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container) / sum(kube_pod_container_resource_limits_memory_bytes{namespace=\"$namespace\", pod=\"$pod\"}) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_rss{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name != \"\", container_name != \"POD\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_cache{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name != \"\", container_name != \"POD\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "G", - "step": 10 - }, - { - "expr": "sum(label_replace(container_memory_swap{cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name != \"\", container_name != \"POD\"}, \"container\", \"$1\", \"container_name\", \"(.*)\")) by (container)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "H", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(:kube_pod_info_node_count:, cluster)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "pod", - "multi": false, - "name": "pod", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\", namespace=\"$namespace\"}, pod)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / Compute Resources / Pod", - "uid": "6581e46e4e5c7ba40a07646395ef7b23", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-workload.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-workload.yaml deleted file mode 100644 index af1a153d6..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-workload.yaml +++ /dev/null @@ -1,936 +0,0 @@ -{{- /* -Generated from 'k8s-resources-workload' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-workload" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-workload.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n label_replace(\n namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(\n label_replace(\n namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n/sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n label_replace(\n container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n ) by (pod)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}pod{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "./d/6581e46e4e5c7ba40a07646395ef7b23/k8s-resources-pod?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-pod=$__cell", - "pattern": "pod", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum(\n label_replace(\n container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n ) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n ) by (pod)\n/sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n ) by (pod)\n/sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\", workload_type=\"$type\"}\n) by (pod)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(:kube_pod_info_node_count:, cluster)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "workload", - "multi": false, - "name": "workload", - "options": [ - - ], - "query": "label_values(mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}, workload)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "type", - "multi": false, - "name": "type", - "options": [ - - ], - "query": "label_values(mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\", workload=\"$workload\"}, workload_type)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / Compute Resources / Workload", - "uid": "a164a7f0339f99e89cea5cb47e9be617", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-workloads-namespace.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-workloads-namespace.yaml deleted file mode 100644 index c11f51bb2..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/k8s-resources-workloads-namespace.yaml +++ /dev/null @@ -1,972 +0,0 @@ -{{- /* -Generated from 'k8s-resources-workloads-namespace' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "k8s-resources-workloads-namespace" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - k8s-resources-workloads-namespace.json: |- - { - "annotations": { - "list": [ - - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "links": [ - - ], - "refresh": "10s", - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n label_replace(\n namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Running Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "CPU Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "CPU Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "./d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workload Type", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "workload_type", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count(mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}) by (workload, workload_type)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate{cluster=\"$cluster\", namespace=\"$namespace\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits_cpu_cores{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "CPU Quota", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 10, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 0, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(\n label_replace(\n container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n ) by (workload, workload_type)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}workload{{`}}`}} - {{`{{`}}workload_type{{`}}`}}", - "legendLink": null, - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Usage", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "id": 4, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null as zero", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Running Pods", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 0, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #A", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Memory Usage", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #B", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #C", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Requests %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #D", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Memory Limits", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #E", - "thresholds": [ - - ], - "type": "number", - "unit": "bytes" - }, - { - "alias": "Memory Limits %", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "Value #F", - "thresholds": [ - - ], - "type": "number", - "unit": "percentunit" - }, - { - "alias": "Workload", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": true, - "linkTooltip": "Drill down", - "linkUrl": "./d/a164a7f0339f99e89cea5cb47e9be617/k8s-resources-workload?var-datasource=$datasource&var-cluster=$cluster&var-namespace=$namespace&var-workload=$__cell&var-type=$__cell_2", - "pattern": "workload", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "Workload Type", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "link": false, - "linkTooltip": "Drill down", - "linkUrl": "", - "pattern": "workload_type", - "thresholds": [ - - ], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "/.*/", - "thresholds": [ - - ], - "type": "string", - "unit": "short" - } - ], - "targets": [ - { - "expr": "count(mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}) by (workload, workload_type)", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n ) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "C", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n ) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_requests_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "D", - "step": 10 - }, - { - "expr": "sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "E", - "step": 10 - }, - { - "expr": "sum(\n label_replace(\n container_memory_usage_bytes{cluster=\"$cluster\", namespace=\"$namespace\", container_name!=\"\"},\n \"pod\", \"$1\", \"pod_name\", \"(.*)\"\n ) * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n ) by (workload, workload_type)\n/sum(\n kube_pod_container_resource_limits_memory_bytes{cluster=\"$cluster\", namespace=\"$namespace\"}\n * on(namespace,pod) group_left(workload, workload_type) mixin_pod_workload{cluster=\"$cluster\", namespace=\"$namespace\"}\n) by (workload, workload_type)\n", - "format": "table", - "instant": true, - "intervalFactor": 2, - "legendFormat": "", - "refId": "F", - "step": 10 - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Quota", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "transform": "table", - "type": "table", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Memory Quota", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(:kube_pod_info_node_count:, cluster)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "prod", - "value": "prod" - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 1, - "regex": "", - "sort": 2, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / Compute Resources / Namespace (Workloads)", - "uid": "a87fb0d919ec0ea5f6543124e16c42a5", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/nodes.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/nodes.yaml deleted file mode 100644 index 82d332a5c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/nodes.yaml +++ /dev/null @@ -1,1383 +0,0 @@ -{{- /* -Generated from 'nodes' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "nodes" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - nodes.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 2, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(node_load1{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "load 1m", - "refId": "A" - }, - { - "expr": "max(node_load5{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "load 5m", - "refId": "B" - }, - { - "expr": "max(node_load15{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "load 15m", - "refId": "C" - }, - { - "expr": "count(node_cpu_seconds_total{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\", mode=\"user\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "logical cores", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "System load", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (cpu) (irate(node_cpu_seconds_total{cluster=\"$cluster\", job=\"node-exporter\", mode!=\"idle\", instance=\"$instance\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}cpu{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Usage Per Core", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": "true", - "avg": "true", - "current": "true", - "max": "false", - "min": "false", - "rightSide": "true", - "show": "true", - "total": "false", - "values": "true" - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max (sum by (cpu) (irate(node_cpu_seconds_total{cluster=\"$cluster\", job=\"node-exporter\", mode!=\"idle\", instance=\"$instance\"}[2m])) ) * 100\n", - "format": "time_series", - "intervalFactor": 10, - "legendFormat": "{{`{{`}} cpu {{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Utilization", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percent", - "label": null, - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "percent", - "label": null, - "logBase": 1, - "max": 100, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "avg(sum by (cpu) (irate(node_cpu_seconds_total{cluster=\"$cluster\", job=\"node-exporter\", mode!=\"idle\", instance=\"$instance\"}[2m]))) * 100\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "CPU Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(\n node_memory_MemTotal_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n - node_memory_MemFree_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n - node_memory_Buffers_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n - node_memory_Cached_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "memory used", - "refId": "A" - }, - { - "expr": "max(node_memory_Buffers_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "refId": "B" - }, - { - "expr": "max(node_memory_Cached_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "memory cached", - "refId": "C" - }, - { - "expr": "max(node_memory_MemFree_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "memory free", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 7, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(\n (\n (\n node_memory_MemTotal_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n - node_memory_MemFree_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n - node_memory_Buffers_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n - node_memory_Cached_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n )\n / node_memory_MemTotal_bytes{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n ) * 100)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Memory Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 8, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - { - "alias": "read", - "yaxis": 1 - }, - { - "alias": "io time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(rate(node_disk_read_bytes_total{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "read", - "refId": "A" - }, - { - "expr": "max(rate(node_disk_written_bytes_total{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "written", - "refId": "B" - }, - { - "expr": "max(rate(node_disk_io_time_seconds_total{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "io time", - "refId": "C" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "shared": false, - "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": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max by (namespace, pod, device) ((node_filesystem_size_bytes{cluster=\"$cluster\", fstype=~\"ext[234]|btrfs|xfs|zfs\", instance=\"$instance\", job=\"node-exporter\"} - node_filesystem_avail_bytes{cluster=\"$cluster\", fstype=~\"ext[234]|btrfs|xfs|zfs\", instance=\"$instance\", job=\"node-exporter\"}) / node_filesystem_size_bytes{cluster=\"$cluster\", fstype=~\"ext[234]|btrfs|xfs|zfs\", instance=\"$instance\", job=\"node-exporter\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "disk used", - "refId": "A" - }, - { - "expr": "max by (namespace, pod, device) (node_filesystem_avail_bytes{cluster=\"$cluster\", fstype=~\"ext[234]|btrfs|xfs|zfs\", instance=\"$instance\", job=\"node-exporter\"} / node_filesystem_size_bytes{cluster=\"$cluster\", fstype=~\"ext[234]|btrfs|xfs|zfs\", instance=\"$instance\", job=\"node-exporter\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "disk free", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Disk Space Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 10, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(rate(node_network_receive_bytes_total{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\", device!~\"lo\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Network Received", - "tooltip": { - "shared": false, - "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": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(rate(node_network_transmit_bytes_total{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\", device!~\"lo\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{`{{`}}device{{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Network Transmitted", - "tooltip": { - "shared": false, - "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": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 12, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(\n node_filesystem_files{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n - node_filesystem_files_free{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "inodes used", - "refId": "A" - }, - { - "expr": "max(node_filesystem_files_free{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "inodes free", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Inodes Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 13, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(\n (\n (\n node_filesystem_files{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n - node_filesystem_files_free{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n )\n / node_filesystem_files{cluster=\"$cluster\", job=\"node-exporter\", instance=\"$instance\"}\n ) * 100)\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Inodes Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "instance", - "options": [ - - ], - "query": "label_values(node_boot_time_seconds{cluster=\"$cluster\", job=\"node-exporter\"}, instance)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / Nodes", - "uid": "fa49a4706d07a042595b664c87fb33ea", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/persistentvolumesusage.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/persistentvolumesusage.yaml deleted file mode 100644 index 3c51e1178..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/persistentvolumesusage.yaml +++ /dev/null @@ -1,573 +0,0 @@ -{{- /* -Generated from 'persistentvolumesusage' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "persistentvolumesusage" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - persistentvolumesusage.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(\n sum without(instance, node) (kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n -\n sum without(instance, node) (kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n)\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used Space", - "refId": "A" - }, - { - "expr": "sum without(instance, node) (kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Free Space", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Volume Space Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(\n kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n -\n kubelet_volume_stats_available_bytes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n)\n/\nkubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n* 100\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Volume Space Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum without(instance, node) (kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used inodes", - "refId": "A" - }, - { - "expr": "(\n sum without(instance, node) (kubelet_volume_stats_inodes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n -\n sum without(instance, node) (kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"})\n)\n", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": " Free inodes", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Volume inodes Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "$datasource", - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "kubelet_volume_stats_inodes_used{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n/\nkubelet_volume_stats_inodes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\", persistentvolumeclaim=\"$volume\"}\n* 100\n", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "80, 90", - "title": "Volume inodes Usage", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kubelet_volume_stats_capacity_bytes, cluster)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "PersistentVolumeClaim", - "multi": false, - "name": "volume", - "options": [ - - ], - "query": "label_values(kubelet_volume_stats_capacity_bytes{cluster=\"$cluster\", job=\"kubelet\", namespace=\"$namespace\"}, persistentvolumeclaim)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-7d", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / Persistent Volumes", - "uid": "919b92a8e8041bd567af9edab12c840c", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/pods.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/pods.yaml deleted file mode 100644 index e2534d7fd..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/pods.yaml +++ /dev/null @@ -1,680 +0,0 @@ -{{- /* -Generated from 'pods' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "pods" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - pods.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "$datasource", - "enable": true, - "expr": "time() == BOOL timestamp(rate(kube_pod_container_status_restarts_total{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}[2m]) > 0)", - "hide": false, - "iconColor": "rgba(215, 44, 44, 1)", - "name": "Restarts", - "showIn": 0, - "tags": [ - "restart" - ], - "type": "rows" - } - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by(container_name) (container_memory_usage_bytes{job=\"kubelet\", cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\", container_name=~\"$container\", container_name!=\"POD\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Current: {{`{{`}} container_name {{`}}`}}", - "refId": "A" - }, - { - "expr": "sum by(container) (kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\", pod=\"$pod\", container=~\"$container\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Requested: {{`{{`}} container {{`}}`}}", - "refId": "B" - }, - { - "expr": "sum by(container) (kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"memory\", pod=\"$pod\", container=~\"$container\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Limit: {{`{{`}} container {{`}}`}}", - "refId": "C" - }, - { - "expr": "sum by(container_name) (container_memory_cache{job=\"kubelet\", namespace=\"$namespace\", pod_name=~\"$pod\", container_name=~\"$container\", container_name!=\"POD\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Cache: {{`{{`}} container_name {{`}}`}}", - "refId": "D" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (container_name) (rate(container_cpu_usage_seconds_total{job=\"kubelet\", cluster=\"$cluster\", namespace=\"$namespace\", image!=\"\", pod_name=\"$pod\", container_name=~\"$container\", container_name!=\"POD\"}[1m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Current: {{`{{`}} container_name {{`}}`}}", - "refId": "A" - }, - { - "expr": "sum by(container) (kube_pod_container_resource_requests{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\", pod=\"$pod\", container=~\"$container\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Requested: {{`{{`}} container {{`}}`}}", - "refId": "B" - }, - { - "expr": "sum by(container) (kube_pod_container_resource_limits{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", resource=\"cpu\", pod=\"$pod\", container=~\"$container\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Limit: {{`{{`}} container {{`}}`}}", - "refId": "C" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sort_desc(sum by (pod_name) (rate(container_network_receive_bytes_total{job=\"kubelet\", cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\"}[1m])))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "RX: {{`{{`}} pod_name {{`}}`}}", - "refId": "A" - }, - { - "expr": "sort_desc(sum by (pod_name) (rate(container_network_transmit_bytes_total{job=\"kubelet\", cluster=\"$cluster\", namespace=\"$namespace\", pod_name=\"$pod\"}[1m])))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "TX: {{`{{`}} pod_name {{`}}`}}", - "refId": "B" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Network I/O", - "tooltip": { - "shared": false, - "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": 0, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 5, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max by (container) (kube_pod_container_status_restarts_total{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\", container=~\"$container\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Restarts: {{`{{`}} container {{`}}`}}", - "refId": "A" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Total Restarts Per Container", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_pod_info, cluster)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Pod", - "multi": false, - "name": "pod", - "options": [ - - ], - "query": "label_values(kube_pod_info{cluster=\"$cluster\", namespace=~\"$namespace\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": true, - "label": "Container", - "multi": false, - "name": "container", - "options": [ - - ], - "query": "label_values(kube_pod_container_info{cluster=\"$cluster\", namespace=\"$namespace\", pod=\"$pod\"}, container)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / Pods", - "uid": "ab4f13a9892a76a4d21ce8c2445bf4ea", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/statefulset.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/statefulset.yaml deleted file mode 100644 index 04b563be5..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/dashboards/statefulset.yaml +++ /dev/null @@ -1,926 +0,0 @@ -{{- /* -Generated from 'statefulset' from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/grafana-dashboardDefinitions.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" $) "statefulset" | trunc 63 | trimSuffix "-" }} - annotations: -{{ toYaml .Values.grafana.sidecar.dashboards.annotations | indent 4 }} - labels: - {{- if $.Values.grafana.sidecar.dashboards.label }} - {{ $.Values.grafana.sidecar.dashboards.label }}: "1" - {{- end }} - app: {{ template "kube-prometheus-stack.name" $ }}-grafana -{{ include "kube-prometheus-stack.labels" $ | indent 4 }} -data: - statefulset.json: |- - { - "__inputs": [ - - ], - "__requires": [ - - ], - "annotations": { - "list": [ - - ] - }, - "editable": false, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [ - - ], - "refresh": "", - "rows": [ - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 2, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{job=\"kubelet\", cluster=\"$cluster\", namespace=\"$namespace\", pod_name=~\"$statefulset.*\"}[3m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "CPU", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 3, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "GB", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{job=\"kubelet\", cluster=\"$cluster\", namespace=\"$namespace\", pod_name=~\"$statefulset.*\"}) / 1024^3", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Memory", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 4, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "Bps", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{job=\"kubelet\", cluster=\"$cluster\", namespace=\"$namespace\", pod_name=~\"$statefulset.*\"}[3m])) + sum(rate(container_network_receive_bytes_total{cluster=\"$cluster\", namespace=\"$namespace\",pod_name=~\"$statefulset.*\"}[3m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Network", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "height": "100px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 5, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_replicas{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Desired Replicas", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 6, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "min(kube_statefulset_status_replicas_current{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Replicas of current version", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 7, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_status_observed_generation{job=\"kube-state-metrics\", cluster=\"$cluster\", namespace=\"$namespace\", statefulset=\"$statefulset\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Observed Generation", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - - }, - "id": 8, - "interval": null, - "links": [ - - ], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_metadata_generation{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A" - } - ], - "thresholds": "", - "title": "Metadata Generation", - "tooltip": { - "shared": false - }, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - }, - { - "collapse": false, - "collapsed": false, - "panels": [ - { - "aliasColors": { - - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - - }, - "id": 9, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [ - - ], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": null, - "seriesOverrides": [ - - ], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(kube_statefulset_replicas{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "replicas specified", - "refId": "A" - }, - { - "expr": "max(kube_statefulset_status_replicas{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "replicas created", - "refId": "B" - }, - { - "expr": "min(kube_statefulset_status_replicas_ready{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "ready", - "refId": "C" - }, - { - "expr": "min(kube_statefulset_status_replicas_current{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "replicas of current version", - "refId": "D" - }, - { - "expr": "min(kube_statefulset_status_replicas_updated{job=\"kube-state-metrics\", statefulset=\"$statefulset\", cluster=\"$cluster\", namespace=\"$namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "updated", - "refId": "E" - } - ], - "thresholds": [ - - ], - "timeFrom": null, - "timeShift": null, - "title": "Replicas", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [ - - ] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6", - "type": "row" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes-mixin" - ], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "label": null, - "name": "datasource", - "options": [ - - ], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": {{ if .Values.grafana.sidecar.dashboards.multicluster }}0{{ else }}2{{ end }}, - "includeAll": false, - "label": "cluster", - "multi": false, - "name": "cluster", - "options": [ - - ], - "query": "label_values(kube_statefulset_metadata_generation, cluster)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [ - - ], - "query": "label_values(kube_statefulset_metadata_generation{job=\"kube-state-metrics\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - - }, - "datasource": "$datasource", - "hide": 0, - "includeAll": false, - "label": "Name", - "multi": false, - "name": "statefulset", - "options": [ - - ], - "query": "label_values(kube_statefulset_metadata_generation{job=\"kube-state-metrics\", namespace=\"$namespace\"}, statefulset)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [ - - ], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes / StatefulSets", - "uid": "a31c1f46e6f727cb37c0d731a7245005", - "version": 0 - } -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/servicemonitor.yaml deleted file mode 100644 index 1e839d707..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/grafana/servicemonitor.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if and .Values.grafana.enabled .Values.grafana.serviceMonitor.selfMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-grafana - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-grafana -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - selector: - matchLabels: - app.kubernetes.io/name: grafana - app.kubernetes.io/instance: {{ $.Release.Name | quote }} - namespaceSelector: - matchNames: - - {{ printf "%s" (include "kube-prometheus-stack.namespace" .) | quote }} - endpoints: - - port: {{ .Values.grafana.service.portName }} - {{- if .Values.grafana.serviceMonitor.interval }} - interval: {{ .Values.grafana.serviceMonitor.interval }} - {{- end }} - path: {{ .Values.grafana.serviceMonitor.path | quote }} -{{- if .Values.grafana.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.grafana.serviceMonitor.metricRelabelings | indent 6) . }} -{{- end }} -{{- if .Values.grafana.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.grafana.serviceMonitor.relabelings | indent 6 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/clusterrole.yaml deleted file mode 100644 index 249af770a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/clusterrole.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -rules: - - apiGroups: - - admissionregistration.k8s.io - resources: - - validatingwebhookconfigurations - - mutatingwebhookconfigurations - verbs: - - get - - update -{{- if .Values.global.rbac.pspEnabled }} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} - - apiGroups: ['policy'] -{{- else }} - - apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "kube-prometheus-stack.fullname" . }}-admission -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/clusterrolebinding.yaml deleted file mode 100644 index 31fd2def0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/clusterrolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "kube-prometheus-stack.fullname" . }}-admission -subjects: - - kind: ServiceAccount - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/job-createSecret.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/job-createSecret.yaml deleted file mode 100644 index f8afcb854..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/job-createSecret.yaml +++ /dev/null @@ -1,65 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission-create - namespace: {{ template "kube-prometheus-stack.namespace" . }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission-create -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -spec: - {{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }} - # Alpha feature since k8s 1.12 - ttlSecondsAfterFinished: 0 - {{- end }} - template: - metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission-create -{{- with .Values.prometheusOperator.admissionWebhooks.patch.podAnnotations }} - annotations: -{{ toYaml . | indent 8 }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission-create -{{- include "kube-prometheus-stack.labels" $ | indent 8 }} - spec: - {{- if .Values.prometheusOperator.admissionWebhooks.patch.priorityClassName }} - priorityClassName: {{ .Values.prometheusOperator.admissionWebhooks.patch.priorityClassName }} - {{- end }} - containers: - - name: create - {{- if .Values.prometheusOperator.admissionWebhooks.patch.image.sha }} - image: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.repository }}:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.tag }}@sha256:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.sha }} - {{- else }} - image: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.repository }}:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.tag }} - {{- end }} - imagePullPolicy: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.pullPolicy }} - args: - - create - - --host={{ template "kube-prometheus-stack.operator.fullname" . }},{{ template "kube-prometheus-stack.operator.fullname" . }}.{{ template "kube-prometheus-stack.namespace" . }}.svc - - --namespace={{ template "kube-prometheus-stack.namespace" . }} - - --secret-name={{ template "kube-prometheus-stack.fullname" . }}-admission - resources: -{{ toYaml .Values.prometheusOperator.admissionWebhooks.patch.resources | indent 12 }} - restartPolicy: OnFailure - serviceAccountName: {{ template "kube-prometheus-stack.fullname" . }}-admission - {{- with .Values.prometheusOperator.admissionWebhooks.patch.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.prometheusOperator.admissionWebhooks.patch.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.prometheusOperator.admissionWebhooks.patch.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - securityContext: - runAsGroup: 2000 - runAsNonRoot: true - runAsUser: 2000 -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/job-patchWebhook.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/job-patchWebhook.yaml deleted file mode 100644 index b2d8912f8..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/job-patchWebhook.yaml +++ /dev/null @@ -1,66 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission-patch - namespace: {{ template "kube-prometheus-stack.namespace" . }} - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission-patch -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -spec: - {{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }} - # Alpha feature since k8s 1.12 - ttlSecondsAfterFinished: 0 - {{- end }} - template: - metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission-patch -{{- with .Values.prometheusOperator.admissionWebhooks.patch.podAnnotations }} - annotations: -{{ toYaml . | indent 8 }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission-patch -{{- include "kube-prometheus-stack.labels" $ | indent 8 }} - spec: - {{- if .Values.prometheusOperator.admissionWebhooks.patch.priorityClassName }} - priorityClassName: {{ .Values.prometheusOperator.admissionWebhooks.patch.priorityClassName }} - {{- end }} - containers: - - name: patch - {{- if .Values.prometheusOperator.admissionWebhooks.patch.image.sha }} - image: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.repository }}:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.tag }}@sha256:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.sha }} - {{- else }} - image: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.repository }}:{{ .Values.prometheusOperator.admissionWebhooks.patch.image.tag }} - {{- end }} - imagePullPolicy: {{ .Values.prometheusOperator.admissionWebhooks.patch.image.pullPolicy }} - args: - - patch - - --webhook-name={{ template "kube-prometheus-stack.fullname" . }}-admission - - --namespace={{ template "kube-prometheus-stack.namespace" . }} - - --secret-name={{ template "kube-prometheus-stack.fullname" . }}-admission - - --patch-failure-policy={{ .Values.prometheusOperator.admissionWebhooks.failurePolicy }} - resources: -{{ toYaml .Values.prometheusOperator.admissionWebhooks.patch.resources | indent 12 }} - restartPolicy: OnFailure - serviceAccountName: {{ template "kube-prometheus-stack.fullname" . }}-admission - {{- with .Values.prometheusOperator.admissionWebhooks.patch.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.prometheusOperator.admissionWebhooks.patch.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.prometheusOperator.admissionWebhooks.patch.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - securityContext: - runAsGroup: 2000 - runAsNonRoot: true - runAsUser: 2000 -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/psp.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/psp.yaml deleted file mode 100644 index 5834c483c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/psp.yaml +++ /dev/null @@ -1,54 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - app: {{ template "kube-prometheus-stack.name" . }}-admission -{{- if .Values.global.rbac.pspAnnotations }} - annotations: -{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} -{{- end }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - privileged: false - # Required to prevent escalations to root. - # allowPrivilegeEscalation: false - # This is redundant with non-root + disallow privilege escalation, - # but we can provide it for defense in depth. - #requiredDropCapabilities: - # - ALL - # Allow core volume types. - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/role.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/role.yaml deleted file mode 100644 index d229f76ef..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/role.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - namespace: {{ template "kube-prometheus-stack.namespace" . }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -rules: - - apiGroups: - - "" - resources: - - secrets - verbs: - - get - - create -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/rolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/rolebinding.yaml deleted file mode 100644 index f4b1fbf0e..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/rolebinding.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - namespace: {{ template "kube-prometheus-stack.namespace" . }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "kube-prometheus-stack.fullname" . }}-admission -subjects: - - kind: ServiceAccount - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/serviceaccount.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/serviceaccount.yaml deleted file mode 100644 index 2048f049c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/job-patch/serviceaccount.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled .Values.prometheusOperator.admissionWebhooks.patch.enabled .Values.global.rbac.create (not .Values.prometheusOperator.admissionWebhooks.certManager.enabled) }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - namespace: {{ template "kube-prometheus-stack.namespace" . }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -imagePullSecrets: -{{ toYaml .Values.global.imagePullSecrets | indent 2 }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/mutatingWebhookConfiguration.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/mutatingWebhookConfiguration.yaml deleted file mode 100644 index a08ba533f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/mutatingWebhookConfiguration.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled }} -apiVersion: admissionregistration.k8s.io/v1 -kind: MutatingWebhookConfiguration -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission -{{- if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }} - annotations: - certmanager.k8s.io/inject-ca-from: {{ printf "%s/%s-root-cert" .Release.Namespace (include "kube-prometheus-stack.fullname" .) | quote }} - cert-manager.io/inject-ca-from: {{ printf "%s/%s-root-cert" .Release.Namespace (include "kube-prometheus-stack.fullname" .) | quote }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -webhooks: - - name: prometheusrulemutate.monitoring.coreos.com - {{- if .Values.prometheusOperator.admissionWebhooks.patch.enabled }} - failurePolicy: Ignore - {{- else }} - failurePolicy: {{ .Values.prometheusOperator.admissionWebhooks.failurePolicy }} - {{- end }} - rules: - - apiGroups: - - monitoring.coreos.com - apiVersions: - - "*" - resources: - - prometheusrules - operations: - - CREATE - - UPDATE - clientConfig: - service: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ template "kube-prometheus-stack.operator.fullname" $ }} - path: /admission-prometheusrules/mutate - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/validatingWebhookConfiguration.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/validatingWebhookConfiguration.yaml deleted file mode 100644 index 196727bca..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/admission-webhooks/validatingWebhookConfiguration.yaml +++ /dev/null @@ -1,38 +0,0 @@ -{{- if and .Values.prometheusOperator.admissionWebhooks.enabled }} -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission -{{- if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }} - annotations: - certmanager.k8s.io/inject-ca-from: {{ printf "%s/%s-root-cert" .Release.Namespace (include "kube-prometheus-stack.fullname" .) | quote }} - cert-manager.io/inject-ca-from: {{ printf "%s/%s-root-cert" .Release.Namespace (include "kube-prometheus-stack.fullname" .) | quote }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-admission -{{- include "kube-prometheus-stack.labels" $ | indent 4 }} -webhooks: - - name: prometheusrulemutate.monitoring.coreos.com - {{- if .Values.prometheusOperator.admissionWebhooks.patch.enabled }} - failurePolicy: Ignore - {{- else }} - failurePolicy: {{ .Values.prometheusOperator.admissionWebhooks.failurePolicy }} - {{- end }} - rules: - - apiGroups: - - monitoring.coreos.com - apiVersions: - - "*" - resources: - - prometheusrules - operations: - - CREATE - - UPDATE - clientConfig: - service: - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ template "kube-prometheus-stack.operator.fullname" $ }} - path: /admission-prometheusrules/validate - admissionReviewVersions: ["v1", "v1beta1"] - sideEffects: None -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/certmanager.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/certmanager.yaml deleted file mode 100644 index 090e6a5bb..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/certmanager.yaml +++ /dev/null @@ -1,57 +0,0 @@ -{{- if .Values.prometheusOperator.admissionWebhooks.certManager.enabled -}} -{{- if not .Values.prometheusOperator.admissionWebhooks.certManager.issuerRef -}} -# Create a selfsigned Issuer, in order to create a root CA certificate for -# signing webhook serving certificates -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-self-signed-issuer - namespace: {{ template "kube-prometheus-stack.namespace" . }} -spec: - selfSigned: {} ---- -# Generate a CA Certificate used to sign certificates for the webhook -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-root-cert - namespace: {{ template "kube-prometheus-stack.namespace" . }} -spec: - secretName: {{ template "kube-prometheus-stack.fullname" . }}-root-cert - duration: 43800h # 5y - issuerRef: - name: {{ template "kube-prometheus-stack.fullname" . }}-self-signed-issuer - commonName: "ca.webhook.kube-prometheus-stack" - isCA: true ---- -# Create an Issuer that uses the above generated CA certificate to issue certs -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-root-issuer - namespace: {{ template "kube-prometheus-stack.namespace" . }} -spec: - ca: - secretName: {{ template "kube-prometheus-stack.fullname" . }}-root-cert -{{- end }} ---- -# generate a serving certificate for the apiservices to use -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - namespace: {{ template "kube-prometheus-stack.namespace" . }} -spec: - secretName: {{ template "kube-prometheus-stack.fullname" . }}-admission - duration: 8760h # 1y - issuerRef: - {{- if .Values.prometheusOperator.admissionWebhooks.certManager.issuerRef }} - {{- toYaml .Values.prometheusOperator.admissionWebhooks.certManager.issuerRef | nindent 4 }} - {{- else }} - name: {{ template "kube-prometheus-stack.fullname" . }}-root-issuer - {{- end }} - dnsNames: - - {{ template "kube-prometheus-stack.operator.fullname" . }} - - {{ template "kube-prometheus-stack.operator.fullname" . }}.{{ template "kube-prometheus-stack.namespace" . }} - - {{ template "kube-prometheus-stack.operator.fullname" . }}.{{ template "kube-prometheus-stack.namespace" . }}.svc -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/clusterrole.yaml deleted file mode 100644 index e5568534c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/clusterrole.yaml +++ /dev/null @@ -1,80 +0,0 @@ -{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-operator - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -rules: -- apiGroups: - - monitoring.coreos.com - resources: - - alertmanagers - - alertmanagers/finalizers - - alertmanagerconfigs - - prometheuses - - prometheuses/finalizers - - thanosrulers - - thanosrulers/finalizers - - servicemonitors - - podmonitors - - probes - - prometheusrules - verbs: - - '*' -- apiGroups: - - apps - resources: - - statefulsets - verbs: - - '*' -- apiGroups: - - "" - resources: - - configmaps - - secrets - verbs: - - '*' -- apiGroups: - - "" - resources: - - pods - verbs: - - list - - delete -- apiGroups: - - "" - resources: - - services - - services/finalizers - - endpoints - verbs: - - get - - create - - update - - delete -- apiGroups: - - "" - resources: - - nodes - verbs: - - list - - watch -- apiGroups: - - "" - resources: - - namespaces - verbs: - - get - - list - - watch -- apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: - - get - - list - - watch -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/clusterrolebinding.yaml deleted file mode 100644 index c9ab0ab87..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/clusterrolebinding.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-operator - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "kube-prometheus-stack.fullname" . }}-operator -subjects: -- kind: ServiceAccount - name: {{ template "kube-prometheus-stack.operator.serviceAccountName" . }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/deployment.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/deployment.yaml deleted file mode 100644 index 5dcb85054..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/deployment.yaml +++ /dev/null @@ -1,144 +0,0 @@ -{{- $namespace := printf "%s" (include "kube-prometheus-stack.namespace" .) }} -{{- if .Values.prometheusOperator.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-operator - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-operator - release: {{ $.Release.Name | quote }} - template: - metadata: - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 8 }} -{{- if .Values.prometheusOperator.podLabels }} -{{ toYaml .Values.prometheusOperator.podLabels | indent 8 }} -{{- end }} -{{- if .Values.prometheusOperator.podAnnotations }} - annotations: -{{ toYaml .Values.prometheusOperator.podAnnotations | indent 8 }} -{{- end }} - spec: - {{- if .Values.prometheusOperator.priorityClassName }} - priorityClassName: {{ .Values.prometheusOperator.priorityClassName }} - {{- end }} - containers: - - name: {{ template "kube-prometheus-stack.name" . }} - {{- if .Values.prometheusOperator.image.sha }} - image: "{{ .Values.prometheusOperator.image.repository }}:{{ .Values.prometheusOperator.image.tag }}@sha256:{{ .Values.prometheusOperator.image.sha }}" - {{- else }} - image: "{{ .Values.prometheusOperator.image.repository }}:{{ .Values.prometheusOperator.image.tag }}" - {{- end }} - imagePullPolicy: "{{ .Values.prometheusOperator.image.pullPolicy }}" - args: - {{- if .Values.prometheusOperator.kubeletService.enabled }} - - --kubelet-service={{ .Values.prometheusOperator.kubeletService.namespace }}/{{ template "kube-prometheus-stack.fullname" . }}-kubelet - {{- end }} - {{- if .Values.prometheusOperator.logFormat }} - - --log-format={{ .Values.prometheusOperator.logFormat }} - {{- end }} - {{- if .Values.prometheusOperator.logLevel }} - - --log-level={{ .Values.prometheusOperator.logLevel }} - {{- end }} - {{- if .Values.prometheusOperator.denyNamespaces }} - - --deny-namespaces={{ .Values.prometheusOperator.denyNamespaces | join "," }} - {{- end }} - {{- with $.Values.prometheusOperator.namespaces }} - {{ $ns := .additional }} - {{- if .releaseNamespace }} - {{- $ns = append $ns $namespace }} - {{- end }} - - --namespaces={{ $ns | join "," }} - {{- end }} - {{- if (semverCompare "< v0.44.0" .Values.prometheusOperator.image.tag) -}} - - --logtostderr=true - {{- end }} - - --localhost=127.0.0.1 - {{- if .Values.prometheusOperator.prometheusConfigReloaderImage.sha }} - - --prometheus-config-reloader={{ .Values.prometheusOperator.prometheusConfigReloaderImage.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloaderImage.tag }}@sha256:{{ .Values.prometheusOperator.prometheusConfigReloaderImage.sha }} - {{- else }} - - --prometheus-config-reloader={{ .Values.prometheusOperator.prometheusConfigReloaderImage.repository }}:{{ .Values.prometheusOperator.prometheusConfigReloaderImage.tag }} - {{- end }} - # Empty if statement to catch non-semver master tags that do not need the --config-reloader-image flag - {{- if regexMatch "master.*" .Values.prometheusOperator.image.tag -}} - {{- else if (semverCompare "< v0.43.0" .Values.prometheusOperator.image.tag) -}} - {{- if .Values.prometheusOperator.configmapReloadImage.sha }} - - --config-reloader-image={{ .Values.prometheusOperator.configmapReloadImage.repository }}:{{ .Values.prometheusOperator.configmapReloadImage.tag }}@sha256:{{ .Values.prometheusOperator.configmapReloadImage.sha }} - {{- else }} - - --config-reloader-image={{ .Values.prometheusOperator.configmapReloadImage.repository }}:{{ .Values.prometheusOperator.configmapReloadImage.tag }} - {{- end }} - {{- end }} - - --config-reloader-cpu={{ .Values.prometheusOperator.configReloaderCpu }} - - --config-reloader-memory={{ .Values.prometheusOperator.configReloaderMemory }} - {{- if .Values.prometheusOperator.alertmanagerInstanceNamespaces }} - - --alertmanager-instance-namespaces={{ .Values.prometheusOperator.alertmanagerInstanceNamespaces | join "," }} - {{- end }} - {{- if .Values.prometheusOperator.prometheusInstanceNamespaces }} - - --prometheus-instance-namespaces={{ .Values.prometheusOperator.prometheusInstanceNamespaces | join "," }} - {{- end }} - {{- if .Values.prometheusOperator.thanosRulerInstanceNamespaces }} - - --thanos-ruler-instance-namespaces={{ .Values.prometheusOperator.thanosRulerInstanceNamespaces | join "," }} - {{- end }} - {{- if .Values.prometheusOperator.secretFieldSelector }} - - --secret-field-selector={{ .Values.prometheusOperator.secretFieldSelector }} - {{- end }} - {{- if .Values.prometheusOperator.tls.enabled }} - - --web.enable-tls=true - - --web.cert-file=cert/{{ if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }}tls.crt{{ else }}cert{{ end }} - - --web.key-file=cert/{{ if .Values.prometheusOperator.admissionWebhooks.certManager.enabled }}tls.key{{ else }}key{{ end }} - - --web.listen-address=:8443 - - --web.tls-min-version={{ .Values.prometheusOperator.tls.tlsMinVersion }} - ports: - - containerPort: 8443 - name: https - {{- else }} - ports: - - containerPort: 8080 - name: http - {{- end }} - resources: -{{ toYaml .Values.prometheusOperator.resources | indent 12 }} - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true -{{- if .Values.prometheusOperator.tls.enabled }} - volumeMounts: - - name: tls-secret - mountPath: /cert - readOnly: true - volumes: - - name: tls-secret - secret: - defaultMode: 420 - secretName: {{ template "kube-prometheus-stack.fullname" . }}-admission -{{- end }} -{{- if .Values.prometheusOperator.securityContext }} - securityContext: -{{ toYaml .Values.prometheusOperator.securityContext | indent 8 }} -{{- end }} - serviceAccountName: {{ template "kube-prometheus-stack.operator.serviceAccountName" . }} -{{- if .Values.prometheusOperator.hostNetwork }} - hostNetwork: true - dnsPolicy: ClusterFirstWithHostNet -{{- end }} - {{- with .Values.prometheusOperator.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.prometheusOperator.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.prometheusOperator.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp-clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp-clusterrole.yaml deleted file mode 100644 index d667d6275..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp-clusterrole.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-operator-psp - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -rules: -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} -- apiGroups: ['policy'] -{{- else }} -- apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "kube-prometheus-stack.fullname" . }}-operator -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp-clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp-clusterrolebinding.yaml deleted file mode 100644 index c538cd173..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp-clusterrolebinding.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-operator-psp - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "kube-prometheus-stack.fullname" . }}-operator-psp -subjects: - - kind: ServiceAccount - name: {{ template "kube-prometheus-stack.operator.serviceAccountName" . }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp.yaml deleted file mode 100644 index 18d1d37df..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/psp.yaml +++ /dev/null @@ -1,51 +0,0 @@ -{{- if and .Values.prometheusOperator.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-operator - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{- if .Values.global.rbac.pspAnnotations }} - annotations: -{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} -{{- end }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - privileged: false - # Required to prevent escalations to root. - # allowPrivilegeEscalation: false - # This is redundant with non-root + disallow privilege escalation, - # but we can provide it for defense in depth. - #requiredDropCapabilities: - # - ALL - # Allow core volume types. - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - hostNetwork: {{ .Values.prometheusOperator.hostNetwork }} - hostIPC: false - hostPID: false - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/service.yaml deleted file mode 100644 index 8ccb2bb2d..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/service.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if .Values.prometheusOperator.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-operator - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheusOperator.service.labels }} -{{ toYaml .Values.prometheusOperator.service.labels | indent 4 }} -{{- end }} -{{- if .Values.prometheusOperator.service.annotations }} - annotations: -{{ toYaml .Values.prometheusOperator.service.annotations | indent 4 }} -{{- end }} -spec: -{{- if .Values.prometheusOperator.service.clusterIP }} - clusterIP: {{ .Values.prometheusOperator.service.clusterIP }} -{{- end }} -{{- if .Values.prometheusOperator.service.externalIPs }} - externalIPs: -{{ toYaml .Values.prometheusOperator.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.prometheusOperator.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.prometheusOperator.service.loadBalancerIP }} -{{- end }} -{{- if .Values.prometheusOperator.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.prometheusOperator.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} - ports: - {{- if not .Values.prometheusOperator.tls.enabled }} - - name: http - {{- if eq .Values.prometheusOperator.service.type "NodePort" }} - nodePort: {{ .Values.prometheusOperator.service.nodePort }} - {{- end }} - port: 8080 - targetPort: http - {{- end }} - {{- if .Values.prometheusOperator.tls.enabled }} - - name: https - {{- if eq .Values.prometheusOperator.service.type "NodePort"}} - nodePort: {{ .Values.prometheusOperator.service.nodePortTls }} - {{- end }} - port: 443 - targetPort: https - {{- end }} - selector: - app: {{ template "kube-prometheus-stack.name" . }}-operator - release: {{ $.Release.Name | quote }} - type: "{{ .Values.prometheusOperator.service.type }}" -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/serviceaccount.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/serviceaccount.yaml deleted file mode 100644 index ab41797e3..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "kube-prometheus-stack.operator.serviceAccountName" . }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -imagePullSecrets: -{{ toYaml .Values.global.imagePullSecrets | indent 2 }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/servicemonitor.yaml deleted file mode 100644 index 59b61aa19..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus-operator/servicemonitor.yaml +++ /dev/null @@ -1,44 +0,0 @@ -{{- if and .Values.prometheusOperator.enabled .Values.prometheusOperator.serviceMonitor.selfMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-operator - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-operator -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - endpoints: - {{- if .Values.prometheusOperator.tls.enabled }} - - port: https - scheme: https - tlsConfig: - serverName: {{ template "kube-prometheus-stack.operator.fullname" . }} - ca: - secret: - name: {{ template "kube-prometheus-stack.fullname" . }}-admission - key: {{ if .Values.prometheusOperator.tls.enabled }}ca.crt{{ else }}ca{{ end }} - optional: false - {{- else }} - - port: http - {{- end }} - honorLabels: true - {{- if .Values.prometheusOperator.serviceMonitor.interval }} - interval: {{ .Values.prometheusOperator.serviceMonitor.interval }} - {{- end }} -{{- if .Values.prometheusOperator.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.prometheusOperator.serviceMonitor.metricRelabelings | indent 6) . }} -{{- end }} -{{- if .Values.prometheusOperator.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.prometheusOperator.serviceMonitor.relabelings | indent 6 }} -{{- end }} - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-operator - release: {{ $.Release.Name | quote }} - namespaceSelector: - matchNames: - - {{ printf "%s" (include "kube-prometheus-stack.namespace" .) | quote }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalAlertRelabelConfigs.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalAlertRelabelConfigs.yaml deleted file mode 100644 index bff930981..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalAlertRelabelConfigs.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigs }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-am-relabel-confg - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- if .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations }} - annotations: -{{ toYaml .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations | indent 4 }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus-am-relabel-confg -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -data: - additional-alert-relabel-configs.yaml: {{ toYaml .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigs | b64enc | quote }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalAlertmanagerConfigs.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalAlertmanagerConfigs.yaml deleted file mode 100644 index 8aebc96c3..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalAlertmanagerConfigs.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.prometheusSpec.additionalAlertManagerConfigs }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-am-confg - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- if .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations }} - annotations: -{{ toYaml .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations | indent 4 }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus-am-confg -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -data: - additional-alertmanager-configs.yaml: {{ toYaml .Values.prometheus.prometheusSpec.additionalAlertManagerConfigs | b64enc | quote }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalPrometheusRules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalPrometheusRules.yaml deleted file mode 100644 index 794e9ad27..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalPrometheusRules.yaml +++ /dev/null @@ -1,40 +0,0 @@ -{{- if or .Values.additionalPrometheusRules .Values.additionalPrometheusRulesMap}} -apiVersion: v1 -kind: List -items: -{{- if .Values.additionalPrometheusRulesMap }} -{{- range $prometheusRuleName, $prometheusRule := .Values.additionalPrometheusRulesMap }} - - apiVersion: monitoring.coreos.com/v1 - kind: PrometheusRule - metadata: - name: {{ template "kube-prometheus-stack.name" $ }}-{{ $prometheusRuleName }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - app: {{ template "kube-prometheus-stack.name" $ }} -{{ include "kube-prometheus-stack.labels" $ | indent 8 }} - {{- if $prometheusRule.additionalLabels }} -{{ toYaml $prometheusRule.additionalLabels | indent 8 }} - {{- end }} - spec: - groups: -{{ toYaml $prometheusRule.groups| indent 8 }} -{{- end }} -{{- else }} -{{- range .Values.additionalPrometheusRules }} - - apiVersion: monitoring.coreos.com/v1 - kind: PrometheusRule - metadata: - name: {{ template "kube-prometheus-stack.name" $ }}-{{ .name }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - app: {{ template "kube-prometheus-stack.name" $ }} -{{ include "kube-prometheus-stack.labels" $ | indent 8 }} - {{- if .additionalLabels }} -{{ toYaml .additionalLabels | indent 8 }} - {{- end }} - spec: - groups: -{{ toYaml .groups| indent 8 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalScrapeConfigs.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalScrapeConfigs.yaml deleted file mode 100644 index 21d9429d8..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/additionalScrapeConfigs.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.prometheusSpec.additionalScrapeConfigs }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-scrape-confg - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- if .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations }} - annotations: -{{ toYaml .Values.prometheus.prometheusSpec.additionalPrometheusSecretsAnnotations | indent 4 }} -{{- end }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus-scrape-confg -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -data: - additional-scrape-configs.yaml: {{ tpl (toYaml .Values.prometheus.prometheusSpec.additionalScrapeConfigs) $ | b64enc | quote }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/clusterrole.yaml deleted file mode 100644 index 3585b5db1..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/clusterrole.yaml +++ /dev/null @@ -1,30 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -rules: -# This permission are not in the kube-prometheus repo -# they're grabbed from https://github.com/prometheus/prometheus/blob/master/documentation/examples/rbac-setup.yml -- apiGroups: [""] - resources: - - nodes - - nodes/metrics - - services - - endpoints - - pods - verbs: ["get", "list", "watch"] -- apiGroups: - - "networking.k8s.io" - resources: - - ingresses - verbs: ["get", "list", "watch"] -- nonResourceURLs: ["/metrics", "/metrics/cadvisor"] - verbs: ["get"] -{{- if .Values.prometheus.additionalRulesForClusterRole }} -{{ toYaml .Values.prometheus.additionalRulesForClusterRole | indent 0 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/clusterrolebinding.yaml deleted file mode 100644 index 9fc4f65da..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/clusterrolebinding.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus -subjects: - - kind: ServiceAccount - name: {{ template "kube-prometheus-stack.prometheus.serviceAccountName" . }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- end }} - diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingress.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingress.yaml deleted file mode 100644 index fece24063..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingress.yaml +++ /dev/null @@ -1,58 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.ingress.enabled }} -{{- $serviceName := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus" }} -{{- $servicePort := .Values.prometheus.service.port -}} -{{- $routePrefix := list .Values.prometheus.prometheusSpec.routePrefix }} -{{- $paths := .Values.prometheus.ingress.paths | default $routePrefix -}} -{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} -apiVersion: networking.k8s.io/v1beta1 -{{ else }} -apiVersion: extensions/v1beta1 -{{ end -}} -kind: Ingress -metadata: -{{- if .Values.prometheus.ingress.annotations }} - annotations: -{{ toYaml .Values.prometheus.ingress.annotations | indent 4 }} -{{- end }} - name: {{ $serviceName }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.ingress.labels }} -{{ toYaml .Values.prometheus.ingress.labels | indent 4 }} -{{- end }} -spec: - {{- if or (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1") }} - {{- if .Values.prometheus.ingress.ingressClassName }} - ingressClassName: {{ .Values.prometheus.ingress.ingressClassName }} - {{- end }} - {{- end }} - rules: - {{- if .Values.prometheus.ingress.hosts }} - {{- range $host := .Values.prometheus.ingress.hosts }} - - host: {{ tpl $host $ }} - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end -}} - {{- end -}} - {{- else }} - - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end -}} - {{- end -}} - {{- if .Values.prometheus.ingress.tls }} - tls: -{{ tpl (toYaml .Values.prometheus.ingress.tls | indent 4) . }} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingressThanosSidecar.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingressThanosSidecar.yaml deleted file mode 100644 index efad4558a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingressThanosSidecar.yaml +++ /dev/null @@ -1,53 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.thanosIngress.enabled }} -{{- $serviceName := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus" }} -{{- $thanosPort := .Values.prometheus.thanosIngress.servicePort -}} -{{- $routePrefix := list .Values.prometheus.prometheusSpec.routePrefix }} -{{- $paths := .Values.prometheus.thanosIngress.paths | default $routePrefix -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: -{{- if .Values.prometheus.thanosIngress.annotations }} - annotations: -{{ toYaml .Values.prometheus.thanosIngress.annotations | indent 4 }} -{{- end }} - name: {{ template "kube-prometheus-stack.fullname" . }}-thanos-gateway - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.thanosIngress.labels }} -{{ toYaml .Values.prometheus.thanosIngress.labels | indent 4 }} -{{- end }} -spec: - {{- if or (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1") }} - {{- if .Values.prometheus.thanosIngress.ingressClassName }} - ingressClassName: {{ .Values.prometheus.thanosIngress.ingressClassName }} - {{- end }} - {{- end }} - rules: - {{- if .Values.prometheus.thanosIngress.hosts }} - {{- range $host := .Values.prometheus.thanosIngress.hosts }} - - host: {{ tpl $host $ }} - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $thanosPort }} - {{- end -}} - {{- end -}} - {{- else }} - - http: - paths: - {{- range $p := $paths }} - - path: {{ tpl $p $ }} - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $thanosPort }} - {{- end -}} - {{- end -}} - {{- if .Values.prometheus.thanosIngress.tls }} - tls: -{{ toYaml .Values.prometheus.thanosIngress.tls | indent 4 }} - {{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingressperreplica.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingressperreplica.yaml deleted file mode 100644 index a4dcde524..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/ingressperreplica.yaml +++ /dev/null @@ -1,58 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.servicePerReplica.enabled .Values.prometheus.ingressPerReplica.enabled }} -{{- $count := .Values.prometheus.prometheusSpec.replicas | int -}} -{{- $servicePort := .Values.prometheus.servicePerReplica.port -}} -{{- $ingressValues := .Values.prometheus.ingressPerReplica -}} -apiVersion: v1 -kind: List -metadata: - name: {{ include "kube-prometheus-stack.fullname" $ }}-prometheus-ingressperreplica - namespace: {{ template "kube-prometheus-stack.namespace" $ }} -items: -{{ range $i, $e := until $count }} - - kind: Ingress - {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} - apiVersion: networking.k8s.io/v1beta1 - {{ else }} - apiVersion: extensions/v1beta1 - {{ end -}} - metadata: - name: {{ include "kube-prometheus-stack.fullname" $ }}-prometheus-{{ $i }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - app: {{ include "kube-prometheus-stack.name" $ }}-prometheus -{{ include "kube-prometheus-stack.labels" $ | indent 8 }} - {{- if $ingressValues.labels }} -{{ toYaml $ingressValues.labels | indent 8 }} - {{- end }} - {{- if $ingressValues.annotations }} - annotations: -{{ toYaml $ingressValues.annotations | indent 8 }} - {{- end }} - spec: - {{- if or ($.Capabilities.APIVersions.Has "networking.k8s.io/v1") ($.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1") }} - {{- if $ingressValues.ingressClassName }} - ingressClassName: {{ $ingressValues.ingressClassName }} - {{- end }} - {{- end }} - rules: - - host: {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }} - http: - paths: - {{- range $p := $ingressValues.paths }} - - path: {{ tpl $p $ }} - backend: - serviceName: {{ include "kube-prometheus-stack.fullname" $ }}-prometheus-{{ $i }} - servicePort: {{ $servicePort }} - {{- end -}} - {{- if or $ingressValues.tlsSecretName $ingressValues.tlsSecretPerReplica.enabled }} - tls: - - hosts: - - {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }} - {{- if $ingressValues.tlsSecretPerReplica.enabled }} - secretName: {{ $ingressValues.tlsSecretPerReplica.prefix }}-{{ $i }} - {{- else }} - secretName: {{ $ingressValues.tlsSecretName }} - {{- end }} - {{- end }} -{{- end -}} -{{- end -}} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/podDisruptionBudget.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/podDisruptionBudget.yaml deleted file mode 100644 index 573317a32..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/podDisruptionBudget.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.podDisruptionBudget.enabled }} -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - {{- if .Values.prometheus.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.prometheus.podDisruptionBudget.minAvailable }} - {{- end }} - {{- if .Values.prometheus.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.prometheus.podDisruptionBudget.maxUnavailable }} - {{- end }} - selector: - matchLabels: - app: prometheus - prometheus: {{ template "kube-prometheus-stack.fullname" . }}-prometheus -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/podmonitors.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/podmonitors.yaml deleted file mode 100644 index 95d568e13..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/podmonitors.yaml +++ /dev/null @@ -1,37 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.additionalPodMonitors }} -apiVersion: v1 -kind: List -items: -{{- range .Values.prometheus.additionalPodMonitors }} - - apiVersion: monitoring.coreos.com/v1 - kind: PodMonitor - metadata: - name: {{ .name }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-prometheus -{{ include "kube-prometheus-stack.labels" $ | indent 8 }} - {{- if .additionalLabels }} -{{ toYaml .additionalLabels | indent 8 }} - {{- end }} - spec: - podMetricsEndpoints: -{{ toYaml .podMetricsEndpoints | indent 8 }} - {{- if .jobLabel }} - jobLabel: {{ .jobLabel }} - {{- end }} - {{- if .namespaceSelector }} - namespaceSelector: -{{ toYaml .namespaceSelector | indent 8 }} - {{- end }} - selector: -{{ toYaml .selector | indent 8 }} - {{- if .podTargetLabels }} - podTargetLabels: -{{ toYaml .podTargetLabels | indent 8 }} - {{- end }} - {{- if .sampleLimit }} - sampleLimit: {{ .sampleLimit }} - {{- end }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/prometheus.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/prometheus.yaml deleted file mode 100644 index 66ac5a88d..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/prometheus.yaml +++ /dev/null @@ -1,302 +0,0 @@ -{{- if .Values.prometheus.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: Prometheus -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.annotations }} - annotations: -{{ toYaml .Values.prometheus.annotations | indent 4 }} -{{- end }} -spec: - alerting: - alertmanagers: -{{- if .Values.prometheus.prometheusSpec.alertingEndpoints }} -{{ toYaml .Values.prometheus.prometheusSpec.alertingEndpoints | indent 6 }} -{{- else if .Values.alertmanager.enabled }} - - namespace: {{ template "kube-prometheus-stack.namespace" . }} - name: {{ template "kube-prometheus-stack.fullname" . }}-alertmanager - port: {{ .Values.alertmanager.alertmanagerSpec.portName }} - {{- if .Values.alertmanager.alertmanagerSpec.routePrefix }} - pathPrefix: "{{ .Values.alertmanager.alertmanagerSpec.routePrefix }}" - {{- end }} - apiVersion: {{ .Values.alertmanager.apiVersion }} -{{- else }} - [] -{{- end }} -{{- if .Values.prometheus.prometheusSpec.apiserverConfig }} - apiserverConfig: -{{ toYaml .Values.prometheus.prometheusSpec.apiserverConfig | indent 4}} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.image }} - image: {{ .Values.prometheus.prometheusSpec.image.repository }}:{{ .Values.prometheus.prometheusSpec.image.tag }} - version: {{ .Values.prometheus.prometheusSpec.image.tag }} - {{- if .Values.prometheus.prometheusSpec.image.sha }} - sha: {{ .Values.prometheus.prometheusSpec.image.sha }} - {{- end }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.externalLabels }} - externalLabels: -{{ toYaml .Values.prometheus.prometheusSpec.externalLabels | indent 4}} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.prometheusExternalLabelNameClear }} - prometheusExternalLabelName: "" -{{- else if .Values.prometheus.prometheusSpec.prometheusExternalLabelName }} - prometheusExternalLabelName: "{{ .Values.prometheus.prometheusSpec.prometheusExternalLabelName }}" -{{- end }} -{{- if .Values.prometheus.prometheusSpec.replicaExternalLabelNameClear }} - replicaExternalLabelName: "" -{{- else if .Values.prometheus.prometheusSpec.replicaExternalLabelName }} - replicaExternalLabelName: "{{ .Values.prometheus.prometheusSpec.replicaExternalLabelName }}" -{{- end }} -{{- if .Values.prometheus.prometheusSpec.externalUrl }} - externalUrl: "{{ tpl .Values.prometheus.prometheusSpec.externalUrl . }}" -{{- else if and .Values.prometheus.ingress.enabled .Values.prometheus.ingress.hosts }} - externalUrl: "http://{{ tpl (index .Values.prometheus.ingress.hosts 0) . }}{{ .Values.prometheus.prometheusSpec.routePrefix }}" -{{- else }} - externalUrl: http://{{ template "kube-prometheus-stack.fullname" . }}-prometheus.{{ template "kube-prometheus-stack.namespace" . }}:{{ .Values.prometheus.service.port }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.nodeSelector }} - nodeSelector: -{{ toYaml .Values.prometheus.prometheusSpec.nodeSelector | indent 4 }} -{{- end }} - paused: {{ .Values.prometheus.prometheusSpec.paused }} - replicas: {{ .Values.prometheus.prometheusSpec.replicas }} - logLevel: {{ .Values.prometheus.prometheusSpec.logLevel }} - logFormat: {{ .Values.prometheus.prometheusSpec.logFormat }} - listenLocal: {{ .Values.prometheus.prometheusSpec.listenLocal }} - enableAdminAPI: {{ .Values.prometheus.prometheusSpec.enableAdminAPI }} -{{- if .Values.prometheus.prometheusSpec.scrapeInterval }} - scrapeInterval: {{ .Values.prometheus.prometheusSpec.scrapeInterval }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.scrapeTimeout }} - scrapeTimeout: {{ .Values.prometheus.prometheusSpec.scrapeTimeout }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.evaluationInterval }} - evaluationInterval: {{ .Values.prometheus.prometheusSpec.evaluationInterval }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.resources }} - resources: -{{ toYaml .Values.prometheus.prometheusSpec.resources | indent 4 }} -{{- end }} - retention: {{ .Values.prometheus.prometheusSpec.retention | quote }} -{{- if .Values.prometheus.prometheusSpec.retentionSize }} - retentionSize: {{ .Values.prometheus.prometheusSpec.retentionSize | quote }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.walCompression }} - walCompression: {{ .Values.prometheus.prometheusSpec.walCompression }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.routePrefix }} - routePrefix: {{ .Values.prometheus.prometheusSpec.routePrefix | quote }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.secrets }} - secrets: -{{ toYaml .Values.prometheus.prometheusSpec.secrets | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.configMaps }} - configMaps: -{{ toYaml .Values.prometheus.prometheusSpec.configMaps | indent 4 }} -{{- end }} - serviceAccountName: {{ template "kube-prometheus-stack.prometheus.serviceAccountName" . }} -{{- if .Values.prometheus.prometheusSpec.serviceMonitorSelector }} - serviceMonitorSelector: -{{ toYaml .Values.prometheus.prometheusSpec.serviceMonitorSelector | indent 4 }} -{{ else if .Values.prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues }} - serviceMonitorSelector: - matchLabels: - release: {{ $.Release.Name | quote }} -{{ else }} - serviceMonitorSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.serviceMonitorNamespaceSelector }} - serviceMonitorNamespaceSelector: -{{ toYaml .Values.prometheus.prometheusSpec.serviceMonitorNamespaceSelector | indent 4 }} -{{ else }} - serviceMonitorNamespaceSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.podMonitorSelector }} - podMonitorSelector: -{{ toYaml .Values.prometheus.prometheusSpec.podMonitorSelector | indent 4 }} -{{ else if .Values.prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues }} - podMonitorSelector: - matchLabels: - release: {{ $.Release.Name | quote }} -{{ else }} - podMonitorSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.podMonitorNamespaceSelector }} - podMonitorNamespaceSelector: -{{ toYaml .Values.prometheus.prometheusSpec.podMonitorNamespaceSelector | indent 4 }} -{{ else }} - podMonitorNamespaceSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.probeSelector }} - probeSelector: -{{ toYaml .Values.prometheus.prometheusSpec.probeSelector | indent 4 }} -{{ else if .Values.prometheus.prometheusSpec.probeSelectorNilUsesHelmValues }} - probeSelector: - matchLabels: - release: {{ $.Release.Name | quote }} -{{ else }} - probeSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.probeNamespaceSelector }} - probeNamespaceSelector: -{{ toYaml .Values.prometheus.prometheusSpec.probeNamespaceSelector | indent 4 }} -{{ else }} - probeNamespaceSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.remoteRead }} - remoteRead: -{{ toYaml .Values.prometheus.prometheusSpec.remoteRead | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.remoteWrite }} - remoteWrite: -{{ toYaml .Values.prometheus.prometheusSpec.remoteWrite | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.securityContext }} - securityContext: -{{ toYaml .Values.prometheus.prometheusSpec.securityContext | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.ruleNamespaceSelector }} - ruleNamespaceSelector: -{{ toYaml .Values.prometheus.prometheusSpec.ruleNamespaceSelector | indent 4 }} -{{ else }} - ruleNamespaceSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.ruleSelector }} - ruleSelector: -{{ toYaml .Values.prometheus.prometheusSpec.ruleSelector | indent 4}} -{{- else if .Values.prometheus.prometheusSpec.ruleSelectorNilUsesHelmValues }} - ruleSelector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }} - release: {{ $.Release.Name | quote }} -{{ else }} - ruleSelector: {} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.storageSpec }} - storage: -{{ toYaml .Values.prometheus.prometheusSpec.storageSpec | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.podMetadata }} - podMetadata: -{{ tpl (toYaml .Values.prometheus.prometheusSpec.podMetadata | indent 4) . }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.query }} - query: -{{ toYaml .Values.prometheus.prometheusSpec.query | indent 4}} -{{- end }} -{{- if or .Values.prometheus.prometheusSpec.podAntiAffinity .Values.prometheus.prometheusSpec.affinity }} - affinity: -{{- if .Values.prometheus.prometheusSpec.affinity }} -{{ toYaml .Values.prometheus.prometheusSpec.affinity | indent 4 }} -{{- end }} -{{- if eq .Values.prometheus.prometheusSpec.podAntiAffinity "hard" }} - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }} - labelSelector: - matchLabels: - app: prometheus - prometheus: {{ template "kube-prometheus-stack.fullname" . }}-prometheus -{{- else if eq .Values.prometheus.prometheusSpec.podAntiAffinity "soft" }} - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - topologyKey: {{ .Values.prometheus.prometheusSpec.podAntiAffinityTopologyKey }} - labelSelector: - matchLabels: - app: prometheus - prometheus: {{ template "kube-prometheus-stack.fullname" . }}-prometheus -{{- end }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.tolerations }} - tolerations: -{{ toYaml .Values.prometheus.prometheusSpec.tolerations | indent 4 }} -{{- end }} -{{- if .Values.global.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.global.imagePullSecrets | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalScrapeConfigs }} - additionalScrapeConfigs: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-scrape-confg - key: additional-scrape-configs.yaml -{{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.enabled }} - additionalScrapeConfigs: - name: {{ .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.name }} - key: {{ .Values.prometheus.prometheusSpec.additionalScrapeConfigsSecret.key }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalAlertManagerConfigs }} - additionalAlertManagerConfigs: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-am-confg - key: additional-alertmanager-configs.yaml -{{- end }} -{{- if .Values.prometheus.prometheusSpec.additionalAlertRelabelConfigs }} - additionalAlertRelabelConfigs: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-am-relabel-confg - key: additional-alert-relabel-configs.yaml -{{- end }} -{{- if .Values.prometheus.prometheusSpec.containers }} - containers: -{{ toYaml .Values.prometheus.prometheusSpec.containers | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.initContainers }} - initContainers: -{{ toYaml .Values.prometheus.prometheusSpec.initContainers | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.priorityClassName }} - priorityClassName: {{ .Values.prometheus.prometheusSpec.priorityClassName }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.thanos }} - thanos: -{{ toYaml .Values.prometheus.prometheusSpec.thanos | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.disableCompaction }} - disableCompaction: {{ .Values.prometheus.prometheusSpec.disableCompaction }} -{{- end }} - portName: {{ .Values.prometheus.prometheusSpec.portName }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }} - enforcedNamespaceLabel: {{ .Values.prometheus.prometheusSpec.enforcedNamespaceLabel }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.volumes }} - volumes: -{{ toYaml .Values.prometheus.prometheusSpec.volumes | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.volumeMounts }} - volumeMounts: -{{ toYaml .Values.prometheus.prometheusSpec.volumeMounts | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs }} - arbitraryFSAccessThroughSMs: -{{ toYaml .Values.prometheus.prometheusSpec.arbitraryFSAccessThroughSMs | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.overrideHonorLabels }} - overrideHonorLabels: {{ .Values.prometheus.prometheusSpec.overrideHonorLabels }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.overrideHonorTimestamps }} - overrideHonorTimestamps: {{ .Values.prometheus.prometheusSpec.overrideHonorTimestamps }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.ignoreNamespaceSelectors }} - ignoreNamespaceSelectors: {{ .Values.prometheus.prometheusSpec.ignoreNamespaceSelectors }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce }} - prometheusRulesExcludedFromEnforce: -{{ toYaml .Values.prometheus.prometheusSpec.prometheusRulesExcludedFromEnforce | indent 4 }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.queryLogFile }} - queryLogFile: {{ .Values.prometheus.prometheusSpec.queryLogFile }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.enforcedSampleLimit }} - enforcedSampleLimit: {{ .Values.prometheus.prometheusSpec.enforcedSampleLimit }} -{{- end }} -{{- if .Values.prometheus.prometheusSpec.allowOverlappingBlocks }} - allowOverlappingBlocks: {{ .Values.prometheus.prometheusSpec.allowOverlappingBlocks }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp-clusterrole.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp-clusterrole.yaml deleted file mode 100644 index a279fb241..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp-clusterrole.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-psp - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -rules: -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} -- apiGroups: ['policy'] -{{- else }} -- apiGroups: ['extensions'] -{{- end }} - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: - - {{ template "kube-prometheus-stack.fullname" . }}-prometheus -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp-clusterrolebinding.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp-clusterrolebinding.yaml deleted file mode 100644 index 27b73b74b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp-clusterrolebinding.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-psp - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus-psp -subjects: - - kind: ServiceAccount - name: {{ template "kube-prometheus-stack.prometheus.serviceAccountName" . }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} -{{- end }} - diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp.yaml deleted file mode 100644 index bd2b270d5..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/psp.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.global.rbac.create .Values.global.rbac.pspEnabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{- if .Values.global.rbac.pspAnnotations }} - annotations: -{{ toYaml .Values.global.rbac.pspAnnotations | indent 4 }} -{{- end }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - privileged: false - # Required to prevent escalations to root. - # allowPrivilegeEscalation: false - # This is redundant with non-root + disallow privilege escalation, - # but we can provide it for defense in depth. - #requiredDropCapabilities: - # - ALL - # Allow core volume types. - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - # Permits the container to run with root privileges as well. - rule: 'RunAsAny' - seLinux: - # This policy assumes the nodes are using AppArmor rather than SELinux. - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 0 - max: 65535 - readOnlyRootFilesystem: false -{{- if .Values.prometheus.podSecurityPolicy.allowedCapabilities }} - allowedCapabilities: -{{ toYaml .Values.prometheus.podSecurityPolicy.allowedCapabilities | indent 4 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/alertmanager.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/alertmanager.rules.yaml deleted file mode 100644 index 387a67715..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/alertmanager.rules.yaml +++ /dev/null @@ -1,70 +0,0 @@ -{{- /* -Generated from 'alertmanager.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.alertmanager }} -{{- $alertmanagerJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "alertmanager" }} -{{- $namespace := printf "%s" (include "kube-prometheus-stack.namespace" .) }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "alertmanager.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: alertmanager.rules - rules: - - alert: AlertmanagerConfigInconsistent - annotations: - message: 'The configuration of the instances of the Alertmanager cluster `{{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.service {{`}}`}}` are out of sync. - - {{`{{`}} range printf "alertmanager_config_hash{namespace=\"%s\",service=\"%s\"}" $labels.namespace $labels.service | query {{`}}`}} - - Configuration hash for pod {{`{{`}} .Labels.pod {{`}}`}} is "{{`{{`}} printf "%.f" .Value {{`}}`}}" - - {{`{{`}} end {{`}}`}} - - ' - expr: count by(namespace,service) (count_values by(namespace,service) ("config_hash", alertmanager_config_hash{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"})) != 1 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: AlertmanagerFailedReload - annotations: - message: Reloading Alertmanager's configuration has failed for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}}. - expr: alertmanager_config_last_reload_successful{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} == 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: AlertmanagerMembersInconsistent - annotations: - message: Alertmanager has not found all other members of the cluster. - expr: |- - alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} - != on (service) GROUP_LEFT() - count by (service) (alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}) - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/etcd.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/etcd.yaml deleted file mode 100644 index b4309510b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/etcd.yaml +++ /dev/null @@ -1,197 +0,0 @@ -{{- /* -Generated from 'etcd' group from https://raw.githubusercontent.com/etcd-io/etcd/master/Documentation/op-guide/etcd3_alert.rules.yml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeEtcd.enabled .Values.defaultRules.rules.etcd }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "etcd" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: etcd - rules: - - alert: etcdMembersDown - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": members are down ({{`{{`}} $value {{`}}`}}).' - expr: |- - max by (job) ( - sum by (job) (up{job=~".*etcd.*"} == bool 0) - or - count by (job,endpoint) ( - sum by (job,endpoint,To) (rate(etcd_network_peer_sent_failures_total{job=~".*etcd.*"}[3m])) > 0.01 - ) - ) - > 0 - for: 3m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdInsufficientMembers - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": insufficient members ({{`{{`}} $value {{`}}`}}).' - expr: sum(up{job=~".*etcd.*"} == bool 1) by (job) < ((count(up{job=~".*etcd.*"}) by (job) + 1) / 2) - for: 3m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdNoLeader - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": member {{`{{`}} $labels.instance {{`}}`}} has no leader.' - expr: etcd_server_has_leader{job=~".*etcd.*"} == 0 - for: 1m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfLeaderChanges - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": {{`{{`}} $value {{`}}`}} leader changes within the last 15 minutes. Frequent elections may be a sign of insufficient resources, high network latency, or disruptions by other components and should be investigated.' - expr: increase((max by (job) (etcd_server_leader_changes_seen_total{job=~".*etcd.*"}) or 0*absent(etcd_server_leader_changes_seen_total{job=~".*etcd.*"}))[15m:1m]) >= 3 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedGRPCRequests - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": {{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.grpc_method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - 100 * sum(rate(grpc_server_handled_total{job=~".*etcd.*", grpc_code!="OK"}[5m])) BY (job, instance, grpc_service, grpc_method) - / - sum(rate(grpc_server_handled_total{job=~".*etcd.*"}[5m])) BY (job, instance, grpc_service, grpc_method) - > 1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedGRPCRequests - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": {{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.grpc_method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - 100 * sum(rate(grpc_server_handled_total{job=~".*etcd.*", grpc_code!="OK"}[5m])) BY (job, instance, grpc_service, grpc_method) - / - sum(rate(grpc_server_handled_total{job=~".*etcd.*"}[5m])) BY (job, instance, grpc_service, grpc_method) - > 5 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdGRPCRequestsSlow - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": gRPC requests to {{`{{`}} $labels.grpc_method {{`}}`}} are taking {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - histogram_quantile(0.99, sum(rate(grpc_server_handling_seconds_bucket{job=~".*etcd.*", grpc_type="unary"}[5m])) by (job, instance, grpc_service, grpc_method, le)) - > 0.15 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdMemberCommunicationSlow - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": member communication with {{`{{`}} $labels.To {{`}}`}} is taking {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - histogram_quantile(0.99, rate(etcd_network_peer_round_trip_time_seconds_bucket{job=~".*etcd.*"}[5m])) - > 0.15 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedProposals - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": {{`{{`}} $value {{`}}`}} proposal failures within the last 30 minutes on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: rate(etcd_server_proposals_failed_total{job=~".*etcd.*"}[15m]) > 5 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighFsyncDurations - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": 99th percentile fync durations are {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - histogram_quantile(0.99, rate(etcd_disk_wal_fsync_duration_seconds_bucket{job=~".*etcd.*"}[5m])) - > 0.5 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighCommitDurations - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": 99th percentile commit durations {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - histogram_quantile(0.99, rate(etcd_disk_backend_commit_duration_seconds_bucket{job=~".*etcd.*"}[5m])) - > 0.25 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedHTTPRequests - annotations: - message: '{{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}' - expr: |- - sum(rate(etcd_http_failed_total{job=~".*etcd.*", code!="404"}[5m])) BY (method) / sum(rate(etcd_http_received_total{job=~".*etcd.*"}[5m])) - BY (method) > 0.01 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedHTTPRequests - annotations: - message: '{{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - sum(rate(etcd_http_failed_total{job=~".*etcd.*", code!="404"}[5m])) BY (method) / sum(rate(etcd_http_received_total{job=~".*etcd.*"}[5m])) - BY (method) > 0.05 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHTTPRequestsSlow - annotations: - message: etcd instance {{`{{`}} $labels.instance {{`}}`}} HTTP requests to {{`{{`}} $labels.method {{`}}`}} are slow. - expr: |- - histogram_quantile(0.99, rate(etcd_http_successful_duration_seconds_bucket[5m])) - > 0.15 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/general.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/general.rules.yaml deleted file mode 100644 index 80771f4f8..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/general.rules.yaml +++ /dev/null @@ -1,56 +0,0 @@ -{{- /* -Generated from 'general.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.general }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "general.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: general.rules - rules: - - alert: TargetDown - annotations: - message: '{{`{{`}} printf "%.4g" $value {{`}}`}}% of the {{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.service {{`}}`}} targets in {{`{{`}} $labels.namespace {{`}}`}} namespace are down.' - expr: 100 * (count(up == 0) BY (job, namespace, service) / count(up) BY (job, namespace, service)) > 10 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: Watchdog - annotations: - message: 'This is an alert meant to ensure that the entire alerting pipeline is functional. - - This alert is always firing, therefore it should always be firing in Alertmanager - - and always fire against a receiver. There are integrations with various notification - - mechanisms that send a notification when this alert is not firing. For example the - - "DeadMansSnitch" integration in PagerDuty. - - ' - expr: vector(1) - labels: - severity: none -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/k8s.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/k8s.rules.yaml deleted file mode 100644 index 35e4edebf..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/k8s.rules.yaml +++ /dev/null @@ -1,121 +0,0 @@ -{{- /* -Generated from 'k8s.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.k8s }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "k8s.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: k8s.rules - rules: - - expr: sum(rate(container_cpu_usage_seconds_total{job="kubelet", metrics_path="/metrics/cadvisor", image!="", container!="POD"}[5m])) by (namespace) - record: namespace:container_cpu_usage_seconds_total:sum_rate - - expr: |- - sum by (cluster, namespace, pod, container) ( - rate(container_cpu_usage_seconds_total{job="kubelet", metrics_path="/metrics/cadvisor", image!="", container!="POD"}[5m]) - ) * on (cluster, namespace, pod) group_left(node) topk by (cluster, namespace, pod) ( - 1, max by(cluster, namespace, pod, node) (kube_pod_info{node!=""}) - ) - record: node_namespace_pod_container:container_cpu_usage_seconds_total:sum_rate - - expr: |- - container_memory_working_set_bytes{job="kubelet", metrics_path="/metrics/cadvisor", image!=""} - * on (namespace, pod) group_left(node) topk by(namespace, pod) (1, - max by(namespace, pod, node) (kube_pod_info{node!=""}) - ) - record: node_namespace_pod_container:container_memory_working_set_bytes - - expr: |- - container_memory_rss{job="kubelet", metrics_path="/metrics/cadvisor", image!=""} - * on (namespace, pod) group_left(node) topk by(namespace, pod) (1, - max by(namespace, pod, node) (kube_pod_info{node!=""}) - ) - record: node_namespace_pod_container:container_memory_rss - - expr: |- - container_memory_cache{job="kubelet", metrics_path="/metrics/cadvisor", image!=""} - * on (namespace, pod) group_left(node) topk by(namespace, pod) (1, - max by(namespace, pod, node) (kube_pod_info{node!=""}) - ) - record: node_namespace_pod_container:container_memory_cache - - expr: |- - container_memory_swap{job="kubelet", metrics_path="/metrics/cadvisor", image!=""} - * on (namespace, pod) group_left(node) topk by(namespace, pod) (1, - max by(namespace, pod, node) (kube_pod_info{node!=""}) - ) - record: node_namespace_pod_container:container_memory_swap - - expr: sum(container_memory_usage_bytes{job="kubelet", metrics_path="/metrics/cadvisor", image!="", container!="POD"}) by (namespace) - record: namespace:container_memory_usage_bytes:sum - - expr: |- - sum by (namespace) ( - sum by (namespace, pod) ( - max by (namespace, pod, container) ( - kube_pod_container_resource_requests_memory_bytes{job="kube-state-metrics"} - ) * on(namespace, pod) group_left() max by (namespace, pod) ( - kube_pod_status_phase{phase=~"Pending|Running"} == 1 - ) - ) - ) - record: namespace:kube_pod_container_resource_requests_memory_bytes:sum - - expr: |- - sum by (namespace) ( - sum by (namespace, pod) ( - max by (namespace, pod, container) ( - kube_pod_container_resource_requests_cpu_cores{job="kube-state-metrics"} - ) * on(namespace, pod) group_left() max by (namespace, pod) ( - kube_pod_status_phase{phase=~"Pending|Running"} == 1 - ) - ) - ) - record: namespace:kube_pod_container_resource_requests_cpu_cores:sum - - expr: |- - max by (cluster, namespace, workload, pod) ( - label_replace( - label_replace( - kube_pod_owner{job="kube-state-metrics", owner_kind="ReplicaSet"}, - "replicaset", "$1", "owner_name", "(.*)" - ) * on(replicaset, namespace) group_left(owner_name) topk by(replicaset, namespace) ( - 1, max by (replicaset, namespace, owner_name) ( - kube_replicaset_owner{job="kube-state-metrics"} - ) - ), - "workload", "$1", "owner_name", "(.*)" - ) - ) - labels: - workload_type: deployment - record: namespace_workload_pod:kube_pod_owner:relabel - - expr: |- - max by (cluster, namespace, workload, pod) ( - label_replace( - kube_pod_owner{job="kube-state-metrics", owner_kind="DaemonSet"}, - "workload", "$1", "owner_name", "(.*)" - ) - ) - labels: - workload_type: daemonset - record: namespace_workload_pod:kube_pod_owner:relabel - - expr: |- - max by (cluster, namespace, workload, pod) ( - label_replace( - kube_pod_owner{job="kube-state-metrics", owner_kind="StatefulSet"}, - "workload", "$1", "owner_name", "(.*)" - ) - ) - labels: - workload_type: statefulset - record: namespace_workload_pod:kube_pod_owner:relabel -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-availability.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-availability.rules.yaml deleted file mode 100644 index 78a09e323..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-availability.rules.yaml +++ /dev/null @@ -1,158 +0,0 @@ -{{- /* -Generated from 'kube-apiserver-availability.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserverAvailability }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-apiserver-availability.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - interval: 3m - name: kube-apiserver-availability.rules - rules: - - expr: |- - 1 - ( - ( - # write too slow - sum(increase(apiserver_request_duration_seconds_count{verb=~"POST|PUT|PATCH|DELETE"}[30d])) - - - sum(increase(apiserver_request_duration_seconds_bucket{verb=~"POST|PUT|PATCH|DELETE",le="1"}[30d])) - ) + - ( - # read too slow - sum(increase(apiserver_request_duration_seconds_count{verb=~"LIST|GET"}[30d])) - - - ( - ( - sum(increase(apiserver_request_duration_seconds_bucket{verb=~"LIST|GET",scope=~"resource|",le="0.1"}[30d])) - or - vector(0) - ) - + - sum(increase(apiserver_request_duration_seconds_bucket{verb=~"LIST|GET",scope="namespace",le="0.5"}[30d])) - + - sum(increase(apiserver_request_duration_seconds_bucket{verb=~"LIST|GET",scope="cluster",le="5"}[30d])) - ) - ) + - # errors - sum(code:apiserver_request_total:increase30d{code=~"5.."} or vector(0)) - ) - / - sum(code:apiserver_request_total:increase30d) - labels: - verb: all - record: apiserver_request:availability30d - - expr: |- - 1 - ( - sum(increase(apiserver_request_duration_seconds_count{job="apiserver",verb=~"LIST|GET"}[30d])) - - - ( - # too slow - ( - sum(increase(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope=~"resource|",le="0.1"}[30d])) - or - vector(0) - ) - + - sum(increase(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="namespace",le="0.5"}[30d])) - + - sum(increase(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="cluster",le="5"}[30d])) - ) - + - # errors - sum(code:apiserver_request_total:increase30d{verb="read",code=~"5.."} or vector(0)) - ) - / - sum(code:apiserver_request_total:increase30d{verb="read"}) - labels: - verb: read - record: apiserver_request:availability30d - - expr: |- - 1 - ( - ( - # too slow - sum(increase(apiserver_request_duration_seconds_count{verb=~"POST|PUT|PATCH|DELETE"}[30d])) - - - sum(increase(apiserver_request_duration_seconds_bucket{verb=~"POST|PUT|PATCH|DELETE",le="1"}[30d])) - ) - + - # errors - sum(code:apiserver_request_total:increase30d{verb="write",code=~"5.."} or vector(0)) - ) - / - sum(code:apiserver_request_total:increase30d{verb="write"}) - labels: - verb: write - record: apiserver_request:availability30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="LIST",code=~"2.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="GET",code=~"2.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="POST",code=~"2.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="PUT",code=~"2.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="PATCH",code=~"2.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="DELETE",code=~"2.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="LIST",code=~"3.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="GET",code=~"3.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="POST",code=~"3.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="PUT",code=~"3.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="PATCH",code=~"3.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="DELETE",code=~"3.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="LIST",code=~"4.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="GET",code=~"4.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="POST",code=~"4.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="PUT",code=~"4.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="PATCH",code=~"4.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="DELETE",code=~"4.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="LIST",code=~"5.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="GET",code=~"5.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="POST",code=~"5.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="PUT",code=~"5.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="PATCH",code=~"5.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code, verb) (increase(apiserver_request_total{job="apiserver",verb="DELETE",code=~"5.."}[30d])) - record: code_verb:apiserver_request_total:increase30d - - expr: sum by (code) (code_verb:apiserver_request_total:increase30d{verb=~"LIST|GET"}) - labels: - verb: read - record: code:apiserver_request_total:increase30d - - expr: sum by (code) (code_verb:apiserver_request_total:increase30d{verb=~"POST|PUT|PATCH|DELETE"}) - labels: - verb: write - record: code:apiserver_request_total:increase30d -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-slos.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-slos.yaml deleted file mode 100644 index da0de91a3..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver-slos.yaml +++ /dev/null @@ -1,95 +0,0 @@ -{{- /* -Generated from 'kube-apiserver-slos' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserverSlos }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-apiserver-slos" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-apiserver-slos - rules: - - alert: KubeAPIErrorBudgetBurn - annotations: - description: The API server is burning too much error budget. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorbudgetburn - summary: The API server is burning too much error budget. - expr: |- - sum(apiserver_request:burnrate1h) > (14.40 * 0.01000) - and - sum(apiserver_request:burnrate5m) > (14.40 * 0.01000) - for: 2m - labels: - long: 1h - severity: critical - short: 5m -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPIErrorBudgetBurn - annotations: - description: The API server is burning too much error budget. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorbudgetburn - summary: The API server is burning too much error budget. - expr: |- - sum(apiserver_request:burnrate6h) > (6.00 * 0.01000) - and - sum(apiserver_request:burnrate30m) > (6.00 * 0.01000) - for: 15m - labels: - long: 6h - severity: critical - short: 30m -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPIErrorBudgetBurn - annotations: - description: The API server is burning too much error budget. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorbudgetburn - summary: The API server is burning too much error budget. - expr: |- - sum(apiserver_request:burnrate1d) > (3.00 * 0.01000) - and - sum(apiserver_request:burnrate2h) > (3.00 * 0.01000) - for: 1h - labels: - long: 1d - severity: warning - short: 2h -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPIErrorBudgetBurn - annotations: - description: The API server is burning too much error budget. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorbudgetburn - summary: The API server is burning too much error budget. - expr: |- - sum(apiserver_request:burnrate3d) > (1.00 * 0.01000) - and - sum(apiserver_request:burnrate6h) > (1.00 * 0.01000) - for: 3h - labels: - long: 3d - severity: warning - short: 6h -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver.rules.yaml deleted file mode 100644 index b4d1a0f39..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-apiserver.rules.yaml +++ /dev/null @@ -1,363 +0,0 @@ -{{- /* -Generated from 'kube-apiserver.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserver }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-apiserver.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-apiserver.rules - rules: - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"LIST|GET"}[1d])) - - - ( - ( - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope=~"resource|",le="0.1"}[1d])) - or - vector(0) - ) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="namespace",le="0.5"}[1d])) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="cluster",le="5"}[1d])) - ) - ) - + - # errors - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[1d])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[1d])) - labels: - verb: read - record: apiserver_request:burnrate1d - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"LIST|GET"}[1h])) - - - ( - ( - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope=~"resource|",le="0.1"}[1h])) - or - vector(0) - ) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="namespace",le="0.5"}[1h])) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="cluster",le="5"}[1h])) - ) - ) - + - # errors - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[1h])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[1h])) - labels: - verb: read - record: apiserver_request:burnrate1h - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"LIST|GET"}[2h])) - - - ( - ( - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope=~"resource|",le="0.1"}[2h])) - or - vector(0) - ) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="namespace",le="0.5"}[2h])) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="cluster",le="5"}[2h])) - ) - ) - + - # errors - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[2h])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[2h])) - labels: - verb: read - record: apiserver_request:burnrate2h - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"LIST|GET"}[30m])) - - - ( - ( - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope=~"resource|",le="0.1"}[30m])) - or - vector(0) - ) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="namespace",le="0.5"}[30m])) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="cluster",le="5"}[30m])) - ) - ) - + - # errors - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[30m])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[30m])) - labels: - verb: read - record: apiserver_request:burnrate30m - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"LIST|GET"}[3d])) - - - ( - ( - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope=~"resource|",le="0.1"}[3d])) - or - vector(0) - ) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="namespace",le="0.5"}[3d])) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="cluster",le="5"}[3d])) - ) - ) - + - # errors - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[3d])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[3d])) - labels: - verb: read - record: apiserver_request:burnrate3d - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"LIST|GET"}[5m])) - - - ( - ( - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope=~"resource|",le="0.1"}[5m])) - or - vector(0) - ) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="namespace",le="0.5"}[5m])) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="cluster",le="5"}[5m])) - ) - ) - + - # errors - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[5m])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[5m])) - labels: - verb: read - record: apiserver_request:burnrate5m - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"LIST|GET"}[6h])) - - - ( - ( - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope=~"resource|",le="0.1"}[6h])) - or - vector(0) - ) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="namespace",le="0.5"}[6h])) - + - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET",scope="cluster",le="5"}[6h])) - ) - ) - + - # errors - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET",code=~"5.."}[6h])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[6h])) - labels: - verb: read - record: apiserver_request:burnrate6h - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[1d])) - - - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",le="1"}[1d])) - ) - + - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[1d])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[1d])) - labels: - verb: write - record: apiserver_request:burnrate1d - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[1h])) - - - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",le="1"}[1h])) - ) - + - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[1h])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[1h])) - labels: - verb: write - record: apiserver_request:burnrate1h - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[2h])) - - - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",le="1"}[2h])) - ) - + - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[2h])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[2h])) - labels: - verb: write - record: apiserver_request:burnrate2h - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[30m])) - - - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",le="1"}[30m])) - ) - + - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[30m])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[30m])) - labels: - verb: write - record: apiserver_request:burnrate30m - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[3d])) - - - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",le="1"}[3d])) - ) - + - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[3d])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[3d])) - labels: - verb: write - record: apiserver_request:burnrate3d - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[5m])) - - - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",le="1"}[5m])) - ) - + - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[5m])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[5m])) - labels: - verb: write - record: apiserver_request:burnrate5m - - expr: |- - ( - ( - # too slow - sum(rate(apiserver_request_duration_seconds_count{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[6h])) - - - sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",le="1"}[6h])) - ) - + - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE",code=~"5.."}[6h])) - ) - / - sum(rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[6h])) - labels: - verb: write - record: apiserver_request:burnrate6h - - expr: sum by (code,resource) (rate(apiserver_request_total{job="apiserver",verb=~"LIST|GET"}[5m])) - labels: - verb: read - record: code_resource:apiserver_request_total:rate5m - - expr: sum by (code,resource) (rate(apiserver_request_total{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[5m])) - labels: - verb: write - record: code_resource:apiserver_request_total:rate5m - - expr: histogram_quantile(0.99, sum by (le, resource) (rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"LIST|GET"}[5m]))) > 0 - labels: - quantile: '0.99' - verb: read - record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.99, sum by (le, resource) (rate(apiserver_request_duration_seconds_bucket{job="apiserver",verb=~"POST|PUT|PATCH|DELETE"}[5m]))) > 0 - labels: - quantile: '0.99' - verb: write - record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile - - expr: |- - sum(rate(apiserver_request_duration_seconds_sum{subresource!="log",verb!~"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT"}[5m])) without(instance, pod) - / - sum(rate(apiserver_request_duration_seconds_count{subresource!="log",verb!~"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT"}[5m])) without(instance, pod) - record: cluster:apiserver_request_duration_seconds:mean5m - - expr: histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",subresource!="log",verb!~"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT"}[5m])) without(instance, pod)) - labels: - quantile: '0.99' - record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",subresource!="log",verb!~"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT"}[5m])) without(instance, pod)) - labels: - quantile: '0.9' - record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(apiserver_request_duration_seconds_bucket{job="apiserver",subresource!="log",verb!~"LIST|WATCH|WATCHLIST|DELETECOLLECTION|PROXY|CONNECT"}[5m])) without(instance, pod)) - labels: - quantile: '0.5' - record: cluster_quantile:apiserver_request_duration_seconds:histogram_quantile -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-prometheus-general.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-prometheus-general.rules.yaml deleted file mode 100644 index e54bee587..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-prometheus-general.rules.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- /* -Generated from 'kube-prometheus-general.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubePrometheusGeneral }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-prometheus-general.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-prometheus-general.rules - rules: - - expr: count without(instance, pod, node) (up == 1) - record: count:up1 - - expr: count without(instance, pod, node) (up == 0) - record: count:up0 -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-prometheus-node-recording.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-prometheus-node-recording.rules.yaml deleted file mode 100644 index 27271f1b5..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-prometheus-node-recording.rules.yaml +++ /dev/null @@ -1,39 +0,0 @@ -{{- /* -Generated from 'kube-prometheus-node-recording.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubePrometheusNodeRecording }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-prometheus-node-recording.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-prometheus-node-recording.rules - rules: - - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait",mode!="steal"}[3m])) BY (instance) - record: instance:node_cpu:rate:sum - - expr: sum(rate(node_network_receive_bytes_total[3m])) BY (instance) - record: instance:node_network_receive_bytes:rate:sum - - expr: sum(rate(node_network_transmit_bytes_total[3m])) BY (instance) - record: instance:node_network_transmit_bytes:rate:sum - - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait",mode!="steal"}[5m])) WITHOUT (cpu, mode) / ON(instance) GROUP_LEFT() count(sum(node_cpu_seconds_total) BY (instance, cpu)) BY (instance) - record: instance:node_cpu:ratio - - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait",mode!="steal"}[5m])) - record: cluster:node_cpu:sum_rate5m - - expr: cluster:node_cpu_seconds_total:rate5m / count(sum(node_cpu_seconds_total) BY (instance, cpu)) - record: cluster:node_cpu:ratio -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-scheduler.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-scheduler.rules.yaml deleted file mode 100644 index 594f1bb3b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-scheduler.rules.yaml +++ /dev/null @@ -1,63 +0,0 @@ -{{- /* -Generated from 'kube-scheduler.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeScheduler.enabled .Values.defaultRules.rules.kubeScheduler }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-scheduler.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-scheduler.rules - rules: - - expr: histogram_quantile(0.99, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.99' - record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.99, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.99' - record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.99, sum(rate(scheduler_binding_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.99' - record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.9' - record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.9' - record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(scheduler_binding_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.9' - record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(scheduler_e2e_scheduling_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.5' - record: cluster_quantile:scheduler_e2e_scheduling_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(scheduler_scheduling_algorithm_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.5' - record: cluster_quantile:scheduler_scheduling_algorithm_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(scheduler_binding_duration_seconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) - labels: - quantile: '0.5' - record: cluster_quantile:scheduler_binding_duration_seconds:histogram_quantile -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-state-metrics.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-state-metrics.yaml deleted file mode 100644 index 0fa5032ba..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kube-state-metrics.yaml +++ /dev/null @@ -1,59 +0,0 @@ -{{- /* -Generated from 'kube-state-metrics' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubeStateMetrics }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-state-metrics" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-state-metrics - rules: - - alert: KubeStateMetricsListErrors - annotations: - description: kube-state-metrics is experiencing errors at an elevated rate in list operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatemetricslisterrors - summary: kube-state-metrics is experiencing errors in list operations. - expr: |- - (sum(rate(kube_state_metrics_list_total{job="kube-state-metrics",result="error"}[5m])) - / - sum(rate(kube_state_metrics_list_total{job="kube-state-metrics"}[5m]))) - > 0.01 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeStateMetricsWatchErrors - annotations: - description: kube-state-metrics is experiencing errors at an elevated rate in watch operations. This is likely causing it to not be able to expose metrics about Kubernetes objects correctly or at all. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatemetricswatcherrors - summary: kube-state-metrics is experiencing errors in watch operations. - expr: |- - (sum(rate(kube_state_metrics_watch_total{job="kube-state-metrics",result="error"}[5m])) - / - sum(rate(kube_state_metrics_watch_total{job="kube-state-metrics"}[5m]))) - > 0.01 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubelet.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubelet.rules.yaml deleted file mode 100644 index f9bd1ccd6..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubelet.rules.yaml +++ /dev/null @@ -1,39 +0,0 @@ -{{- /* -Generated from 'kubelet.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.kubelet.enabled .Values.defaultRules.rules.kubelet }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubelet.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubelet.rules - rules: - - expr: histogram_quantile(0.99, sum(rate(kubelet_pleg_relist_duration_seconds_bucket[5m])) by (instance, le) * on(instance) group_left(node) kubelet_node_name{job="kubelet", metrics_path="/metrics"}) - labels: - quantile: '0.99' - record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(kubelet_pleg_relist_duration_seconds_bucket[5m])) by (instance, le) * on(instance) group_left(node) kubelet_node_name{job="kubelet", metrics_path="/metrics"}) - labels: - quantile: '0.9' - record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(kubelet_pleg_relist_duration_seconds_bucket[5m])) by (instance, le) * on(instance) group_left(node) kubelet_node_name{job="kubelet", metrics_path="/metrics"}) - labels: - quantile: '0.5' - record: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-apps.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-apps.yaml deleted file mode 100644 index 6eb5e0295..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-apps.yaml +++ /dev/null @@ -1,298 +0,0 @@ -{{- /* -Generated from 'kubernetes-apps' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesApps }} -{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-apps" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-apps - rules: - - alert: KubePodCrashLooping - annotations: - description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} ({{`{{`}} $labels.container {{`}}`}}) is restarting {{`{{`}} printf "%.2f" $value {{`}}`}} times / 5 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepodcrashlooping - summary: Pod is crash looping. - expr: rate(kube_pod_container_status_restarts_total{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) * 60 * 5 > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubePodNotReady - annotations: - description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} has been in a non-ready state for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepodnotready - summary: Pod has been in a non-ready state for more than 15 minutes. - expr: |- - sum by (namespace, pod) ( - max by(namespace, pod) ( - kube_pod_status_phase{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}", phase=~"Pending|Unknown"} - ) * on(namespace, pod) group_left(owner_kind) topk by(namespace, pod) ( - 1, max by(namespace, pod, owner_kind) (kube_pod_owner{owner_kind!="Job"}) - ) - ) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDeploymentGenerationMismatch - annotations: - description: Deployment generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} does not match, this indicates that the Deployment has failed but has not been rolled back. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedeploymentgenerationmismatch - summary: Deployment generation mismatch due to possible roll-back - expr: |- - kube_deployment_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_deployment_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDeploymentReplicasMismatch - annotations: - description: Deployment {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedeploymentreplicasmismatch - summary: Deployment has not matched the expected number of replicas. - expr: |- - ( - kube_deployment_spec_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_deployment_status_replicas_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) and ( - changes(kube_deployment_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) - == - 0 - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeStatefulSetReplicasMismatch - annotations: - description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetreplicasmismatch - summary: Deployment has not matched the expected number of replicas. - expr: |- - ( - kube_statefulset_status_replicas_ready{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_status_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) and ( - changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) - == - 0 - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeStatefulSetGenerationMismatch - annotations: - description: StatefulSet generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} does not match, this indicates that the StatefulSet has failed but has not been rolled back. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetgenerationmismatch - summary: StatefulSet generation mismatch due to possible roll-back - expr: |- - kube_statefulset_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeStatefulSetUpdateNotRolledOut - annotations: - description: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} update has not been rolled out. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetupdatenotrolledout - summary: StatefulSet update has not been rolled out. - expr: |- - ( - max without (revision) ( - kube_statefulset_status_current_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - unless - kube_statefulset_status_update_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) - * - ( - kube_statefulset_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) - ) and ( - changes(kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) - == - 0 - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDaemonSetRolloutStuck - annotations: - description: DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} has not finished or progressed for at least 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetrolloutstuck - summary: DaemonSet rollout is stuck. - expr: |- - ( - ( - kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) or ( - kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - 0 - ) or ( - kube_daemonset_updated_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) or ( - kube_daemonset_status_number_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) - ) and ( - changes(kube_daemonset_updated_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[5m]) - == - 0 - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeContainerWaiting - annotations: - description: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} container {{`{{`}} $labels.container{{`}}`}} has been in waiting state for longer than 1 hour. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecontainerwaiting - summary: Pod container waiting longer than 1 hour - expr: sum by (namespace, pod, container) (kube_pod_container_status_waiting_reason{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) > 0 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDaemonSetNotScheduled - annotations: - description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are not scheduled.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetnotscheduled - summary: DaemonSet pods are not scheduled. - expr: |- - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - - - kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDaemonSetMisScheduled - annotations: - description: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are running where they are not supposed to run.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetmisscheduled - summary: DaemonSet pods are misscheduled. - expr: kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeJobCompletion - annotations: - description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} is taking more than 12 hours to complete. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubejobcompletion - summary: Job did not complete in time - expr: kube_job_spec_completions{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - kube_job_status_succeeded{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 12h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeJobFailed - annotations: - description: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} failed to complete. Removing failed job after investigation should clear this alert. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubejobfailed - summary: Job failed to complete. - expr: kube_job_failed{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeHpaReplicasMismatch - annotations: - description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.hpa {{`}}`}} has not matched the desired number of replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubehpareplicasmismatch - summary: HPA has not matched descired number of replicas. - expr: |- - (kube_hpa_status_desired_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_hpa_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) - and - (kube_hpa_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - > - kube_hpa_spec_min_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) - and - (kube_hpa_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - < - kube_hpa_spec_max_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}) - and - changes(kube_hpa_status_current_replicas[15m]) == 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeHpaMaxedOut - annotations: - description: HPA {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.hpa {{`}}`}} has been running at max replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubehpamaxedout - summary: HPA is running at max replicas - expr: |- - kube_hpa_status_current_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - == - kube_hpa_spec_max_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-resources.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-resources.yaml deleted file mode 100644 index 87933e5b2..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-resources.yaml +++ /dev/null @@ -1,159 +0,0 @@ -{{- /* -Generated from 'kubernetes-resources' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesResources }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-resources" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-resources - rules: - - alert: KubeCPUOvercommit - annotations: - description: Cluster has overcommitted CPU resource requests for Pods and cannot tolerate node failure. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecpuovercommit - summary: Cluster has overcommitted CPU resource requests. - expr: |- - sum(namespace:kube_pod_container_resource_requests_cpu_cores:sum{}) - / - sum(kube_node_status_allocatable_cpu_cores) - > - (count(kube_node_status_allocatable_cpu_cores)-1) / count(kube_node_status_allocatable_cpu_cores) - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeMemoryOvercommit - annotations: - description: Cluster has overcommitted memory resource requests for Pods and cannot tolerate node failure. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubememoryovercommit - summary: Cluster has overcommitted memory resource requests. - expr: |- - sum(namespace:kube_pod_container_resource_requests_memory_bytes:sum{}) - / - sum(kube_node_status_allocatable_memory_bytes) - > - (count(kube_node_status_allocatable_memory_bytes)-1) - / - count(kube_node_status_allocatable_memory_bytes) - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeCPUQuotaOvercommit - annotations: - description: Cluster has overcommitted CPU resource requests for Namespaces. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecpuquotaovercommit - summary: Cluster has overcommitted CPU resource requests. - expr: |- - sum(kube_resourcequota{job="kube-state-metrics", type="hard", resource="cpu"}) - / - sum(kube_node_status_allocatable_cpu_cores) - > 1.5 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeMemoryQuotaOvercommit - annotations: - description: Cluster has overcommitted memory resource requests for Namespaces. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubememoryquotaovercommit - summary: Cluster has overcommitted memory resource requests. - expr: |- - sum(kube_resourcequota{job="kube-state-metrics", type="hard", resource="memory"}) - / - sum(kube_node_status_allocatable_memory_bytes{job="kube-state-metrics"}) - > 1.5 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeQuotaAlmostFull - annotations: - description: Namespace {{`{{`}} $labels.namespace {{`}}`}} is using {{`{{`}} $value | humanizePercentage {{`}}`}} of its {{`{{`}} $labels.resource {{`}}`}} quota. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubequotaalmostfull - summary: Namespace quota is going to be full. - expr: |- - kube_resourcequota{job="kube-state-metrics", type="used"} - / ignoring(instance, job, type) - (kube_resourcequota{job="kube-state-metrics", type="hard"} > 0) - > 0.9 < 1 - for: 15m - labels: - severity: info -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeQuotaFullyUsed - annotations: - description: Namespace {{`{{`}} $labels.namespace {{`}}`}} is using {{`{{`}} $value | humanizePercentage {{`}}`}} of its {{`{{`}} $labels.resource {{`}}`}} quota. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubequotafullyused - summary: Namespace quota is fully used. - expr: |- - kube_resourcequota{job="kube-state-metrics", type="used"} - / ignoring(instance, job, type) - (kube_resourcequota{job="kube-state-metrics", type="hard"} > 0) - == 1 - for: 15m - labels: - severity: info -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeQuotaExceeded - annotations: - description: Namespace {{`{{`}} $labels.namespace {{`}}`}} is using {{`{{`}} $value | humanizePercentage {{`}}`}} of its {{`{{`}} $labels.resource {{`}}`}} quota. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubequotaexceeded - summary: Namespace quota has exceeded the limits. - expr: |- - kube_resourcequota{job="kube-state-metrics", type="used"} - / ignoring(instance, job, type) - (kube_resourcequota{job="kube-state-metrics", type="hard"} > 0) - > 1 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: CPUThrottlingHigh - annotations: - description: '{{`{{`}} $value | humanizePercentage {{`}}`}} throttling of CPU in namespace {{`{{`}} $labels.namespace {{`}}`}} for container {{`{{`}} $labels.container {{`}}`}} in pod {{`{{`}} $labels.pod {{`}}`}}.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-cputhrottlinghigh - summary: Processes experience elevated CPU throttling. - expr: |- - sum(increase(container_cpu_cfs_throttled_periods_total{container!="", }[5m])) by (container, pod, namespace) - / - sum(increase(container_cpu_cfs_periods_total{}[5m])) by (container, pod, namespace) - > ( 25 / 100 ) - for: 15m - labels: - severity: info -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-storage.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-storage.yaml deleted file mode 100644 index 1fadb59f4..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-storage.yaml +++ /dev/null @@ -1,75 +0,0 @@ -{{- /* -Generated from 'kubernetes-storage' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesStorage }} -{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-storage" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-storage - rules: - - alert: KubePersistentVolumeFillingUp - annotations: - description: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is only {{`{{`}} $value | humanizePercentage {{`}}`}} free. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumefillingup - summary: PersistentVolume is filling up. - expr: |- - kubelet_volume_stats_available_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - / - kubelet_volume_stats_capacity_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - < 0.03 - for: 1m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubePersistentVolumeFillingUp - annotations: - description: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to fill up within four days. Currently {{`{{`}} $value | humanizePercentage {{`}}`}} is available. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumefillingup - summary: PersistentVolume is filling up. - expr: |- - ( - kubelet_volume_stats_available_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - / - kubelet_volume_stats_capacity_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"} - ) < 0.15 - and - predict_linear(kubelet_volume_stats_available_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}", metrics_path="/metrics"}[6h], 4 * 24 * 3600) < 0 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubePersistentVolumeErrors - annotations: - description: The persistent volume {{`{{`}} $labels.persistentvolume {{`}}`}} has status {{`{{`}} $labels.phase {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumeerrors - summary: PersistentVolume is having issues with provisioning. - expr: kube_persistentvolume_status_phase{phase=~"Failed|Pending",job="kube-state-metrics"} > 0 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-apiserver.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-apiserver.yaml deleted file mode 100644 index f9acb6a50..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-apiserver.yaml +++ /dev/null @@ -1,88 +0,0 @@ -{{- /* -Generated from 'kubernetes-system-apiserver' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesSystem }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-system-apiserver" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-system-apiserver - rules: - - alert: KubeClientCertificateExpiration - annotations: - description: A client certificate used to authenticate to the apiserver is expiring in less than 7.0 days. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclientcertificateexpiration - summary: Client certificate is about to expire. - expr: apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 and on(job) histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 604800 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeClientCertificateExpiration - annotations: - description: A client certificate used to authenticate to the apiserver is expiring in less than 24.0 hours. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclientcertificateexpiration - summary: Client certificate is about to expire. - expr: apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 and on(job) histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 86400 - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: AggregatedAPIErrors - annotations: - description: An aggregated API {{`{{`}} $labels.name {{`}}`}}/{{`{{`}} $labels.namespace {{`}}`}} has reported errors. The number of errors have increased for it in the past five minutes. High values indicate that the availability of the service changes too often. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-aggregatedapierrors - summary: An aggregated API has reported errors. - expr: sum by(name, namespace)(increase(aggregator_unavailable_apiservice_count[5m])) > 2 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- if semverCompare ">=1.18.0-0" $kubeTargetVersion }} - - alert: AggregatedAPIDown - annotations: - description: An aggregated API {{`{{`}} $labels.name {{`}}`}}/{{`{{`}} $labels.namespace {{`}}`}} has been only {{`{{`}} $value | humanize {{`}}`}}% available over the last 10m. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-aggregatedapidown - summary: An aggregated API is down. - expr: (1 - max by(name, namespace)(avg_over_time(aggregator_unavailable_apiservice[10m]))) * 100 < 85 - for: 5m - labels: - severity: warning -{{- end }} -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- if .Values.kubeApiServer.enabled }} - - alert: KubeAPIDown - annotations: - description: KubeAPI has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapidown - summary: Target disappeared from Prometheus target discovery. - expr: absent(up{job="apiserver"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-controller-manager.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-controller-manager.yaml deleted file mode 100644 index bc9dab862..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-controller-manager.yaml +++ /dev/null @@ -1,41 +0,0 @@ -{{- /* -Generated from 'kubernetes-system-controller-manager' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeControllerManager.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-system-controller-manager" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-system-controller-manager - rules: -{{- if .Values.kubeControllerManager.enabled }} - - alert: KubeControllerManagerDown - annotations: - description: KubeControllerManager has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecontrollermanagerdown - summary: Target disappeared from Prometheus target discovery. - expr: absent(up{job="kube-controller-manager"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-kubelet.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-kubelet.yaml deleted file mode 100644 index cde9da437..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-kubelet.yaml +++ /dev/null @@ -1,188 +0,0 @@ -{{- /* -Generated from 'kubernetes-system-kubelet' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesSystem }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-system-kubelet" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-system-kubelet - rules: - - alert: KubeNodeNotReady - annotations: - description: '{{`{{`}} $labels.node {{`}}`}} has been unready for more than 15 minutes.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubenodenotready - summary: Node is not ready. - expr: kube_node_status_condition{job="kube-state-metrics",condition="Ready",status="true"} == 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeNodeUnreachable - annotations: - description: '{{`{{`}} $labels.node {{`}}`}} is unreachable and some workloads may be rescheduled.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubenodeunreachable - summary: Node is unreachable. - expr: (kube_node_spec_taint{job="kube-state-metrics",key="node.kubernetes.io/unreachable",effect="NoSchedule"} unless ignoring(key,value) kube_node_spec_taint{job="kube-state-metrics",key=~"ToBeDeletedByClusterAutoscaler|cloud.google.com/impending-node-termination|aws-node-termination-handler/spot-itn"}) == 1 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletTooManyPods - annotations: - description: Kubelet '{{`{{`}} $labels.node {{`}}`}}' is running at {{`{{`}} $value | humanizePercentage {{`}}`}} of its Pod capacity. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubelettoomanypods - summary: Kubelet is running at capacity. - expr: |- - count by(node) ( - (kube_pod_status_phase{job="kube-state-metrics",phase="Running"} == 1) * on(instance,pod,namespace,cluster) group_left(node) topk by(instance,pod,namespace,cluster) (1, kube_pod_info{job="kube-state-metrics"}) - ) - / - max by(node) ( - kube_node_status_capacity_pods{job="kube-state-metrics"} != 1 - ) > 0.95 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeNodeReadinessFlapping - annotations: - description: The readiness status of node {{`{{`}} $labels.node {{`}}`}} has changed {{`{{`}} $value {{`}}`}} times in the last 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubenodereadinessflapping - summary: Node readiness status is flapping. - expr: sum(changes(kube_node_status_condition{status="true",condition="Ready"}[15m])) by (node) > 2 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletPlegDurationHigh - annotations: - description: The Kubelet Pod Lifecycle Event Generator has a 99th percentile duration of {{`{{`}} $value {{`}}`}} seconds on node {{`{{`}} $labels.node {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletplegdurationhigh - summary: Kubelet Pod Lifecycle Event Generator is taking too long to relist. - expr: node_quantile:kubelet_pleg_relist_duration_seconds:histogram_quantile{quantile="0.99"} >= 10 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletPodStartUpLatencyHigh - annotations: - description: Kubelet Pod startup 99th percentile latency is {{`{{`}} $value {{`}}`}} seconds on node {{`{{`}} $labels.node {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletpodstartuplatencyhigh - summary: Kubelet Pod startup latency is too high. - expr: histogram_quantile(0.99, sum(rate(kubelet_pod_worker_duration_seconds_bucket{job="kubelet", metrics_path="/metrics"}[5m])) by (instance, le)) * on(instance) group_left(node) kubelet_node_name{job="kubelet", metrics_path="/metrics"} > 60 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletClientCertificateExpiration - annotations: - description: Client certificate for Kubelet on node {{`{{`}} $labels.node {{`}}`}} expires in {{`{{`}} $value | humanizeDuration {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletclientcertificateexpiration - summary: Kubelet client certificate is about to expire. - expr: kubelet_certificate_manager_client_ttl_seconds < 604800 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletClientCertificateExpiration - annotations: - description: Client certificate for Kubelet on node {{`{{`}} $labels.node {{`}}`}} expires in {{`{{`}} $value | humanizeDuration {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletclientcertificateexpiration - summary: Kubelet client certificate is about to expire. - expr: kubelet_certificate_manager_client_ttl_seconds < 86400 - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletServerCertificateExpiration - annotations: - description: Server certificate for Kubelet on node {{`{{`}} $labels.node {{`}}`}} expires in {{`{{`}} $value | humanizeDuration {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletservercertificateexpiration - summary: Kubelet server certificate is about to expire. - expr: kubelet_certificate_manager_server_ttl_seconds < 604800 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletServerCertificateExpiration - annotations: - description: Server certificate for Kubelet on node {{`{{`}} $labels.node {{`}}`}} expires in {{`{{`}} $value | humanizeDuration {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletservercertificateexpiration - summary: Kubelet server certificate is about to expire. - expr: kubelet_certificate_manager_server_ttl_seconds < 86400 - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletClientCertificateRenewalErrors - annotations: - description: Kubelet on node {{`{{`}} $labels.node {{`}}`}} has failed to renew its client certificate ({{`{{`}} $value | humanize {{`}}`}} errors in the last 5 minutes). - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletclientcertificaterenewalerrors - summary: Kubelet has failed to renew its client certificate. - expr: increase(kubelet_certificate_manager_client_expiration_renew_errors[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletServerCertificateRenewalErrors - annotations: - description: Kubelet on node {{`{{`}} $labels.node {{`}}`}} has failed to renew its server certificate ({{`{{`}} $value | humanize {{`}}`}} errors in the last 5 minutes). - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletservercertificaterenewalerrors - summary: Kubelet has failed to renew its server certificate. - expr: increase(kubelet_server_expiration_renew_errors[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- if .Values.prometheusOperator.kubeletService.enabled }} - - alert: KubeletDown - annotations: - description: Kubelet has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletdown - summary: Target disappeared from Prometheus target discovery. - expr: absent(up{job="kubelet", metrics_path="/metrics"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-scheduler.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-scheduler.yaml deleted file mode 100644 index a2c12725f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system-scheduler.yaml +++ /dev/null @@ -1,41 +0,0 @@ -{{- /* -Generated from 'kubernetes-system-scheduler' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeScheduler.enabled .Values.defaultRules.rules.kubeScheduler }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-system-scheduler" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-system-scheduler - rules: -{{- if .Values.kubeScheduler.enabled }} - - alert: KubeSchedulerDown - annotations: - description: KubeScheduler has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeschedulerdown - summary: Target disappeared from Prometheus target discovery. - expr: absent(up{job="kube-scheduler"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system.yaml deleted file mode 100644 index 3aca2e6cc..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/kubernetes-system.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- /* -Generated from 'kubernetes-system' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesSystem }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-system" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-system - rules: - - alert: KubeVersionMismatch - annotations: - description: There are {{`{{`}} $value {{`}}`}} different semantic versions of Kubernetes components running. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeversionmismatch - summary: Different semantic versions of Kubernetes components running. - expr: count(count by (gitVersion) (label_replace(kubernetes_build_info{job!~"kube-dns|coredns"},"gitVersion","$1","gitVersion","(v[0-9]*.[0-9]*).*"))) > 1 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeClientErrors - annotations: - description: Kubernetes API server client '{{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.instance {{`}}`}}' is experiencing {{`{{`}} $value | humanizePercentage {{`}}`}} errors.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclienterrors - summary: Kubernetes API server client is experiencing errors. - expr: |- - (sum(rate(rest_client_requests_total{code=~"5.."}[5m])) by (instance, job) - / - sum(rate(rest_client_requests_total[5m])) by (instance, job)) - > 0.01 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-exporter.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-exporter.rules.yaml deleted file mode 100644 index b6ae1bbeb..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-exporter.rules.yaml +++ /dev/null @@ -1,79 +0,0 @@ -{{- /* -Generated from 'node-exporter.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.node }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "node-exporter.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: node-exporter.rules - rules: - - expr: |- - count without (cpu) ( - count without (mode) ( - node_cpu_seconds_total{job="node-exporter"} - ) - ) - record: instance:node_num_cpu:sum - - expr: |- - 1 - avg without (cpu, mode) ( - rate(node_cpu_seconds_total{job="node-exporter", mode="idle"}[1m]) - ) - record: instance:node_cpu_utilisation:rate1m - - expr: |- - ( - node_load1{job="node-exporter"} - / - instance:node_num_cpu:sum{job="node-exporter"} - ) - record: instance:node_load1_per_cpu:ratio - - expr: |- - 1 - ( - node_memory_MemAvailable_bytes{job="node-exporter"} - / - node_memory_MemTotal_bytes{job="node-exporter"} - ) - record: instance:node_memory_utilisation:ratio - - expr: rate(node_vmstat_pgmajfault{job="node-exporter"}[1m]) - record: instance:node_vmstat_pgmajfault:rate1m - - expr: rate(node_disk_io_time_seconds_total{job="node-exporter", device=~"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+"}[1m]) - record: instance_device:node_disk_io_time_seconds:rate1m - - expr: rate(node_disk_io_time_weighted_seconds_total{job="node-exporter", device=~"mmcblk.p.+|nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+|dasd.+"}[1m]) - record: instance_device:node_disk_io_time_weighted_seconds:rate1m - - expr: |- - sum without (device) ( - rate(node_network_receive_bytes_total{job="node-exporter", device!="lo"}[1m]) - ) - record: instance:node_network_receive_bytes_excluding_lo:rate1m - - expr: |- - sum without (device) ( - rate(node_network_transmit_bytes_total{job="node-exporter", device!="lo"}[1m]) - ) - record: instance:node_network_transmit_bytes_excluding_lo:rate1m - - expr: |- - sum without (device) ( - rate(node_network_receive_drop_total{job="node-exporter", device!="lo"}[1m]) - ) - record: instance:node_network_receive_drop_excluding_lo:rate1m - - expr: |- - sum without (device) ( - rate(node_network_transmit_drop_total{job="node-exporter", device!="lo"}[1m]) - ) - record: instance:node_network_transmit_drop_excluding_lo:rate1m -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-exporter.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-exporter.yaml deleted file mode 100644 index 7d5ab7dc6..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-exporter.yaml +++ /dev/null @@ -1,278 +0,0 @@ -{{- /* -Generated from 'node-exporter' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.node }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "node-exporter" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: node-exporter - rules: - - alert: NodeFilesystemSpaceFillingUp - annotations: - description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf "%.2f" $value {{`}}`}}% available space left and is filling up. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemspacefillingup - summary: Filesystem is predicted to run out of space within the next 24 hours. - expr: |- - ( - node_filesystem_avail_bytes{job="node-exporter",fstype!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!=""} * 100 < 40 - and - predict_linear(node_filesystem_avail_bytes{job="node-exporter",fstype!=""}[6h], 24*60*60) < 0 - and - node_filesystem_readonly{job="node-exporter",fstype!=""} == 0 - ) - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeFilesystemSpaceFillingUp - annotations: - description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf "%.2f" $value {{`}}`}}% available space left and is filling up fast. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemspacefillingup - summary: Filesystem is predicted to run out of space within the next 4 hours. - expr: |- - ( - node_filesystem_avail_bytes{job="node-exporter",fstype!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!=""} * 100 < 15 - and - predict_linear(node_filesystem_avail_bytes{job="node-exporter",fstype!=""}[6h], 4*60*60) < 0 - and - node_filesystem_readonly{job="node-exporter",fstype!=""} == 0 - ) - for: 1h - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeFilesystemAlmostOutOfSpace - annotations: - description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf "%.2f" $value {{`}}`}}% available space left. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemalmostoutofspace - summary: Filesystem has less than 5% space left. - expr: |- - ( - node_filesystem_avail_bytes{job="node-exporter",fstype!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!=""} * 100 < 5 - and - node_filesystem_readonly{job="node-exporter",fstype!=""} == 0 - ) - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeFilesystemAlmostOutOfSpace - annotations: - description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf "%.2f" $value {{`}}`}}% available space left. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemalmostoutofspace - summary: Filesystem has less than 3% space left. - expr: |- - ( - node_filesystem_avail_bytes{job="node-exporter",fstype!=""} / node_filesystem_size_bytes{job="node-exporter",fstype!=""} * 100 < 3 - and - node_filesystem_readonly{job="node-exporter",fstype!=""} == 0 - ) - for: 1h - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeFilesystemFilesFillingUp - annotations: - description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf "%.2f" $value {{`}}`}}% available inodes left and is filling up. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemfilesfillingup - summary: Filesystem is predicted to run out of inodes within the next 24 hours. - expr: |- - ( - node_filesystem_files_free{job="node-exporter",fstype!=""} / node_filesystem_files{job="node-exporter",fstype!=""} * 100 < 40 - and - predict_linear(node_filesystem_files_free{job="node-exporter",fstype!=""}[6h], 24*60*60) < 0 - and - node_filesystem_readonly{job="node-exporter",fstype!=""} == 0 - ) - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeFilesystemFilesFillingUp - annotations: - description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf "%.2f" $value {{`}}`}}% available inodes left and is filling up fast. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemfilesfillingup - summary: Filesystem is predicted to run out of inodes within the next 4 hours. - expr: |- - ( - node_filesystem_files_free{job="node-exporter",fstype!=""} / node_filesystem_files{job="node-exporter",fstype!=""} * 100 < 20 - and - predict_linear(node_filesystem_files_free{job="node-exporter",fstype!=""}[6h], 4*60*60) < 0 - and - node_filesystem_readonly{job="node-exporter",fstype!=""} == 0 - ) - for: 1h - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeFilesystemAlmostOutOfFiles - annotations: - description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf "%.2f" $value {{`}}`}}% available inodes left. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemalmostoutoffiles - summary: Filesystem has less than 5% inodes left. - expr: |- - ( - node_filesystem_files_free{job="node-exporter",fstype!=""} / node_filesystem_files{job="node-exporter",fstype!=""} * 100 < 5 - and - node_filesystem_readonly{job="node-exporter",fstype!=""} == 0 - ) - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeFilesystemAlmostOutOfFiles - annotations: - description: Filesystem on {{`{{`}} $labels.device {{`}}`}} at {{`{{`}} $labels.instance {{`}}`}} has only {{`{{`}} printf "%.2f" $value {{`}}`}}% available inodes left. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodefilesystemalmostoutoffiles - summary: Filesystem has less than 3% inodes left. - expr: |- - ( - node_filesystem_files_free{job="node-exporter",fstype!=""} / node_filesystem_files{job="node-exporter",fstype!=""} * 100 < 3 - and - node_filesystem_readonly{job="node-exporter",fstype!=""} == 0 - ) - for: 1h - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeNetworkReceiveErrs - annotations: - description: '{{`{{`}} $labels.instance {{`}}`}} interface {{`{{`}} $labels.device {{`}}`}} has encountered {{`{{`}} printf "%.0f" $value {{`}}`}} receive errors in the last two minutes.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodenetworkreceiveerrs - summary: Network interface is reporting many receive errors. - expr: rate(node_network_receive_errs_total[2m]) / rate(node_network_receive_packets_total[2m]) > 0.01 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeNetworkTransmitErrs - annotations: - description: '{{`{{`}} $labels.instance {{`}}`}} interface {{`{{`}} $labels.device {{`}}`}} has encountered {{`{{`}} printf "%.0f" $value {{`}}`}} transmit errors in the last two minutes.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodenetworktransmiterrs - summary: Network interface is reporting many transmit errors. - expr: rate(node_network_transmit_errs_total[2m]) / rate(node_network_transmit_packets_total[2m]) > 0.01 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeHighNumberConntrackEntriesUsed - annotations: - description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of conntrack entries are used.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodehighnumberconntrackentriesused - summary: Number of conntrack are getting close to the limit. - expr: (node_nf_conntrack_entries / node_nf_conntrack_entries_limit) > 0.75 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeTextFileCollectorScrapeError - annotations: - description: Node Exporter text file collector failed to scrape. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodetextfilecollectorscrapeerror - summary: Node Exporter text file collector failed to scrape. - expr: node_textfile_scrape_error{job="node-exporter"} == 1 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeClockSkewDetected - annotations: - message: Clock on {{`{{`}} $labels.instance {{`}}`}} is out of sync by more than 300s. Ensure NTP is configured correctly on this host. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodeclockskewdetected - summary: Clock skew detected. - expr: |- - ( - node_timex_offset_seconds > 0.05 - and - deriv(node_timex_offset_seconds[5m]) >= 0 - ) - or - ( - node_timex_offset_seconds < -0.05 - and - deriv(node_timex_offset_seconds[5m]) <= 0 - ) - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeClockNotSynchronising - annotations: - message: Clock on {{`{{`}} $labels.instance {{`}}`}} is not synchronising. Ensure NTP is configured on this host. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodeclocknotsynchronising - summary: Clock not synchronising. - expr: |- - min_over_time(node_timex_sync_status[5m]) == 0 - and - node_timex_maxerror_seconds >= 16 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeRAIDDegraded - annotations: - description: RAID array '{{`{{`}} $labels.device {{`}}`}}' on {{`{{`}} $labels.instance {{`}}`}} is in degraded state due to one or more disks failures. Number of spare drives is insufficient to fix issue automatically. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-noderaiddegraded - summary: RAID Array is degraded - expr: node_md_disks_required - ignoring (state) (node_md_disks{state="active"}) > 0 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeRAIDDiskFailure - annotations: - description: At least one device in RAID array on {{`{{`}} $labels.instance {{`}}`}} failed. Array '{{`{{`}} $labels.device {{`}}`}}' needs attention and possibly a disk swap. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-noderaiddiskfailure - summary: Failed device in RAID array - expr: node_md_disks{state="fail"} > 0 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-network.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-network.yaml deleted file mode 100644 index 9a6955ae9..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node-network.yaml +++ /dev/null @@ -1,37 +0,0 @@ -{{- /* -Generated from 'node-network' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.network }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "node-network" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: node-network - rules: - - alert: NodeNetworkInterfaceFlapping - annotations: - message: Network interface "{{`{{`}} $labels.device {{`}}`}}" changing it's up status often on node-exporter {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}}" - expr: changes(node_network_up{job="node-exporter",device!~"veth.+"}[2m]) > 2 - for: 2m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node.rules.yaml deleted file mode 100644 index 7253b311b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/node.rules.yaml +++ /dev/null @@ -1,53 +0,0 @@ -{{- /* -Generated from 'node.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.node }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "node.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: node.rules - rules: - - expr: sum(min(kube_pod_info{node!=""}) by (cluster, node)) - record: ':kube_pod_info_node_count:' - - expr: |- - topk by(namespace, pod) (1, - max by (node, namespace, pod) ( - label_replace(kube_pod_info{job="kube-state-metrics",node!=""}, "pod", "$1", "pod", "(.*)") - )) - record: 'node_namespace_pod:kube_pod_info:' - - expr: |- - count by (cluster, node) (sum by (node, cpu) ( - node_cpu_seconds_total{job="node-exporter"} - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - )) - record: node:node_num_cpu:sum - - expr: |- - sum( - node_memory_MemAvailable_bytes{job="node-exporter"} or - ( - node_memory_Buffers_bytes{job="node-exporter"} + - node_memory_Cached_bytes{job="node-exporter"} + - node_memory_MemFree_bytes{job="node-exporter"} + - node_memory_Slab_bytes{job="node-exporter"} - ) - ) by (cluster) - record: :node_memory_MemAvailable_bytes:sum -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/prometheus-operator.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/prometheus-operator.yaml deleted file mode 100644 index d1c1f6545..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/prometheus-operator.yaml +++ /dev/null @@ -1,113 +0,0 @@ -{{- /* -Generated from 'prometheus-operator' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheusOperator }} -{{- $operatorJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "operator" }} -{{- $namespace := printf "%s" (include "kube-prometheus-stack.namespace" .) }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus-operator" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: prometheus-operator - rules: - - alert: PrometheusOperatorListErrors - annotations: - description: Errors while performing List operations in controller {{`{{`}}$labels.controller{{`}}`}} in {{`{{`}}$labels.namespace{{`}}`}} namespace. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorlisterrors - summary: Errors while performing list operations in controller. - expr: (sum by (controller,namespace) (rate(prometheus_operator_list_operations_failed_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[10m])) / sum by (controller,namespace) (rate(prometheus_operator_list_operations_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[10m]))) > 0.4 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusOperatorWatchErrors - annotations: - description: Errors while performing watch operations in controller {{`{{`}}$labels.controller{{`}}`}} in {{`{{`}}$labels.namespace{{`}}`}} namespace. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorwatcherrors - summary: Errors while performing watch operations in controller. - expr: (sum by (controller,namespace) (rate(prometheus_operator_watch_operations_failed_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[10m])) / sum by (controller,namespace) (rate(prometheus_operator_watch_operations_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[10m]))) > 0.4 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusOperatorSyncFailed - annotations: - description: Controller {{`{{`}} $labels.controller {{`}}`}} in {{`{{`}} $labels.namespace {{`}}`}} namespace fails to reconcile {{`{{`}} $value {{`}}`}} objects. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorsyncfailed - summary: Last controller reconciliation failed - expr: min_over_time(prometheus_operator_syncs{status="failed",job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusOperatorReconcileErrors - annotations: - description: '{{`{{`}} $value | humanizePercentage {{`}}`}} of reconciling operations failed for {{`{{`}} $labels.controller {{`}}`}} controller in {{`{{`}} $labels.namespace {{`}}`}} namespace.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorreconcileerrors - summary: Errors while reconciling controller. - expr: (sum by (controller,namespace) (rate(prometheus_operator_reconcile_errors_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[5m]))) / (sum by (controller,namespace) (rate(prometheus_operator_reconcile_operations_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[5m]))) > 0.1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusOperatorNodeLookupErrors - annotations: - description: Errors while reconciling Prometheus in {{`{{`}} $labels.namespace {{`}}`}} Namespace. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatornodelookuperrors - summary: Errors while reconciling Prometheus. - expr: rate(prometheus_operator_node_address_lookup_errors_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[5m]) > 0.1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusOperatorNotReady - annotations: - description: Prometheus operator in {{`{{`}} $labels.namespace {{`}}`}} namespace isn't ready to reconcile {{`{{`}} $labels.controller {{`}}`}} resources. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatornotready - summary: Prometheus operator not ready - expr: min by(namespace, controller) (max_over_time(prometheus_operator_ready{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[5m]) == 0) - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusOperatorRejectedResources - annotations: - description: Prometheus operator in {{`{{`}} $labels.namespace {{`}}`}} namespace rejected {{`{{`}} printf "%0.0f" $value {{`}}`}} {{`{{`}} $labels.controller {{`}}`}}/{{`{{`}} $labels.resource {{`}}`}} resources. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatorrejectedresources - summary: Resources rejected by Prometheus operator - expr: min_over_time(prometheus_operator_managed_resources{state="rejected",job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/prometheus.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/prometheus.yaml deleted file mode 100644 index c9c805eea..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules-1.14/prometheus.yaml +++ /dev/null @@ -1,258 +0,0 @@ -{{- /* -Generated from 'prometheus' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/master/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheus }} -{{- $prometheusJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus" }} -{{- $namespace := printf "%s" (include "kube-prometheus-stack.namespace" .) }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: prometheus - rules: - - alert: PrometheusBadConfig - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to reload its configuration. - summary: Failed Prometheus configuration reload. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - max_over_time(prometheus_config_last_reload_successful{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) == 0 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusNotificationQueueRunningFull - annotations: - description: Alert notification queue of Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is running full. - summary: Prometheus alert notification queue predicted to run full in less than 30m. - expr: |- - # Without min_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - ( - predict_linear(prometheus_notifications_queue_length{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m], 60 * 30) - > - min_over_time(prometheus_notifications_queue_capacity{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusErrorSendingAlertsToSomeAlertmanagers - annotations: - description: '{{`{{`}} printf "%.1f" $value {{`}}`}}% errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to Alertmanager {{`{{`}}$labels.alertmanager{{`}}`}}.' - summary: Prometheus has encountered more than 1% errors sending alerts to a specific Alertmanager. - expr: |- - ( - rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - / - rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - * 100 - > 1 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusErrorSendingAlertsToAnyAlertmanager - annotations: - description: '{{`{{`}} printf "%.1f" $value {{`}}`}}% minimum errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} to any Alertmanager.' - summary: Prometheus encounters more than 3% errors sending alerts to any Alertmanager. - expr: |- - min without(alertmanager) ( - rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - / - rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - * 100 - > 3 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusNotConnectedToAlertmanagers - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not connected to any Alertmanagers. - summary: Prometheus is not connected to any Alertmanagers. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - max_over_time(prometheus_notifications_alertmanagers_discovered{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) < 1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusTSDBReloadsFailing - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} reload failures over the last 3h. - summary: Prometheus has issues reloading blocks from disk. - expr: increase(prometheus_tsdb_reloads_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[3h]) > 0 - for: 4h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusTSDBCompactionsFailing - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has detected {{`{{`}}$value | humanize{{`}}`}} compaction failures over the last 3h. - summary: Prometheus has issues compacting blocks. - expr: increase(prometheus_tsdb_compactions_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[3h]) > 0 - for: 4h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusNotIngestingSamples - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is not ingesting samples. - summary: Prometheus is not ingesting samples. - expr: rate(prometheus_tsdb_head_samples_appended_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) <= 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusDuplicateTimestamps - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf "%.4g" $value {{`}}`}} samples/s with different values but duplicated timestamp. - summary: Prometheus is dropping samples with duplicate timestamps. - expr: rate(prometheus_target_scrapes_sample_duplicate_timestamp_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusOutOfOrderTimestamps - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} is dropping {{`{{`}} printf "%.4g" $value {{`}}`}} samples/s with timestamps arriving out of order. - summary: Prometheus drops samples with out-of-order timestamps. - expr: rate(prometheus_target_scrapes_sample_out_of_order_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusRemoteStorageFailures - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} failed to send {{`{{`}} printf "%.1f" $value {{`}}`}}% of the samples to {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}} - summary: Prometheus fails to send samples to remote storage. - expr: |- - ( - rate(prometheus_remote_storage_failed_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - / - ( - rate(prometheus_remote_storage_failed_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - + - rate(prometheus_remote_storage_succeeded_samples_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - ) - * 100 - > 1 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusRemoteWriteBehind - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write is {{`{{`}} printf "%.1f" $value {{`}}`}}s behind for {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}. - summary: Prometheus remote write is behind. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - ( - max_over_time(prometheus_remote_storage_highest_timestamp_in_seconds{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - - on(job, instance) group_right - max_over_time(prometheus_remote_storage_queue_highest_sent_timestamp_seconds{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - > 120 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusRemoteWriteDesiredShards - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} remote write desired shards calculation wants to run {{`{{`}} $value {{`}}`}} shards for queue {{`{{`}} $labels.remote_name{{`}}`}}:{{`{{`}} $labels.url {{`}}`}}, which is more than the max of {{`{{`}} printf `prometheus_remote_storage_shards_max{instance="%s",job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}` $labels.instance | query | first | value {{`}}`}}. - summary: Prometheus remote write desired shards calculation wants to run more than configured max shards. - expr: |- - # Without max_over_time, failed scrapes could create false negatives, see - # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details. - ( - max_over_time(prometheus_remote_storage_shards_desired{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - > - max_over_time(prometheus_remote_storage_shards_max{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) - ) - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusRuleFailures - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has failed to evaluate {{`{{`}} printf "%.0f" $value {{`}}`}} rules in the last 5m. - summary: Prometheus is failing rule evaluations. - expr: increase(prometheus_rule_evaluation_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusMissingRuleEvaluations - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has missed {{`{{`}} printf "%.0f" $value {{`}}`}} rule group evaluations in the last 5m. - summary: Prometheus is missing rule evaluations due to slow rule group evaluation. - expr: increase(prometheus_rule_group_iterations_missed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusTargetLimitHit - annotations: - description: Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has dropped {{`{{`}} printf "%.0f" $value {{`}}`}} targets because the number of targets exceeded the configured target_limit. - summary: Prometheus has dropped targets because some scrape configs have exceeded the targets limit. - expr: increase(prometheus_target_scrape_pool_exceeded_target_limit_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/alertmanager.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/alertmanager.rules.yaml deleted file mode 100644 index 71159849c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/alertmanager.rules.yaml +++ /dev/null @@ -1,63 +0,0 @@ -{{- /* -Generated from 'alertmanager.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.alertmanager }} -{{- $operatorJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "operator" }} -{{- $alertmanagerJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "alertmanager" }} -{{- $namespace := printf "%s" (include "kube-prometheus-stack.namespace" .) }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "alertmanager.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: alertmanager.rules - rules: - - alert: AlertmanagerConfigInconsistent - annotations: - message: The configuration of the instances of the Alertmanager cluster `{{`{{`}}$labels.service{{`}}`}}` are out of sync. - expr: count_values("config_hash", alertmanager_config_hash{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}) BY (service) / ON(service) GROUP_LEFT() label_replace(max(prometheus_operator_spec_replicas{job="{{ $operatorJob }}",namespace="{{ $namespace }}",controller="alertmanager"}) by (name, job, namespace, controller), "service", "$1", "name", "(.*)") != 1 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: AlertmanagerFailedReload - annotations: - message: Reloading Alertmanager's configuration has failed for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}}. - expr: alertmanager_config_last_reload_successful{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} == 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: AlertmanagerMembersInconsistent - annotations: - message: Alertmanager has not found all other members of the cluster. - expr: |- - alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} - != on (service) GROUP_LEFT() - count by (service) (alertmanager_cluster_members{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"}) - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/etcd.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/etcd.yaml deleted file mode 100644 index e9c4f6cbb..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/etcd.yaml +++ /dev/null @@ -1,197 +0,0 @@ -{{- /* -Generated from 'etcd' group from https://raw.githubusercontent.com/etcd-io/etcd/master/Documentation/op-guide/etcd3_alert.rules.yml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeEtcd.enabled .Values.defaultRules.rules.etcd }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "etcd" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: etcd - rules: - - alert: etcdMembersDown - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": members are down ({{`{{`}} $value {{`}}`}}).' - expr: |- - max by (job) ( - sum by (job) (up{job=~".*etcd.*"} == bool 0) - or - count by (job,endpoint) ( - sum by (job,endpoint,To) (rate(etcd_network_peer_sent_failures_total{job=~".*etcd.*"}[3m])) > 0.01 - ) - ) - > 0 - for: 3m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdInsufficientMembers - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": insufficient members ({{`{{`}} $value {{`}}`}}).' - expr: sum(up{job=~".*etcd.*"} == bool 1) by (job) < ((count(up{job=~".*etcd.*"}) by (job) + 1) / 2) - for: 3m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdNoLeader - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": member {{`{{`}} $labels.instance {{`}}`}} has no leader.' - expr: etcd_server_has_leader{job=~".*etcd.*"} == 0 - for: 1m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfLeaderChanges - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": {{`{{`}} $value {{`}}`}} leader changes within the last 15 minutes. Frequent elections may be a sign of insufficient resources, high network latency, or disruptions by other components and should be investigated.' - expr: increase((max by (job) (etcd_server_leader_changes_seen_total{job=~".*etcd.*"}) or 0*absent(etcd_server_leader_changes_seen_total{job=~".*etcd.*"}))[15m:1m]) >= 3 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedGRPCRequests - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": {{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.grpc_method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - 100 * sum(rate(grpc_server_handled_total{job=~".*etcd.*", grpc_code!="OK"}[5m])) BY (job, instance, grpc_service, grpc_method) - / - sum(rate(grpc_server_handled_total{job=~".*etcd.*"}[5m])) BY (job, instance, grpc_service, grpc_method) - > 1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedGRPCRequests - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": {{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.grpc_method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - 100 * sum(rate(grpc_server_handled_total{job=~".*etcd.*", grpc_code!="OK"}[5m])) BY (job, instance, grpc_service, grpc_method) - / - sum(rate(grpc_server_handled_total{job=~".*etcd.*"}[5m])) BY (job, instance, grpc_service, grpc_method) - > 5 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdGRPCRequestsSlow - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": gRPC requests to {{`{{`}} $labels.grpc_method {{`}}`}} are taking {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - histogram_quantile(0.99, sum(rate(grpc_server_handling_seconds_bucket{job=~".*etcd.*", grpc_type="unary"}[5m])) by (job, instance, grpc_service, grpc_method, le)) - > 0.15 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdMemberCommunicationSlow - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": member communication with {{`{{`}} $labels.To {{`}}`}} is taking {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - histogram_quantile(0.99, rate(etcd_network_peer_round_trip_time_seconds_bucket{job=~".*etcd.*"}[5m])) - > 0.15 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedProposals - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": {{`{{`}} $value {{`}}`}} proposal failures within the last 30 minutes on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: rate(etcd_server_proposals_failed_total{job=~".*etcd.*"}[15m]) > 5 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighFsyncDurations - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": 99th percentile fync durations are {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - histogram_quantile(0.99, rate(etcd_disk_wal_fsync_duration_seconds_bucket{job=~".*etcd.*"}[5m])) - > 0.5 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighCommitDurations - annotations: - message: 'etcd cluster "{{`{{`}} $labels.job {{`}}`}}": 99th percentile commit durations {{`{{`}} $value {{`}}`}}s on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - histogram_quantile(0.99, rate(etcd_disk_backend_commit_duration_seconds_bucket{job=~".*etcd.*"}[5m])) - > 0.25 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedHTTPRequests - annotations: - message: '{{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}' - expr: |- - sum(rate(etcd_http_failed_total{job=~".*etcd.*", code!="404"}[5m])) BY (method) / sum(rate(etcd_http_received_total{job=~".*etcd.*"}[5m])) - BY (method) > 0.01 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHighNumberOfFailedHTTPRequests - annotations: - message: '{{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.method {{`}}`}} failed on etcd instance {{`{{`}} $labels.instance {{`}}`}}.' - expr: |- - sum(rate(etcd_http_failed_total{job=~".*etcd.*", code!="404"}[5m])) BY (method) / sum(rate(etcd_http_received_total{job=~".*etcd.*"}[5m])) - BY (method) > 0.05 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: etcdHTTPRequestsSlow - annotations: - message: etcd instance {{`{{`}} $labels.instance {{`}}`}} HTTP requests to {{`{{`}} $labels.method {{`}}`}} are slow. - expr: |- - histogram_quantile(0.99, rate(etcd_http_successful_duration_seconds_bucket[5m])) - > 0.15 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/general.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/general.rules.yaml deleted file mode 100644 index cde6feb5c..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/general.rules.yaml +++ /dev/null @@ -1,56 +0,0 @@ -{{- /* -Generated from 'general.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.general }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "general.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: general.rules - rules: - - alert: TargetDown - annotations: - message: '{{`{{`}} $value {{`}}`}}% of the {{`{{`}} $labels.job {{`}}`}} targets are down.' - expr: 100 * (count(up == 0) BY (job) / count(up) BY (job)) > 10 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: Watchdog - annotations: - message: 'This is an alert meant to ensure that the entire alerting pipeline is functional. - - This alert is always firing, therefore it should always be firing in Alertmanager - - and always fire against a receiver. There are integrations with various notification - - mechanisms that send a notification when this alert is not firing. For example the - - "DeadMansSnitch" integration in PagerDuty. - - ' - expr: vector(1) - labels: - severity: none -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/k8s.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/k8s.rules.yaml deleted file mode 100644 index 08aa7fe2b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/k8s.rules.yaml +++ /dev/null @@ -1,83 +0,0 @@ -{{- /* -Generated from 'k8s.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.k8s }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "k8s.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: k8s.rules - rules: - - expr: sum(rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m])) by (namespace) - record: namespace:container_cpu_usage_seconds_total:sum_rate - - expr: sum(container_memory_usage_bytes{job="kubelet", image!="", container_name!=""}) by (namespace) - record: namespace:container_memory_usage_bytes:sum - - expr: |- - sum by (namespace, pod_name, container_name) ( - rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m]) - ) - record: namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate - - expr: |- - sum by(namespace) ( - kube_pod_container_resource_requests_memory_bytes{job="kube-state-metrics"} - * on (endpoint, instance, job, namespace, pod, service) - group_left(phase) (kube_pod_status_phase{phase=~"^(Pending|Running)$"} == 1) - ) - record: namespace_name:kube_pod_container_resource_requests_memory_bytes:sum - - expr: |- - sum by (namespace) ( - kube_pod_container_resource_requests_cpu_cores{job="kube-state-metrics"} - * on (endpoint, instance, job, namespace, pod, service) - group_left(phase) (kube_pod_status_phase{phase=~"^(Pending|Running)$"} == 1) - ) - record: namespace_name:kube_pod_container_resource_requests_cpu_cores:sum - - expr: |- - sum( - label_replace( - label_replace( - kube_pod_owner{job="kube-state-metrics", owner_kind="ReplicaSet"}, - "replicaset", "$1", "owner_name", "(.*)" - ) * on(replicaset, namespace) group_left(owner_name) kube_replicaset_owner{job="kube-state-metrics"}, - "workload", "$1", "owner_name", "(.*)" - ) - ) by (namespace, workload, pod) - labels: - workload_type: deployment - record: mixin_pod_workload - - expr: |- - sum( - label_replace( - kube_pod_owner{job="kube-state-metrics", owner_kind="DaemonSet"}, - "workload", "$1", "owner_name", "(.*)" - ) - ) by (namespace, workload, pod) - labels: - workload_type: daemonset - record: mixin_pod_workload - - expr: |- - sum( - label_replace( - kube_pod_owner{job="kube-state-metrics", owner_kind="StatefulSet"}, - "workload", "$1", "owner_name", "(.*)" - ) - ) by (namespace, workload, pod) - labels: - workload_type: statefulset - record: mixin_pod_workload -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-apiserver.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-apiserver.rules.yaml deleted file mode 100644 index e3a929692..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-apiserver.rules.yaml +++ /dev/null @@ -1,39 +0,0 @@ -{{- /* -Generated from 'kube-apiserver.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserver }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-apiserver.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-apiserver.rules - rules: - - expr: histogram_quantile(0.99, sum(rate(apiserver_request_latencies_bucket{job="apiserver"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.99' - record: cluster_quantile:apiserver_request_latencies:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(apiserver_request_latencies_bucket{job="apiserver"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.9' - record: cluster_quantile:apiserver_request_latencies:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(apiserver_request_latencies_bucket{job="apiserver"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.5' - record: cluster_quantile:apiserver_request_latencies:histogram_quantile -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-prometheus-node-alerting.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-prometheus-node-alerting.rules.yaml deleted file mode 100644 index a8d5400cb..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-prometheus-node-alerting.rules.yaml +++ /dev/null @@ -1,47 +0,0 @@ -{{- /* -Generated from 'kube-prometheus-node-alerting.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubePrometheusNodeAlerting }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-prometheus-node-alerting.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-prometheus-node-alerting.rules - rules: - - alert: NodeDiskRunningFull - annotations: - message: Device {{`{{`}} $labels.device {{`}}`}} of node-exporter {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} will be full within the next 24 hours. - expr: '(node:node_filesystem_usage: > 0.85) and (predict_linear(node:node_filesystem_avail:[6h], 3600 * 24) < 0)' - for: 30m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeDiskRunningFull - annotations: - message: Device {{`{{`}} $labels.device {{`}}`}} of node-exporter {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} will be full within the next 2 hours. - expr: '(node:node_filesystem_usage: > 0.85) and (predict_linear(node:node_filesystem_avail:[30m], 3600 * 2) < 0)' - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-prometheus-node-recording.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-prometheus-node-recording.rules.yaml deleted file mode 100644 index 87f072fd0..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-prometheus-node-recording.rules.yaml +++ /dev/null @@ -1,41 +0,0 @@ -{{- /* -Generated from 'kube-prometheus-node-recording.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubePrometheusNodeRecording }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-prometheus-node-recording.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-prometheus-node-recording.rules - rules: - - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait"}[3m])) BY (instance) - record: instance:node_cpu:rate:sum - - expr: sum((node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"})) BY (instance) - record: instance:node_filesystem_usage:sum - - expr: sum(rate(node_network_receive_bytes_total[3m])) BY (instance) - record: instance:node_network_receive_bytes:rate:sum - - expr: sum(rate(node_network_transmit_bytes_total[3m])) BY (instance) - record: instance:node_network_transmit_bytes:rate:sum - - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait"}[5m])) WITHOUT (cpu, mode) / ON(instance) GROUP_LEFT() count(sum(node_cpu_seconds_total) BY (instance, cpu)) BY (instance) - record: instance:node_cpu:ratio - - expr: sum(rate(node_cpu_seconds_total{mode!="idle",mode!="iowait"}[5m])) - record: cluster:node_cpu:sum_rate5m - - expr: cluster:node_cpu_seconds_total:rate5m / count(sum(node_cpu_seconds_total) BY (instance, cpu)) - record: cluster:node_cpu:ratio -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-scheduler.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-scheduler.rules.yaml deleted file mode 100644 index 46c8d1d4a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kube-scheduler.rules.yaml +++ /dev/null @@ -1,63 +0,0 @@ -{{- /* -Generated from 'kube-scheduler.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.kubeScheduler.enabled .Values.defaultRules.rules.kubeScheduler }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kube-scheduler.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kube-scheduler.rules - rules: - - expr: histogram_quantile(0.99, sum(rate(scheduler_e2e_scheduling_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.99' - record: cluster_quantile:scheduler_e2e_scheduling_latency:histogram_quantile - - expr: histogram_quantile(0.99, sum(rate(scheduler_scheduling_algorithm_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.99' - record: cluster_quantile:scheduler_scheduling_algorithm_latency:histogram_quantile - - expr: histogram_quantile(0.99, sum(rate(scheduler_binding_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.99' - record: cluster_quantile:scheduler_binding_latency:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(scheduler_e2e_scheduling_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.9' - record: cluster_quantile:scheduler_e2e_scheduling_latency:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(scheduler_scheduling_algorithm_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.9' - record: cluster_quantile:scheduler_scheduling_algorithm_latency:histogram_quantile - - expr: histogram_quantile(0.9, sum(rate(scheduler_binding_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.9' - record: cluster_quantile:scheduler_binding_latency:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(scheduler_e2e_scheduling_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.5' - record: cluster_quantile:scheduler_e2e_scheduling_latency:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(scheduler_scheduling_algorithm_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.5' - record: cluster_quantile:scheduler_scheduling_algorithm_latency:histogram_quantile - - expr: histogram_quantile(0.5, sum(rate(scheduler_binding_latency_microseconds_bucket{job="kube-scheduler"}[5m])) without(instance, pod)) / 1e+06 - labels: - quantile: '0.5' - record: cluster_quantile:scheduler_binding_latency:histogram_quantile -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-absent.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-absent.yaml deleted file mode 100644 index 5c1ebce9e..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-absent.yaml +++ /dev/null @@ -1,159 +0,0 @@ -{{- /* -Generated from 'kubernetes-absent' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesAbsent }} -{{- $operatorJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "operator" }} -{{- $prometheusJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus" }} -{{- $alertmanagerJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "alertmanager" }} -{{- $namespace := printf "%s" (include "kube-prometheus-stack.namespace" .) }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-absent" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-absent - rules: -{{- if .Values.alertmanager.enabled }} - - alert: AlertmanagerDown - annotations: - message: Alertmanager has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-alertmanagerdown - expr: absent(up{job="{{ $alertmanagerJob }}",namespace="{{ $namespace }}"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if .Values.kubeDns.enabled }} - - alert: CoreDNSDown - annotations: - message: CoreDNS has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-corednsdown - expr: absent(up{job="kube-dns"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if .Values.kubeApiServer.enabled }} - - alert: KubeAPIDown - annotations: - message: KubeAPI has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapidown - expr: absent(up{job="apiserver"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if .Values.kubeControllerManager.enabled }} - - alert: KubeControllerManagerDown - annotations: - message: KubeControllerManager has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecontrollermanagerdown - expr: absent(up{job="kube-controller-manager"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if .Values.kubeScheduler.enabled }} - - alert: KubeSchedulerDown - annotations: - message: KubeScheduler has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeschedulerdown - expr: absent(up{job="kube-scheduler"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if .Values.kubeStateMetrics.enabled }} - - alert: KubeStateMetricsDown - annotations: - message: KubeStateMetrics has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatemetricsdown - expr: absent(up{job="kube-state-metrics"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if .Values.prometheusOperator.kubeletService.enabled }} - - alert: KubeletDown - annotations: - message: Kubelet has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeletdown - expr: absent(up{job="kubelet"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- if .Values.nodeExporter.enabled }} - - alert: NodeExporterDown - annotations: - message: NodeExporter has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-nodeexporterdown - expr: absent(up{job="node-exporter"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} - - alert: PrometheusDown - annotations: - message: Prometheus has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusdown - expr: absent(up{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- if .Values.prometheusOperator.enabled }} - - alert: PrometheusOperatorDown - annotations: - message: PrometheusOperator has disappeared from Prometheus target discovery. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-prometheusoperatordown - expr: absent(up{job="{{ $operatorJob }}",namespace="{{ $namespace }}"} == 1) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-apps.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-apps.yaml deleted file mode 100644 index e7a41ca2a..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-apps.yaml +++ /dev/null @@ -1,200 +0,0 @@ -{{- /* -Generated from 'kubernetes-apps' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesApps }} -{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-apps" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-apps - rules: - - alert: KubePodCrashLooping - annotations: - message: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} ({{`{{`}} $labels.container {{`}}`}}) is restarting {{`{{`}} printf "%.2f" $value {{`}}`}} times / 5 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepodcrashlooping - expr: rate(kube_pod_container_status_restarts_total{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"}[15m]) * 60 * 5 > 0 - for: 1h - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubePodNotReady - annotations: - message: Pod {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}} has been in a non-ready state for longer than an hour. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepodnotready - expr: sum by (namespace, pod) (kube_pod_status_phase{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}", phase=~"Pending|Unknown"}) > 0 - for: 1h - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDeploymentGenerationMismatch - annotations: - message: Deployment generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} does not match, this indicates that the Deployment has failed but has not been rolled back. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedeploymentgenerationmismatch - expr: |- - kube_deployment_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_deployment_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDeploymentReplicasMismatch - annotations: - message: Deployment {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.deployment {{`}}`}} has not matched the expected number of replicas for longer than an hour. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedeploymentreplicasmismatch - expr: |- - kube_deployment_spec_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_deployment_status_replicas_available{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 1h - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeStatefulSetReplicasMismatch - annotations: - message: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} has not matched the expected number of replicas for longer than 15 minutes. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetreplicasmismatch - expr: |- - kube_statefulset_status_replicas_ready{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_status_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeStatefulSetGenerationMismatch - annotations: - message: StatefulSet generation for {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} does not match, this indicates that the StatefulSet has failed but has not been rolled back. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetgenerationmismatch - expr: |- - kube_statefulset_status_observed_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_metadata_generation{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeStatefulSetUpdateNotRolledOut - annotations: - message: StatefulSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.statefulset {{`}}`}} update has not been rolled out. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubestatefulsetupdatenotrolledout - expr: |- - max without (revision) ( - kube_statefulset_status_current_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - unless - kube_statefulset_status_update_revision{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) - * - ( - kube_statefulset_replicas{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - != - kube_statefulset_status_replicas_updated{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - ) - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDaemonSetRolloutStuck - annotations: - message: Only {{`{{`}} $value {{`}}`}}% of the desired Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are scheduled and ready. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetrolloutstuck - expr: |- - kube_daemonset_status_number_ready{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - / - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} * 100 < 100 - for: 15m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDaemonSetNotScheduled - annotations: - message: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are not scheduled.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetnotscheduled - expr: |- - kube_daemonset_status_desired_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - - - kube_daemonset_status_current_number_scheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeDaemonSetMisScheduled - annotations: - message: '{{`{{`}} $value {{`}}`}} Pods of DaemonSet {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.daemonset {{`}}`}} are running where they are not supposed to run.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubedaemonsetmisscheduled - expr: kube_daemonset_status_number_misscheduled{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeCronJobRunning - annotations: - message: CronJob {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.cronjob {{`}}`}} is taking more than 1h to complete. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecronjobrunning - expr: time() - kube_cronjob_next_schedule_time{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 3600 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeJobCompletion - annotations: - message: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} is taking more than one hour to complete. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubejobcompletion - expr: kube_job_spec_completions{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} - kube_job_status_succeeded{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeJobFailed - annotations: - message: Job {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.job_name {{`}}`}} failed to complete. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubejobfailed - expr: kube_job_status_failed{job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"} > 0 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-resources.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-resources.yaml deleted file mode 100644 index b34b442f3..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-resources.yaml +++ /dev/null @@ -1,121 +0,0 @@ -{{- /* -Generated from 'kubernetes-resources' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesResources }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-resources" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-resources - rules: - - alert: KubeCPUOvercommit - annotations: - message: Cluster has overcommitted CPU resource requests for Pods and cannot tolerate node failure. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecpuovercommit - expr: |- - sum(namespace_name:kube_pod_container_resource_requests_cpu_cores:sum) - / - sum(node:node_num_cpu:sum) - > - (count(node:node_num_cpu:sum)-1) / count(node:node_num_cpu:sum) - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeMemOvercommit - annotations: - message: Cluster has overcommitted memory resource requests for Pods and cannot tolerate node failure. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubememovercommit - expr: |- - sum(namespace_name:kube_pod_container_resource_requests_memory_bytes:sum) - / - sum(node_memory_MemTotal_bytes) - > - (count(node:node_num_cpu:sum)-1) - / - count(node:node_num_cpu:sum) - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeCPUOvercommit - annotations: - message: Cluster has overcommitted CPU resource requests for Namespaces. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubecpuovercommit - expr: |- - sum(kube_resourcequota{job="kube-state-metrics", type="hard", resource="cpu"}) - / - sum(node:node_num_cpu:sum) - > 1.5 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeMemOvercommit - annotations: - message: Cluster has overcommitted memory resource requests for Namespaces. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubememovercommit - expr: |- - sum(kube_resourcequota{job="kube-state-metrics", type="hard", resource="memory"}) - / - sum(node_memory_MemTotal_bytes{job="node-exporter"}) - > 1.5 - for: 5m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeQuotaExceeded - annotations: - message: Namespace {{`{{`}} $labels.namespace {{`}}`}} is using {{`{{`}} printf "%0.0f" $value {{`}}`}}% of its {{`{{`}} $labels.resource {{`}}`}} quota. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubequotaexceeded - expr: |- - 100 * kube_resourcequota{job="kube-state-metrics", type="used"} - / ignoring(instance, job, type) - (kube_resourcequota{job="kube-state-metrics", type="hard"} > 0) - > 90 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: CPUThrottlingHigh - annotations: - message: '{{`{{`}} printf "%0.0f" $value {{`}}`}}% throttling of CPU in namespace {{`{{`}} $labels.namespace {{`}}`}} for container {{`{{`}} $labels.container_name {{`}}`}} in pod {{`{{`}} $labels.pod_name {{`}}`}}.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-cputhrottlinghigh - expr: |- - 100 * sum(increase(container_cpu_cfs_throttled_periods_total{container_name!="", }[5m])) by (container_name, pod_name, namespace) - / - sum(increase(container_cpu_cfs_periods_total{}[5m])) by (container_name, pod_name, namespace) - > 25 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-storage.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-storage.yaml deleted file mode 100644 index 6469fffc5..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-storage.yaml +++ /dev/null @@ -1,72 +0,0 @@ -{{- /* -Generated from 'kubernetes-storage' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesStorage }} -{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-storage" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-storage - rules: - - alert: KubePersistentVolumeUsageCritical - annotations: - message: The PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is only {{`{{`}} printf "%0.2f" $value {{`}}`}}% free. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumeusagecritical - expr: |- - 100 * kubelet_volume_stats_available_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}"} - / - kubelet_volume_stats_capacity_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}"} - < 3 - for: 1m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubePersistentVolumeFullInFourDays - annotations: - message: Based on recent sampling, the PersistentVolume claimed by {{`{{`}} $labels.persistentvolumeclaim {{`}}`}} in Namespace {{`{{`}} $labels.namespace {{`}}`}} is expected to fill up within four days. Currently {{`{{`}} printf "%0.2f" $value {{`}}`}}% is available. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumefullinfourdays - expr: |- - 100 * ( - kubelet_volume_stats_available_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}"} - / - kubelet_volume_stats_capacity_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}"} - ) < 15 - and - predict_linear(kubelet_volume_stats_available_bytes{job="kubelet", namespace=~"{{ $targetNamespace }}"}[6h], 4 * 24 * 3600) < 0 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubePersistentVolumeErrors - annotations: - message: The persistent volume {{`{{`}} $labels.persistentvolume {{`}}`}} has status {{`{{`}} $labels.phase {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubepersistentvolumeerrors - expr: kube_persistentvolume_status_phase{phase=~"Failed|Pending",job="kube-state-metrics"} > 0 - for: 5m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-system.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-system.yaml deleted file mode 100644 index da232057b..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/kubernetes-system.yaml +++ /dev/null @@ -1,184 +0,0 @@ -{{- /* -Generated from 'kubernetes-system' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.kubernetesSystem }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "kubernetes-system" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: kubernetes-system - rules: - - alert: KubeNodeNotReady - annotations: - message: '{{`{{`}} $labels.node {{`}}`}} has been unready for more than an hour.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubenodenotready - expr: kube_node_status_condition{job="kube-state-metrics",condition="Ready",status="true"} == 0 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeVersionMismatch - annotations: - message: There are {{`{{`}} $value {{`}}`}} different semantic versions of Kubernetes components running. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeversionmismatch - expr: count(count by (gitVersion) (label_replace(kubernetes_build_info{job!~"kube-dns|coredns"},"gitVersion","$1","gitVersion","(v[0-9]*.[0-9]*.[0-9]*).*"))) > 1 - for: 1h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeClientErrors - annotations: - message: Kubernetes API server client '{{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.instance {{`}}`}}' is experiencing {{`{{`}} printf "%0.0f" $value {{`}}`}}% errors.' - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclienterrors - expr: |- - (sum(rate(rest_client_requests_total{code=~"5.."}[5m])) by (instance, job) - / - sum(rate(rest_client_requests_total[5m])) by (instance, job)) - * 100 > 1 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeClientErrors - annotations: - message: Kubernetes API server client '{{`{{`}} $labels.job {{`}}`}}/{{`{{`}} $labels.instance {{`}}`}}' is experiencing {{`{{`}} printf "%0.0f" $value {{`}}`}} errors / second. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclienterrors - expr: sum(rate(ksm_scrape_error_total{job="kube-state-metrics"}[5m])) by (instance, job) > 0.1 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeletTooManyPods - annotations: - message: Kubelet {{`{{`}} $labels.instance {{`}}`}} is running {{`{{`}} $value {{`}}`}} Pods, close to the limit of 110. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubelettoomanypods - expr: kubelet_running_pod_count{job="kubelet"} > 110 * 0.9 - for: 15m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPILatencyHigh - annotations: - message: The API server has a 99th percentile latency of {{`{{`}} $value {{`}}`}} seconds for {{`{{`}} $labels.verb {{`}}`}} {{`{{`}} $labels.resource {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapilatencyhigh - expr: cluster_quantile:apiserver_request_latencies:histogram_quantile{job="apiserver",quantile="0.99",subresource!="log",verb!~"^(?:LIST|WATCH|WATCHLIST|PROXY|CONNECT)$"} > 1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPILatencyHigh - annotations: - message: The API server has a 99th percentile latency of {{`{{`}} $value {{`}}`}} seconds for {{`{{`}} $labels.verb {{`}}`}} {{`{{`}} $labels.resource {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapilatencyhigh - expr: cluster_quantile:apiserver_request_latencies:histogram_quantile{job="apiserver",quantile="0.99",subresource!="log",verb!~"^(?:LIST|WATCH|WATCHLIST|PROXY|CONNECT)$"} > 4 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPIErrorsHigh - annotations: - message: API server is returning errors for {{`{{`}} $value {{`}}`}}% of requests. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorshigh - expr: |- - sum(rate(apiserver_request_count{job="apiserver",code=~"^(?:5..)$"}[5m])) - / - sum(rate(apiserver_request_count{job="apiserver"}[5m])) * 100 > 3 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPIErrorsHigh - annotations: - message: API server is returning errors for {{`{{`}} $value {{`}}`}}% of requests. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorshigh - expr: |- - sum(rate(apiserver_request_count{job="apiserver",code=~"^(?:5..)$"}[5m])) - / - sum(rate(apiserver_request_count{job="apiserver"}[5m])) * 100 > 1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPIErrorsHigh - annotations: - message: API server is returning errors for {{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.verb {{`}}`}} {{`{{`}} $labels.resource {{`}}`}} {{`{{`}} $labels.subresource {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorshigh - expr: |- - sum(rate(apiserver_request_count{job="apiserver",code=~"^(?:5..)$"}[5m])) by (resource,subresource,verb) - / - sum(rate(apiserver_request_count{job="apiserver"}[5m])) by (resource,subresource,verb) * 100 > 10 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeAPIErrorsHigh - annotations: - message: API server is returning errors for {{`{{`}} $value {{`}}`}}% of requests for {{`{{`}} $labels.verb {{`}}`}} {{`{{`}} $labels.resource {{`}}`}} {{`{{`}} $labels.subresource {{`}}`}}. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeapierrorshigh - expr: |- - sum(rate(apiserver_request_count{job="apiserver",code=~"^(?:5..)$"}[5m])) by (resource,subresource,verb) - / - sum(rate(apiserver_request_count{job="apiserver"}[5m])) by (resource,subresource,verb) * 100 > 5 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeClientCertificateExpiration - annotations: - message: A client certificate used to authenticate to the apiserver is expiring in less than 7.0 days. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclientcertificateexpiration - expr: apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 and histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 604800 - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: KubeClientCertificateExpiration - annotations: - message: A client certificate used to authenticate to the apiserver is expiring in less than 24.0 hours. - runbook_url: {{ .Values.defaultRules.runbookUrl }}alert-name-kubeclientcertificateexpiration - expr: apiserver_client_certificate_expiration_seconds_count{job="apiserver"} > 0 and histogram_quantile(0.01, sum by (job, le) (rate(apiserver_client_certificate_expiration_seconds_bucket{job="apiserver"}[5m]))) < 86400 - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node-network.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node-network.yaml deleted file mode 100644 index c75f1ae07..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node-network.yaml +++ /dev/null @@ -1,57 +0,0 @@ -{{- /* -Generated from 'node-network' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.network }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "node-network" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: node-network - rules: - - alert: NetworkReceiveErrors - annotations: - message: Network interface "{{`{{`}} $labels.device {{`}}`}}" showing receive errors on node-exporter {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}}" - expr: rate(node_network_receive_errs_total{job="node-exporter",device!~"veth.+"}[2m]) > 0 - for: 2m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NetworkTransmitErrors - annotations: - message: Network interface "{{`{{`}} $labels.device {{`}}`}}" showing transmit errors on node-exporter {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}}" - expr: rate(node_network_transmit_errs_total{job="node-exporter",device!~"veth.+"}[2m]) > 0 - for: 2m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: NodeNetworkInterfaceFlapping - annotations: - message: Network interface "{{`{{`}} $labels.device {{`}}`}}" changing it's up status often on node-exporter {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}}" - expr: changes(node_network_up{job="node-exporter",device!~"veth.+"}[2m]) > 2 - for: 2m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node-time.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node-time.yaml deleted file mode 100644 index b7a2fc92f..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node-time.yaml +++ /dev/null @@ -1,37 +0,0 @@ -{{- /* -Generated from 'node-time' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.time }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "node-time" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: node-time - rules: - - alert: ClockSkewDetected - annotations: - message: Clock skew detected on node-exporter {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod {{`}}`}}. Ensure NTP is configured correctly on this host. - expr: abs(node_timex_offset_seconds{job="node-exporter"}) > 0.03 - for: 2m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node.rules.yaml deleted file mode 100644 index 2bc7af3a9..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/node.rules.yaml +++ /dev/null @@ -1,202 +0,0 @@ -{{- /* -Generated from 'node.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.node }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "node.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: node.rules - rules: - - expr: sum(min(kube_pod_info) by (node)) - record: ':kube_pod_info_node_count:' - - expr: max(label_replace(kube_pod_info{job="kube-state-metrics"}, "pod", "$1", "pod", "(.*)")) by (node, namespace, pod) - record: 'node_namespace_pod:kube_pod_info:' - - expr: |- - count by (node) (sum by (node, cpu) ( - node_cpu_seconds_total{job="node-exporter"} - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - )) - record: node:node_num_cpu:sum - - expr: 1 - avg(rate(node_cpu_seconds_total{job="node-exporter",mode="idle"}[1m])) - record: :node_cpu_utilisation:avg1m - - expr: |- - 1 - avg by (node) ( - rate(node_cpu_seconds_total{job="node-exporter",mode="idle"}[1m]) - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info:) - record: node:node_cpu_utilisation:avg1m - - expr: |- - node:node_cpu_utilisation:avg1m - * - node:node_num_cpu:sum - / - scalar(sum(node:node_num_cpu:sum)) - record: node:cluster_cpu_utilisation:ratio - - expr: |- - sum(node_load1{job="node-exporter"}) - / - sum(node:node_num_cpu:sum) - record: ':node_cpu_saturation_load1:' - - expr: |- - sum by (node) ( - node_load1{job="node-exporter"} - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - / - node:node_num_cpu:sum - record: 'node:node_cpu_saturation_load1:' - - expr: |- - 1 - - sum(node_memory_MemFree_bytes{job="node-exporter"} + node_memory_Cached_bytes{job="node-exporter"} + node_memory_Buffers_bytes{job="node-exporter"}) - / - sum(node_memory_MemTotal_bytes{job="node-exporter"}) - record: ':node_memory_utilisation:' - - expr: sum(node_memory_MemFree_bytes{job="node-exporter"} + node_memory_Cached_bytes{job="node-exporter"} + node_memory_Buffers_bytes{job="node-exporter"}) - record: :node_memory_MemFreeCachedBuffers_bytes:sum - - expr: sum(node_memory_MemTotal_bytes{job="node-exporter"}) - record: :node_memory_MemTotal_bytes:sum - - expr: |- - sum by (node) ( - (node_memory_MemFree_bytes{job="node-exporter"} + node_memory_Cached_bytes{job="node-exporter"} + node_memory_Buffers_bytes{job="node-exporter"}) - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - record: node:node_memory_bytes_available:sum - - expr: |- - sum by (node) ( - node_memory_MemTotal_bytes{job="node-exporter"} - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - record: node:node_memory_bytes_total:sum - - expr: |- - (node:node_memory_bytes_total:sum - node:node_memory_bytes_available:sum) - / - node:node_memory_bytes_total:sum - record: node:node_memory_utilisation:ratio - - expr: |- - (node:node_memory_bytes_total:sum - node:node_memory_bytes_available:sum) - / - scalar(sum(node:node_memory_bytes_total:sum)) - record: node:cluster_memory_utilisation:ratio - - expr: |- - 1e3 * sum( - (rate(node_vmstat_pgpgin{job="node-exporter"}[1m]) - + rate(node_vmstat_pgpgout{job="node-exporter"}[1m])) - ) - record: :node_memory_swap_io_bytes:sum_rate - - expr: |- - 1 - - sum by (node) ( - (node_memory_MemFree_bytes{job="node-exporter"} + node_memory_Cached_bytes{job="node-exporter"} + node_memory_Buffers_bytes{job="node-exporter"}) - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - / - sum by (node) ( - node_memory_MemTotal_bytes{job="node-exporter"} - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - record: 'node:node_memory_utilisation:' - - expr: 1 - (node:node_memory_bytes_available:sum / node:node_memory_bytes_total:sum) - record: 'node:node_memory_utilisation_2:' - - expr: |- - 1e3 * sum by (node) ( - (rate(node_vmstat_pgpgin{job="node-exporter"}[1m]) - + rate(node_vmstat_pgpgout{job="node-exporter"}[1m])) - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - record: node:node_memory_swap_io_bytes:sum_rate - - expr: avg(irate(node_disk_io_time_seconds_total{job="node-exporter",device=~"nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+"}[1m])) - record: :node_disk_utilisation:avg_irate - - expr: |- - avg by (node) ( - irate(node_disk_io_time_seconds_total{job="node-exporter",device=~"nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+"}[1m]) - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - record: node:node_disk_utilisation:avg_irate - - expr: avg(irate(node_disk_io_time_weighted_seconds_total{job="node-exporter",device=~"nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+"}[1m])) - record: :node_disk_saturation:avg_irate - - expr: |- - avg by (node) ( - irate(node_disk_io_time_weighted_seconds_total{job="node-exporter",device=~"nvme.+|rbd.+|sd.+|vd.+|xvd.+|dm-.+"}[1m]) - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - record: node:node_disk_saturation:avg_irate - - expr: |- - max by (instance, namespace, pod, device) ((node_filesystem_size_bytes{fstype=~"ext[234]|btrfs|xfs|zfs"} - - node_filesystem_avail_bytes{fstype=~"ext[234]|btrfs|xfs|zfs"}) - / node_filesystem_size_bytes{fstype=~"ext[234]|btrfs|xfs|zfs"}) - record: 'node:node_filesystem_usage:' - - expr: max by (instance, namespace, pod, device) (node_filesystem_avail_bytes{fstype=~"ext[234]|btrfs|xfs|zfs"} / node_filesystem_size_bytes{fstype=~"ext[234]|btrfs|xfs|zfs"}) - record: 'node:node_filesystem_avail:' - - expr: |- - sum(irate(node_network_receive_bytes_total{job="node-exporter",device!~"veth.+"}[1m])) + - sum(irate(node_network_transmit_bytes_total{job="node-exporter",device!~"veth.+"}[1m])) - record: :node_net_utilisation:sum_irate - - expr: |- - sum by (node) ( - (irate(node_network_receive_bytes_total{job="node-exporter",device!~"veth.+"}[1m]) + - irate(node_network_transmit_bytes_total{job="node-exporter",device!~"veth.+"}[1m])) - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - record: node:node_net_utilisation:sum_irate - - expr: |- - sum(irate(node_network_receive_drop_total{job="node-exporter",device!~"veth.+"}[1m])) + - sum(irate(node_network_transmit_drop_total{job="node-exporter",device!~"veth.+"}[1m])) - record: :node_net_saturation:sum_irate - - expr: |- - sum by (node) ( - (irate(node_network_receive_drop_total{job="node-exporter",device!~"veth.+"}[1m]) + - irate(node_network_transmit_drop_total{job="node-exporter",device!~"veth.+"}[1m])) - * on (namespace, pod) group_left(node) - node_namespace_pod:kube_pod_info: - ) - record: node:node_net_saturation:sum_irate - - expr: |- - max( - max( - kube_pod_info{job="kube-state-metrics", host_ip!=""} - ) by (node, host_ip) - * on (host_ip) group_right (node) - label_replace( - (max(node_filesystem_files{job="node-exporter", mountpoint="/"}) by (instance)), "host_ip", "$1", "instance", "(.*):.*" - ) - ) by (node) - record: 'node:node_inodes_total:' - - expr: |- - max( - max( - kube_pod_info{job="kube-state-metrics", host_ip!=""} - ) by (node, host_ip) - * on (host_ip) group_right (node) - label_replace( - (max(node_filesystem_files_free{job="node-exporter", mountpoint="/"}) by (instance)), "host_ip", "$1", "instance", "(.*):.*" - ) - ) by (node) - record: 'node:node_inodes_free:' -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/prometheus-operator.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/prometheus-operator.yaml deleted file mode 100644 index a8a8915b6..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/prometheus-operator.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- /* -Generated from 'prometheus-operator' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheusOperator }} -{{- $operatorJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "operator" }} -{{- $namespace := printf "%s" (include "kube-prometheus-stack.namespace" .) }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus-operator" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: prometheus-operator - rules: - - alert: PrometheusOperatorReconcileErrors - annotations: - message: Errors while reconciling {{`{{`}} $labels.controller {{`}}`}} in {{`{{`}} $labels.namespace {{`}}`}} Namespace. - expr: rate(prometheus_operator_reconcile_errors_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[5m]) > 0.1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusOperatorNodeLookupErrors - annotations: - message: Errors while reconciling Prometheus in {{`{{`}} $labels.namespace {{`}}`}} Namespace. - expr: rate(prometheus_operator_node_address_lookup_errors_total{job="{{ $operatorJob }}",namespace="{{ $namespace }}"}[5m]) > 0.1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/prometheus.rules.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/prometheus.rules.yaml deleted file mode 100644 index 0480c83b5..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/rules/prometheus.rules.yaml +++ /dev/null @@ -1,139 +0,0 @@ -{{- /* -Generated from 'prometheus.rules' group from https://raw.githubusercontent.com/prometheus-operator/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml -Do not change in-place! In order to change this file first read following link: -https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack/hack -*/ -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if and (semverCompare ">=1.10.0-0" $kubeTargetVersion) (semverCompare "<1.14.0-0" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.prometheus }} -{{- $prometheusJob := printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus" }} -{{- $namespace := printf "%s" (include "kube-prometheus-stack.namespace" .) }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ printf "%s-%s" (include "kube-prometheus-stack.fullname" .) "prometheus.rules" | trunc 63 | trimSuffix "-" }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.defaultRules.labels }} -{{ toYaml .Values.defaultRules.labels | indent 4 }} -{{- end }} -{{- if .Values.defaultRules.annotations }} - annotations: -{{ toYaml .Values.defaultRules.annotations | indent 4 }} -{{- end }} -spec: - groups: - - name: prometheus.rules - rules: - - alert: PrometheusConfigReloadFailed - annotations: - description: Reloading Prometheus' configuration has failed for {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} - summary: Reloading Prometheus' configuration failed - expr: prometheus_config_last_reload_successful{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"} == 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusNotificationQueueRunningFull - annotations: - description: Prometheus' alert notification queue is running full for {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} - summary: Prometheus' alert notification queue is running full - expr: predict_linear(prometheus_notifications_queue_length{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m], 60 * 30) > prometheus_notifications_queue_capacity{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"} - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusErrorSendingAlerts - annotations: - description: Errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} to Alertmanager {{`{{`}}$labels.Alertmanager{{`}}`}} - summary: Errors while sending alert from Prometheus - expr: rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) / rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0.01 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusErrorSendingAlerts - annotations: - description: Errors while sending alerts from Prometheus {{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} to Alertmanager {{`{{`}}$labels.Alertmanager{{`}}`}} - summary: Errors while sending alerts from Prometheus - expr: rate(prometheus_notifications_errors_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) / rate(prometheus_notifications_sent_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0.03 - for: 10m - labels: - severity: critical -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusNotConnectedToAlertmanagers - annotations: - description: Prometheus {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} is not connected to any Alertmanagers - summary: Prometheus is not connected to any Alertmanagers - expr: prometheus_notifications_alertmanagers_discovered{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"} < 1 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusTSDBReloadsFailing - annotations: - description: '{{`{{`}}$labels.job{{`}}`}} at {{`{{`}}$labels.instance{{`}}`}} had {{`{{`}}$value | humanize{{`}}`}} reload failures over the last four hours.' - summary: Prometheus has issues reloading data blocks from disk - expr: increase(prometheus_tsdb_reloads_failures_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[2h]) > 0 - for: 12h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusTSDBCompactionsFailing - annotations: - description: '{{`{{`}}$labels.job{{`}}`}} at {{`{{`}}$labels.instance{{`}}`}} had {{`{{`}}$value | humanize{{`}}`}} compaction failures over the last four hours.' - summary: Prometheus has issues compacting sample blocks - expr: increase(prometheus_tsdb_compactions_failed_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[2h]) > 0 - for: 12h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusTSDBWALCorruptions - annotations: - description: '{{`{{`}}$labels.job{{`}}`}} at {{`{{`}}$labels.instance{{`}}`}} has a corrupted write-ahead log (WAL).' - summary: Prometheus write-ahead log is corrupted - expr: prometheus_tsdb_wal_corruptions_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"} > 0 - for: 4h - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusNotIngestingSamples - annotations: - description: Prometheus {{`{{`}} $labels.namespace {{`}}`}}/{{`{{`}} $labels.pod{{`}}`}} isn't ingesting samples. - summary: Prometheus isn't ingesting samples - expr: rate(prometheus_tsdb_head_samples_appended_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) <= 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} - - alert: PrometheusTargetScrapesDuplicate - annotations: - description: '{{`{{`}}$labels.namespace{{`}}`}}/{{`{{`}}$labels.pod{{`}}`}} has many samples rejected due to duplicate timestamps but different values' - summary: Prometheus has many samples rejected - expr: increase(prometheus_target_scrapes_sample_duplicate_timestamp_total{job="{{ $prometheusJob }}",namespace="{{ $namespace }}"}[5m]) > 0 - for: 10m - labels: - severity: warning -{{- if .Values.defaultRules.additionalRuleLabels }} -{{ toYaml .Values.defaultRules.additionalRuleLabels | indent 8 }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/service.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/service.yaml deleted file mode 100644 index cb831c7a2..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/service.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if .Values.prometheus.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus - self-monitor: {{ .Values.prometheus.serviceMonitor.selfMonitor | quote }} -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.service.labels }} -{{ toYaml .Values.prometheus.service.labels | indent 4 }} -{{- end }} -{{- if .Values.prometheus.service.annotations }} - annotations: -{{ toYaml .Values.prometheus.service.annotations | indent 4 }} -{{- end }} -spec: -{{- if .Values.prometheus.service.clusterIP }} - clusterIP: {{ .Values.prometheus.service.clusterIP }} -{{- end }} -{{- if .Values.prometheus.service.externalIPs }} - externalIPs: -{{ toYaml .Values.prometheus.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.prometheus.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.prometheus.service.loadBalancerIP }} -{{- end }} -{{- if .Values.prometheus.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.prometheus.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} - ports: - - name: {{ .Values.prometheus.prometheusSpec.portName }} - {{- if eq .Values.prometheus.service.type "NodePort" }} - nodePort: {{ .Values.prometheus.service.nodePort }} - {{- end }} - port: {{ .Values.prometheus.service.port }} - targetPort: {{ .Values.prometheus.service.targetPort }} -{{- if .Values.prometheus.service.additionalPorts }} -{{ toYaml .Values.prometheus.service.additionalPorts | indent 2 }} -{{- end }} - selector: - app: prometheus - prometheus: {{ template "kube-prometheus-stack.fullname" . }}-prometheus -{{- if .Values.prometheus.service.sessionAffinity }} - sessionAffinity: {{ .Values.prometheus.service.sessionAffinity }} -{{- end }} - type: "{{ .Values.prometheus.service.type }}" -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/serviceaccount.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/serviceaccount.yaml deleted file mode 100644 index 862d5f8e4..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/serviceaccount.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ template "kube-prometheus-stack.prometheus.serviceAccountName" . }} - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -{{- if .Values.prometheus.serviceAccount.annotations }} - annotations: -{{ toYaml .Values.prometheus.serviceAccount.annotations | indent 4 }} -{{- end }} -imagePullSecrets: -{{ toYaml .Values.global.imagePullSecrets | indent 2 }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/servicemonitor.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/servicemonitor.yaml deleted file mode 100644 index 356c013ff..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/servicemonitor.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.serviceMonitor.selfMonitor }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ template "kube-prometheus-stack.fullname" . }}-prometheus - namespace: {{ template "kube-prometheus-stack.namespace" . }} - labels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus -{{ include "kube-prometheus-stack.labels" . | indent 4 }} -spec: - selector: - matchLabels: - app: {{ template "kube-prometheus-stack.name" . }}-prometheus - release: {{ $.Release.Name | quote }} - self-monitor: "true" - namespaceSelector: - matchNames: - - {{ printf "%s" (include "kube-prometheus-stack.namespace" .) | quote }} - endpoints: - - port: {{ .Values.prometheus.prometheusSpec.portName }} - {{- if .Values.prometheus.serviceMonitor.interval }} - interval: {{ .Values.prometheus.serviceMonitor.interval }} - {{- end }} - {{- if .Values.prometheus.serviceMonitor.scheme }} - scheme: {{ .Values.prometheus.serviceMonitor.scheme }} - {{- end }} - {{- if .Values.prometheus.serviceMonitor.tlsConfig }} - tlsConfig: {{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | nindent 6 }} - {{- end }} - {{- if .Values.prometheus.serviceMonitor.bearerTokenFile }} - bearerTokenFile: {{ .Values.prometheus.serviceMonitor.bearerTokenFile }} - {{- end }} - path: "{{ trimSuffix "/" .Values.prometheus.prometheusSpec.routePrefix }}/metrics" -{{- if .Values.prometheus.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.prometheus.serviceMonitor.metricRelabelings | indent 6) . }} -{{- end }} -{{- if .Values.prometheus.serviceMonitor.relabelings }} - relabelings: -{{ toYaml .Values.prometheus.serviceMonitor.relabelings | indent 6 }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/servicemonitors.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/servicemonitors.yaml deleted file mode 100644 index 959df2124..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/servicemonitors.yaml +++ /dev/null @@ -1,34 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.additionalServiceMonitors }} -apiVersion: v1 -kind: List -items: -{{- range .Values.prometheus.additionalServiceMonitors }} - - apiVersion: monitoring.coreos.com/v1 - kind: ServiceMonitor - metadata: - name: {{ .name }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - app: {{ template "kube-prometheus-stack.name" $ }}-prometheus -{{ include "kube-prometheus-stack.labels" $ | indent 8 }} - {{- if .additionalLabels }} -{{ toYaml .additionalLabels | indent 8 }} - {{- end }} - spec: - endpoints: -{{ toYaml .endpoints | indent 8 }} - {{- if .jobLabel }} - jobLabel: {{ .jobLabel }} - {{- end }} - {{- if .namespaceSelector }} - namespaceSelector: -{{ toYaml .namespaceSelector | indent 8 }} - {{- end }} - selector: -{{ toYaml .selector | indent 8 }} - {{- if .targetLabels }} - targetLabels: -{{ toYaml .targetLabels | indent 8 }} - {{- end }} -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/serviceperreplica.yaml b/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/serviceperreplica.yaml deleted file mode 100644 index 1a5543362..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/templates/prometheus/serviceperreplica.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if and .Values.prometheus.enabled .Values.prometheus.servicePerReplica.enabled }} -{{- $count := .Values.prometheus.prometheusSpec.replicas | int -}} -{{- $serviceValues := .Values.prometheus.servicePerReplica -}} -apiVersion: v1 -kind: List -metadata: - name: {{ include "kube-prometheus-stack.fullname" $ }}-prometheus-serviceperreplica - namespace: {{ template "kube-prometheus-stack.namespace" . }} -items: -{{- range $i, $e := until $count }} - - apiVersion: v1 - kind: Service - metadata: - name: {{ include "kube-prometheus-stack.fullname" $ }}-prometheus-{{ $i }} - namespace: {{ template "kube-prometheus-stack.namespace" $ }} - labels: - app: {{ include "kube-prometheus-stack.name" $ }}-prometheus -{{ include "kube-prometheus-stack.labels" $ | indent 8 }} - {{- if $serviceValues.annotations }} - annotations: -{{ toYaml $serviceValues.annotations | indent 8 }} - {{- end }} - spec: - {{- if $serviceValues.clusterIP }} - clusterIP: {{ $serviceValues.clusterIP }} - {{- end }} - {{- if $serviceValues.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := $serviceValues.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} - {{- end }} - ports: - - name: {{ $.Values.prometheus.prometheusSpec.portName }} - {{- if eq $serviceValues.type "NodePort" }} - nodePort: {{ $serviceValues.nodePort }} - {{- end }} - port: {{ $serviceValues.port }} - targetPort: {{ $serviceValues.targetPort }} - selector: - app: prometheus - prometheus: {{ include "kube-prometheus-stack.fullname" $ }}-prometheus - statefulset.kubernetes.io/pod-name: prometheus-{{ include "kube-prometheus-stack.fullname" $ }}-prometheus-{{ $i }} - type: "{{ $serviceValues.type }}" -{{- end }} -{{- end }} diff --git a/scripts/helm/monitoring/kube-prometheus-stack/values.yaml b/scripts/helm/monitoring/kube-prometheus-stack/values.yaml deleted file mode 100644 index 690b53efb..000000000 --- a/scripts/helm/monitoring/kube-prometheus-stack/values.yaml +++ /dev/null @@ -1,2278 +0,0 @@ -# Default values for kube-prometheus-stack. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -## Provide a name in place of kube-prometheus-stack for `app:` labels -## -nameOverride: "" - -## Override the deployment namespace -## -namespaceOverride: "" - -## Provide a k8s version to auto dashboard import script example: kubeTargetVersionOverride: 1.16.6 -## -kubeTargetVersionOverride: "" - -## Provide a name to substitute for the full names of resources -## -fullnameOverride: "" - -## Labels to apply to all resources -## -commonLabels: {} -# scmhash: abc123 -# myLabel: aakkmd - -## Create default rules for monitoring the cluster -## -defaultRules: - create: true - rules: - alertmanager: true - etcd: true - general: true - k8s: true - kubeApiserver: true - kubeApiserverAvailability: true - kubeApiserverError: true - kubeApiserverSlos: true - kubelet: true - kubePrometheusGeneral: true - kubePrometheusNodeAlerting: true - kubePrometheusNodeRecording: true - kubernetesAbsent: true - kubernetesApps: true - kubernetesResources: true - kubernetesStorage: true - kubernetesSystem: true - kubeScheduler: true - kubeStateMetrics: true - network: true - node: true - prometheus: true - prometheusOperator: true - time: true - - ## Runbook url prefix for default rules - runbookUrl: https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/runbook.md# - ## Reduce app namespace alert scope - appNamespacesTarget: ".*" - - ## Labels for default rules - labels: {} - ## Annotations for default rules - annotations: {} - - ## Additional labels for PrometheusRule alerts - additionalRuleLabels: {} - -## Deprecated way to provide custom recording or alerting rules to be deployed into the cluster. -## -# additionalPrometheusRules: [] -# - name: my-rule-file -# groups: -# - name: my_group -# rules: -# - record: my_record -# expr: 100 * my_record - -## Provide custom recording or alerting rules to be deployed into the cluster. -## -additionalPrometheusRulesMap: {} -# rule-name: -# groups: -# - name: my_group -# rules: -# - record: my_record -# expr: 100 * my_record - -## -global: - rbac: - create: true - pspEnabled: true - pspAnnotations: {} - ## Specify pod annotations - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp - ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl - ## - # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' - # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - - ## Reference to one or more secrets to be used when pulling images - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - imagePullSecrets: [] - # - name: "image-pull-secret" - -## Configuration for alertmanager -## ref: https://prometheus.io/docs/alerting/alertmanager/ -## -alertmanager: - - ## Deploy alertmanager - ## - enabled: true - - ## Api that prometheus will use to communicate with alertmanager. Possible values are v1, v2 - ## - apiVersion: v2 - - ## Service account for Alertmanager to use. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - ## - serviceAccount: - create: true - name: "" - annotations: {} - - ## Configure pod disruption budgets for Alertmanager - ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget - ## This configuration is immutable once created and will require the PDB to be deleted to be changed - ## https://github.com/kubernetes/kubernetes/issues/45398 - ## - podDisruptionBudget: - enabled: false - minAvailable: 1 - maxUnavailable: "" - - ## Alertmanager configuration directives - ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file - ## https://prometheus.io/webtools/alerting/routing-tree-editor/ - ## - config: - global: - resolve_timeout: 5m - route: - group_by: ['job'] - group_wait: 30s - group_interval: 5m - repeat_interval: 12h - receiver: 'null' - routes: - - match: - alertname: Watchdog - receiver: 'null' - receivers: - - name: 'null' - - ## Pass the Alertmanager configuration directives through Helm's templating - ## engine. If the Alertmanager configuration contains Alertmanager templates, - ## they'll need to be properly escaped so that they are not interpreted by - ## Helm - ## ref: https://helm.sh/docs/developing_charts/#using-the-tpl-function - ## https://prometheus.io/docs/alerting/configuration/#tmpl_string - ## https://prometheus.io/docs/alerting/notifications/ - ## https://prometheus.io/docs/alerting/notification_examples/ - tplConfig: false - - ## Alertmanager template files to format alerts - ## ref: https://prometheus.io/docs/alerting/notifications/ - ## https://prometheus.io/docs/alerting/notification_examples/ - ## - templateFiles: {} - # - ## An example template: - # template_1.tmpl: |- - # {{ define "cluster" }}{{ .ExternalURL | reReplaceAll ".*alertmanager\\.(.*)" "$1" }}{{ end }} - # - # {{ define "slack.myorg.text" }} - # {{- $root := . -}} - # {{ range .Alerts }} - # *Alert:* {{ .Annotations.summary }} - `{{ .Labels.severity }}` - # *Cluster:* {{ template "cluster" $root }} - # *Description:* {{ .Annotations.description }} - # *Graph:* <{{ .GeneratorURL }}|:chart_with_upwards_trend:> - # *Runbook:* <{{ .Annotations.runbook }}|:spiral_note_pad:> - # *Details:* - # {{ range .Labels.SortedPairs }} • *{{ .Name }}:* `{{ .Value }}` - # {{ end }} - # {{ end }} - # {{ end }} - - ingress: - enabled: false - - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - - annotations: {} - - labels: {} - - ## Hosts must be provided if Ingress is enabled. - ## - hosts: [] - # - alertmanager.domain.com - - ## Paths to use for ingress rules - one path should match the alertmanagerSpec.routePrefix - ## - paths: [] - # - / - - ## TLS configuration for Alertmanager Ingress - ## Secret must be manually created in the namespace - ## - tls: [] - # - secretName: alertmanager-general-tls - # hosts: - # - alertmanager.example.com - - ## Configuration for Alertmanager secret - ## - secret: - annotations: {} - - ## Configuration for creating an Ingress that will map to each Alertmanager replica service - ## alertmanager.servicePerReplica must be enabled - ## - ingressPerReplica: - enabled: false - - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - - annotations: {} - labels: {} - - ## Final form of the hostname for each per replica ingress is - ## {{ ingressPerReplica.hostPrefix }}-{{ $replicaNumber }}.{{ ingressPerReplica.hostDomain }} - ## - ## Prefix for the per replica ingress that will have `-$replicaNumber` - ## appended to the end - hostPrefix: "" - ## Domain that will be used for the per replica ingress - hostDomain: "" - - ## Paths to use for ingress rules - ## - paths: [] - # - / - - ## Secret name containing the TLS certificate for alertmanager per replica ingress - ## Secret must be manually created in the namespace - tlsSecretName: "" - - ## Separated secret for each per replica Ingress. Can be used together with cert-manager - ## - tlsSecretPerReplica: - enabled: false - ## Final form of the secret for each per replica ingress is - ## {{ tlsSecretPerReplica.prefix }}-{{ $replicaNumber }} - ## - prefix: "alertmanager" - - ## Configuration for Alertmanager service - ## - service: - annotations: {} - labels: {} - clusterIP: "" - - ## Port for Alertmanager Service to listen on - ## - port: 9093 - ## To be used with a proxy extraContainer port - ## - targetPort: 9093 - ## Port to expose on each node - ## Only used if service.type is 'NodePort' - ## - nodePort: 30903 - ## List of IP addresses at which the Prometheus server service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - - ## Additional ports to open for Alertmanager service - additionalPorts: [] - - externalIPs: [] - loadBalancerIP: "" - loadBalancerSourceRanges: [] - ## Service type - ## - type: ClusterIP - - ## Configuration for creating a separate Service for each statefulset Alertmanager replica - ## - servicePerReplica: - enabled: false - annotations: {} - - ## Port for Alertmanager Service per replica to listen on - ## - port: 9093 - - ## To be used with a proxy extraContainer port - targetPort: 9093 - - ## Port to expose on each node - ## Only used if servicePerReplica.type is 'NodePort' - ## - nodePort: 30904 - - ## Loadbalancer source IP ranges - ## Only used if servicePerReplica.type is "loadbalancer" - loadBalancerSourceRanges: [] - ## Service type - ## - type: ClusterIP - - ## If true, create a serviceMonitor for alertmanager - ## - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - selfMonitor: true - - ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. - scheme: "" - - ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. - ## Of type: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#tlsconfig - tlsConfig: {} - - bearerTokenFile: - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - ## Settings affecting alertmanagerSpec - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#alertmanagerspec - ## - alertmanagerSpec: - ## Standard object’s metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata - ## Metadata Labels and Annotations gets propagated to the Alertmanager pods. - ## - podMetadata: {} - - ## Image of Alertmanager - ## - image: - repository: quay.io/prometheus/alertmanager - tag: v0.21.0 - sha: "" - - ## If true then the user will be responsible to provide a secret with alertmanager configuration - ## So when true the config part will be ignored (including templateFiles) and the one in the secret will be used - ## - useExistingSecret: false - - ## Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the - ## Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/. - ## - secrets: [] - - ## ConfigMaps is a list of ConfigMaps in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. - ## The ConfigMaps are mounted into /etc/alertmanager/configmaps/. - ## - configMaps: [] - - ## ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains configuration for - ## this Alertmanager instance. Defaults to 'alertmanager-' The secret is mounted into /etc/alertmanager/config. - ## - # configSecret: - - ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with. - ## - alertmanagerConfigSelector: {} - ## Example which selects all alertmanagerConfig resources - ## with label "alertconfig" with values any of "example-config" or "example-config-2" - # alertmanagerConfigSelector: - # matchExpressions: - # - key: alertconfig - # operator: In - # values: - # - example-config - # - example-config-2 - # - ## Example which selects all alertmanagerConfig resources with label "role" set to "example-config" - # alertmanagerConfigSelector: - # matchLabels: - # role: example-config - - ## Namespaces to be selected for AlertmanagerConfig discovery. If nil, only check own namespace. - ## - alertmanagerConfigNamespaceSelector: {} - ## Example which selects all namespaces - ## with label "alertmanagerconfig" with values any of "example-namespace" or "example-namespace-2" - # alertmanagerConfigNamespaceSelector: - # matchExpressions: - # - key: alertmanagerconfig - # operator: In - # values: - # - example-namespace - # - example-namespace-2 - - ## Example which selects all namespaces with label "alertmanagerconfig" set to "enabled" - # alertmanagerConfigNamespaceSelector: - # matchLabels: - # alertmanagerconfig: enabled - - ## Define Log Format - # Use logfmt (default) or json logging - logFormat: logfmt - - ## Log level for Alertmanager to be configured with. - ## - logLevel: info - - ## Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the - ## running cluster equal to the expected size. - replicas: 1 - - ## Time duration Alertmanager shall retain data for. Default is '120h', and must match the regular expression - ## [0-9]+(ms|s|m|h) (milliseconds seconds minutes hours). - ## - retention: 120h - - ## Storage is the definition of how storage will be used by the Alertmanager instances. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md - ## - storage: {} - # volumeClaimTemplate: - # spec: - # storageClassName: gluster - # accessModes: ["ReadWriteOnce"] - # resources: - # requests: - # storage: 50Gi - # selector: {} - - - ## The external URL the Alertmanager instances will be available under. This is necessary to generate correct URLs. This is necessary if Alertmanager is not served from root of a DNS name. string false - ## - externalUrl: - - ## The route prefix Alertmanager registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, - ## but the server serves requests under a different route prefix. For example for use with kubectl proxy. - ## - routePrefix: / - - ## If set to true all actions on the underlying managed objects are not going to be performed, except for delete actions. - ## - paused: false - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Define resources requests and limits for single Pods. - ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # requests: - # memory: 400Mi - - ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node. - ## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. - ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. - ## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. - ## - podAntiAffinity: "" - - ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. - ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone - ## - podAntiAffinityTopologyKey: kubernetes.io/hostname - - ## Assign custom affinity rules to the alertmanager instance - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - ## - affinity: {} - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: kubernetes.io/e2e-az-name - # operator: In - # values: - # - e2e-az1 - # - e2e-az2 - - ## If specified, the pod's tolerations. - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - ## SecurityContext holds pod-level security attributes and common container settings. - ## This defaults to non root user with uid 1000 and gid 2000. *v1.PodSecurityContext false - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - ## - securityContext: - runAsGroup: 2000 - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 2000 - - ## ListenLocal makes the Alertmanager server listen on loopback, so that it does not bind against the Pod IP. - ## Note this is only for the Alertmanager UI, not the gossip communication. - ## - listenLocal: false - - ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to an Alertmanager pod. - ## - containers: [] - - # Additional volumes on the output StatefulSet definition. - volumes: [] - - # Additional VolumeMounts on the output StatefulSet definition. - volumeMounts: [] - - ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes - ## (permissions, dir tree) on mounted volumes before starting prometheus - initContainers: [] - - ## Priority class assigned to the Pods - ## - priorityClassName: "" - - ## AdditionalPeers allows injecting a set of additional Alertmanagers to peer with to form a highly available cluster. - ## - additionalPeers: [] - - ## PortName to use for Alert Manager. - ## - portName: "web" - - ## ClusterAdvertiseAddress is the explicit address to advertise in cluster. Needs to be provided for non RFC1918 [1] (public) addresses. [1] RFC1918: https://tools.ietf.org/html/rfc1918 - ## - clusterAdvertiseAddress: false - - ## ForceEnableClusterMode ensures Alertmanager does not deactivate the cluster mode when running with a single replica. - ## Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each. - forceEnableClusterMode: false - - -## Using default values from https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml -## -grafana: - enabled: true - namespaceOverride: "" - - ## Deploy default dashboards. - ## - defaultDashboardsEnabled: true - - adminPassword: prom-operator - - ingress: - ## If true, Grafana Ingress will be created - ## - enabled: false - - ## Annotations for Grafana Ingress - ## - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - - ## Labels to be added to the Ingress - ## - labels: {} - - ## Hostnames. - ## Must be provided if Ingress is enable. - ## - # hosts: - # - grafana.domain.com - hosts: [] - - ## Path for grafana ingress - path: / - - ## TLS configuration for grafana Ingress - ## Secret must be manually created in the namespace - ## - tls: [] - # - secretName: grafana-general-tls - # hosts: - # - grafana.example.com - - sidecar: - dashboards: - enabled: true - label: grafana_dashboard - - ## Annotations for Grafana dashboard configmaps - ## - annotations: {} - multicluster: false - datasources: - enabled: true - defaultDatasourceEnabled: true - - ## Annotations for Grafana datasource configmaps - ## - annotations: {} - - ## Create datasource for each Pod of Prometheus StatefulSet; - ## this uses headless service `prometheus-operated` which is - ## created by Prometheus Operator - ## ref: https://git.io/fjaBS - createPrometheusReplicasDatasources: false - label: grafana_datasource - - extraConfigmapMounts: [] - # - name: certs-configmap - # mountPath: /etc/grafana/ssl/ - # configMap: certs-configmap - # readOnly: true - - ## Configure additional grafana datasources (passed through tpl) - ## ref: http://docs.grafana.org/administration/provisioning/#datasources - additionalDataSources: [] - # - name: prometheus-sample - # access: proxy - # basicAuth: true - # basicAuthPassword: pass - # basicAuthUser: daco - # editable: false - # jsonData: - # tlsSkipVerify: true - # orgId: 1 - # type: prometheus - # url: https://{{ printf "%s-prometheus.svc" .Release.Name }}:9090 - # version: 1 - - ## Passed to grafana subchart and used by servicemonitor below - ## - service: - portName: service - - ## If true, create a serviceMonitor for grafana - ## - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - selfMonitor: true - - # Path to use for scraping metrics. Might be different if server.root_url is set - # in grafana.ini - path: "/metrics" - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - -## Component scraping the kube api server -## -kubeApiServer: - enabled: true - tlsConfig: - serverName: kubernetes - insecureSkipVerify: false - - ## If your API endpoint address is not reachable (as in AKS) you can replace it with the kubernetes service - ## - relabelings: [] - # - sourceLabels: - # - __meta_kubernetes_namespace - # - __meta_kubernetes_service_name - # - __meta_kubernetes_endpoint_port_name - # action: keep - # regex: default;kubernetes;https - # - targetLabel: __address__ - # replacement: kubernetes.default.svc:443 - - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - jobLabel: component - selector: - matchLabels: - component: apiserver - provider: kubernetes - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - -## Component scraping the kubelet and kubelet-hosted cAdvisor -## -kubelet: - enabled: true - namespace: kube-system - - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - - ## Enable scraping the kubelet over https. For requirements to enable this see - ## https://github.com/prometheus-operator/prometheus-operator/issues/926 - ## - https: true - - ## Enable scraping /metrics/cadvisor from kubelet's service - ## - cAdvisor: true - - ## Enable scraping /metrics/probes from kubelet's service - ## - probes: true - - ## Enable scraping /metrics/resource from kubelet's service - ## This is disabled by default because container metrics are already exposed by cAdvisor - ## - resource: false - # From kubernetes 1.18, /metrics/resource/v1alpha1 renamed to /metrics/resource - resourcePath: "/metrics/resource/v1alpha1" - ## Metric relabellings to apply to samples before ingestion - ## - cAdvisorMetricRelabelings: [] - # - sourceLabels: [__name__, image] - # separator: ; - # regex: container_([a-z_]+); - # replacement: $1 - # action: drop - # - sourceLabels: [__name__] - # separator: ; - # regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s) - # replacement: $1 - # action: drop - - ## Metric relabellings to apply to samples before ingestion - ## - probesMetricRelabelings: [] - # - sourceLabels: [__name__, image] - # separator: ; - # regex: container_([a-z_]+); - # replacement: $1 - # action: drop - # - sourceLabels: [__name__] - # separator: ; - # regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s) - # replacement: $1 - # action: drop - - # relabel configs to apply to samples before ingestion. - # metrics_path is required to match upstream rules and charts - ## - cAdvisorRelabelings: - - sourceLabels: [__metrics_path__] - targetLabel: metrics_path - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - probesRelabelings: - - sourceLabels: [__metrics_path__] - targetLabel: metrics_path - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - resourceRelabelings: - - sourceLabels: [__metrics_path__] - targetLabel: metrics_path - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - metricRelabelings: [] - # - sourceLabels: [__name__, image] - # separator: ; - # regex: container_([a-z_]+); - # replacement: $1 - # action: drop - # - sourceLabels: [__name__] - # separator: ; - # regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s) - # replacement: $1 - # action: drop - - # relabel configs to apply to samples before ingestion. - # metrics_path is required to match upstream rules and charts - ## - relabelings: - - sourceLabels: [__metrics_path__] - targetLabel: metrics_path - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - -## Component scraping the kube controller manager -## -kubeControllerManager: - enabled: true - - ## If your kube controller manager is not deployed as a pod, specify IPs it can be found on - ## - endpoints: [] - # - 10.141.4.22 - # - 10.141.4.23 - # - 10.141.4.24 - - ## If using kubeControllerManager.endpoints only the port and targetPort are used - ## - service: - port: 10252 - targetPort: 10252 - # selector: - # component: kube-controller-manager - - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - - ## Enable scraping kube-controller-manager over https. - ## Requires proper certs (not self-signed) and delegated authentication/authorization checks - ## - https: false - - # Skip TLS certificate validation when scraping - insecureSkipVerify: null - - # Name of the server to use when validating TLS certificate - serverName: null - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - -## Component scraping coreDns. Use either this or kubeDns -## -coreDns: - enabled: true - service: - port: 9153 - targetPort: 9153 - # selector: - # k8s-app: kube-dns - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - -## Component scraping kubeDns. Use either this or coreDns -## -kubeDns: - enabled: false - service: - dnsmasq: - port: 10054 - targetPort: 10054 - skydns: - port: 10055 - targetPort: 10055 - # selector: - # k8s-app: kube-dns - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - dnsmasqMetricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - dnsmasqRelabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - -## Component scraping etcd -## -kubeEtcd: - enabled: true - - ## If your etcd is not deployed as a pod, specify IPs it can be found on - ## - endpoints: [] - # - 10.141.4.22 - # - 10.141.4.23 - # - 10.141.4.24 - - ## Etcd service. If using kubeEtcd.endpoints only the port and targetPort are used - ## - service: - port: 2379 - targetPort: 2379 - # selector: - # component: etcd - - ## Configure secure access to the etcd cluster by loading a secret into prometheus and - ## specifying security configuration below. For example, with a secret named etcd-client-cert - ## - ## serviceMonitor: - ## scheme: https - ## insecureSkipVerify: false - ## serverName: localhost - ## caFile: /etc/prometheus/secrets/etcd-client-cert/etcd-ca - ## certFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client - ## keyFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client-key - ## - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - scheme: http - insecureSkipVerify: false - serverName: "" - caFile: "" - certFile: "" - keyFile: "" - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - -## Component scraping kube scheduler -## -kubeScheduler: - enabled: true - - ## If your kube scheduler is not deployed as a pod, specify IPs it can be found on - ## - endpoints: [] - # - 10.141.4.22 - # - 10.141.4.23 - # - 10.141.4.24 - - ## If using kubeScheduler.endpoints only the port and targetPort are used - ## - service: - port: 10251 - targetPort: 10251 - # selector: - # component: kube-scheduler - - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - ## Enable scraping kube-scheduler over https. - ## Requires proper certs (not self-signed) and delegated authentication/authorization checks - ## - https: false - - ## Skip TLS certificate validation when scraping - insecureSkipVerify: null - - ## Name of the server to use when validating TLS certificate - serverName: null - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - -## Component scraping kube proxy -## -kubeProxy: - enabled: true - - ## If your kube proxy is not deployed as a pod, specify IPs it can be found on - ## - endpoints: [] - # - 10.141.4.22 - # - 10.141.4.23 - # - 10.141.4.24 - - service: - port: 10249 - targetPort: 10249 - # selector: - # k8s-app: kube-proxy - - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - - ## Enable scraping kube-proxy over https. - ## Requires proper certs (not self-signed) and delegated authentication/authorization checks - ## - https: false - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - -## Component scraping kube state metrics -## -kubeStateMetrics: - enabled: true - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - -## Configuration for kube-state-metrics subchart -## -kube-state-metrics: - namespaceOverride: "" - rbac: - create: true - podSecurityPolicy: - enabled: true - -## Deploy node exporter as a daemonset to all nodes -## -nodeExporter: - enabled: true - - ## Use the value configured in prometheus-node-exporter.podLabels - ## - jobLabel: jobLabel - - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - - ## How long until a scrape request times out. If not set, the Prometheus default scape timeout is used. - ## - scrapeTimeout: "" - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - sourceLabels: [__name__] - # separator: ; - # regex: ^node_mountstats_nfs_(event|operations|transport)_.+ - # replacement: $1 - # action: drop - - ## relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - -## Configuration for prometheus-node-exporter subchart -## -prometheus-node-exporter: - namespaceOverride: "" - podLabels: - ## Add the 'node-exporter' label to be used by serviceMonitor to match standard common usage in rules and grafana dashboards - ## - jobLabel: node-exporter - extraArgs: - - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/) - - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$ - -## Manages Prometheus and Alertmanager components -## -prometheusOperator: - enabled: true - - # Prometheus-Operator v0.39.0 and later support TLS natively. - tls: - enabled: true - # Value must match version names from https://golang.org/pkg/crypto/tls/#pkg-constants - tlsMinVersion: VersionTLS13 - - ## Admission webhook support for PrometheusRules resources added in Prometheus Operator 0.30 can be enabled to prevent incorrectly formatted - ## rules from making their way into prometheus and potentially preventing the container from starting - admissionWebhooks: - failurePolicy: Fail - enabled: true - ## If enabled, generate a self-signed certificate, then patch the webhook configurations with the generated data. - ## On chart upgrades (or if the secret exists) the cert will not be re-generated. You can use this to provide your own - ## certs ahead of time if you wish. - ## - patch: - enabled: true - image: - repository: jettech/kube-webhook-certgen - tag: v1.5.0 - sha: "" - pullPolicy: IfNotPresent - resources: {} - ## Provide a priority class name to the webhook patching job - ## - priorityClassName: "" - podAnnotations: {} - nodeSelector: {} - affinity: {} - tolerations: [] - # Use certmanager to generate webhook certs - certManager: - enabled: false - # issuerRef: - # name: "issuer" - # kind: "ClusterIssuer" - - ## Namespaces to scope the interaction of the Prometheus Operator and the apiserver (allow list). - ## This is mutually exclusive with denyNamespaces. Setting this to an empty object will disable the configuration - ## - namespaces: {} - # releaseNamespace: true - # additional: - # - kube-system - - ## Namespaces not to scope the interaction of the Prometheus Operator (deny list). - ## - denyNamespaces: [] - - ## Filter namespaces to look for prometheus-operator custom resources - ## - alertmanagerInstanceNamespaces: [] - prometheusInstanceNamespaces: [] - thanosRulerInstanceNamespaces: [] - - ## Service account for Alertmanager to use. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - ## - serviceAccount: - create: true - name: "" - - ## Configuration for Prometheus operator service - ## - service: - annotations: {} - labels: {} - clusterIP: "" - - ## Port to expose on each node - ## Only used if service.type is 'NodePort' - ## - nodePort: 30080 - - nodePortTls: 30443 - - ## Additional ports to open for Prometheus service - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#multi-port-services - ## - additionalPorts: [] - - ## Loadbalancer IP - ## Only use if service.type is "loadbalancer" - ## - loadBalancerIP: "" - loadBalancerSourceRanges: [] - - ## Service type - ## NodePort, ClusterIP, loadbalancer - ## - type: ClusterIP - - ## List of IP addresses at which the Prometheus server service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - externalIPs: [] - - ## Labels to add to the operator pod - ## - podLabels: {} - - ## Annotations to add to the operator pod - ## - podAnnotations: {} - - ## Assign a PriorityClassName to pods if set - # priorityClassName: "" - - ## Define Log Format - # Use logfmt (default) or json logging - # logFormat: logfmt - - ## Decrease log verbosity to errors only - # logLevel: error - - ## If true, the operator will create and maintain a service for scraping kubelets - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/helm/prometheus-operator/README.md - ## - kubeletService: - enabled: true - namespace: kube-system - - ## Create a servicemonitor for the operator - ## - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - ## Scrape timeout. If not set, the Prometheus default scrape timeout is used. - scrapeTimeout: "" - selfMonitor: true - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - ## Resource limits & requests - ## - resources: {} - # limits: - # cpu: 200m - # memory: 200Mi - # requests: - # cpu: 100m - # memory: 100Mi - - # Required for use in managed kubernetes clusters (such as AWS EKS) with custom CNI (such as calico), - # because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working - ## - hostNetwork: false - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Tolerations for use with node taints - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - ## Assign custom affinity rules to the prometheus operator - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - ## - affinity: {} - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: kubernetes.io/e2e-az-name - # operator: In - # values: - # - e2e-az1 - # - e2e-az2 - - securityContext: - fsGroup: 65534 - runAsGroup: 65534 - runAsNonRoot: true - runAsUser: 65534 - - ## Prometheus-operator image - ## - image: - repository: quay.io/prometheus-operator/prometheus-operator - tag: v0.44.0 - sha: "" - pullPolicy: IfNotPresent - - ## Configmap-reload image to use for reloading configmaps - ## - configmapReloadImage: - repository: docker.io/jimmidyson/configmap-reload - tag: v0.4.0 - sha: "" - - ## Prometheus-config-reloader image to use for config and rule reloading - ## - prometheusConfigReloaderImage: - repository: quay.io/prometheus-operator/prometheus-config-reloader - tag: v0.44.0 - sha: "" - - ## Set the prometheus config reloader side-car CPU limit - ## - configReloaderCpu: 100m - - ## Set the prometheus config reloader side-car memory limit - ## - configReloaderMemory: 25Mi - - ## Set a Field Selector to filter watched secrets - ## - secretFieldSelector: "" - -## Deploy a Prometheus instance -## -prometheus: - - enabled: true - - ## Annotations for Prometheus - ## - annotations: {} - - ## Service account for Prometheuses to use. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - ## - serviceAccount: - create: true - name: "" - - ## Configuration for Prometheus service - ## - service: - annotations: {} - labels: {} - clusterIP: "" - - ## Port for Prometheus Service to listen on - ## - port: 9090 - - ## To be used with a proxy extraContainer port - targetPort: 9090 - - ## List of IP addresses at which the Prometheus server service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - externalIPs: [] - - ## Port to expose on each node - ## Only used if service.type is 'NodePort' - ## - nodePort: 30090 - - ## Loadbalancer IP - ## Only use if service.type is "loadbalancer" - loadBalancerIP: "" - loadBalancerSourceRanges: [] - ## Service type - ## - type: ClusterIP - - sessionAffinity: "" - - ## Configuration for creating a separate Service for each statefulset Prometheus replica - ## - servicePerReplica: - enabled: false - annotations: {} - - ## Port for Prometheus Service per replica to listen on - ## - port: 9090 - - ## To be used with a proxy extraContainer port - targetPort: 9090 - - ## Port to expose on each node - ## Only used if servicePerReplica.type is 'NodePort' - ## - nodePort: 30091 - - ## Loadbalancer source IP ranges - ## Only used if servicePerReplica.type is "loadbalancer" - loadBalancerSourceRanges: [] - ## Service type - ## - type: ClusterIP - - ## Configure pod disruption budgets for Prometheus - ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget - ## This configuration is immutable once created and will require the PDB to be deleted to be changed - ## https://github.com/kubernetes/kubernetes/issues/45398 - ## - podDisruptionBudget: - enabled: false - minAvailable: 1 - maxUnavailable: "" - - # Ingress exposes thanos sidecar outside the cluster - thanosIngress: - enabled: false - - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - - annotations: {} - labels: {} - servicePort: 10901 - ## Hosts must be provided if Ingress is enabled. - ## - hosts: [] - # - thanos-gateway.domain.com - - ## Paths to use for ingress rules - ## - paths: [] - # - / - - ## TLS configuration for Thanos Ingress - ## Secret must be manually created in the namespace - ## - tls: [] - # - secretName: thanos-gateway-tls - # hosts: - # - thanos-gateway.domain.com - - ingress: - enabled: false - - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - - annotations: {} - labels: {} - - ## Hostnames. - ## Must be provided if Ingress is enabled. - ## - # hosts: - # - prometheus.domain.com - hosts: [] - - ## Paths to use for ingress rules - one path should match the prometheusSpec.routePrefix - ## - paths: [] - # - / - - ## TLS configuration for Prometheus Ingress - ## Secret must be manually created in the namespace - ## - tls: [] - # - secretName: prometheus-general-tls - # hosts: - # - prometheus.example.com - - ## Configuration for creating an Ingress that will map to each Prometheus replica service - ## prometheus.servicePerReplica must be enabled - ## - ingressPerReplica: - enabled: false - - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - - annotations: {} - labels: {} - - ## Final form of the hostname for each per replica ingress is - ## {{ ingressPerReplica.hostPrefix }}-{{ $replicaNumber }}.{{ ingressPerReplica.hostDomain }} - ## - ## Prefix for the per replica ingress that will have `-$replicaNumber` - ## appended to the end - hostPrefix: "" - ## Domain that will be used for the per replica ingress - hostDomain: "" - - ## Paths to use for ingress rules - ## - paths: [] - # - / - - ## Secret name containing the TLS certificate for Prometheus per replica ingress - ## Secret must be manually created in the namespace - tlsSecretName: "" - - ## Separated secret for each per replica Ingress. Can be used together with cert-manager - ## - tlsSecretPerReplica: - enabled: false - ## Final form of the secret for each per replica ingress is - ## {{ tlsSecretPerReplica.prefix }}-{{ $replicaNumber }} - ## - prefix: "prometheus" - - ## Configure additional options for default pod security policy for Prometheus - ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ - podSecurityPolicy: - allowedCapabilities: [] - - serviceMonitor: - ## Scrape interval. If not set, the Prometheus default scrape interval is used. - ## - interval: "" - selfMonitor: true - - ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS. - scheme: "" - - ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS. - ## Of type: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#tlsconfig - tlsConfig: {} - - bearerTokenFile: - - ## metric relabel configs to apply to samples before ingestion. - ## - metricRelabelings: [] - # - action: keep - # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' - # sourceLabels: [__name__] - - # relabel configs to apply to samples before ingestion. - ## - relabelings: [] - # - sourceLabels: [__meta_kubernetes_pod_node_name] - # separator: ; - # regex: ^(.*)$ - # targetLabel: nodename - # replacement: $1 - # action: replace - - ## Settings affecting prometheusSpec - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#prometheusspec - ## - prometheusSpec: - ## If true, pass --storage.tsdb.max-block-duration=2h to prometheus. This is already done if using Thanos - ## - disableCompaction: false - ## APIServerConfig - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#apiserverconfig - ## - apiserverConfig: {} - - ## Interval between consecutive scrapes. - ## Defaults to 30s. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183 - ## - scrapeInterval: "" - - ## Number of seconds to wait for target to respond before erroring - ## - scrapeTimeout: "" - - ## Interval between consecutive evaluations. - ## - evaluationInterval: "" - - ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP. - ## - listenLocal: false - - ## EnableAdminAPI enables Prometheus the administrative HTTP API which includes functionality such as deleting time series. - ## This is disabled by default. - ## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis - ## - enableAdminAPI: false - - ## Image of Prometheus. - ## - image: - repository: quay.io/prometheus/prometheus - tag: v2.22.1 - sha: "" - - ## Tolerations for use with node taints - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal" - # value: "value" - # effect: "NoSchedule" - - ## Alertmanagers to which alerts will be sent - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#alertmanagerendpoints - ## - ## Default configuration will connect to the alertmanager deployed as part of this release - ## - alertingEndpoints: [] - # - name: "" - # namespace: "" - # port: http - # scheme: http - # pathPrefix: "" - # tlsConfig: {} - # bearerTokenFile: "" - # apiVersion: v2 - - ## External labels to add to any time series or alerts when communicating with external systems - ## - externalLabels: {} - - ## Name of the external label used to denote replica name - ## - replicaExternalLabelName: "" - - ## If true, the Operator won't add the external label used to denote replica name - ## - replicaExternalLabelNameClear: false - - ## Name of the external label used to denote Prometheus instance name - ## - prometheusExternalLabelName: "" - - ## If true, the Operator won't add the external label used to denote Prometheus instance name - ## - prometheusExternalLabelNameClear: false - - ## External URL at which Prometheus will be reachable. - ## - externalUrl: "" - - ## Define which Nodes the Pods are scheduled on. - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. - ## The Secrets are mounted into /etc/prometheus/secrets/. Secrets changes after initial creation of a Prometheus object are not - ## reflected in the running Pods. To change the secrets mounted into the Prometheus Pods, the object must be deleted and recreated - ## with the new list of secrets. - ## - secrets: [] - - ## ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods. - ## The ConfigMaps are mounted into /etc/prometheus/configmaps/. - ## - configMaps: [] - - ## QuerySpec defines the query command line flags when starting Prometheus. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#queryspec - ## - query: {} - - ## Namespaces to be selected for PrometheusRules discovery. - ## If nil, select own namespace. Namespaces to be selected for ServiceMonitor discovery. - ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage - ## - ruleNamespaceSelector: {} - - ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the - ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the PrometheusRule resources created - ## - ruleSelectorNilUsesHelmValues: true - - ## PrometheusRules to be selected for target discovery. - ## If {}, select all ServiceMonitors - ## - ruleSelector: {} - ## Example which select all prometheusrules resources - ## with label "prometheus" with values any of "example-rules" or "example-rules-2" - # ruleSelector: - # matchExpressions: - # - key: prometheus - # operator: In - # values: - # - example-rules - # - example-rules-2 - # - ## Example which select all prometheusrules resources with label "role" set to "example-rules" - # ruleSelector: - # matchLabels: - # role: example-rules - - ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the - ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the servicemonitors created - ## - serviceMonitorSelectorNilUsesHelmValues: true - - ## ServiceMonitors to be selected for target discovery. - ## If {}, select all ServiceMonitors - ## - serviceMonitorSelector: {} - ## Example which selects ServiceMonitors with label "prometheus" set to "somelabel" - # serviceMonitorSelector: - # matchLabels: - # prometheus: somelabel - - ## Namespaces to be selected for ServiceMonitor discovery. - ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage - ## - serviceMonitorNamespaceSelector: {} - - ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the - ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the podmonitors created - ## - podMonitorSelectorNilUsesHelmValues: true - - ## PodMonitors to be selected for target discovery. - ## If {}, select all PodMonitors - ## - podMonitorSelector: {} - ## Example which selects PodMonitors with label "prometheus" set to "somelabel" - # podMonitorSelector: - # matchLabels: - # prometheus: somelabel - - ## Namespaces to be selected for PodMonitor discovery. - ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage - ## - podMonitorNamespaceSelector: {} - - ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the - ## prometheus resource to be created with selectors based on values in the helm deployment, - ## which will also match the probes created - ## - probeSelectorNilUsesHelmValues: true - - ## Probes to be selected for target discovery. - ## If {}, select all Probes - ## - probeSelector: {} - ## Example which selects Probes with label "prometheus" set to "somelabel" - # probeSelector: - # matchLabels: - # prometheus: somelabel - - ## Namespaces to be selected for Probe discovery. - ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage - ## - probeNamespaceSelector: {} - - ## How long to retain metrics - ## - retention: 10d - - ## Maximum size of metrics - ## - retentionSize: "" - - ## Enable compression of the write-ahead log using Snappy. - ## - walCompression: false - - ## If true, the Operator won't process any Prometheus configuration changes - ## - paused: false - - ## Number of Prometheus replicas desired - ## - replicas: 1 - - ## Log level for Prometheus be configured in - ## - logLevel: info - - ## Log format for Prometheus be configured in - ## - logFormat: logfmt - - ## Prefix used to register routes, overriding externalUrl route. - ## Useful for proxies that rewrite URLs. - ## - routePrefix: / - - ## Standard object’s metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata - ## Metadata Labels and Annotations gets propagated to the prometheus pods. - ## - podMetadata: {} - # labels: - # app: prometheus - # k8s-app: prometheus - - ## Pod anti-affinity can prevent the scheduler from placing Prometheus replicas on the same node. - ## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided. - ## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node. - ## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured. - podAntiAffinity: "" - - ## If anti-affinity is enabled sets the topologyKey to use for anti-affinity. - ## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone - ## - podAntiAffinityTopologyKey: kubernetes.io/hostname - - ## Assign custom affinity rules to the prometheus instance - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - ## - affinity: {} - # nodeAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # nodeSelectorTerms: - # - matchExpressions: - # - key: kubernetes.io/e2e-az-name - # operator: In - # values: - # - e2e-az1 - # - e2e-az2 - - ## The remote_read spec configuration for Prometheus. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#remotereadspec - remoteRead: [] - # - url: http://remote1/read - - ## The remote_write spec configuration for Prometheus. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#remotewritespec - remoteWrite: [] - # - url: http://remote1/push - - ## Enable/Disable Grafana dashboards provisioning for prometheus remote write feature - remoteWriteDashboards: false - - ## Resource limits & requests - ## - resources: {} - # requests: - # memory: 400Mi - - ## Prometheus StorageSpec for persistent data - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md - ## - storageSpec: {} - ## Using PersistentVolumeClaim - ## - # volumeClaimTemplate: - # spec: - # storageClassName: gluster - # accessModes: ["ReadWriteOnce"] - # resources: - # requests: - # storage: 50Gi - # selector: {} - - ## Using tmpfs volume - ## - # emptyDir: - # medium: Memory - - # Additional volumes on the output StatefulSet definition. - volumes: [] - - # Additional VolumeMounts on the output StatefulSet definition. - volumeMounts: [] - - ## AdditionalScrapeConfigs allows specifying additional Prometheus scrape configurations. Scrape configurations - ## are appended to the configurations generated by the Prometheus Operator. Job configurations must have the form - ## as specified in the official Prometheus documentation: - ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config. As scrape configs are - ## appended, the user is responsible to make sure it is valid. Note that using this feature may expose the possibility - ## to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible - ## scrape configs are going to break Prometheus after the upgrade. - ## - ## The scrape configuration example below will find master nodes, provided they have the name .*mst.*, relabel the - ## port to 2379 and allow etcd scraping provided it is running on all Kubernetes master nodes - ## - additionalScrapeConfigs: [] - # - job_name: kube-etcd - # kubernetes_sd_configs: - # - role: node - # scheme: https - # tls_config: - # ca_file: /etc/prometheus/secrets/etcd-client-cert/etcd-ca - # cert_file: /etc/prometheus/secrets/etcd-client-cert/etcd-client - # key_file: /etc/prometheus/secrets/etcd-client-cert/etcd-client-key - # relabel_configs: - # - action: labelmap - # regex: __meta_kubernetes_node_label_(.+) - # - source_labels: [__address__] - # action: replace - # targetLabel: __address__ - # regex: ([^:;]+):(\d+) - # replacement: ${1}:2379 - # - source_labels: [__meta_kubernetes_node_name] - # action: keep - # regex: .*mst.* - # - source_labels: [__meta_kubernetes_node_name] - # action: replace - # targetLabel: node - # regex: (.*) - # replacement: ${1} - # metric_relabel_configs: - # - regex: (kubernetes_io_hostname|failure_domain_beta_kubernetes_io_region|beta_kubernetes_io_os|beta_kubernetes_io_arch|beta_kubernetes_io_instance_type|failure_domain_beta_kubernetes_io_zone) - # action: labeldrop - - ## If additional scrape configurations are already deployed in a single secret file you can use this section. - ## Expected values are the secret name and key - ## Cannot be used with additionalScrapeConfigs - additionalScrapeConfigsSecret: {} - # enabled: false - # name: - # key: - - ## additionalPrometheusSecretsAnnotations allows to add annotations to the kubernetes secret. This can be useful - ## when deploying via spinnaker to disable versioning on the secret, strategy.spinnaker.io/versioned: 'false' - additionalPrometheusSecretsAnnotations: {} - - ## AdditionalAlertManagerConfigs allows for manual configuration of alertmanager jobs in the form as specified - ## in the official Prometheus documentation https://prometheus.io/docs/prometheus/latest/configuration/configuration/#<alertmanager_config>. - ## AlertManager configurations specified are appended to the configurations generated by the Prometheus Operator. - ## As AlertManager configs are appended, the user is responsible to make sure it is valid. Note that using this - ## feature may expose the possibility to break upgrades of Prometheus. It is advised to review Prometheus release - ## notes to ensure that no incompatible AlertManager configs are going to break Prometheus after the upgrade. - ## - additionalAlertManagerConfigs: [] - # - consul_sd_configs: - # - server: consul.dev.test:8500 - # scheme: http - # datacenter: dev - # tag_separator: ',' - # services: - # - metrics-prometheus-alertmanager - - ## AdditionalAlertRelabelConfigs allows specifying Prometheus alert relabel configurations. Alert relabel configurations specified are appended - ## to the configurations generated by the Prometheus Operator. Alert relabel configurations specified must have the form as specified in the - ## official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs. - ## As alert relabel configs are appended, the user is responsible to make sure it is valid. Note that using this feature may expose the - ## possibility to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible alert relabel - ## configs are going to break Prometheus after the upgrade. - ## - additionalAlertRelabelConfigs: [] - # - separator: ; - # regex: prometheus_replica - # replacement: $1 - # action: labeldrop - - ## SecurityContext holds pod-level security attributes and common container settings. - ## This defaults to non root user with uid 1000 and gid 2000. - ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md - ## - securityContext: - runAsGroup: 2000 - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 2000 - - ## Priority class assigned to the Pods - ## - priorityClassName: "" - - ## Thanos configuration allows configuring various aspects of a Prometheus server in a Thanos environment. - ## This section is experimental, it may change significantly without deprecation notice in any release. - ## This is experimental and may change significantly without backward compatibility in any release. - ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#thanosspec - ## - thanos: {} - - ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod. - ## if using proxy extraContainer update targetPort with proxy container port - containers: [] - - ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes - ## (permissions, dir tree) on mounted volumes before starting prometheus - initContainers: [] - - ## PortName to use for Prometheus. - ## - portName: "web" - - ## ArbitraryFSAccessThroughSMs configures whether configuration based on a service monitor can access arbitrary files - ## on the file system of the Prometheus container e.g. bearer token files. - arbitraryFSAccessThroughSMs: false - - ## OverrideHonorLabels if set to true overrides all user configured honor_labels. If HonorLabels is set in ServiceMonitor - ## or PodMonitor to true, this overrides honor_labels to false. - overrideHonorLabels: false - - ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs. - overrideHonorTimestamps: false - - ## IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector settings from the podmonitor and servicemonitor - ## configs, and they will only discover endpoints within their current namespace. Defaults to false. - ignoreNamespaceSelectors: false - - ## PrometheusRulesExcludedFromEnforce - list of prometheus rules to be excluded from enforcing of adding namespace labels. - ## Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair - prometheusRulesExcludedFromEnforce: false - - ## QueryLogFile specifies the file to which PromQL queries are logged. Note that this location must be writable, - ## and can be persisted using an attached volume. Alternatively, the location can be set to a stdout location such - ## as /dev/stdout to log querie information to the default Prometheus log stream. This is only available in versions - ## of Prometheus >= 2.16.0. For more details, see the Prometheus docs (https://prometheus.io/docs/guides/query-log/) - queryLogFile: false - - ## EnforcedSampleLimit defines global limit on number of scraped samples that will be accepted. This overrides any SampleLimit - ## set per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the SampleLimit to keep overall - ## number of samples/series under the desired limit. Note that if SampleLimit is lower that value will be taken instead. - enforcedSampleLimit: false - - ## AllowOverlappingBlocks enables vertical compaction and vertical query merge in Prometheus. This is still experimental - ## in Prometheus so it may change in any upcoming release. - allowOverlappingBlocks: false - - additionalRulesForClusterRole: [] - # - apiGroups: [ "" ] - # resources: - # - nodes/proxy - # verbs: [ "get", "list", "watch" ] - - additionalServiceMonitors: [] - ## Name of the ServiceMonitor to create - ## - # - name: "" - - ## Additional labels to set used for the ServiceMonitorSelector. Together with standard labels from - ## the chart - ## - # additionalLabels: {} - - ## Service label for use in assembling a job name of the form <label value>-<port> - ## If no label is specified, the service name is used. - ## - # jobLabel: "" - - ## labels to transfer from the kubernetes service to the target - ## - # targetLabels: "" - - ## Label selector for services to which this ServiceMonitor applies - ## - # selector: {} - - ## Namespaces from which services are selected - ## - # namespaceSelector: - ## Match any namespace - ## - # any: false - - ## Explicit list of namespace names to select - ## - # matchNames: [] - - ## Endpoints of the selected service to be monitored - ## - # endpoints: [] - ## Name of the endpoint's service port - ## Mutually exclusive with targetPort - # - port: "" - - ## Name or number of the endpoint's target port - ## Mutually exclusive with port - # - targetPort: "" - - ## File containing bearer token to be used when scraping targets - ## - # bearerTokenFile: "" - - ## Interval at which metrics should be scraped - ## - # interval: 30s - - ## HTTP path to scrape for metrics - ## - # path: /metrics - - ## HTTP scheme to use for scraping - ## - # scheme: http - - ## TLS configuration to use when scraping the endpoint - ## - # tlsConfig: - - ## Path to the CA file - ## - # caFile: "" - - ## Path to client certificate file - ## - # certFile: "" - - ## Skip certificate verification - ## - # insecureSkipVerify: false - - ## Path to client key file - ## - # keyFile: "" - - ## Server name used to verify host name - ## - # serverName: "" - - additionalPodMonitors: [] - ## Name of the PodMonitor to create - ## - # - name: "" - - ## Additional labels to set used for the PodMonitorSelector. Together with standard labels from - ## the chart - ## - # additionalLabels: {} - - ## Pod label for use in assembling a job name of the form <label value>-<port> - ## If no label is specified, the pod endpoint name is used. - ## - # jobLabel: "" - - ## Label selector for pods to which this PodMonitor applies - ## - # selector: {} - - ## PodTargetLabels transfers labels on the Kubernetes Pod onto the target. - ## - # podTargetLabels: {} - - ## SampleLimit defines per-scrape limit on number of scraped samples that will be accepted. - ## - # sampleLimit: 0 - - ## Namespaces from which pods are selected - ## - # namespaceSelector: - ## Match any namespace - ## - # any: false - - ## Explicit list of namespace names to select - ## - # matchNames: [] - - ## Endpoints of the selected pods to be monitored - ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#podmetricsendpoint - ## - # podMetricsEndpoints: [] diff --git a/scripts/helm/nginx-ingress/.helmignore b/scripts/helm/nginx-ingress/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/scripts/helm/nginx-ingress/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/scripts/helm/nginx-ingress/certbot.yaml b/scripts/helm/nginx-ingress/certbot.yaml deleted file mode 100644 index 40c421d48..000000000 --- a/scripts/helm/nginx-ingress/certbot.yaml +++ /dev/null @@ -1,41 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: certbot - namespace: nginx-ingress -spec: - replicas: 1 - selector: - matchLabels: - app: certbot - template: - metadata: - labels: - app: certbot - spec: - containers: - - name: certbot - image: certbot/certbot - command: - - /bin/sh - - -c - args: - - sleep 1d - resources: - requests: - cpu: 100m - memory: 200Mi - ports: - - containerPort: 80 ---- -apiVersion: v1 -kind: Service -metadata: - name: certbot - namespace: nginx-ingress -spec: - ports: - - port: 80 - targetPort: 80 - selector: - app: certbot diff --git a/scripts/helm/nginx-ingress/nginx-ingress/Chart.yaml b/scripts/helm/nginx-ingress/nginx-ingress/Chart.yaml deleted file mode 100644 index ee8ef93af..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/Chart.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v2 -name: nginx -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 1.16.0 diff --git a/scripts/helm/nginx-ingress/nginx-ingress/README.md b/scripts/helm/nginx-ingress/nginx-ingress/README.md deleted file mode 100644 index 89797d6e4..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## Description - -This is the frontend of the OpenReplay web app (internet). - -## Endpoints - -- /api -> chalice -- / -> frontend (in minio) -- /assets -> sessions-assets bucket in minio -- /minio -> minio api endpoint -- /ingest -> events ingestor -- /assist -> live sessions and webRTC -- /grafana -> monitoring (Enterprise Edition only) \ No newline at end of file diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/NOTES.txt b/scripts/helm/nginx-ingress/nginx-ingress/templates/NOTES.txt deleted file mode 100644 index 08bee15ea..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/NOTES.txt +++ /dev/null @@ -1,22 +0,0 @@ -1. Get the application URL by running these commands: -{{- if .Values.ingress.enabled }} -{{- range $host := .Values.ingress.hosts }} - {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} - {{- end }} -{{- end }} -{{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "nginx.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "nginx.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "nginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} -{{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "nginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") - export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") - echo "Visit http://127.0.0.1:8080 to use your application" - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT -{{- end }} diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/_helpers.tpl b/scripts/helm/nginx-ingress/nginx-ingress/templates/_helpers.tpl deleted file mode 100644 index ad9f4328e..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "nginx.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "nginx.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "nginx.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "nginx.labels" -}} -helm.sh/chart: {{ include "nginx.chart" . }} -{{ include "nginx.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "nginx.selectorLabels" -}} -app.kubernetes.io/name: {{ include "nginx.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "nginx.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "nginx.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/configmap.yaml b/scripts/helm/nginx-ingress/nginx-ingress/templates/configmap.yaml deleted file mode 100644 index ea59aa82d..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/configmap.yaml +++ /dev/null @@ -1,156 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: nginx - namespace: {{ .Release.Namespace }} -data: - location.list: |- - location ~* /general_stats { - deny all; - } - location /healthz { - return 200 'OK'; - } - location ~ ^/(mobs|sessions-assets|frontend|static|sourcemaps|ios-images)/ { - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $http_host; - - proxy_connect_timeout 300; - # Default is HTTP/1, keepalive is only enabled in HTTP/1.1 - proxy_http_version 1.1; - proxy_set_header Connection ""; - chunked_transfer_encoding off; - - proxy_pass http://minio.db.svc.cluster.local:9000; - } - - location /minio/ { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_pass http://minio.db.svc.cluster.local:9000; - } - location /ingest/ { - rewrite ^/ingest/(.*) /$1 break; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header X-Forwarded-For $real_ip; - proxy_set_header X-Forwarded-Host $real_ip; - proxy_set_header X-Real-IP $real_ip; - proxy_set_header Host $host; - proxy_pass http://http-openreplay.app.svc.cluster.local; - proxy_read_timeout 300; - proxy_connect_timeout 120; - proxy_send_timeout 300; - } - location /grafana { - set $target http://monitoring-grafana.monitoring.svc.cluster.local; - rewrite ^/grafana/(.*) /$1 break; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_pass $target; - } - location /api/ { - rewrite ^/api/(.*) /$1 break; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $origin_proto; - proxy_pass http://chalice-openreplay.app.svc.cluster.local:8000; - } - location /assist/ { - rewrite ^/assist/(.*) /$1 break; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_pass http://utilities-openreplay.app.svc.cluster.local:9000; - } - location /assets/ { - rewrite ^/assets/(.*) /sessions-assets/$1 break; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_pass http://minio.db.svc.cluster.local:9000; - } - location / { - index /index.html; - rewrite ^((?!.(js|css|png|svg|jpg|woff|woff2)).)*$ /frontend/index.html break; - include /etc/nginx/conf.d/compression.conf; - proxy_set_header Host $http_host; - proxy_pass http://minio.db.svc.cluster.local:9000/frontend/; - proxy_intercept_errors on; # see http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors - error_page 404 =200 /index.html; - } - compression.conf: |- - # Compression - gzip on; - gzip_comp_level 5; - gzip_min_length 256; # 256Bytes - gzip_proxied any; - gzip_vary on; - # Content types for compression - gzip_types - application/atom+xml - application/javascript - application/json - application/ld+json - application/manifest+json - application/rss+xml - application/vnd.geo+json - application/vnd.ms-fontobject - application/x-font-ttf - application/x-web-app-manifest+json - application/xhtml+xml - application/xml - font/opentype - image/bmp - image/svg+xml - image/x-icon - text/cache-manifest - text/css - text/plain - ; - - sites.conf: |- - resolver {{ .Values.kubeDnsIP }}; - # Need real ip address for flags in replay. - # Some LBs will forward real ips as x-forwarded-for - # So making that as priority - map $http_x_forwarded_for $real_ip { - ~^(\d+\.\d+\.\d+\.\d+) $1; - default $remote_addr; - } - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - map $http_x_forwarded_proto $origin_proto { - default $http_x_forwarded_proto; - '' $scheme; - } - server { - listen 80 default_server; - listen [::]:80 default_server; - # server_name _; - # return 301 https://$host$request_uri; - include /etc/nginx/conf.d/location.list; - client_max_body_size 10M; - } - server { - listen 443 ssl; - ssl_certificate /etc/secrets/site.crt; - ssl_certificate_key /etc/secrets/site.key; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA HIGH !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"; - include /etc/nginx/conf.d/location.list; - client_max_body_size 10M; - } diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/deployment.yaml b/scripts/helm/nginx-ingress/nginx-ingress/templates/deployment.yaml deleted file mode 100644 index 9cc018dc1..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/deployment.yaml +++ /dev/null @@ -1,65 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "nginx.fullname" . }} - labels: - {{- include "nginx.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "nginx.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - nginxRolloutID: {{ randAlphaNum 5 | quote }} # Restart nginx after every deployment - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "nginx.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "nginx.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: https - containerPort: 443 - protocol: TCP - - name: http - containerPort: 80 - protocol: TCP - livenessProbe: - httpGet: - path: /healthz - port: http - readinessProbe: - httpGet: - path: /healthz - port: http - resources: - {{- toYaml .Values.resources | nindent 12 }} - volumeMounts: - - name: nginx - mountPath: /etc/nginx/conf.d/ - - name: ssl - mountPath: /etc/secrets/ - volumes: - - name: nginx - configMap: - name: nginx - - name: ssl - secret: - secretName: ssl diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/ingress.yaml b/scripts/helm/nginx-ingress/nginx-ingress/templates/ingress.yaml deleted file mode 100644 index c90297ca9..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/ingress.yaml +++ /dev/null @@ -1,41 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "nginx.fullname" . -}} -{{- $svcPort := .Values.service.port -}} -{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "nginx.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ . }} - backend: - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/service.yaml b/scripts/helm/nginx-ingress/nginx-ingress/templates/service.yaml deleted file mode 100644 index 38912bf78..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "nginx.fullname" . }} - labels: - {{- include "nginx.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - # Make sure to get client ip - externalTrafficPolicy: Local - ports: - {{- range .Values.service.ports }} - - port: {{ .port }} - targetPort: {{ .targetPort }} - protocol: TCP - name: {{ .targetPort }} - {{- end }} - selector: - {{- include "nginx.selectorLabels" . | nindent 4 }} diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/serviceaccount.yaml b/scripts/helm/nginx-ingress/nginx-ingress/templates/serviceaccount.yaml deleted file mode 100644 index 365060380..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "nginx.serviceAccountName" . }} - labels: - {{- include "nginx.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/tests/test-connection.yaml b/scripts/helm/nginx-ingress/nginx-ingress/templates/tests/test-connection.yaml deleted file mode 100644 index 5879b4f6f..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/tests/test-connection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: "{{ include "nginx.fullname" . }}-test-connection" - labels: - {{- include "nginx.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test -spec: - containers: - - name: wget - image: busybox - command: ['wget'] - args: ['{{ include "nginx.fullname" . }}:{{ .Values.service.port }}'] - restartPolicy: Never diff --git a/scripts/helm/nginx-ingress/nginx-ingress/tls.yaml b/scripts/helm/nginx-ingress/nginx-ingress/tls.yaml deleted file mode 100644 index 6be88049a..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/tls.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -data: - tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZKRENDQkF5Z0F3SUJBZ0lTQkdrb0hRbThITEJ1dlR0RGZacHVBcTk3TUEwR0NTcUdTSWIzRFFFQkN3VUEKTURJeEN6QUpCZ05WQkFZVEFsVlRNUll3RkFZRFZRUUtFdzFNWlhRbmN5QkZibU55ZVhCME1Rc3dDUVlEVlFRRApFd0pTTXpBZUZ3MHlNVEF4TWpJeE5USTRORE5hRncweU1UQTBNakl4TlRJNE5ETmFNQnN4R1RBWEJnTlZCQU1UCkVHOXVjSEpsYlM1aGMyRjVaWEl1YVc4d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUIKQVFEQzA2bGJUNGJJWmlTSTBaOFZ3M2VyZVp1TjVnckdYV2YxNkZOd0kxb2pqU0RhVHJpSithU0FORklzcVpZcwozbm1hYjFKVDhaa1dHVVg0RWJaalJKR2JVZnZZYWQvWUlLbnpIRGRaa080MXY4ZzNYZWFseFltSmtMNVFBR0d6CnIwbTBHSENENmdxTU0xYThOd05FZTV0enRaZ0VwOWM0U2FZQ3ZzQkZ4YWdCMTZ0SnNBU0VaZkF6djh2Z05WenkKcE1SYURWNWc2UWVZdXBkeWZGb2Q5bldmdHZoTWgvZHROMWt5ZVlyanJSelpKOGRpQWRUWCtPZGJiNG52K3d3UwpwVGR4cVhsOFNxemh5U0V5aDVoRXArcVd3NEVWb3FzeFM5VU1rRmg0dktuNkExSGFGWGxmeERVWmxUVzdqeXpTCndiZmlXOTJhTFlUTHlxYk4wTU5pMEdJaEFnTUJBQUdqZ2dKSk1JSUNSVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXcKSFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01Bd0dBMVVkRXdFQi93UUNNQUF3SFFZRApWUjBPQkJZRUZHa05sY2FKRk1XMlMrR2IvS0N3ZmF0M2lyUUpNQjhHQTFVZEl3UVlNQmFBRkJRdXN4ZTNXRmJMCnJsQUpRT1lmcjUyTEZNTEdNRlVHQ0NzR0FRVUZCd0VCQkVrd1J6QWhCZ2dyQmdFRkJRY3dBWVlWYUhSMGNEb3YKTDNJekxtOHViR1Z1WTNJdWIzSm5NQ0lHQ0NzR0FRVUZCekFDaGhab2RIUndPaTh2Y2pNdWFTNXNaVzVqY2k1dgpjbWN2TUJzR0ExVWRFUVFVTUJLQ0VHOXVjSEpsYlM1aGMyRjVaWEl1YVc4d1RBWURWUjBnQkVVd1F6QUlCZ1puCmdRd0JBZ0V3TndZTEt3WUJCQUdDM3hNQkFRRXdLREFtQmdnckJnRUZCUWNDQVJZYWFIUjBjRG92TDJOd2N5NXMKWlhSelpXNWpjbmx3ZEM1dmNtY3dnZ0VDQmdvckJnRUVBZFo1QWdRQ0JJSHpCSUh3QU80QWRRQ1VJTHdlanRXTgpiSWh6SDRLTElpd04wZHBOWG14UGxEMWgyMDR2V0UyaXdnQUFBWGNxN1RIS0FBQUVBd0JHTUVRQ0lIalMrMUl4CmxtdDNkditvWDRmbTRXeDZ3YVBBUGlhcXBuSGVrL3I3LytXQ0FpQXhpTEdzMUttOXQzTm5tNnV1bGpkUWY3UHYKRW0rS056T01rbXg3OW9YVDBnQjFBSDArOHZpUC80aFZhQ1RDd01xZVVvbDVLOFVPZUFsL0xtcVhhSmwrSXZEWApBQUFCZHlydE1mUUFBQVFEQUVZd1JBSWdlVzRwUWl2bWNIMGwva1g0WDNaQTRoWGVDR1lCWkx1LzBFWjEzUkVQCjk4TUNJR1d4N3RvRlhJV3NEZ1Nhc241RWlhZFlmY29PTnFYVC9PVEpJL0FMOXdqOE1BMEdDU3FHU0liM0RRRUIKQ3dVQUE0SUJBUUI5Nm1HVUtaTG9QQk9lVm5sVFR3Vy9sSytLYnhsUkJrcXYrc2x1VGVUTmdrSFdSTy9JVGRMYQpDaDVidUdKc253dklCQktpSnIzSG04U3hkWXdKdUpmRUJsTW9kK1dHWktXQTQ1YjJkd1RTRll4OXdjL0lSWi91CjE1QldmVW9tOFhoVHd1Q1o0bG0xN05ET0w0eUpmWWNXVFZmZUo4SFJXK2N3QVo2OUE3Vm5tK2E3YWxCQkpSQksKUUNZL3hZTm8zT21WcE1IVVlicGJHSlg1QkVSMjJmV3lSU2wvWXZBNmJ5c0YxR3ZZMlJGcS83cHVQM3BQamZsbwpVU3FMYkJCL3ZzeXZiNkUxZW5OTkRORmFaMkk0dlZ4WUJaU1hvOEZpTmkycGI3elNpY1JkTjljeThFdlVnS05oCkRUVEJ0TFVjcStpQjlhNkNveTYrNERQMENldVM3YW1kCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVaVENDQTAyZ0F3SUJBZ0lRUUFGMUJJTVVwTWdoaklTcERCYk4zekFOQmdrcWhraUc5dzBCQVFzRkFEQS8KTVNRd0lnWURWUVFLRXh0RWFXZHBkR0ZzSUZOcFoyNWhkSFZ5WlNCVWNuVnpkQ0JEYnk0eEZ6QVZCZ05WQkFNVApEa1JUVkNCU2IyOTBJRU5CSUZnek1CNFhEVEl3TVRBd056RTVNakUwTUZvWERUSXhNRGt5T1RFNU1qRTBNRm93Ck1qRUxNQWtHQTFVRUJoTUNWVk14RmpBVUJnTlZCQW9URFV4bGRDZHpJRVZ1WTNKNWNIUXhDekFKQmdOVkJBTVQKQWxJek1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdXdJVktNejJvSlRURHhMcwpqVldTdy9pQzhabW1la0tJcDEwbXFyVXJ1Y1ZNc2ErT2EvbDF5S1BYRDBlVUZGVTFWNHllcUtJNUdmV0NQRUtwClRtNzFPOE11MjQzQXNGenpXVGpuN2M5cDhGb0xHNzdBbENRbGgvbzNjYk1UNXh5czRadnYyK1E3UlZKRmxxbkIKVTg0MHlGTHV0YTd0ajk1Z2NPS2xWS3UyYlE2WHBVQTBheXZUdkdiclpqUjgrbXVMajFjcG1mZ3dGMTI2Y20vNwpnY1d0MG9aWVBSZkg1d203OFN2M2h0ekIybkZkMUVianpLMGx3WWk4WUdkMVpyUHhHUGVpWE9aVC96cUl0a2VsCi94TVk2cGdKZHorZFUvblBBZVgxcG5BWEZLOWpwUCtaczVPZDNGT25CdjVJaFIyaGFhNGxkYnNUekZJRDllMVIKb1l2YkZRSURBUUFCbzRJQmFEQ0NBV1F3RWdZRFZSMFRBUUgvQkFnd0JnRUIvd0lCQURBT0JnTlZIUThCQWY4RQpCQU1DQVlZd1N3WUlLd1lCQlFVSEFRRUVQekE5TURzR0NDc0dBUVVGQnpBQ2hpOW9kSFJ3T2k4dllYQndjeTVwClpHVnVkSEoxYzNRdVkyOXRMM0p2YjNSekwyUnpkSEp2YjNSallYZ3pMbkEzWXpBZkJnTlZIU01FR0RBV2dCVEUKcDdHa2V5eHgrdHZoUzVCMS84UVZZSVdKRURCVUJnTlZIU0FFVFRCTE1BZ0dCbWVCREFFQ0FUQS9CZ3NyQmdFRQpBWUxmRXdFQkFUQXdNQzRHQ0NzR0FRVUZCd0lCRmlKb2RIUndPaTh2WTNCekxuSnZiM1F0ZURFdWJHVjBjMlZ1ClkzSjVjSFF1YjNKbk1Ed0dBMVVkSHdRMU1ETXdNYUF2b0MyR0syaDBkSEE2THk5amNtd3VhV1JsYm5SeWRYTjAKTG1OdmJTOUVVMVJTVDA5VVEwRllNME5TVEM1amNtd3dIUVlEVlIwT0JCWUVGQlF1c3hlM1dGYkxybEFKUU9ZZgpyNTJMRk1MR01CMEdBMVVkSlFRV01CUUdDQ3NHQVFVRkJ3TUJCZ2dyQmdFRkJRY0RBakFOQmdrcWhraUc5dzBCCkFRc0ZBQU9DQVFFQTJVemd5ZldFaURjeDI3c1Q0clA4aTJ0aUVteFl0MGwrUEFLM3FCOG9ZZXZPNEM1ejcwa0gKZWpXRUh4MnRhUERZL2xhQkwyMS9XS1p1TlRZUUhIUEQ1YjF0WGdIWGJuTDdLcUM0MDFkazVWdkNhZFRRc3ZkOApTOE1Yam9oeWM5ejkvRzI5NDhrTGptRTZGbGg5ZERZclZZQTl4Mk8raEVQR09hRU9hMWVlUHluQmdQYXl2VWZMCnFqQnN0ekxoV1ZRTEdBa1hYbU5zKzVablBCeHpESk9MeGhGMkpJYmVRQWNINUgwdFpyVWxvNVpZeU9xQTdzOXAKTzViODVvM0FNL09KK0NrdEZCUXRmdkJoY0pWZDl3dmx3UHNrK3V5T3kySEk3bU54S0tnc0JUdDM3NXRlQTJUdwpVZEhraFZOY3NBS1gxSDdHTk5MT0VBRGtzZDg2d3VvWHZnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRREMwNmxiVDRiSVppU0kKMFo4VnczZXJlWnVONWdyR1hXZjE2Rk53STFvampTRGFUcmlKK2FTQU5GSXNxWllzM25tYWIxSlQ4WmtXR1VYNApFYlpqUkpHYlVmdllhZC9ZSUtuekhEZFprTzQxdjhnM1hlYWx4WW1Ka0w1UUFHR3pyMG0wR0hDRDZncU1NMWE4Ck53TkVlNXR6dFpnRXA5YzRTYVlDdnNCRnhhZ0IxNnRKc0FTRVpmQXp2OHZnTlZ6eXBNUmFEVjVnNlFlWXVwZHkKZkZvZDluV2Z0dmhNaC9kdE4xa3llWXJqclJ6Wko4ZGlBZFRYK09kYmI0bnYrd3dTcFRkeHFYbDhTcXpoeVNFeQpoNWhFcCtxV3c0RVZvcXN4UzlVTWtGaDR2S242QTFIYUZYbGZ4RFVabFRXN2p5elN3YmZpVzkyYUxZVEx5cWJOCjBNTmkwR0loQWdNQkFBRUNnZ0VBQ1dOVnA5YS9NZXpxR2NXd0dzWmVmOTdPUmhvdHJyMVZneDM4MTB4OHpYWEIKZllPSmxPeDRwc3plb05SVExqcFNOY1RqZkxRSm9tejVXQ2pTVnhvNHdmbERYM3hLa3dtUDV1MFhKYk84SnM3bApBUFgvWlVHTmpSbHljanh5ZU13Yml4Z2FZK0RsUFRoRUY3RzI4SmZjTjhrcVdCOFdXZG9DcStNeE5LdC9td2NKCjdad2hDRXQrd1E3a2tzbU42VHpBcC9RY1U4R244dVpScXluYm4wVFNydVR4VVlKY3pVQit1bXdtVFF3bUNQNGYKUE1LS2pKTFRFMjIxeWdvV1FrYWtaOHMvL052ZmZiWG9FR2hXZkJ4U05wdGNwak82bU1Pcnp0UGhrUFR6d3oxaQpoajJmVHBuZXcvN3U3K0pkekwrZDloMHNuTCszV2RJS3VhQ2tBMDdvMlFLQmdRRGlFOHBsMEdYcWRtR2hwNHFkCk9rVjNxampraEx5NkJId3FkNGhqMVFYWlFMTWFiVkswOXd3WWY1SVJXR3NhZHB0WWwyUnczSThlWllkWFdVWXoKL1gxV2dHMEdBNWgxYWMySmk4R1JydTRWdk5YTExaQzVBYUJZTjFsUU42eXpRS2trUldFTXRCZTIrdi9TWjFBaQpCdFpKRnRRR21UcHNaR1gzNjdrbGx0YjNid0tCZ1FEY25RRjBNUFU4cC83ZEV3ci9ERXo4M05iaW12Kzk0NEN3Cm9Td29JUVUwZUZaZllDQW9ZK2ZQSW9vSHk1WVE0a3JxR1cxTGFRLyttcm8zZVF3TGNxRnJYVDNFQ2t4Zk9VbkIKbmZ4dHFYQ3ZmSlBLTlRaY0xZcGQvUFltTGcwbU5rS0d5QlppN01ENDNIV3lpeG9hUlQwV2RRWTlvdzBIRi8vMQpISUo4NDVIM2J3S0JnQWVQd2VWRjR5TEVjdCtGU3cyWE5WdWJSZXZleExFMEZUTVdiR2xxWnBldG9rL3YrQ1ExClh5SXlvaUFTWlFLdGxPU1JxN3BhcGk3T0ZvakZZNk81aHNldDQvZWZoeW5tTUFtNXN1KzhlaG9nQnNhVTc1SkEKaTZ4bnJZVVJWNlZuTkVFU1VQeXJ5VjlGWmVrVHE0cDMwQk1Cd0hXNENrdzF6M05MWHhYeXhaM2hBb0dBTEJQYQpoSUo3blFEYnRRUG5BSXBPbjM3b0dDSnIwbDZ3Q1pwS0hrSnFyYzhWUXIwTDc4WDJQTFpqNmFiTmR0WWZyYUlpCjZodzFxK0x5TGI4cm51WHFSbTg4dGZ4d3dkM0tWTHJpQW04R0txbXpSWVZZTlJhTVBMY2Izd2o0YTVnUHRxb24KZnVCYXRkNG1UZVBvOVRLOFA4NWx6czdTL1lYWUIvc0lQemVncEZVQ2dZQjJCdWN0OFZMS2d3aWx4aDFpU1NSMAo3UTl6S25WbWVld0haeG9tVFlxMGhyM0J0ZkJlWDIwZ2VWSTVHRUNVSFhxa0doS3RhNE9pbjl5WVNmY0ljdm1XClV1NFRVS3VaaGs0QkxFSGVHaGM3K1lKM2tJb09NZkpla0tQMEYydlk3SitYNkFOdm40UmQrbmdCclMwQjZZdnQKUXRSYzVBci9RMlhSZGZXQlhrL3dIdz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K -kind: Secret -metadata: - creationTimestamp: null - name: tls - namespace: nginx-ingress -type: kubernetes.io/tls diff --git a/scripts/helm/nginx-ingress/nginx-ingress/values.yaml b/scripts/helm/nginx-ingress/nginx-ingress/values.yaml deleted file mode 100644 index 9a703e387..000000000 --- a/scripts/helm/nginx-ingress/nginx-ingress/values.yaml +++ /dev/null @@ -1,86 +0,0 @@ -# Default values for nginx. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -image: - repository: nginx - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "" - -# DNS address of the kubernetes resolver -kubeDnsIP: "" - -imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -podAnnotations: {} - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -service: - type: LoadBalancer - ports: - - port: 80 - targetPort: http - - port: 443 - targetPort: https - -ingress: - enabled: false - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: [] - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/scripts/helm/nginx-ingress/site.crt b/scripts/helm/nginx-ingress/site.crt deleted file mode 100644 index 4b97f7298..000000000 --- a/scripts/helm/nginx-ingress/site.crt +++ /dev/null @@ -1,91 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFKjCCBBKgAwIBAgISBMcSyyqsERCX2y8Vs6krA7xwMA0GCSqGSIb3DQEBCwUA -MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD -EwJSMzAeFw0yMTA1MDkxNTU2NDBaFw0yMTA4MDcxNTU2NDBaMB4xHDAaBgNVBAMT -E2Zvc3Mub3BlbnJlcGxheS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQDsavxm+oAztJc+onR/PwAF8ZZnbNZt4BYyIZe9jxtN9hvQtq7tAJG5iNOo -g+aLz7NKQcztkGtptdy3lRAgXuPW2HSi0lrdDEAWvrKSdWQ0w/1FluyLUqyOU7Wx -uoR66/q/MwYVFiTAhgUd1DBnioQ4Y7VIS0HflyG6932D0bYCD/cNwJBRAUXWKsY4 -dkm14gTuuDgnKjAwaEwfsyOv2MU5z/YcmOMPOQfjyt0MJtkw8uzWbno9WmfkfFYP -Kq7h8doFrwwXZOTpMLVp+/Kh/FoUJ0xvQGrVK6Xxn+mj5jTPUYqhJIAgopO2Ic/h -+cDz8PY/luKKjLeWzro5NBeRXJf/AgMBAAGjggJMMIICSDAOBgNVHQ8BAf8EBAMC -BaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAw -HQYDVR0OBBYEFA0YCzc/BPv85t9VmjB1h/A9m3v0MB8GA1UdIwQYMBaAFBQusxe3 -WFbLrlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYVaHR0 -cDovL3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRwOi8vcjMuaS5sZW5j -ci5vcmcvMB4GA1UdEQQXMBWCE2Zvc3Mub3BlbnJlcGxheS5jb20wTAYDVR0gBEUw -QzAIBgZngQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDov -L2Nwcy5sZXRzZW5jcnlwdC5vcmcwggECBgorBgEEAdZ5AgQCBIHzBIHwAO4AdQBE -lGUusO7Or8RAB9io/ijA2uaCvtjLMbU/0zOWtbaBqAAAAXlSDzsmAAAEAwBGMEQC -IEAEguH2NQROl0oKTcQ13i6z61MiN5eFK3yWbPWVrNphAiBIxCkIm7CRY+/ULxZ9 -6Bwy8ycro3KN4A6HYQ6KPuFK9wB1APZclC/RdzAiFFQYCDCUVo7jTRMZM7/fDC8g -C8xO8WTjAAABeVIPOxsAAAQDAEYwRAIgLTrAzI6jkTxF5zgOPRcjsNRC1x0EJrv1 -KKrXpQZckysCIBaQxIyVcsXDLaQvxMR15C8CuAV4PN8x+1cWlR47SoPjMA0GCSqG -SIb3DQEBCwUAA4IBAQBKwF63JexmojwWUnTOQ/x9U0S7ba+3rtl2u9XxDjr97dLj -2VnGCzrngh1td+sd1W7jhckM2oWI7wEdOWvyUO3XmbI6XzcQ94bgiOP9ZUIPlb/5 -ofQhlGqmoLvzQMNsZuweSYdbIWovvLPuT6IdnZwW3LStLYdaN5ov6oNSvT7J8K1C -ja4MTl+fZeL26RgJCV+TKPiuR7vCrXidhaGgyfmTUGA71xsrgeRg3EIxs8iAz8Vj -R0pL2GPpaIRUBWGZLkZRDipPd/3RLEDZim8tzDietyhm0rSqm9OLGtGGiJ10/BAc -wzNH7/FUUiA30lze+OvyPPyEC08h2qC9BnjakXJM ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw -WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg -RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP -R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx -sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm -NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg -Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG -/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB -Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA -FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw -AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw -Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB -gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W -PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl -ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz -CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm -lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 -avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 -yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O -yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids -hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ -HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv -MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX -nLRbwHOoq7hHwg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC -ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL -wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D -LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK -4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5 -bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y -sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ -Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4 -FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc -SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql -PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND -TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1 -c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx -+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB -ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu -b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E -U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu -MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC -5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW -9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG -WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O -he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC -Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5 ------END CERTIFICATE----- diff --git a/scripts/helm/nginx-ingress/site.key b/scripts/helm/nginx-ingress/site.key deleted file mode 100644 index efec608d5..000000000 --- a/scripts/helm/nginx-ingress/site.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDsavxm+oAztJc+ -onR/PwAF8ZZnbNZt4BYyIZe9jxtN9hvQtq7tAJG5iNOog+aLz7NKQcztkGtptdy3 -lRAgXuPW2HSi0lrdDEAWvrKSdWQ0w/1FluyLUqyOU7WxuoR66/q/MwYVFiTAhgUd -1DBnioQ4Y7VIS0HflyG6932D0bYCD/cNwJBRAUXWKsY4dkm14gTuuDgnKjAwaEwf -syOv2MU5z/YcmOMPOQfjyt0MJtkw8uzWbno9WmfkfFYPKq7h8doFrwwXZOTpMLVp -+/Kh/FoUJ0xvQGrVK6Xxn+mj5jTPUYqhJIAgopO2Ic/h+cDz8PY/luKKjLeWzro5 -NBeRXJf/AgMBAAECggEBAJXl660bbUfbW/4hoP3BIzGhkPx4nKjD6S7V79EHuIdA -4Tf/bH/m2X6qy5DQONAy2/ncKKQD6qb24UAhKj1sDMf/LEzEVUpMZyJEvRJxjhyK -m76Qx+A6hiAj4VMT8MXDc5PhNR0PkjPjhcD49cvgnp7mUV3KIbUzrPZPz2xR/jXl -U2JcNQtaumPH6qS2uhur17VbiGRkeP1RIY1kgppWySIOsIrIq68DhatN7+OVl1gk -wF/LV4KasqnCvcHuu40FHbLK6qqwU0y30umI0pyOPq7VQa4YY6GApKutQnxv6DCy -wKpfd82ZbNCEurmJC5cKGoZpQYRsfhMPefdoFqPY8kECgYEA/YCm74VGEcjfTn/2 -r7ANB9AvIhnmBNXyExCDfR4R9RZxAkC2aNSlYbF47XhzUoT9fXO3R67IT6YJmnWR -kb24AAcecO7YwAh6qjdQOaa0KvlEQQtcVYHZC42N/DsWPutTGMiNfd6LOnQQXAdV -96P2xt+ikS9UxhBOh84Tsq74tt8CgYEA7r8+1KqWaAozPzW7qIXaliowtGpzBq3r -6EzckOiycUf8VTWF6iRN3iGwNRLk8tBhfhHR3zUrgNhvXzoT84CMN5PeRDHjJBB0 -46sBW12j37KqNswNINc3uoR9FmMGYZcQdOg+YNz0OS3Z6VB6nOk0YGY7y8FKbD01 -WvURENIN4uECgYAupyeRuwg7K6mVC829ZXvwbSrPbs67IxiK06YvN4J8hWXE0V4A -iunowb2MjndCv4DbPpmDUrJAnkD0MSDaHn0nXCgJBpvTM3xHqShVg81yfy9FfS6/ -+caU7rcrrUAZ0jsXu4j2micrWcLM/PigO4el7/A+IeTLEqMxMQbFAph5JwKBgBup -KrVnAkARlnhnWFOhFn85aiUtBCCs+90RMqjTXQFE7tZMejRzelYXHxw3ETGUtQbv -N5qdxWmLKfQlfXRD23sA9cp+4SsngPNzt5eHVNoxEAmDQK4iYUGJ4hg65t1drDlv -QvLkBqOtTUb73Qja+AeHMLxdq6q4uLrOE+kX/SXhAoGAEAUo15o5zG+RjP05VN1H -7o6f+i0ERX9BIlxPmttG8iJV4P/1UdVcLSFMDPRZ+b2MD8FuSTBQSF5Tfzl94y+E -TD+aCioFX2LORWGwUc/CzU5rS7f6c8l3QbqEh4OYXy+/lT0OYMlq2BCLcszGZdMX -VqXDNwxw76NgshMj9gYD0cM= ------END PRIVATE KEY----- diff --git a/scripts/helm/nginx-ingress/ssl_creator.yaml b/scripts/helm/nginx-ingress/ssl_creator.yaml deleted file mode 100644 index 81ec8dce5..000000000 --- a/scripts/helm/nginx-ingress/ssl_creator.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: ssl-creator - labels: - app: ssl-creator -spec: - template: - metadata: - name: ssl-creator - spec: - containers: - - name: ssl-creator - image: bitnami/minideb:buster - command: - - "/bin/bash" - - "-c" - - |- - sudo apt-get update - sudo apt-get install -y software-properties-common - sudo add-apt-repository ppa:certbot/certbot - sudo apt-get update - sudo apt-get install -y certbot - echo This script won't work for aws, as it's black listed in letsencrypt - certbot_home=/etc/letsencrypt/archive/$dns_name - restartPolicy: OnFailure diff --git a/scripts/helm/openreplay-cli b/scripts/helm/openreplay-cli deleted file mode 100755 index b9db53b6c..000000000 --- a/scripts/helm/openreplay-cli +++ /dev/null @@ -1,158 +0,0 @@ -#!/bin/bash - -## This script is a helper for managing your OpenReplay instance - -set -eE -o pipefail # same as: `set -o errexit -o errtrace` -# Trapping the error -trap err EXIT - -err() { - case "$?" in - 0) - ;; - *) - ;; - esac -} - -# make all stderr red -color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1 - -# color schemes -# Ansi color code variables -red="\e[0;91m" -blue="\e[0;94m" -expand_bg="\e[K" -blue_bg="\e[0;104m${expand_bg}" -red_bg="\e[0;101m${expand_bg}" -green_bg="\e[0;102m${expand_bg}" -green="\e[0;92m" -white="\e[0;97m" -bold="\e[1m" -uline="\e[4m" -reset="\e[0m" - -CWD=$pwd - -usage() -{ -clear -cat <<"EOF" - ___ ____ _ - / _ \ _ __ ___ _ __ | _ \ ___ _ __ | | __ _ _ _ -| | | | '_ \ / _ \ '_ \| |_) / _ \ '_ \| |/ _` | | | | -| |_| | |_) | __/ | | | _ < __/ |_) | | (_| | |_| | - \___/| .__/ \___|_| |_|_| \_\___| .__/|_|\__,_|\__, | - |_| |_| |___/ - -EOF - - echo -e "${green}Usage: openreplay-cli [ -h | --help ] - [ -d | --status ] - [ -v | --verbose ] - [ -l | --logs SERVICE ] - [ -i | --legacy-install SERVICE ] - [ -I | --helm-install SERVICE ] - [ -s | --stop SERVICE|all ] - [ -S | --start SERVICE|all ] - [ -r | --restart SERVICE|all ]" - echo -e "${reset}${blue}services: ${services[*]}${reset}" - exit 0 -} -services=( alerts assets chalice clickhouse ender sink storage http integrations ios-proxy db pg redis postgresql ) - -check() { - if ! command -v kubectl &> /dev/null - then - >&2 echo "Kubectl not found. Please refer https://kubernetes.io/docs/tasks/tools/install-kubectl/ " - exit 2 - fi - kubectl cluster-info &> /dev/null - if [[ $? -ne 0 ]]; then - echo -e "${red}Kubernetes cluster is not accessible.\nPlease check ${bold}KUBECONFIG${reset}${red} env variable is set or ${bold}~/.kube/config exists.${reset}" - exit 1 - fi -} - -stop() { - if [[ $1 == "all" ]]; then - kubectl scale deployment -n app --replicas=0 --all - return - fi - kubectl scale -n app deployment --replicas=0 $1-openreplay -} - -start() { - if [[ $1 == "all" ]]; then - cd ./app - for apps in $(ls *.yaml);do - app=$(echo $apps | cut -d '.' -f1) - helm upgrade --install -n app $app openreplay -f $app.yaml - done - cd $CWD - return - fi - helm upgrade --install -n app $1 ./app/openreplay -f ./app/$1.yaml -} - - -restart() { - if [[ $1 == "all" ]]; then - kubectl rollout restart deployment -n app - return - fi - kubectl rollout restart -n app deployment $1-openreplay -} - -legacyInstall() { - bash kube-install.sh --app $1 -} - -helmInstall() { - helm upgrade --install openreplay -n app openreplay -f vars.yaml -} - -upgrade() { - sed -i "s/tag:.*/ tag: 'latest'/g" ./app/$1.yaml -} - -logs() { - check - kubectl logs --timestamps -n app -l app.kubernetes.io/instance=$1 -f -} - -status() { - kubectl get deployment.apps -n app -} - -[[ $# -eq 0 ]] && usage && exit 1 - -PARSED_ARGUMENTS=$(color getopt -a -n openreplay-cli -o vhds:S:l:r:i:I --long verbose,help,status,start:,stop:,logs:,restart:,legacy-install:,helm-install -- "$@") -VALID_ARGUMENTS=$? -if [[ "$VALID_ARGUMENTS" != "0" ]]; then - usage -fi - -eval set -- "$PARSED_ARGUMENTS" -while : -do - case "$1" in - -v | --verbose) VERBOSE=1 ; shift ;; - -h | --help) usage ; shift ;; - -d | --status) status ; shift ;; - -I | --helm-install) helmInstall; shift ;; - -s | --stop) stop $2 ; shift 2 ;; - -S | --start) start $2 ; shift 2 ;; - -l | --logs) logs "$2" ; shift 2 ;; - -r | --restart) restart "$2" ; shift 2 ;; - -i | --legacy-install) legacyInstall "$2" ; shift 2 ;; - # -- means the end of the arguments; drop this, and break out of the while loop - --) shift; break ;; - # If invalid options were passed, then getopt should have reported an error, - # which we checked as VALID_ARGUMENTS when getopt was called... - *) echo "Unexpected option: $1 - this should not happen." - usage ;; - esac -done - -[[ $VERBOSE -eq 1 ]] && set -x diff --git a/scripts/helm/roles/openreplay/.travis.yml b/scripts/helm/roles/openreplay/.travis.yml deleted file mode 100644 index 36bbf6208..000000000 --- a/scripts/helm/roles/openreplay/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ ---- -language: python -python: "2.7" - -# Use the new container infrastructure -sudo: false - -# Install ansible -addons: - apt: - packages: - - python-pip - -install: - # Install ansible - - pip install ansible - - # Check ansible version - - ansible --version - - # Create ansible.cfg with correct roles_path - - printf '[defaults]\nroles_path=../' >ansible.cfg - -script: - # Basic role syntax check - - ansible-playbook tests/test.yml -i tests/inventory --syntax-check - -notifications: - webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/scripts/helm/roles/openreplay/README.md b/scripts/helm/roles/openreplay/README.md deleted file mode 100644 index 225dd44b9..000000000 --- a/scripts/helm/roles/openreplay/README.md +++ /dev/null @@ -1,38 +0,0 @@ -Role Name -========= - -A brief description of the role goes here. - -Requirements ------------- - -Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. - -Role Variables --------------- - -A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. - -Dependencies ------------- - -A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. - -Example Playbook ----------------- - -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - - - hosts: servers - roles: - - { role: username.rolename, x: 42 } - -License -------- - -BSD - -Author Information ------------------- - -An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/scripts/helm/roles/openreplay/defaults/main.yaml b/scripts/helm/roles/openreplay/defaults/main.yaml deleted file mode 100644 index e706891fb..000000000 --- a/scripts/helm/roles/openreplay/defaults/main.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -# defaults file for openreplay -db_name: "" -app_name: "" -db_list: - - "minio" - - "postgresql" - - "redis" - # - "nfs-server-provisioner" diff --git a/scripts/helm/roles/openreplay/tasks/install-apps.yaml b/scripts/helm/roles/openreplay/tasks/install-apps.yaml deleted file mode 100644 index 4f45a9608..000000000 --- a/scripts/helm/roles/openreplay/tasks/install-apps.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# vim: set ft=yaml.ansible : ---- -- name: Installing specific app - shell: | - override='' - [[ -f /tmp/'{{ app_name }}.yaml' ]] && override='-f /tmp/{{ app_name }}.yaml' || true - helm upgrade --install -n app "{{ app_name }}" -f app/{{ app_name }}.yaml ${override} ./app/openreplay --create-namespace - args: - executable: /bin/bash - when: app_name|length > 0 - tags: app -- name: Installing OpenReplay core applications - shell: | - override='' - [[ -f /tmp/'{{ item|basename }}' ]] && override='-f /tmp/{{ item|basename }}' || true - helm upgrade --install -n app "{{ (item|basename).split ('.') | first }}" -f "{{ item }}" ${override} ./app/openreplay --create-namespace - args: - executable: /bin/bash - with_fileglob: - - "app/*.yaml" - when: app_name|length == 0 - tags: apps - -- name: getting kube dns ip - shell: kubectl get service --namespace kube-system kube-dns -o jsonpath="{.spec.clusterIP}" - register: kube_dns_ip - tags: nginx -- name: Installing Proxy - shell: | - helm upgrade --install -n nginx-ingress nginx-ingress "./nginx-ingress/nginx-ingress" --create-namespace --set kubeDnsIP="{{ kube_dns_ip.stdout }}" - tags: nginx -- name: Installing Monitoring - shell: | - helm upgrade --install -n monitoring monitoring "./monitoring/kube-prometheus-stack" -f "/tmp/monitoring.yaml" --create-namespace - tags: monitoring - when: enable_monitoring == "true" diff --git a/scripts/helm/roles/openreplay/tasks/install-dbs.yaml b/scripts/helm/roles/openreplay/tasks/install-dbs.yaml deleted file mode 100644 index fd8f1993b..000000000 --- a/scripts/helm/roles/openreplay/tasks/install-dbs.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# vim: set ft=yaml.ansible : ---- -- name: Installing specific db - shell: | - helm upgrade --install -n db {{ db_name }} -f /tmp/{{ db_name }}.yaml ./db/{{ db_name }} --wait --create-namespace - args: - executable: /bin/bash - when: db_name|length > 0 - tags: db -- name: installing dbs - shell: | - helm upgrade --install -n db "{{ item }}" "./db/{{ item }}" -f "/tmp/{{ item }}.yaml" --wait --create-namespace &>> "{{ playbook_dir }}"/db_helm.log - with_items: "{{ db_list }}" -- name: Wait for all pods to be up - pause: - minutes: 2 -- name: Initializing data - block: - - name: Restoring postgres data - shell: | - file="{{ item|basename }}" - kubectl exec -n db postgresql-postgresql-0 -- /bin/bash -c "rm -rf /tmp/$file" - kubectl cp -n db $file postgresql-postgresql-0:/tmp/ - kubectl exec -n db postgresql-postgresql-0 -- /bin/bash -c "PGPASSWORD=asayerPostgres psql -v ON_ERROR_STOP=1 -U postgres -f /tmp/$file" &> "{{ playbook_dir }}"/postgresql_init.log - args: - chdir: db/init_dbs/postgresql - with_fileglob: - - db/init_dbs/postgresql/*.sql - retries: 3 - delay: 60 - register: result - until: result.rc == 0 - - name: Restoring clickhouse data - shell: | - file="{{ item|basename }}" - kubectl exec -n db clickhouse-0 -- /bin/bash -c "rm -rf /tmp/$file" - kubectl cp -n db $file clickhouse-0:/tmp/ - kubectl exec -n db clickhouse-0 -- /bin/bash -c "clickhouse-client < /tmp/$file" 2>&1 | tee -a "{{ playbook_dir }}"/clickhouse_init.log - args: - chdir: db/init_dbs/clickhouse/create - with_fileglob: - - db/init_dbs/clickhouse/create/*.sql - retries: 3 - delay: 60 - register: result - until: result.rc == 0 - when: enterprise_edition_license|length > 0 - - name: Initializing Minio - shell: | - minio_pod=$(kubectl get po -n db -l app.kubernetes.io/name=minio -n db --output custom-columns=name:.metadata.name | tail -n+2) - kubectl cp -n db db/bucket_policy.sh $minio_pod:/tmp/bucket_policy.sh - kubectl exec -n db $minio_pod -- bash /tmp/bucket_policy.sh "{{ minio_access_key }}" "{{ minio_secret_key }}" - retries: 3 - delay: 60 - register: result - until: result.rc == 0 - - name: Creating kafka topics - shell: | - # Creating topic - kubectl exec -n db kafka-0 -- /bin/bash -c '/opt/bitnami/kafka/bin/kafka-topics.sh --create --zookeeper kafka-zookeeper.db.svc.cluster.local:2181 --replication-factor 2 --partitions 16 --topic {{ item.name }} || true' - ### Set retention time: - kubectl exec -n db kafka-0 -- /bin/bash -c '/opt/bitnami/kafka/bin/kafka-configs.sh --zookeeper kafka-zookeeper.db.svc.cluster.local:2181 --entity-type topics --alter --add-config retention.ms={{ item.retention }} --entity-name {{ item.name }}' - with_items: - - {name: "raw", retention: "3456000000"} - - {name: "raw-ios", retention: "3456000000"} - - {name: "trigger", retention: "3456000000"} - - {name: "cache", retention: "3456000000"} - - {name: "analytics", retention: "3456000000"} - retries: 3 - delay: 60 - register: result - until: result.rc == 0 - when: enterprise_edition_license|length > 0 -- name: Downloading frontend archive - unarchive: - src: "https://github.com/openreplay/openreplay/releases/download/{{ openreplay_version }}/frontend.tar.gz" - dest: "{{ role_path }}" - remote_src: true - tags: - - frontend -- name: initializing frontend - shell: | - # Download frontend archive - minio_pod=$(kubectl get po -n db -l app.kubernetes.io/name=minio -n db --output custom-columns=name:.metadata.name | tail -n+2) - kubectl -n db cp frontend $minio_pod:/data/ - args: - chdir: "{{ role_path }}" - tags: - - frontend diff --git a/scripts/helm/roles/openreplay/tasks/main.yml b/scripts/helm/roles/openreplay/tasks/main.yml deleted file mode 100644 index 873aa771d..000000000 --- a/scripts/helm/roles/openreplay/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -# Checking user defined variables -- import_tasks: pre-check.yaml - -- name: Creating kubernetes namespaces - shell: | - kubectl create ns {{ item }} --dry-run=client -o yaml | kubectl apply -f - - with_items: - - "app" - - "db" - - "nginx-ingress" - -- name: Creating docker secrets - shell: | - kubectl delete -n app secret aws-registry || true - kubectl create secret -n app docker-registry aws-registry \ - --docker-server="{{ docker_registry_url }}" \ - --docker-username="{{ docker_registry_username }}" \ - --docker-password="{{ docker_registry_password }}" \ - --docker-email=no@email.local - when: docker_registry_username|length != 0 and docker_registry_password|length != 0 - -# Creating helm override files. -- name: Creating override files - template: - dest: "/tmp/{{ item|basename }}" - src: "{{ item }}" - with_fileglob: - - templates/*.yaml - tags: - - app - - template - -# Installing and initializing dbs -- import_tasks: install-dbs.yaml - -# Installing and initializing apps -- import_tasks: install-apps.yaml diff --git a/scripts/helm/roles/openreplay/tasks/pre-check.yaml b/scripts/helm/roles/openreplay/tasks/pre-check.yaml deleted file mode 100644 index 90e6021c8..000000000 --- a/scripts/helm/roles/openreplay/tasks/pre-check.yaml +++ /dev/null @@ -1,144 +0,0 @@ -# vim: set ft=yaml.ansible : ---- -- name: Checking user variables - block: - - name: Checking mandatory variables - fail: - msg: "Didn't find OpenReplay docker credentials." - when: kubeconfig_path|length == 0 or docker_registry_url|length == 0 - - name: Generaing minio access key - block: - - name: Generating minio access key - set_fact: - minio_access_key_generated: "{{ lookup('password', '/dev/null length=30 chars=ascii_letters') }}" - - name: Updating vars.yaml - lineinfile: - regexp: '^minio_access_key' - line: 'minio_access_key: "{{ minio_access_key_generated }}"' - path: vars.yaml - - name: Generating minio access key - set_fact: - minio_access_key: "{{ minio_access_key_generated }}" - when: minio_access_key|length == 0 - - name: Generating minio secret key - block: - - name: Generating minio access key - set_fact: - minio_secret_key_generated: "{{ lookup('password', '/dev/null length=30 chars=ascii_letters') }}" - - name: Updating vars.yaml - lineinfile: - regexp: '^minio_secret_key' - line: 'minio_secret_key: "{{minio_secret_key_generated}}"' - path: vars.yaml - - name: Generating minio secret key - set_fact: - minio_access_key: "{{ minio_secret_key_generated }}" - when: minio_secret_key|length == 0 - - name: Generating jwt secret key - block: - - name: Generating jwt access key - set_fact: - jwt_secret_key_generated: "{{ lookup('password', '/dev/null length=30 chars=ascii_letters') }}" - - name: Updating vars.yaml - lineinfile: - regexp: '^jwt_secret_key' - line: 'jwt_secret_key: "{{jwt_secret_key_generated}}"' - path: vars.yaml - - name: Generating jwt secret key - set_fact: - jwt_access_key: "{{ jwt_secret_key_generated }}" - when: jwt_secret_key|length == 0 - rescue: - - name: Caught error - debug: - msg: - - Below variables are mandatory. Please make sure it is updated in vars.yaml - - kubeconfig_path - - domain_name - failed_when: true - tags: pre-check -- name: Creating Nginx SSL certificate - block: - - name: Creating ssl - command: > - openssl req -x509 -nodes -subj '/CN=openreplay.local.host' -days 365 - -newkey rsa:4096 -sha256 -keyout {{ role_path }}/openreplay.local.pem -out {{ role_path }}/openreplay.local.crt - - name: Updating vars.yaml - lineinfile: - regexp: '^{{ item.name }}' - line: '{{ item.name }}: "{{role_path}}/{{ item.path }}"' - path: vars.yaml - with_items: - - { name: nginx_ssl_cert_file_path, path: "openreplay.local.crt" } - - { name: nginx_ssl_key_file_path, path: "openreplay.local.pem" } - when: nginx_ssl_cert_file_path|length == 0 or nginx_ssl_key_file_path|length == 0 - tags: pre-check -- name: updating ansible in_memory_variable - set_fact: - # in default varible, have to pass true to make sure the value is not "" - # ref: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#defaulting-undefined-variables - nginx_ssl_key_file_path_generated: "{{ nginx_ssl_key_file_path | default(role_path+'/openreplay.local.pem', true) }}" - nginx_ssl_cert_file_path_generated: "{{ nginx_ssl_cert_file_path | default(role_path+'/openreplay.local.crt', true) }}" - tags: - - pre-check - - nginx - - all -- name: Creating kubernetes ssl secrets - shell: - cmd: | - cat <<EOF | kubectl apply -f - - apiVersion: v1 - kind: Namespace - metadata: - name: "nginx-ingress" - --- - apiVersion: v1 - kind: Secret - metadata: - name: ssl - namespace: "nginx-ingress" - data: - ca.crt: "" - site.crt: "{{ lookup('file', nginx_ssl_cert_file_path_generated) | b64encode }}" - site.key: "{{ lookup('file', nginx_ssl_key_file_path_generated) | b64encode }}" - EOF - tags: - - pre-check - - nginx - - all -- name: Checking Enterprise Licence - uri: - url: https://api.openreplay.com/os/license - body: - mid: "UUID of the machine" - license: "{{ enterprise_edition_license }}" - body_format: json - creates: "{{ ansible_env.HOME }}/.config/openreplay.license" - follow_redirects: yes - force: false - http_agent: ansible-httpget - method: POST - return_content: true - status_code: [200] - timeout: 30 - unsafe_writes: false - validate_certs: true - when: enterprise_edition_license|length > 0 - register: enterprise_edition_license_check - failed_when: enterprise_edition_license_check.json.data.valid != true -- name: Generaing grafana password - block: - - name: Generating grafana password - set_fact: - grafana_password_generated: "{{ lookup('password', '/dev/null length=30 chars=ascii_letters') }}" - - name: Updating vars.yaml - lineinfile: - regexp: '^grafana_password' - line: 'grafana_password: "{{ grafana_password_generated }}"' - path: vars.yaml - - name: Generating grafana access key - set_fact: - grafana_password: "{{ grafana_password_generated }}" - when: grafana_password|length == 0 - tags: - - pre-check diff --git a/scripts/helm/roles/openreplay/templates/alerts.yaml b/scripts/helm/roles/openreplay/templates/alerts.yaml deleted file mode 100644 index 97178c1ce..000000000 --- a/scripts/helm/roles/openreplay/templates/alerts.yaml +++ /dev/null @@ -1,39 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} -env: - S3_KEY: "{{ minio_access_key }}" - S3_SECRET: "{{ minio_secret_key }}" - SITE_URL: "https://{{ domain_name }}" - pg_host: "{{ postgres_endpoint }}" - pg_port: "{{ postgres_port }}" - pg_dbname: "{{ postgres_db_name }}" - pg_user: "{{ postgres_db_user }}" - pg_password: "{{ postgres_db_password }}" - EMAIL_HOST: "{{ email_host }}" - EMAIL_PORT: "{{ email_port }}" - EMAIL_USER: "{{ email_user }}" - EMAIL_PASSWORD: "{{ email_password }}" - EMAIL_USE_TLS: "{{ email_use_tls }}" - EMAIL_USE_SSL: "{{ email_use_ssl }}" - EMAIL_SSL_KEY: "{{ email_ssl_key }}" - EMAIL_SSL_CERT: "{{ email_ssl_cert }}" - EMAIL_FROM: "{{ email_from }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - LICENSE_KEY: "{{ enterprise_edition_license }}" - # In case of minio, the instance is running inside kuberntes, - # which is accessible via nginx ingress. -{% if s3_endpoint == "http://minio.db.svc.cluster.local:9000" %} - S3_HOST: "https://{{ domain_name }}" -{% else %} - S3_HOST: "{{ s3_endpoint }}" -{% endif %} - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/assets.yaml b/scripts/helm/roles/openreplay/templates/assets.yaml deleted file mode 100644 index 5e435e822..000000000 --- a/scripts/helm/roles/openreplay/templates/assets.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} -env: - AWS_ACCESS_KEY_ID: "{{ minio_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ minio_secret_key }}" - S3_BUCKET_ASSETS: "{{ assets_bucket }}" - LICENSE_KEY: "{{ enterprise_edition_license }}" - AWS_ENDPOINT: "{{ s3_endpoint }}" - AWS_REGION: "{{ aws_region }}" - REDIS_STRING: "{{ redis_endpoint }}" - KAFKA_SERVERS: "{{ kafka_endpoint }}" - KAFKA_USE_SSL: "{{ kafka_ssl }}" - # In case of minio, the instance is running inside kuberntes, - # which is accessible via nginx ingress. -{% if s3_endpoint != "http://minio.db.svc.cluster.local:9000" %} - ASSETS_ORIGIN: "https://{{assets_bucket}}.{{ s3_endpoint.split('https://')[-1] }}" -{% endif %} - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/chalice.yaml b/scripts/helm/roles/openreplay/templates/chalice.yaml deleted file mode 100644 index 68c1cf9ff..000000000 --- a/scripts/helm/roles/openreplay/templates/chalice.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} -env: - S3_KEY: "{{ minio_access_key }}" - S3_SECRET: "{{ minio_secret_key }}" - sourcemaps_bucket_key: "{{ minio_access_key }}" - sourcemaps_bucket_secret: "{{ minio_secret_key }}" - SITE_URL: "https://{{ domain_name }}" - jwt_secret: "{{ jwt_secret_key }}" - pg_host: "{{ postgres_endpoint }}" - pg_port: "{{ postgres_port }}" - pg_dbname: "{{ postgres_db_name }}" - pg_user: "{{ postgres_db_user }}" - pg_password: "{{ postgres_db_password }}" - EMAIL_HOST: "{{ email_host }}" - EMAIL_PORT: "{{ email_port }}" - EMAIL_USER: "{{ email_user }}" - EMAIL_PASSWORD: "{{ email_password }}" - EMAIL_USE_TLS: "{{ email_use_tls }}" - EMAIL_USE_SSL: "{{ email_use_ssl }}" - EMAIL_SSL_KEY: "{{ email_ssl_key }}" - EMAIL_SSL_CERT: "{{ email_ssl_cert }}" - EMAIL_FROM: "{{ email_from }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - sessions_region: "{{ aws_region }}" - sessions_bucket: "{{ recordings_bucket }}" - sourcemaps_bucket: "{{ sourcemaps_bucket }}" - js_cache_bucket: "{{ assets_bucket }}" - # In case of minio, the instance is running inside kuberntes, - # which is accessible via nginx ingress. -{% if s3_endpoint == "http://minio.db.svc.cluster.local:9000" %} - S3_HOST: "https://{{ domain_name }}" -{% else %} - S3_HOST: "{{ s3_endpoint }}" -{% endif %} -{% if env is defined and env.chalice is defined and env.chalice%} - {{ env.chalice | to_nice_yaml | trim | indent(2) }} -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/clickhouse.yaml b/scripts/helm/roles/openreplay/templates/clickhouse.yaml deleted file mode 100644 index b8631a749..000000000 --- a/scripts/helm/roles/openreplay/templates/clickhouse.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{% if db_resource_override.clickhouse %}{ -{{ db_resource_override.clickhouse|to_nice_yaml(indent=2) }} -{% else %} -resources: - limits: - cpu: {{ ( 2000 * scale|float ) | int }}m - memory: {{ ( 4096 * scale|float ) | int }}Mi - requests: - cpu: 100m - memory: 128Mi -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/db.yaml b/scripts/helm/roles/openreplay/templates/db.yaml deleted file mode 100644 index bc128593d..000000000 --- a/scripts/helm/roles/openreplay/templates/db.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} -env: - LICENSE_KEY: "{{ enterprise_edition_license }}" - POSTGRES_STRING: "postgres://{{ postgres_db_user }}:{{ postgres_db_password }}@{{ postgres_endpoint }}:{{ postgres_port }}/{{ postgres_db_name }}" - REDIS_STRING: "{{ redis_endpoint }}" - KAFKA_SERVERS: "{{ kafka_endpoint }}" - KAFKA_USE_SSL: "{{ kafka_ssl }}" -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/ender.yaml b/scripts/helm/roles/openreplay/templates/ender.yaml deleted file mode 100644 index b5d256b2d..000000000 --- a/scripts/helm/roles/openreplay/templates/ender.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} -env: - LICENSE_KEY: "{{ enterprise_edition_license }}" - REDIS_STRING: "{{ redis_endpoint }}" - KAFKA_SERVERS: "{{ kafka_endpoint }}" - KAFKA_USE_SSL: "{{ kafka_ssl }}" - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/http.yaml b/scripts/helm/roles/openreplay/templates/http.yaml deleted file mode 100644 index 9c11a0a69..000000000 --- a/scripts/helm/roles/openreplay/templates/http.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} -env: - AWS_ACCESS_KEY_ID: "{{ minio_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ minio_secret_key }}" - LICENSE_KEY: "{{ enterprise_edition_license }}" - AWS_REGION: "{{ aws_region }}" - POSTGRES_STRING: "postgres://{{ postgres_db_user }}:{{ postgres_db_password }}@{{ postgres_endpoint }}:{{ postgres_port }}/{{ postgres_db_name }}" - REDIS_STRING: "{{ redis_endpoint }}" - KAFKA_SERVERS: "{{ kafka_endpoint }}" - KAFKA_USE_SSL: "{{ kafka_ssl }}" - # In case of minio, the instance is running inside kuberntes, - # which is accessible via nginx ingress. -{% if s3_endpoint != "http://minio.db.svc.cluster.local:9000" %} - ASSETS_ORIGIN: "https://{{assets_bucket}}.{{ s3_endpoint.split('https://')[-1] }}" -{% endif %} - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/integrations.yaml b/scripts/helm/roles/openreplay/templates/integrations.yaml deleted file mode 100644 index f7ea17428..000000000 --- a/scripts/helm/roles/openreplay/templates/integrations.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} -env: - LICENSE_KEY: "{{ enterprise_edition_license }}" - POSTGRES_STRING: "postgres://{{ postgres_db_user }}:{{ postgres_db_password }}@{{ postgres_endpoint }}:{{ postgres_port }}/{{ postgres_db_name }}" - # - REDIS_STRING: "{{ redis_endpoint }}" - KAFKA_SERVERS: "{{ kafka_endpoint }}" - KAFKA_USE_SSL: "{{ kafka_ssl }}" - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/kafka.yaml b/scripts/helm/roles/openreplay/templates/kafka.yaml deleted file mode 100644 index efd046d56..000000000 --- a/scripts/helm/roles/openreplay/templates/kafka.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resources: - limits: - cpu: {{ ( 256 * scale|float ) | int }}m - memory: {{ ( 1000 * scale|float ) | int }}Mi - requests: - cpu: 250m - memory: 256Mi diff --git a/scripts/helm/roles/openreplay/templates/minio.yaml b/scripts/helm/roles/openreplay/templates/minio.yaml deleted file mode 100644 index af4173d71..000000000 --- a/scripts/helm/roles/openreplay/templates/minio.yaml +++ /dev/null @@ -1,11 +0,0 @@ -global: - minio: - accessKey: "{{ minio_access_key }}" - secretKey: "{{ minio_secret_key }}" -resources: - limits: - cpu: {{ ( 256 * scale|float ) | int }}m - memory: {{ ( 512 * scale|float ) | int }}Mi - requests: - cpu: 100m - memory: 128Mi diff --git a/scripts/helm/roles/openreplay/templates/monitoring.yaml b/scripts/helm/roles/openreplay/templates/monitoring.yaml deleted file mode 100644 index 48c9146f0..000000000 --- a/scripts/helm/roles/openreplay/templates/monitoring.yaml +++ /dev/null @@ -1,6 +0,0 @@ -fullnameOverride: "openreplay" -grafana: - adminPassword: "{{ grafana_password }}" - env: - GF_SERVER_ROOT_URL: http://grafana.local.com/grafana - diff --git a/scripts/helm/roles/openreplay/templates/nfs-server-provisioner.yaml b/scripts/helm/roles/openreplay/templates/nfs-server-provisioner.yaml deleted file mode 100644 index 8f36baa35..000000000 --- a/scripts/helm/roles/openreplay/templates/nfs-server-provisioner.yaml +++ /dev/null @@ -1,8 +0,0 @@ -resources: - limits: - cpu: {{ ( 256 * scale|float ) | int }}m - memory: {{ ( 256 * scale|float ) | int }}Mi - requests: - cpu: 100m - memory: 128Mi - diff --git a/scripts/helm/roles/openreplay/templates/postgresql.yaml b/scripts/helm/roles/openreplay/templates/postgresql.yaml deleted file mode 100644 index bb5dbacb3..000000000 --- a/scripts/helm/roles/openreplay/templates/postgresql.yaml +++ /dev/null @@ -1,13 +0,0 @@ -image: - tag: 13.3.0-debian-10-r53 -{% if db_resource_override.postgresql %} -{{ db_resource_override.postgresql|to_nice_yaml(indent=2) }} -{% else %} -resources: - limits: - cpu: {{ ( 1000 * scale|float ) | int }}m - memory: {{ ( 2048 * scale|float ) | int }}Mi - requests: - cpu: 250m - memory: 256Mi -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/redis.yaml b/scripts/helm/roles/openreplay/templates/redis.yaml deleted file mode 100644 index 64f3e1059..000000000 --- a/scripts/helm/roles/openreplay/templates/redis.yaml +++ /dev/null @@ -1,16 +0,0 @@ -fullnameOverride: redis -usePassword: false -cluster: - enabled: false -redis: -{% if db_resource_override.redis %} - {{ db_resource_override.redis|to_nice_yaml(indent=2) }} -{% else %} - resources: - limits: - cpu: {{ ( 500 * scale|float ) | int }}m - memory: {{ ( 1024 * scale|float ) | int }}Mi - requests: - cpu: 100m - memory: 128Mi -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/sink.yaml b/scripts/helm/roles/openreplay/templates/sink.yaml deleted file mode 100644 index b5d256b2d..000000000 --- a/scripts/helm/roles/openreplay/templates/sink.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} -env: - LICENSE_KEY: "{{ enterprise_edition_license }}" - REDIS_STRING: "{{ redis_endpoint }}" - KAFKA_SERVERS: "{{ kafka_endpoint }}" - KAFKA_USE_SSL: "{{ kafka_ssl }}" - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/sqs.yaml b/scripts/helm/roles/openreplay/templates/sqs.yaml deleted file mode 100644 index 5bf2205f2..000000000 --- a/scripts/helm/roles/openreplay/templates/sqs.yaml +++ /dev/null @@ -1,8 +0,0 @@ -resources: - limits: - cpu: {{ ( 250 * scale|float ) | int }}m - memory: {{ ( 512 * scale|float ) | int }}Mi - requests: - cpu: 100m - memory: 128Mi - diff --git a/scripts/helm/roles/openreplay/templates/storage.yaml b/scripts/helm/roles/openreplay/templates/storage.yaml deleted file mode 100644 index 7a4e080d5..000000000 --- a/scripts/helm/roles/openreplay/templates/storage.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} -env: - AWS_ACCESS_KEY_ID: "{{ minio_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ minio_secret_key }}" - LICENSE_KEY: "{{ enterprise_edition_license }}" - AWS_ENDPOINT: "{{ s3_endpoint }}" - AWS_REGION_WEB: "{{ aws_region }}" - AWS_REGION_IOS: "{{ aws_region }}" - S3_BUCKET_WEB: "{{ recordings_bucket }}" - S3_BUCKET_IOS: "{{ recordings_bucket }}" - REDIS_STRING: "{{ redis_endpoint }}" - KAFKA_SERVERS: "{{ kafka_endpoint }}" - KAFKA_USE_SSL: "{{ kafka_ssl }}" - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} diff --git a/scripts/helm/roles/openreplay/templates/utilities.yaml b/scripts/helm/roles/openreplay/templates/utilities.yaml deleted file mode 100644 index 5646b3944..000000000 --- a/scripts/helm/roles/openreplay/templates/utilities.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{% if docker_registry_url is defined and docker_registry_url %} -image: - repository: {{ docker_registry_url }} - tag: {{ image_tag }} -{% endif %} - -{% if not (docker_registry_username is defined and docker_registry_username and docker_registry_password is defined and docker_registry_password) %} -imagePullSecrets: [] -{% endif %} -env: - S3_KEY: "{{ minio_access_key }}" - S3_SECRET: "{{ minio_secret_key }}" - # In case of minio, the instance is running inside kuberntes, - # which is accessible via nginx ingress. -{% if s3_endpoint == "http://minio.db.svc.cluster.local:9000" %} - S3_HOST: "https://{{ domain_name }}" -{% else %} - S3_HOST: "{{ s3_endpoint }}" -{% endif %} - jwt_secret: "{{ jwt_secret_key }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" -{% if env is defined and env.chalice is defined and env.chalice%} - {{ env.chalice | to_nice_yaml | trim | indent(2) }} -{% endif %} diff --git a/scripts/helm/setup.yaml b/scripts/helm/setup.yaml deleted file mode 100644 index 166f5ef19..000000000 --- a/scripts/helm/setup.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# vim: set ft=yaml.ansible : ---- -- hosts: localhost - environment: - KUBECONFIG: "{{ kubeconfig_path }}" - roles: - - openreplay diff --git a/scripts/helm/upgrade.sh b/scripts/helm/upgrade.sh deleted file mode 100644 index 3c437db9a..000000000 --- a/scripts/helm/upgrade.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/bash - -# upgrade.sh v1.10 - -set -e - -cwd=$PWD -openreplay_old_dir=$1 -vars_file_path=${openreplay_old_dir}/scripts/helm/vars.yaml - -[[ $# == 1 ]] || { - echo -e "OpenReplay previous version path not given.\nUsage: bash $0 /path/to/previous_openreplay_code_path" - exit 1 -} -[[ -d $1 ]] || { - echo -e "$1 doesn't exist. Please check the path and run\n \`bash upgrade.sh </path/to/previous/vars.yaml> \`" -} -which ansible &> /dev/null || { - echo "ansible not found. Are you sure, this is the same machine in which openreplay installed ?" - exit 100; -} - -echo -e"Updating vars.yaml\n" -{ - ansible localhost -m template -a "src=vars_template.yaml dest=vars.yaml" -e @${vars_file_path} - ansible localhost -m debug -a "var=openreplay_version" -e @${vars_file_path} -} || { - echo -e "variable file update failed. Update the value from old $vars_file_path to ./vars.yaml by hand" -} - -old_version=`grep openreplay_version ${vars_file_path} | cut -d "v" -f 3 | cut -d '"' -f 1` -[[ -z $old_version ]] && { - old_version=`grep image_tag ${vars_file_path} | cut -d "v" -f 2 | cut -d '"' -f 1` -} -enterprise_edition=`grep enterprise_edition_license ${vars_file_path} | cut -d ":" -f 2 | xargs` -migration(){ - # Ref: https://stackoverflow.com/questions/1527049/how-can-i-join-elements-of-an-array-in-bash - # Creating an array of versions to migrate. - db=$1 - migration_versions=(`ls -l db/init_dbs/$db | grep -E ^d | awk -v number=${old_version} '$NF > number {print $NF}' | grep -v create`) - # Can't pass the space seperated array to ansible for migration. So joining them with , - joined_migration_versions=$(IFS=, ; echo "${migration_versions[*]}") - - [[ $joined_migration_versions == "" ]] || - { - echo -e "Starting db migrations" - echo -e "Migrating versions $migration_versions" - - ansible-playbook -c local migration.yaml -e @vars.yaml -e migration_versions=${joined_migration_versions} --tags $db -v - } -} - -# Patching sendgrid configs for chalice -# This is workaround for chalice email configs. -# Proper variable override will introduce in v1.3.0 -patch(){ - vars=( - EMAIL_HOST - EMAIL_PORT - EMAIL_USER - EMAIL_PASSWORD - EMAIL_USE_TLS - EMAIL_USE_SSL - EMAIL_SSL_KEY - EMAIL_SSL_CERT - EMAIL_FROM - ) - for var in ${vars[@]};do - # Get old value - old_val=`grep $var ${openreplay_old_dir}/scripts/helm/app/chalice.yaml| cut -d" " -f4|xargs` - # Coverting caps env var to small ansible variable. - # In chalice EMAIL_HOST translates to email_host in vars.yaml - # Ref: https://stackoverflow.com/questions/2264428/how-to-convert-a-string-to-lower-case-in-bash - sed -i "s#${var,,}.*#${var,,}: \"$old_val\"#g" vars.yaml - done -} - -# patching chalice with sendgrid configs -patch - -installation_type=1 -if [[ ${ENTERPRISE} -eq 1 ]]; then - cp -rf ../../ee/scripts/* ../../scripts/ - sed 's/\(image_tag.*[0-9]\)\(-pr\)\?"$/\1\2-ee"/' vars.yaml - echo -e "Migrating clickhouse" - migration clickhouse -fi -echo -e "Migrating postgresql" -migration postgresql - -# Re installing apps. -apps=($(ls app/*.yaml|cut -d "." -f1|cut -d '/' -f2)) -ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type --tags template -v -for app in ${apps[@]}; do - ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type -e app_name=$app --tags app --skip-tags template -v -done -# Installing frontend -ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type --tags frontend -v -# Installing nginx -sed -i 's/.* return 301 .*/ # return 301 https:\/\/$host$request_uri;/g' nginx-ingress/nginx-ingress/templates/configmap.yaml -[[ NGINX_REDIRECT_HTTPS -eq 1 ]] && { -sed -i "s/# return 301/return 301/g" nginx-ingress/nginx-ingress/templates/configmap.yaml -} -ansible-playbook -c local setup.yaml -e @vars.yaml -e scale=$installation_type --tags nginx -v diff --git a/scripts/helm/vars.yaml b/scripts/helm/vars.yaml deleted file mode 100644 index f17ec904c..000000000 --- a/scripts/helm/vars.yaml +++ /dev/null @@ -1,112 +0,0 @@ -################### -## Mandatory Fields. -################### - -# Give the path of the kubeconfig_path: /home/user/.kube/config -# we can access the kubernetes cluster. -# Give absolute file path. -# Use following command to get the full file path -# `readlink -f <file>` -kubeconfig_path: "" - -# Using which domain name, you'll be accessing OpenReplay -# for example: domain_name: "openreplay.mycompany.com" -# -# Without domain name session replay is not possible, because we've to -# create signed url for s3 objects. -domain_name: "" - -################### -## Optional Fields. -################### - -# If you've private registry, please update the details here. -docker_registry_username: "" -docker_registry_password: "" -docker_registry_url: "rg.fr-par.scw.cloud/foss" -image_tag: "v1.4.0" -openreplay_version: "v1.4.0" - -# Nginx ssl certificates. -# in cert format -# Give absolute file path. -# Use following command to get the full file path -# `readlink -f <file>` -# For example: -# nginx_ssl_cert_file_path: "/home/openreplay/nginx-cert.crt" -# nginx_ssl_key_file_path: "/home/openreplay/nginx-key.pem" -# -# By Default, we'll create a self signed certificate for nginx, and populate the values here. -# Once you've proper domain name, and ssl certificate -# Change the following variables accordingly. -nginx_ssl_cert_file_path: "" -nginx_ssl_key_file_path: "" - -# This key is used to create password for chalice api requests. -# Create a strong password. -# By default, a default key will be generated and will update the value here. -jwt_secret_key: "" - -# Random password for minio, -# If not defined, will generate at runtime. -# Use following command to generate password -# `openssl rand -base64 30` -minio_access_key: "" -minio_secret_key: "" - -# If you're using enterprise edition. -# Insert the enterprise_edition_License key which you got. -enterprise_edition_license: "" - -# Enable monitoring -# If set, monitoring stack will be installed -# including, prometheus, grafana and other core components, -# to scrape the metrics. But this will cost, additional resources (cpu and memory). -# Monitoring won't be installed on base installation. -enable_monitoring: "false" -# Password for grafana. -# If password is not given, it'll be generated, and updated here. -# -# Use following command to generate password -# `openssl rand -base64 30` -# -# Username: admin -grafana_password: "" - -## Advanced -# If you need to override the default cpu/memory allocation of databases. -db_resource_override: - postgresql: {} - # resources: - # limits: - # cpu: 1000m - # memory: 1024Mi - # requests: - # cpu: 250m - # memory: 256Mi - redis: {} - clickhouse: {} - -## Sane defaults -s3_endpoint: "http://minio.db.svc.cluster.local:9000" -aws_region: "us-east-1" -assets_bucket: sessions-assets -recordings_bucket: mobs -sourcemaps_bucket: sourcemaps -kafka_endpoint: kafka.db.svc.cluster.local:9092 -kafka_ssl: 'false' -postgres_endpoint: postgresql.db.svc.cluster.local -postgres_port: 5432 -postgres_db_name: postgres -postgres_db_user: postgres -postgres_db_password: asayerPostgres -redis_endpoint: redis-master.db.svc.cluster.local:6379 -email_host: '' -email_port: '587' -email_user: '' -email_password: '' -email_use_tls: 'true' -email_use_ssl: 'false' -email_ssl_key: '' -email_ssl_cert: '' -email_from: OpenReplay<do-not-reply@openreplay.com> diff --git a/scripts/helm/vars_template.yaml b/scripts/helm/vars_template.yaml deleted file mode 100644 index 78272fbe9..000000000 --- a/scripts/helm/vars_template.yaml +++ /dev/null @@ -1,112 +0,0 @@ -################### -## Mandatory Fields. -################### - -# Give the path of the kubeconfig_path: /home/user/.kube/config -# we can access the kubernetes cluster. -# Give absolute file path. -# Use following command to get the full file path -# `readlink -f <file>` -kubeconfig_path: "{{ kubeconfig_path }}" - -# Using which domain name, you'll be accessing OpenReplay -# for example: domain_name: "openreplay.mycompany.com" -# -# Without domain name session replay is not possible, because we've to -# create signed url for s3 objects. -domain_name: "{{ domain_name }}" - -################### -## Optional Fields. -################### - -# If you've private registry, please update the details here. -docker_registry_username: "{{ docker_registry_username }}" -docker_registry_password: "{{ docker_registry_password }}" -docker_registry_url: "{{ docker_registry_url }}" -image_tag: "v1.3.6" -openreplay_version: "v1.3.6" - -# Nginx ssl certificates. -# in cert format -# Give absolute file path. -# Use following command to get the full file path -# `readlink -f <file>` -# For example: -# nginx_ssl_cert_file_path: "/home/openreplay/nginx-cert.crt" -# nginx_ssl_key_file_path: "/home/openreplay/nginx-key.pem" -# -# By Default, we'll create a self signed certificate for nginx, and populate the values here. -# Once you've proper domain name, and ssl certificate -# Change the following variables accordingly. -nginx_ssl_cert_file_path: "{{ nginx_ssl_cert_file_path }}" -nginx_ssl_key_file_path: "{{ nginx_ssl_key_file_path }}" - -# This key is used to create password for chalice api requests. -# Create a strong password. -# By default, a default key will be generated and will update the value here. -jwt_secret_key: "{{ jwt_secret_key }}" - -# Random password for minio, -# If not defined, will generate at runtime. -# Use following command to generate password -# `openssl rand -base64 30` -minio_access_key: "{{ minio_access_key }}" -minio_secret_key: "{{ minio_secret_key }}" - -# If you're using enterprise edition. -# Insert the enterprise_edition_License key which you got. -enterprise_edition_license: "{{ enterprise_edition_license }}" - -# Enable monitoring -# If set, monitoring stack will be installed -# including, prometheus, grafana and other core components, -# to scrape the metrics. But this will cost, additional resources (cpu and memory). -# Monitoring won't be installed on base installation. -enable_monitoring: "{{ enable_monitoring }}" -# Password for grafana. -# If password is not given, it'll be generated, and updated here. -# -# Use following command to generate password -# `openssl rand -base64 30` -# -# Username: admin -grafana_password: "{{ grafana_password }}" - -## Advanced -# If you need to override the default cpu/memory allocation of databases. -db_resource_override: - postgresql: {{ db_resource_override.postgresql|default({}) }} - # resources: - # limits: - # cpu: 1000m - # memory: 1024Mi - # requests: - # cpu: 250m - # memory: 256Mi - redis: {{ db_resource_override.redis|default({}) }} - clickhouse: {{ db_resource_override.clickhouse|default({}) }} - -## Sane defaults -s3_endpoint: "http://minio.db.svc.cluster.local:9000" -aws_region: "us-east-1" -assets_bucket: sessions-assets -recordings_bucket: mobs -sourcemaps_bucket: sourcemaps -kafka_endpoint: kafka.db.svc.cluster.local:9042 -kafka_ssl: 'false' -postgres_endpoint: postgresql.db.svc.cluster.local -postgres_port: 5432 -postgres_db_name: postgres -postgres_db_user: postgres -postgres_db_password: asayerPostgres -redis_endpoint: redis-master.db.svc.cluster.local:6379 -email_host: '' -email_port: '587' -email_user: '' -email_password: '' -email_use_tls: 'true' -email_use_ssl: 'false' -email_ssl_key: '' -email_ssl_cert: '' -email_from: OpenReplay<do-not-reply@openreplay.com> diff --git a/scripts/helmcharts/build_deploy.sh b/scripts/helmcharts/build_deploy.sh index c5843a76a..e5714a1b2 100644 --- a/scripts/helmcharts/build_deploy.sh +++ b/scripts/helmcharts/build_deploy.sh @@ -6,7 +6,7 @@ set -e # Usage: IMAGE_TAG=latest DOCKER_REPO=rg.fr-par.scw.cloud/foss bash build_deploy.sh # Removing local alpine:latest image -docker rmi alpine +docker rmi alpine || true echo $DOCKER_REPO [[ -z DOCKER_REPO ]] && { @@ -22,6 +22,8 @@ echo $DOCKER_REPO PUSH_IMAGE=1 bash build.sh $@ cd ../frontend PUSH_IMAGE=1 bash build.sh $@ + cd ../sourcemap-reader + PUSH_IMAGE=1 bash build.sh $@ cd ../api PUSH_IMAGE=1 bash build.sh $@ } diff --git a/scripts/helmcharts/build_deploy_parallel.sh b/scripts/helmcharts/build_deploy_parallel.sh new file mode 100644 index 000000000..76ab9a766 --- /dev/null +++ b/scripts/helmcharts/build_deploy_parallel.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -e +# Must run inside tmux +# This script will build and push docker image to registry + +# Usage: IMAGE_TAG=latest DOCKER_REPO=rg.fr-par.scw.cloud/foss bash build_deploy.sh + +# Removing local alpine:latest image +docker rmi alpine || true + +echo $DOCKER_REPO +[[ -z DOCKER_REPO ]] && { + echo Set DOCKER_REPO="your docker registry" + exit 1 +} || { + docker login $DOCKER_REPO +# tmux set-option remain-on-exit on + tmux split-window "cd ../../backend && IMAGE_TAG=$IMAGE_TAG DOCKER_REPO=$DOCKER_REPO PUSH_IMAGE=1 bash build.sh $@" + tmux split-window "cd ../../utilities && IMAGE_TAG=$IMAGE_TAG DOCKER_REPO=$DOCKER_REPO PUSH_IMAGE=1 bash build.sh $@" + tmux select-layout tiled + tmux split-window "cd ../../peers && IMAGE_TAG=$IMAGE_TAG DOCKER_REPO=$DOCKER_REPO PUSH_IMAGE=1 bash build.sh $@" + tmux split-window "cd ../../frontend && IMAGE_TAG=$IMAGE_TAG DOCKER_REPO=$DOCKER_REPO PUSH_IMAGE=1 bash build.sh $@" + tmux select-layout tiled + tmux split-window "cd ../../sourcemap-reader && IMAGE_TAG=$IMAGE_TAG DOCKER_REPO=$DOCKER_REPO PUSH_IMAGE=1 bash build.sh $@" + tmux split-window "cd ../../api && IMAGE_TAG=$IMAGE_TAG DOCKER_REPO=$DOCKER_REPO PUSH_IMAGE=1 bash build.sh $@" + tmux select-layout tiled + +} diff --git a/scripts/helmcharts/databases/Chart.yaml b/scripts/helmcharts/databases/Chart.yaml index be146afe5..8b5d65988 100644 --- a/scripts/helmcharts/databases/Chart.yaml +++ b/scripts/helmcharts/databases/Chart.yaml @@ -48,3 +48,7 @@ dependencies: repository: file://charts/minio version: 3.7.14 condition: minio.enabled + - name: vault + repository: file://charts/vault + version: 0.22.1 + condition: vault.enabled diff --git a/scripts/helmcharts/databases/charts/clickhouse/Chart.yaml b/scripts/helmcharts/databases/charts/clickhouse/Chart.yaml index 4026f2308..c7a0eb3d6 100644 --- a/scripts/helmcharts/databases/charts/clickhouse/Chart.yaml +++ b/scripts/helmcharts/databases/charts/clickhouse/Chart.yaml @@ -20,9 +20,4 @@ version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "1.16.0" - -dependencies: - - name: altinity-clickhouse-operator - version: 0.0.14 +appVersion: 1.16.0 diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/Chart.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/Chart.yaml deleted file mode 100644 index 5556de4a7..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/Chart.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v2 -appVersion: 0.18.1 -description: Helm chart to deploy [altinity-clickhouse-operator](https://github.com/Altinity/clickhouse-operator). The - ClickHouse Operator creates, configures and manages ClickHouse clusters running - on Kubernetes. Refer to operator repo for additional information. -home: https://github.com/slamdev/helm-charts/tree/master/charts/altinity-clickhouse-operator -icon: https://artifacthub.io/image/2d6aa29c-c74f-4bff-bede-ba7e6e0315a7@2x -maintainers: -- email: valentin.fedoskin@gmail.com - name: slamdev -name: altinity-clickhouse-operator -type: application -version: 0.0.14 diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/README.md b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/README.md deleted file mode 100644 index a05913517..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# altinity-clickhouse-operator - -![Version: 0.0.13](https://img.shields.io/badge/Version-0.0.13-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.18.1](https://img.shields.io/badge/AppVersion-0.18.1-informational?style=flat-square) - -Helm chart to deploy [altinity-clickhouse-operator](https://github.com/Altinity/clickhouse-operator). - -The ClickHouse Operator creates, configures and manages ClickHouse clusters running on Kubernetes. - -Refer to operator repo for additional information. - -**Homepage:** <https://github.com/slamdev/helm-charts/tree/master/charts/altinity-clickhouse-operator> - -## Maintainers - -| Name | Email | Url | -| ---- | ------ | --- | -| slamdev | valentin.fedoskin@gmail.com | | - -## Values - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| affinity | object | `{}` | affinity for scheduler pod assignment | -| configs | object | `{"confdFiles":null,"configdFiles":null,"files":null,"templatesdFiles":null,"usersdFiles":null}` | overrides operator default configmaps | -| fullnameOverride | string | `""` | full name of the chart. | -| imagePullSecrets | list | `[]` | image pull secret for private images | -| metrics.env | list | `[]` | additional environment variables for the deployment | -| metrics.image.pullPolicy | string | `"IfNotPresent"` | image pull policy | -| metrics.image.repository | string | `"altinity/metrics-exporter"` | image repository | -| metrics.image.tag | string | `""` | image tag (chart's appVersion value will be used if not set) | -| metrics.resources | object | `{}` | custom resource configuration | -| metrics.command | list | `nil` | command for metrics-exporter container | -| metrics.args | list | `nil` | args for metrics-exporter container | -| nameOverride | string | `""` | override name of the chart | -| nodeSelector | object | `{}` | node for scheduler pod assignment | -| operator.env | list | `[]` | additional environment variables for the deployment | -| operator.image.pullPolicy | string | `"IfNotPresent"` | image pull policy | -| operator.image.repository | string | `"altinity/clickhouse-operator"` | image repository | -| operator.image.tag | string | `""` | image tag (chart's appVersion value will be used if not set) | -| operator.resources | object | `{}` | custom resource configuration | -| operator.command | list | `nil` | command for operator container | -| operator.args | list | `nil` | args for operator container | -| podAnnotations | object | `nil` | additional pod annotations | -| serviceAccount.annotations | object | `{}` | annotations to add to the service account | -| serviceAccount.create | bool | `true` | specifies whether a service account should be created | -| serviceAccount.name | string | `nil` | the name of the service account to use; if not set and create is true, a name is generated using the fullname template | -| serviceMonitor.additionalLabels | object | `{}` | additional labels for service monitor | -| serviceMonitor.enabled | bool | `false` | ServiceMonitor CRD is created for a prometheus operator | -| tolerations | list | `[]` | tolerations for scheduler pod assignment | diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseinstallations.clickhouse.altinity.com.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseinstallations.clickhouse.altinity.com.yaml deleted file mode 100644 index 908961576..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseinstallations.clickhouse.altinity.com.yaml +++ /dev/null @@ -1,1321 +0,0 @@ -# Template Parameters: -# -# KIND=ClickHouseInstallation -# SINGULAR=clickhouseinstallation -# PLURAL=clickhouseinstallations -# SHORT=chi -# -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: clickhouseinstallations.clickhouse.altinity.com - labels: - clickhouse.altinity.com/chop: 0.18.1 -spec: - group: clickhouse.altinity.com - scope: Namespaced - names: - kind: ClickHouseInstallation - singular: clickhouseinstallation - plural: clickhouseinstallations - shortNames: - - chi - versions: - - name: v1 - served: true - storage: true - additionalPrinterColumns: - - name: version - type: string - description: Operator version - priority: 1 # show in wide view - jsonPath: .status.chop-version - - name: clusters - type: integer - description: Clusters count - priority: 0 # show in standard view - jsonPath: .status.clusters - - name: shards - type: integer - description: Shards count - priority: 1 # show in wide view - jsonPath: .status.shards - - name: hosts - type: integer - description: Hosts count - priority: 0 # show in standard view - jsonPath: .status.hosts - - name: taskID - type: string - description: TaskID - priority: 1 # show in wide view - jsonPath: .status.taskID - - name: status - type: string - description: CHI status - priority: 0 # show in standard view - jsonPath: .status.status - - name: updated - type: integer - description: Updated hosts count - priority: 1 # show in wide view - jsonPath: .status.updated - - name: added - type: integer - description: Added hosts count - priority: 1 # show in wide view - jsonPath: .status.added - - name: deleted - type: integer - description: Hosts deleted count - priority: 1 # show in wide view - jsonPath: .status.deleted - - name: delete - type: integer - description: Hosts to be deleted count - priority: 1 # show in wide view - jsonPath: .status.delete - - name: endpoint - type: string - description: Client access endpoint - priority: 1 # show in wide view - jsonPath: .status.endpoint - subresources: - status: {} - schema: - openAPIV3Schema: - description: "define a set of Kubernetes resources (StatefulSet, PVC, Service, ConfigMap) which describe behavior one or more ClickHouse clusters" - type: object - required: - - spec - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - status: - type: object - description: "Current ClickHouseInstallation manifest status, contains many fields like a normalized configuration, clickhouse-operator version, current action and all applied action list, current taskID and all applied taskIDs and other" - properties: - chop-version: - type: string - description: "ClickHouse operator version" - chop-commit: - type: string - description: "ClickHouse operator git commit SHA" - chop-date: - type: string - description: "ClickHouse operator build date" - clusters: - type: integer - minimum: 0 - description: "Clusters count" - shards: - type: integer - minimum: 0 - description: "Shards count" - replicas: - type: integer - minimum: 0 - description: "Replicas count" - hosts: - type: integer - minimum: 0 - description: "Hosts count" - status: - type: string - description: "Status" - taskID: - type: string - description: "Current task id" - taskIDsStarted: - type: array - description: "Started task ids" - items: - type: string - taskIDsCompleted: - type: array - description: "Completed task ids" - items: - type: string - action: - type: string - description: "Action" - actions: - type: array - description: "Actions" - items: - type: string - error: - type: string - description: "Last error" - errors: - type: array - description: "Errors" - items: - type: string - updated: - type: integer - minimum: 0 - description: "Updated Hosts count" - added: - type: integer - minimum: 0 - description: "Added Hosts count" - deleted: - type: integer - minimum: 0 - description: "Deleted Hosts count" - delete: - type: integer - minimum: 0 - description: "About to delete Hosts count" - pods: - type: array - description: "Pods" - items: - type: string - fqdns: - type: array - description: "Pods FQDNs" - items: - type: string - endpoint: - type: string - description: "Endpoint" - generation: - type: integer - minimum: 0 - description: "Generation" - normalized: - type: object - description: "Normalized CHI" - x-kubernetes-preserve-unknown-fields: true - spec: - type: object - # x-kubernetes-preserve-unknown-fields: true - description: | - Specification of the desired behavior of one or more ClickHouse clusters - More info: https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md" - properties: - taskID: - type: string - description: "Allow define custom taskID for named update and watch status of this update execution in .status.taskIDs field, by default every update of chi manifest will generate random taskID" - # Need to be StringBool - stop: - type: string - description: | - Allow stop all ClickHouse clusters described in current chi. - Stop mechanism works as follows: - - When `stop` is `1` then setup `Replicas: 0` in each related to current `chi` StatefulSet resource, all `Pods` and `Service` resources will desctroy, but PVCs still live - - When `stop` is `0` then `Pods` will created again and will attach retained PVCs and `Service` also will created again - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - restart: - type: string - description: "This is a 'soft restart' button. When set to 'RollingUpdate' operator will restart ClickHouse pods in a graceful way. Remove it after the use in order to avoid unneeded restarts" - enum: - - "" - - "RollingUpdate" - # Need to be StringBool - troubleshoot: - type: string - description: "allows troubleshoot Pods during CrashLoopBack state, when you apply wrong configuration, `clickhouse-server` wouldn't startup" - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - namespaceDomainPattern: - type: string - description: "custom domain suffix which will add to end of `Service` or `Pod` name, use it when you use custom cluster domain in your Kubernetes cluster" - templating: - type: object - # nullable: true - description: "optional, define policy for auto applying ClickHouseInstallationTemplate inside ClickHouseInstallation" - properties: - policy: - type: string - description: "when defined as `auto` inside ClickhouseInstallationTemplate, it will auto add into all ClickHouseInstallation, manual value is default" - enum: - - "auto" - - "manual" - reconciling: - type: object - description: "optional, allows tuning reconciling cycle for ClickhouseInstallation from clickhouse-operator side" - # nullable: true - properties: - policy: - type: string - description: DEPRECATED - configMapPropagationTimeout: - type: integer - description: | - timeout in seconds when `clickhouse-operator` will wait when applied `ConfigMap` during reconcile `ClickhouseInstallation` pods will updated from cache - see details: https://kubernetes.io/docs/concepts/configuration/configmap/#mounted-configmaps-are-updated-automatically - minimum: 0 - maximum: 3600 - cleanup: - type: object - description: "optional, define behavior for cleanup Kubernetes resources during reconcile cycle" - # nullable: true - properties: - unknownObjects: - type: object - description: "what clickhouse-operator shall do when found Kubernetes resources which should be managed with clickhouse-operator, but not have `ownerReference` to any currently managed `ClickHouseInstallation` resource, default behavior is `Delete`" - # nullable: true - properties: - statefulSet: - type: string - description: "behavior policy for unknown StatefulSet, Delete by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - pvc: - type: string - description: "behavior policy for unknown PVC, Delete by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - configMap: - type: string - description: "behavior policy for unknown ConfigMap, Delete by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - service: - type: string - description: "behavior policy for unknown Service, Delete by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - reconcileFailedObjects: - type: object - description: "what clickhouse-operator shall do when reconciling Kubernetes resources are failed, default behavior is `Retain`" - # nullable: true - properties: - statefulSet: - type: string - description: "behavior policy for failed StatefulSet reconciling, Retain by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - pvc: - type: string - description: "behavior policy for failed PVC reconciling, Retain by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - configMap: - type: string - description: "behavior policy for failed ConfigMap reconciling, Retain by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - service: - type: string - description: "behavior policy for failed Service reconciling, Retain by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - defaults: - type: object - description: | - define default behavior for whole ClickHouseInstallation, some behavior can be re-define on cluster, shard and replica level - More info: https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specdefaults - # nullable: true - properties: - # Need to be StringBool - replicasUseFQDN: - type: string - description: | - define should replicas be specified by FQDN in `<host></host>`, then "no" then will use short hostname and clickhouse-server will use kubernetes default suffixes for properly DNS lookup - "yes" by default - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - distributedDDL: - type: object - description: | - allows change `<yandex><distributed_ddl></distributed_ddl></yandex>` settings - More info: https://clickhouse.tech/docs/en/operations/server-configuration-parameters/settings/#server-settings-distributed_ddl - # nullable: true - properties: - profile: - type: string - description: "Settings from this profile will be used to execute DDL queries" - templates: - type: object - description: "optional, configuration of the templates names which will use for generate Kubernetes resources according to one or more ClickHouse clusters described in current ClickHouseInstallation (chi) resource" - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure every `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod`" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters`" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters`" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters`" - serviceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for one `Service` resource which will created by `clickhouse-operator` which cover all clusters in whole `chi` resource" - clusterServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each clickhouse cluster described in `chi.spec.configuration.clusters`" - shardServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each shard inside clickhouse cluster described in `chi.spec.configuration.clusters`" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside each clickhouse cluster described in `chi.spec.configuration.clusters`" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - configuration: - type: object - description: "allows configure multiple aspects and behavior for `clickhouse-server` instance and also allows describe multiple `clickhouse-server` clusters inside one `chi` resource" - # nullable: true - properties: - zookeeper: - type: object - description: | - allows configure <yandex><zookeeper>..</zookeeper></yandex> section in each `Pod` during generate `ConfigMap` which will mounted in `/etc/clickhouse-server/config.d/` - `clickhouse-operator` itself doesn't manage Zookeeper, please install Zookeeper separatelly look examples on https://github.com/Altinity/clickhouse-operator/tree/master/deploy/zookeeper/ - currently, zookeeper (or clickhouse-keeper replacement) used for *ReplicatedMergeTree table engines and for `distributed_ddl` - More details: https://clickhouse.tech/docs/en/operations/server-configuration-parameters/settings/#server-settings_zookeeper - # nullable: true - properties: - nodes: - type: array - description: "describe every available zookeeper cluster node for interaction" - # nullable: true - items: - type: object - #required: - # - host - properties: - host: - type: string - description: "dns name or ip address for Zookeeper node" - port: - type: integer - description: "TCP port which used to connect to Zookeeper node" - minimum: 0 - maximum: 65535 - session_timeout_ms: - type: integer - description: "session timeout during connect to Zookeeper" - operation_timeout_ms: - type: integer - description: "one operation timeout during Zookeeper transactions" - root: - type: string - description: "optional root znode path inside zookeeper to store ClickHouse related data (replication queue or distributed DDL)" - identity: - type: string - description: "optional access credentials string with `user:password` format used when use digest authorization in Zookeeper" - users: - type: object - description: | - allows configure <yandex><users>..</users></yandex> section in each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/users.d/` - you can configure password hashed, authorization restrictions, database level security row filters etc. - More details: https://clickhouse.tech/docs/en/operations/settings/settings-users/ - Your yaml code will convert to XML, see examples https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specconfigurationusers - # nullable: true - x-kubernetes-preserve-unknown-fields: true - profiles: - type: object - description: | - allows configure <yandex><profiles>..</profiles></yandex> section in each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/users.d/` - you can configure any aspect of settings profile - More details: https://clickhouse.tech/docs/en/operations/settings/settings-profiles/ - Your yaml code will convert to XML, see examples https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specconfigurationprofiles - # nullable: true - x-kubernetes-preserve-unknown-fields: true - quotas: - type: object - description: | - allows configure <yandex><quotas>..</quotas></yandex> section in each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/users.d/` - you can configure any aspect of resource quotas - More details: https://clickhouse.tech/docs/en/operations/quotas/ - Your yaml code will convert to XML, see examples https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specconfigurationquotas - # nullable: true - x-kubernetes-preserve-unknown-fields: true - settings: - type: object - description: | - allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - Your yaml code will convert to XML, see examples https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specconfigurationsettings - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - description: | - allows define content of any setting file inside each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - every key in this object is the file name - every value in this object is the file content - you can use `!!binary |` and base64 for binary files, see details here https://yaml.org/type/binary.html - each key could contains prefix like USERS, COMMON, HOST or config.d, users.d, cond.d, wrong prefixes will ignored, subfolders also will ignored - More details: https://github.com/Altinity/clickhouse-operator/blob/master/docs/chi-examples/05-settings-05-files-nested.yaml - # nullable: true - x-kubernetes-preserve-unknown-fields: true - clusters: - type: array - description: | - describes ClickHouse clusters layout and allows change settings on cluster-level, shard-level and replica-level - every cluster is a set of StatefulSet, one StatefulSet contains only one Pod with `clickhouse-server` - all Pods will rendered in <remote_server> part of ClickHouse configs, mounted from ConfigMap as `/etc/clickhouse-server/config.d/chop-generated-remote_servers.xml` - Clusters will use for Distributed table engine, more details: https://clickhouse.tech/docs/en/engines/table-engines/special/distributed/ - If `cluster` contains zookeeper settings (could be inherited from top `chi` level), when you can create *ReplicatedMergeTree tables - # nullable: true - items: - type: object - #required: - # - name - properties: - name: - type: string - description: "cluster name, used to identify set of ClickHouse servers and wide used during generate names of related Kubernetes resources" - minLength: 1 - # See namePartClusterMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - zookeeper: - type: object - description: | - optional, allows configure <yandex><zookeeper>..</zookeeper></yandex> section in each `Pod` only in current ClickHouse cluster, during generate `ConfigMap` which will mounted in `/etc/clickhouse-server/config.d/` - override top-level `chi.spec.configuration.zookeeper` settings - # nullable: true - properties: - nodes: - type: array - description: "describe every available zookeeper cluster node for interaction" - # nullable: true - items: - type: object - #required: - # - host - properties: - host: - type: string - description: "dns name or ip address for Zookeeper node" - port: - type: integer - description: "TCP port which used to connect to Zookeeper node" - minimum: 0 - maximum: 65535 - session_timeout_ms: - type: integer - description: "session timeout during connect to Zookeeper" - operation_timeout_ms: - type: integer - description: "one operation timeout during Zookeeper transactions" - root: - type: string - description: "optional root znode path inside zookeeper to store ClickHouse related data (replication queue or distributed DDL)" - identity: - type: string - description: "optional access credentials string with `user:password` format used when use digest authorization in Zookeeper" - settings: - type: object - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in each `Pod` only in one cluster during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` - override top-level `chi.spec.configuration.settings` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - description: | - optional, allows define content of any setting file inside each `Pod` on current cluster during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files` - # nullable: true - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected cluster - override top-level `chi.spec.configuration.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure each `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one cluster" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one cluster" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one cluster" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one cluster" - serviceTemplate: - type: string - description: "optional, fully ignores for cluster-level" - clusterServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each clickhouse cluster described in `chi.spec.configuration.clusters` only for one cluster" - shardServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one cluster" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside each clickhouse cluster described in `chi.spec.configuration.clusters` only for one cluster" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - layout: - type: object - description: | - describe current cluster layout, how much shards in cluster, how much replica in shard - allows override settings on each shard and replica separatelly - # nullable: true - properties: - type: - type: string - description: "DEPRECATED - to be removed soon" - shardsCount: - type: integer - description: "how much shards for current ClickHouse cluster will run in Kubernetes, each shard contains shared-nothing part of data and contains set of replicas, cluster contains 1 shard by default" - replicasCount: - type: integer - description: "how much replicas in each shards for current ClickHouse cluster will run in Kubernetes, each replica is a separate `StatefulSet` which contains only one `Pod` with `clickhouse-server` instance, every shard contains 1 replica by default" - shards: - type: array - description: "optional, allows override top-level `chi.spec.configuration`, cluster-level `chi.spec.configuration.clusters` settings for each shard separately, use it only if you fully understand what you do" - # nullable: true - items: - type: object - properties: - name: - type: string - description: "optional, by default shard name is generated, but you can override it and setup custom name" - minLength: 1 - # See namePartShardMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - definitionType: - type: string - description: "DEPRECATED - to be removed soon" - weight: - type: integer - description: | - optional, 1 by default, allows setup shard <weight> setting which will use during insert into tables with `Distributed` engine, - will apply in <remote_servers> inside ConfigMap which will mount in /etc/clickhouse-server/config.d/chop-generated-remote_servers.xml - More details: https://clickhouse.tech/docs/en/engines/table-engines/special/distributed/ - # Need to be StringBool - internalReplication: - type: string - description: | - optional, `true` by default when `chi.spec.configuration.clusters[].layout.ReplicaCount` > 1 and 0 otherwise - allows setup <internal_replication> setting which will use during insert into tables with `Distributed` engine for insert only in one live replica and other replicas will download inserted data during replication, - will apply in <remote_servers> inside ConfigMap which will mount in /etc/clickhouse-server/config.d/chop-generated-remote_servers.xml - More details: https://clickhouse.tech/docs/en/engines/table-engines/special/distributed/ - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - settings: - type: object - # nullable: true - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in each `Pod` only in one shard during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` - override top-level `chi.spec.configuration.settings` and cluster-level `chi.spec.configuration.clusters.settings` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - x-kubernetes-preserve-unknown-fields: true - files: - type: object - # nullable: true - description: | - optional, allows define content of any setting file inside each `Pod` only in one shard during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files` and cluster-level `chi.spec.configuration.clusters.files` - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected shard - override top-level `chi.spec.configuration.templates` and cluster-level `chi.spec.configuration.clusters.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure each `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one shard" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - serviceTemplate: - type: string - description: "optional, fully ignores for shard-level" - clusterServiceTemplate: - type: string - description: "optional, fully ignores for shard-level" - shardServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one shard" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one shard" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - replicasCount: - type: integer - description: | - optional, how much replicas in selected shard for selected ClickHouse cluster will run in Kubernetes, each replica is a separate `StatefulSet` which contains only one `Pod` with `clickhouse-server` instance, - shard contains 1 replica by default - override cluster-level `chi.spec.configuration.clusters.layout.replicasCount` - minimum: 1 - replicas: - type: array - description: | - optional, allows override behavior for selected replicas from cluster-level `chi.spec.configuration.clusters` and shard-level `chi.spec.configuration.clusters.layout.shards` - # nullable: true - items: - # Host - type: object - properties: - name: - type: string - description: "optional, by default replica name is generated, but you can override it and setup custom name" - minLength: 1 - # See namePartReplicaMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - tcpPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `tcp` for selected replica, override `chi.spec.templates.hostTemplates.spec.tcpPort` - allows connect to `clickhouse-server` via TCP Native protocol via kubernetes `Service` - minimum: 1 - maximum: 65535 - httpPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `http` for selected replica, override `chi.spec.templates.hostTemplates.spec.httpPort` - allows connect to `clickhouse-server` via HTTP protocol via kubernetes `Service` - minimum: 1 - maximum: 65535 - interserverHTTPPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `interserver` for selected replica, override `chi.spec.templates.hostTemplates.spec.interserverHTTPPort` - allows connect between replicas inside same shard during fetch replicated data parts HTTP protocol - minimum: 1 - maximum: 65535 - settings: - type: object - # nullable: true - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in `Pod` only in one replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/conf.d/` - override top-level `chi.spec.configuration.settings`, cluster-level `chi.spec.configuration.clusters.settings` and shard-level `chi.spec.configuration.clusters.layout.shards.settings` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - x-kubernetes-preserve-unknown-fields: true - files: - type: object - # nullable: true - description: | - optional, allows define content of any setting file inside `Pod` only in one replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files`, cluster-level `chi.spec.configuration.clusters.files` and shard-level `chi.spec.configuration.clusters.layout.shards.files` - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected replica - override top-level `chi.spec.configuration.templates`, cluster-level `chi.spec.configuration.clusters.templates` and shard-level `chi.spec.configuration.clusters.layout.shards.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one replica" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one replica" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - serviceTemplate: - type: string - description: "optional, fully ignores for replica-level" - clusterServiceTemplate: - type: string - description: "optional, fully ignores for replica-level" - shardServiceTemplate: - type: string - description: "optional, fully ignores for replica-level" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one replica" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - replicas: - type: array - description: "optional, allows override top-level `chi.spec.configuration` and cluster-level `chi.spec.configuration.clusters` configuration for each replica and each shard relates to selected replica, use it only if you fully understand what you do" - # nullable: true - items: - type: object - properties: - name: - type: string - description: "optional, by default replica name is generated, but you can override it and setup custom name" - minLength: 1 - # See namePartShardMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - settings: - type: object - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in `Pod` only in one replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/conf.d/` - override top-level `chi.spec.configuration.settings`, cluster-level `chi.spec.configuration.clusters.settings` and will ignore if shard-level `chi.spec.configuration.clusters.layout.shards` present - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - # nullable: true - description: | - optional, allows define content of any setting file inside each `Pod` only in one replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files` and cluster-level `chi.spec.configuration.clusters.files`, will ignore if `chi.spec.configuration.clusters.layout.shards` presents - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected replica - override top-level `chi.spec.configuration.templates`, cluster-level `chi.spec.configuration.clusters.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one replica" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one replica" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - serviceTemplate: - type: string - description: "optional, fully ignores for replica-level" - clusterServiceTemplate: - type: string - description: "optional, fully ignores for replica-level" - shardServiceTemplate: - type: string - description: "optional, fully ignores for replica-level" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one replica" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - shardsCount: - type: integer - description: "optional, count of shards related to current replica, you can override each shard behavior on low-level `chi.spec.configuration.clusters.layout.replicas.shards`" - minimum: 1 - shards: - type: array - description: "optional, list of shards related to current replica, will ignore if `chi.spec.configuration.clusters.layout.shards` presents" - # nullable: true - items: - # Host - type: object - properties: - name: - type: string - description: "optional, by default shard name is generated, but you can override it and setup custom name" - minLength: 1 - # See namePartReplicaMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - tcpPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `tcp` for selected shard, override `chi.spec.templates.hostTemplates.spec.tcpPort` - allows connect to `clickhouse-server` via TCP Native protocol via kubernetes `Service` - minimum: 1 - maximum: 65535 - httpPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `http` for selected shard, override `chi.spec.templates.hostTemplates.spec.httpPort` - allows connect to `clickhouse-server` via HTTP protocol via kubernetes `Service` - minimum: 1 - maximum: 65535 - interserverHTTPPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `interserver` for selected shard, override `chi.spec.templates.hostTemplates.spec.interserverHTTPPort` - allows connect between replicas inside same shard during fetch replicated data parts HTTP protocol - minimum: 1 - maximum: 65535 - settings: - type: object - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in `Pod` only in one shard related to current replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/conf.d/` - override top-level `chi.spec.configuration.settings`, cluster-level `chi.spec.configuration.clusters.settings` and replica-level `chi.spec.configuration.clusters.layout.replicas.settings` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - description: | - optional, allows define content of any setting file inside each `Pod` only in one shard related to current replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files` and cluster-level `chi.spec.configuration.clusters.files`, will ignore if `chi.spec.configuration.clusters.layout.shards` presents - # nullable: true - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected replica - override top-level `chi.spec.configuration.templates`, cluster-level `chi.spec.configuration.clusters.templates`, replica-level `chi.spec.configuration.clusters.layout.replicas.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure each `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one shard" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - serviceTemplate: - type: string - description: "optional, fully ignores for shard-level" - clusterServiceTemplate: - type: string - description: "optional, fully ignores for shard-level" - shardServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one shard" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one shard" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - templates: - type: object - description: "allows define templates which will use for render Kubernetes resources like StatefulSet, ConfigMap, Service, PVC, by default, clickhouse-operator have own templates, but you can override it" - # nullable: true - properties: - hostTemplates: - type: array - description: "hostTemplate will use during apply to generate `clickhose-server` config files" - # nullable: true - items: - type: object - #required: - # - name - properties: - name: - description: "template name, could use to link inside top-level `chi.spec.defaults.templates.hostTemplate`, cluster-level `chi.spec.configuration.clusters.templates.hostTemplate`, shard-level `chi.spec.configuration.clusters.layout.shards.temlates.hostTemplate`, replica-level `chi.spec.configuration.clusters.layout.replicas.templates.hostTemplate`" - type: string - portDistribution: - type: array - description: "define how will distribute numeric values of named ports in `Pod.spec.containers.ports` and clickhouse-server configs" - # nullable: true - items: - type: object - #required: - # - type - properties: - type: - type: string - description: "type of distribution, when `Unspecified` (default value) then all listen ports on clickhouse-server configuration in all Pods will have the same value, when `ClusterScopeIndex` then ports will increment to offset from base value depends on shard and replica index inside cluster with combination of `chi.spec.templates.podTemlates.spec.HostNetwork` it allows setup ClickHouse cluster inside Kubernetes and provide access via external network bypass Kubernetes internal network" - enum: - # List PortDistributionXXX constants - - "" - - "Unspecified" - - "ClusterScopeIndex" - spec: - # Host - type: object - properties: - name: - type: string - description: "by default, hostname will generate, but this allows define custom name for each `clickhuse-server`" - minLength: 1 - # See namePartReplicaMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - tcpPort: - type: integer - description: | - optional, setup `tcp_port` inside `clickhouse-server` settings for each Pod where current template will apply - if specified, should have equal value with `chi.spec.templates.podTemplates.spec.containers.ports[name=tcp]` - More info: https://clickhouse.tech/docs/en/interfaces/tcp/ - minimum: 1 - maximum: 65535 - httpPort: - type: integer - description: | - optional, setup `http_port` inside `clickhouse-server` settings for each Pod where current template will apply - if specified, should have equal value with `chi.spec.templates.podTemplates.spec.containers.ports[name=http]` - More info: https://clickhouse.tech/docs/en/interfaces/http/ - minimum: 1 - maximum: 65535 - interserverHTTPPort: - type: integer - description: | - optional, setup `interserver_http_port` inside `clickhouse-server` settings for each Pod where current template will apply - if specified, should have equal value with `chi.spec.templates.podTemplates.spec.containers.ports[name=interserver]` - More info: https://clickhouse.tech/docs/en/operations/server-configuration-parameters/settings/#interserver-http-port - minimum: 1 - maximum: 65535 - settings: - type: object - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in each `Pod` where this template will apply during generate `ConfigMap` which will mount in `/etc/clickhouse-server/conf.d/` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - description: | - optional, allows define content of any setting file inside each `Pod` where this template will apply during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - # nullable: true - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: "be carefull, this part of CRD allows override template inside template, don't use it if you don't understand what you do" - # nullable: true - properties: - hostTemplate: - type: string - podTemplate: - type: string - dataVolumeClaimTemplate: - type: string - logVolumeClaimTemplate: - type: string - serviceTemplate: - type: string - clusterServiceTemplate: - type: string - shardServiceTemplate: - type: string - replicaServiceTemplate: - type: string - podTemplates: - type: array - description: | - podTemplate will use during render `Pod` inside `StatefulSet.spec` and allows define rendered `Pod.spec`, pod scheduling distribution and pod zone - More information: https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#spectemplatespodtemplates - # nullable: true - items: - type: object - #required: - # - name - properties: - name: - type: string - description: "template name, could use to link inside top-level `chi.spec.defaults.templates.podTemplate`, cluster-level `chi.spec.configuration.clusters.templates.podTemplate`, shard-level `chi.spec.configuration.clusters.layout.shards.temlates.podTemplate`, replica-level `chi.spec.configuration.clusters.layout.replicas.templates.podTemplate`" - generateName: - type: string - description: "allows define format for generated `Pod` name, look to https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#spectemplatesservicetemplates for details about aviailable template variables" - zone: - type: object - description: "allows define custom zone name and will separate ClickHouse `Pods` between nodes, shortcut for `chi.spec.templates.podTemplates.spec.affinity.podAntiAffinity`" - #required: - # - values - properties: - key: - type: string - description: "optional, if defined, allows select kubernetes nodes by label with `name` equal `key`" - values: - type: array - description: "optional, if defined, allows select kubernetes nodes by label with `value` in `values`" - # nullable: true - items: - type: string - distribution: - type: string - description: "DEPRECATED, shortcut for `chi.spec.templates.podTemplates.spec.affinity.podAntiAffinity`" - enum: - - "" - - "Unspecified" - - "OnePerHost" - podDistribution: - type: array - description: "define ClickHouse Pod distibution policy between Kubernetes Nodes inside Shard, Replica, Namespace, CHI, another ClickHouse cluster" - # nullable: true - items: - type: object - #required: - # - type - properties: - type: - type: string - description: "you can define multiple affinity policy types" - enum: - # List PodDistributionXXX constants - - "" - - "Unspecified" - - "ClickHouseAntiAffinity" - - "ShardAntiAffinity" - - "ReplicaAntiAffinity" - - "AnotherNamespaceAntiAffinity" - - "AnotherClickHouseInstallationAntiAffinity" - - "AnotherClusterAntiAffinity" - - "MaxNumberPerNode" - - "NamespaceAffinity" - - "ClickHouseInstallationAffinity" - - "ClusterAffinity" - - "ShardAffinity" - - "ReplicaAffinity" - - "PreviousTailAffinity" - - "CircularReplication" - scope: - type: string - description: "scope for apply each podDistribution" - enum: - # list PodDistributionScopeXXX constants - - "" - - "Unspecified" - - "Shard" - - "Replica" - - "Cluster" - - "ClickHouseInstallation" - - "Namespace" - number: - type: integer - description: "define, how much ClickHouse Pods could be inside selected scope with selected distribution type" - minimum: 0 - maximum: 65535 - topologyKey: - type: string - description: "use for inter-pod affinity look to `pod.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.podAffinityTerm.topologyKey`, More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity" - spec: - # TODO specify PodSpec - type: object - description: "allows define whole Pod.spec inside StaefulSet.spec, look to https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates for details" - # nullable: true - x-kubernetes-preserve-unknown-fields: true - metadata: - type: object - description: | - allows pass standard object's metadata from template to Pod - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - # nullable: true - x-kubernetes-preserve-unknown-fields: true - volumeClaimTemplates: - type: array - description: "allows define template for rendering `PVC` kubernetes resource, which would use inside `Pod` for mount clickhouse `data`, clickhouse `logs` or something else" - # nullable: true - items: - type: object - #required: - # - name - # - spec - properties: - name: - description: | - template name, could use to link inside - top-level `chi.spec.defaults.templates.dataVolumeClaimTemplate` or `chi.spec.defaults.templates.logVolumeClaimTemplate`, - cluster-level `chi.spec.configuration.clusters.templates.dataVolumeClaimTemplate` or `chi.spec.configuration.clusters.templates.logVolumeClaimTemplate`, - shard-level `chi.spec.configuration.clusters.layout.shards.temlates.dataVolumeClaimTemplate` or `chi.spec.configuration.clusters.layout.shards.temlates.logVolumeClaimTemplate` - replica-level `chi.spec.configuration.clusters.layout.replicas.templates.dataVolumeClaimTemplate` or `chi.spec.configuration.clusters.layout.replicas.templates.logVolumeClaimTemplate` - type: string - reclaimPolicy: - type: string - description: "define behavior of `PVC` deletion policy during delete `Pod`, `Delete` by default, when `Retain` then `PVC` still alive even `Pod` will deleted" - enum: - - "" - - "Retain" - - "Delete" - metadata: - type: object - description: | - allows pass standard object's metadata from template to PVC - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - # nullable: true - x-kubernetes-preserve-unknown-fields: true - spec: - type: object - description: | - allows define all aspects of `PVC` resource - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims - # nullable: true - x-kubernetes-preserve-unknown-fields: true - serviceTemplates: - type: array - description: | - allows define template for rendering `Service` which would get endpoint from Pods which scoped chi-wide, cluster-wide, shard-wide, replica-wide level - # nullable: true - items: - type: object - #required: - # - name - # - spec - properties: - name: - type: string - description: | - template name, could use to link inside - chi-level `chi.spec.defaults.templates.serviceTemplate` - cluster-level `chi.spec.configuration.clusters.templates.clusterServiceTemplate` - shard-level `chi.spec.configuration.clusters.layout.shards.temlates.shardServiceTemplate` - replica-level `chi.spec.configuration.clusters.layout.replicas.templates.replicaServiceTemplate` or `chi.spec.configuration.clusters.layout.shards.replicas.replicaServiceTemplate` - generateName: - type: string - description: "allows define format for generated `Service` name, look to https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#spectemplatesservicetemplates for details about aviailable template variables" - metadata: - # TODO specify ObjectMeta - type: object - description: | - allows pass standard object's metadata from template to Service - Could be use for define specificly for Cloud Provider metadata which impact to behavior of service - More info: https://kubernetes.io/docs/concepts/services-networking/service/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - spec: - # TODO specify ServiceSpec - type: object - description: | - describe behavior of generated Service - More info: https://kubernetes.io/docs/concepts/services-networking/service/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - useTemplates: - type: array - description: "list of `ClickHouseInstallationTemplate` (chit) resource names which will merge with current `Chi` manifest during render Kubernetes resources to create related ClickHouse clusters" - # nullable: true - items: - type: object - #required: - # - name - properties: - name: - type: string - description: "name of `ClickHouseInstallationTemplate` (chit) resource" - namespace: - type: string - description: "Kubernetes namespace where need search `chit` resource, depending on `watchNamespaces` settings in `clichouse-operator`" - useType: - type: string - description: "optional, current strategy is only merge, and current `chi` settings have more priority than merged template `chit`" - enum: - # List useTypeXXX constants from model - - "" - - "merge" diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseinstallationtemplates.clickhouse.altinity.com.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseinstallationtemplates.clickhouse.altinity.com.yaml deleted file mode 100644 index 7899b71de..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseinstallationtemplates.clickhouse.altinity.com.yaml +++ /dev/null @@ -1,1321 +0,0 @@ -# Template Parameters: -# -# KIND=ClickHouseInstallationTemplate -# SINGULAR=clickhouseinstallationtemplate -# PLURAL=clickhouseinstallationtemplates -# SHORT=chit -# -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: clickhouseinstallationtemplates.clickhouse.altinity.com - labels: - clickhouse.altinity.com/chop: 0.18.1 -spec: - group: clickhouse.altinity.com - scope: Namespaced - names: - kind: ClickHouseInstallationTemplate - singular: clickhouseinstallationtemplate - plural: clickhouseinstallationtemplates - shortNames: - - chit - versions: - - name: v1 - served: true - storage: true - additionalPrinterColumns: - - name: version - type: string - description: Operator version - priority: 1 # show in wide view - jsonPath: .status.chop-version - - name: clusters - type: integer - description: Clusters count - priority: 0 # show in standard view - jsonPath: .status.clusters - - name: shards - type: integer - description: Shards count - priority: 1 # show in wide view - jsonPath: .status.shards - - name: hosts - type: integer - description: Hosts count - priority: 0 # show in standard view - jsonPath: .status.hosts - - name: taskID - type: string - description: TaskID - priority: 1 # show in wide view - jsonPath: .status.taskID - - name: status - type: string - description: CHI status - priority: 0 # show in standard view - jsonPath: .status.status - - name: updated - type: integer - description: Updated hosts count - priority: 1 # show in wide view - jsonPath: .status.updated - - name: added - type: integer - description: Added hosts count - priority: 1 # show in wide view - jsonPath: .status.added - - name: deleted - type: integer - description: Hosts deleted count - priority: 1 # show in wide view - jsonPath: .status.deleted - - name: delete - type: integer - description: Hosts to be deleted count - priority: 1 # show in wide view - jsonPath: .status.delete - - name: endpoint - type: string - description: Client access endpoint - priority: 1 # show in wide view - jsonPath: .status.endpoint - subresources: - status: {} - schema: - openAPIV3Schema: - description: "define a set of Kubernetes resources (StatefulSet, PVC, Service, ConfigMap) which describe behavior one or more ClickHouse clusters" - type: object - required: - - spec - properties: - apiVersion: - description: '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' - type: string - kind: - description: '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' - type: string - metadata: - type: object - status: - type: object - description: "Current ClickHouseInstallation manifest status, contains many fields like a normalized configuration, clickhouse-operator version, current action and all applied action list, current taskID and all applied taskIDs and other" - properties: - chop-version: - type: string - description: "ClickHouse operator version" - chop-commit: - type: string - description: "ClickHouse operator git commit SHA" - chop-date: - type: string - description: "ClickHouse operator build date" - clusters: - type: integer - minimum: 0 - description: "Clusters count" - shards: - type: integer - minimum: 0 - description: "Shards count" - replicas: - type: integer - minimum: 0 - description: "Replicas count" - hosts: - type: integer - minimum: 0 - description: "Hosts count" - status: - type: string - description: "Status" - taskID: - type: string - description: "Current task id" - taskIDsStarted: - type: array - description: "Started task ids" - items: - type: string - taskIDsCompleted: - type: array - description: "Completed task ids" - items: - type: string - action: - type: string - description: "Action" - actions: - type: array - description: "Actions" - items: - type: string - error: - type: string - description: "Last error" - errors: - type: array - description: "Errors" - items: - type: string - updated: - type: integer - minimum: 0 - description: "Updated Hosts count" - added: - type: integer - minimum: 0 - description: "Added Hosts count" - deleted: - type: integer - minimum: 0 - description: "Deleted Hosts count" - delete: - type: integer - minimum: 0 - description: "About to delete Hosts count" - pods: - type: array - description: "Pods" - items: - type: string - fqdns: - type: array - description: "Pods FQDNs" - items: - type: string - endpoint: - type: string - description: "Endpoint" - generation: - type: integer - minimum: 0 - description: "Generation" - normalized: - type: object - description: "Normalized CHI" - x-kubernetes-preserve-unknown-fields: true - spec: - type: object - # x-kubernetes-preserve-unknown-fields: true - description: | - Specification of the desired behavior of one or more ClickHouse clusters - More info: https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md" - properties: - taskID: - type: string - description: "Allow define custom taskID for named update and watch status of this update execution in .status.taskIDs field, by default every update of chi manifest will generate random taskID" - # Need to be StringBool - stop: - type: string - description: | - Allow stop all ClickHouse clusters described in current chi. - Stop mechanism works as follows: - - When `stop` is `1` then setup `Replicas: 0` in each related to current `chi` StatefulSet resource, all `Pods` and `Service` resources will desctroy, but PVCs still live - - When `stop` is `0` then `Pods` will created again and will attach retained PVCs and `Service` also will created again - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - restart: - type: string - description: "This is a 'soft restart' button. When set to 'RollingUpdate' operator will restart ClickHouse pods in a graceful way. Remove it after the use in order to avoid unneeded restarts" - enum: - - "" - - "RollingUpdate" - # Need to be StringBool - troubleshoot: - type: string - description: "allows troubleshoot Pods during CrashLoopBack state, when you apply wrong configuration, `clickhouse-server` wouldn't startup" - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - namespaceDomainPattern: - type: string - description: "custom domain suffix which will add to end of `Service` or `Pod` name, use it when you use custom cluster domain in your Kubernetes cluster" - templating: - type: object - # nullable: true - description: "optional, define policy for auto applying ClickHouseInstallationTemplate inside ClickHouseInstallation" - properties: - policy: - type: string - description: "when defined as `auto` inside ClickhouseInstallationTemplate, it will auto add into all ClickHouseInstallation, manual value is default" - enum: - - "auto" - - "manual" - reconciling: - type: object - description: "optional, allows tuning reconciling cycle for ClickhouseInstallation from clickhouse-operator side" - # nullable: true - properties: - policy: - type: string - description: DEPRECATED - configMapPropagationTimeout: - type: integer - description: | - timeout in seconds when `clickhouse-operator` will wait when applied `ConfigMap` during reconcile `ClickhouseInstallation` pods will updated from cache - see details: https://kubernetes.io/docs/concepts/configuration/configmap/#mounted-configmaps-are-updated-automatically - minimum: 0 - maximum: 3600 - cleanup: - type: object - description: "optional, define behavior for cleanup Kubernetes resources during reconcile cycle" - # nullable: true - properties: - unknownObjects: - type: object - description: "what clickhouse-operator shall do when found Kubernetes resources which should be managed with clickhouse-operator, but not have `ownerReference` to any currently managed `ClickHouseInstallation` resource, default behavior is `Delete`" - # nullable: true - properties: - statefulSet: - type: string - description: "behavior policy for unknown StatefulSet, Delete by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - pvc: - type: string - description: "behavior policy for unknown PVC, Delete by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - configMap: - type: string - description: "behavior policy for unknown ConfigMap, Delete by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - service: - type: string - description: "behavior policy for unknown Service, Delete by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - reconcileFailedObjects: - type: object - description: "what clickhouse-operator shall do when reconciling Kubernetes resources are failed, default behavior is `Retain`" - # nullable: true - properties: - statefulSet: - type: string - description: "behavior policy for failed StatefulSet reconciling, Retain by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - pvc: - type: string - description: "behavior policy for failed PVC reconciling, Retain by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - configMap: - type: string - description: "behavior policy for failed ConfigMap reconciling, Retain by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - service: - type: string - description: "behavior policy for failed Service reconciling, Retain by default" - enum: - # List ObjectsCleanupXXX constants from model - - "Retain" - - "Delete" - defaults: - type: object - description: | - define default behavior for whole ClickHouseInstallation, some behavior can be re-define on cluster, shard and replica level - More info: https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specdefaults - # nullable: true - properties: - # Need to be StringBool - replicasUseFQDN: - type: string - description: | - define should replicas be specified by FQDN in `<host></host>`, then "no" then will use short hostname and clickhouse-server will use kubernetes default suffixes for properly DNS lookup - "yes" by default - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - distributedDDL: - type: object - description: | - allows change `<yandex><distributed_ddl></distributed_ddl></yandex>` settings - More info: https://clickhouse.tech/docs/en/operations/server-configuration-parameters/settings/#server-settings-distributed_ddl - # nullable: true - properties: - profile: - type: string - description: "Settings from this profile will be used to execute DDL queries" - templates: - type: object - description: "optional, configuration of the templates names which will use for generate Kubernetes resources according to one or more ClickHouse clusters described in current ClickHouseInstallation (chi) resource" - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure every `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod`" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters`" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters`" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters`" - serviceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for one `Service` resource which will created by `clickhouse-operator` which cover all clusters in whole `chi` resource" - clusterServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each clickhouse cluster described in `chi.spec.configuration.clusters`" - shardServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each shard inside clickhouse cluster described in `chi.spec.configuration.clusters`" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside each clickhouse cluster described in `chi.spec.configuration.clusters`" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - configuration: - type: object - description: "allows configure multiple aspects and behavior for `clickhouse-server` instance and also allows describe multiple `clickhouse-server` clusters inside one `chi` resource" - # nullable: true - properties: - zookeeper: - type: object - description: | - allows configure <yandex><zookeeper>..</zookeeper></yandex> section in each `Pod` during generate `ConfigMap` which will mounted in `/etc/clickhouse-server/config.d/` - `clickhouse-operator` itself doesn't manage Zookeeper, please install Zookeeper separatelly look examples on https://github.com/Altinity/clickhouse-operator/tree/master/deploy/zookeeper/ - currently, zookeeper (or clickhouse-keeper replacement) used for *ReplicatedMergeTree table engines and for `distributed_ddl` - More details: https://clickhouse.tech/docs/en/operations/server-configuration-parameters/settings/#server-settings_zookeeper - # nullable: true - properties: - nodes: - type: array - description: "describe every available zookeeper cluster node for interaction" - # nullable: true - items: - type: object - #required: - # - host - properties: - host: - type: string - description: "dns name or ip address for Zookeeper node" - port: - type: integer - description: "TCP port which used to connect to Zookeeper node" - minimum: 0 - maximum: 65535 - session_timeout_ms: - type: integer - description: "session timeout during connect to Zookeeper" - operation_timeout_ms: - type: integer - description: "one operation timeout during Zookeeper transactions" - root: - type: string - description: "optional root znode path inside zookeeper to store ClickHouse related data (replication queue or distributed DDL)" - identity: - type: string - description: "optional access credentials string with `user:password` format used when use digest authorization in Zookeeper" - users: - type: object - description: | - allows configure <yandex><users>..</users></yandex> section in each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/users.d/` - you can configure password hashed, authorization restrictions, database level security row filters etc. - More details: https://clickhouse.tech/docs/en/operations/settings/settings-users/ - Your yaml code will convert to XML, see examples https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specconfigurationusers - # nullable: true - x-kubernetes-preserve-unknown-fields: true - profiles: - type: object - description: | - allows configure <yandex><profiles>..</profiles></yandex> section in each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/users.d/` - you can configure any aspect of settings profile - More details: https://clickhouse.tech/docs/en/operations/settings/settings-profiles/ - Your yaml code will convert to XML, see examples https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specconfigurationprofiles - # nullable: true - x-kubernetes-preserve-unknown-fields: true - quotas: - type: object - description: | - allows configure <yandex><quotas>..</quotas></yandex> section in each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/users.d/` - you can configure any aspect of resource quotas - More details: https://clickhouse.tech/docs/en/operations/quotas/ - Your yaml code will convert to XML, see examples https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specconfigurationquotas - # nullable: true - x-kubernetes-preserve-unknown-fields: true - settings: - type: object - description: | - allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - Your yaml code will convert to XML, see examples https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#specconfigurationsettings - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - description: | - allows define content of any setting file inside each `Pod` during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - every key in this object is the file name - every value in this object is the file content - you can use `!!binary |` and base64 for binary files, see details here https://yaml.org/type/binary.html - each key could contains prefix like USERS, COMMON, HOST or config.d, users.d, cond.d, wrong prefixes will ignored, subfolders also will ignored - More details: https://github.com/Altinity/clickhouse-operator/blob/master/docs/chi-examples/05-settings-05-files-nested.yaml - # nullable: true - x-kubernetes-preserve-unknown-fields: true - clusters: - type: array - description: | - describes ClickHouse clusters layout and allows change settings on cluster-level, shard-level and replica-level - every cluster is a set of StatefulSet, one StatefulSet contains only one Pod with `clickhouse-server` - all Pods will rendered in <remote_server> part of ClickHouse configs, mounted from ConfigMap as `/etc/clickhouse-server/config.d/chop-generated-remote_servers.xml` - Clusters will use for Distributed table engine, more details: https://clickhouse.tech/docs/en/engines/table-engines/special/distributed/ - If `cluster` contains zookeeper settings (could be inherited from top `chi` level), when you can create *ReplicatedMergeTree tables - # nullable: true - items: - type: object - #required: - # - name - properties: - name: - type: string - description: "cluster name, used to identify set of ClickHouse servers and wide used during generate names of related Kubernetes resources" - minLength: 1 - # See namePartClusterMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - zookeeper: - type: object - description: | - optional, allows configure <yandex><zookeeper>..</zookeeper></yandex> section in each `Pod` only in current ClickHouse cluster, during generate `ConfigMap` which will mounted in `/etc/clickhouse-server/config.d/` - override top-level `chi.spec.configuration.zookeeper` settings - # nullable: true - properties: - nodes: - type: array - description: "describe every available zookeeper cluster node for interaction" - # nullable: true - items: - type: object - #required: - # - host - properties: - host: - type: string - description: "dns name or ip address for Zookeeper node" - port: - type: integer - description: "TCP port which used to connect to Zookeeper node" - minimum: 0 - maximum: 65535 - session_timeout_ms: - type: integer - description: "session timeout during connect to Zookeeper" - operation_timeout_ms: - type: integer - description: "one operation timeout during Zookeeper transactions" - root: - type: string - description: "optional root znode path inside zookeeper to store ClickHouse related data (replication queue or distributed DDL)" - identity: - type: string - description: "optional access credentials string with `user:password` format used when use digest authorization in Zookeeper" - settings: - type: object - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in each `Pod` only in one cluster during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` - override top-level `chi.spec.configuration.settings` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - description: | - optional, allows define content of any setting file inside each `Pod` on current cluster during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files` - # nullable: true - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected cluster - override top-level `chi.spec.configuration.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure each `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one cluster" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one cluster" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one cluster" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one cluster" - serviceTemplate: - type: string - description: "optional, fully ignores for cluster-level" - clusterServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each clickhouse cluster described in `chi.spec.configuration.clusters` only for one cluster" - shardServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one cluster" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside each clickhouse cluster described in `chi.spec.configuration.clusters` only for one cluster" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - layout: - type: object - description: | - describe current cluster layout, how much shards in cluster, how much replica in shard - allows override settings on each shard and replica separatelly - # nullable: true - properties: - type: - type: string - description: "DEPRECATED - to be removed soon" - shardsCount: - type: integer - description: "how much shards for current ClickHouse cluster will run in Kubernetes, each shard contains shared-nothing part of data and contains set of replicas, cluster contains 1 shard by default" - replicasCount: - type: integer - description: "how much replicas in each shards for current ClickHouse cluster will run in Kubernetes, each replica is a separate `StatefulSet` which contains only one `Pod` with `clickhouse-server` instance, every shard contains 1 replica by default" - shards: - type: array - description: "optional, allows override top-level `chi.spec.configuration`, cluster-level `chi.spec.configuration.clusters` settings for each shard separately, use it only if you fully understand what you do" - # nullable: true - items: - type: object - properties: - name: - type: string - description: "optional, by default shard name is generated, but you can override it and setup custom name" - minLength: 1 - # See namePartShardMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - definitionType: - type: string - description: "DEPRECATED - to be removed soon" - weight: - type: integer - description: | - optional, 1 by default, allows setup shard <weight> setting which will use during insert into tables with `Distributed` engine, - will apply in <remote_servers> inside ConfigMap which will mount in /etc/clickhouse-server/config.d/chop-generated-remote_servers.xml - More details: https://clickhouse.tech/docs/en/engines/table-engines/special/distributed/ - # Need to be StringBool - internalReplication: - type: string - description: | - optional, `true` by default when `chi.spec.configuration.clusters[].layout.ReplicaCount` > 1 and 0 otherwise - allows setup <internal_replication> setting which will use during insert into tables with `Distributed` engine for insert only in one live replica and other replicas will download inserted data during replication, - will apply in <remote_servers> inside ConfigMap which will mount in /etc/clickhouse-server/config.d/chop-generated-remote_servers.xml - More details: https://clickhouse.tech/docs/en/engines/table-engines/special/distributed/ - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - settings: - type: object - # nullable: true - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in each `Pod` only in one shard during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` - override top-level `chi.spec.configuration.settings` and cluster-level `chi.spec.configuration.clusters.settings` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - x-kubernetes-preserve-unknown-fields: true - files: - type: object - # nullable: true - description: | - optional, allows define content of any setting file inside each `Pod` only in one shard during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files` and cluster-level `chi.spec.configuration.clusters.files` - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected shard - override top-level `chi.spec.configuration.templates` and cluster-level `chi.spec.configuration.clusters.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure each `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one shard" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - serviceTemplate: - type: string - description: "optional, fully ignores for shard-level" - clusterServiceTemplate: - type: string - description: "optional, fully ignores for shard-level" - shardServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one shard" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one shard" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - replicasCount: - type: integer - description: | - optional, how much replicas in selected shard for selected ClickHouse cluster will run in Kubernetes, each replica is a separate `StatefulSet` which contains only one `Pod` with `clickhouse-server` instance, - shard contains 1 replica by default - override cluster-level `chi.spec.configuration.clusters.layout.replicasCount` - minimum: 1 - replicas: - type: array - description: | - optional, allows override behavior for selected replicas from cluster-level `chi.spec.configuration.clusters` and shard-level `chi.spec.configuration.clusters.layout.shards` - # nullable: true - items: - # Host - type: object - properties: - name: - type: string - description: "optional, by default replica name is generated, but you can override it and setup custom name" - minLength: 1 - # See namePartReplicaMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - tcpPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `tcp` for selected replica, override `chi.spec.templates.hostTemplates.spec.tcpPort` - allows connect to `clickhouse-server` via TCP Native protocol via kubernetes `Service` - minimum: 1 - maximum: 65535 - httpPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `http` for selected replica, override `chi.spec.templates.hostTemplates.spec.httpPort` - allows connect to `clickhouse-server` via HTTP protocol via kubernetes `Service` - minimum: 1 - maximum: 65535 - interserverHTTPPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `interserver` for selected replica, override `chi.spec.templates.hostTemplates.spec.interserverHTTPPort` - allows connect between replicas inside same shard during fetch replicated data parts HTTP protocol - minimum: 1 - maximum: 65535 - settings: - type: object - # nullable: true - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in `Pod` only in one replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/conf.d/` - override top-level `chi.spec.configuration.settings`, cluster-level `chi.spec.configuration.clusters.settings` and shard-level `chi.spec.configuration.clusters.layout.shards.settings` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - x-kubernetes-preserve-unknown-fields: true - files: - type: object - # nullable: true - description: | - optional, allows define content of any setting file inside `Pod` only in one replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files`, cluster-level `chi.spec.configuration.clusters.files` and shard-level `chi.spec.configuration.clusters.layout.shards.files` - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected replica - override top-level `chi.spec.configuration.templates`, cluster-level `chi.spec.configuration.clusters.templates` and shard-level `chi.spec.configuration.clusters.layout.shards.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one replica" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one replica" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - serviceTemplate: - type: string - description: "optional, fully ignores for replica-level" - clusterServiceTemplate: - type: string - description: "optional, fully ignores for replica-level" - shardServiceTemplate: - type: string - description: "optional, fully ignores for replica-level" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one replica" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - replicas: - type: array - description: "optional, allows override top-level `chi.spec.configuration` and cluster-level `chi.spec.configuration.clusters` configuration for each replica and each shard relates to selected replica, use it only if you fully understand what you do" - # nullable: true - items: - type: object - properties: - name: - type: string - description: "optional, by default replica name is generated, but you can override it and setup custom name" - minLength: 1 - # See namePartShardMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - settings: - type: object - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in `Pod` only in one replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/conf.d/` - override top-level `chi.spec.configuration.settings`, cluster-level `chi.spec.configuration.clusters.settings` and will ignore if shard-level `chi.spec.configuration.clusters.layout.shards` present - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - # nullable: true - description: | - optional, allows define content of any setting file inside each `Pod` only in one replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files` and cluster-level `chi.spec.configuration.clusters.files`, will ignore if `chi.spec.configuration.clusters.layout.shards` presents - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected replica - override top-level `chi.spec.configuration.templates`, cluster-level `chi.spec.configuration.clusters.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one replica" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one replica" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - serviceTemplate: - type: string - description: "optional, fully ignores for replica-level" - clusterServiceTemplate: - type: string - description: "optional, fully ignores for replica-level" - shardServiceTemplate: - type: string - description: "optional, fully ignores for replica-level" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one replica" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - shardsCount: - type: integer - description: "optional, count of shards related to current replica, you can override each shard behavior on low-level `chi.spec.configuration.clusters.layout.replicas.shards`" - minimum: 1 - shards: - type: array - description: "optional, list of shards related to current replica, will ignore if `chi.spec.configuration.clusters.layout.shards` presents" - # nullable: true - items: - # Host - type: object - properties: - name: - type: string - description: "optional, by default shard name is generated, but you can override it and setup custom name" - minLength: 1 - # See namePartReplicaMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - tcpPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `tcp` for selected shard, override `chi.spec.templates.hostTemplates.spec.tcpPort` - allows connect to `clickhouse-server` via TCP Native protocol via kubernetes `Service` - minimum: 1 - maximum: 65535 - httpPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `http` for selected shard, override `chi.spec.templates.hostTemplates.spec.httpPort` - allows connect to `clickhouse-server` via HTTP protocol via kubernetes `Service` - minimum: 1 - maximum: 65535 - interserverHTTPPort: - type: integer - description: | - optional, setup `Pod.spec.containers.ports` with name `interserver` for selected shard, override `chi.spec.templates.hostTemplates.spec.interserverHTTPPort` - allows connect between replicas inside same shard during fetch replicated data parts HTTP protocol - minimum: 1 - maximum: 65535 - settings: - type: object - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in `Pod` only in one shard related to current replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/conf.d/` - override top-level `chi.spec.configuration.settings`, cluster-level `chi.spec.configuration.clusters.settings` and replica-level `chi.spec.configuration.clusters.layout.replicas.settings` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - description: | - optional, allows define content of any setting file inside each `Pod` only in one shard related to current replica during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - override top-level `chi.spec.configuration.files` and cluster-level `chi.spec.configuration.clusters.files`, will ignore if `chi.spec.configuration.clusters.layout.shards` presents - # nullable: true - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: | - optional, configuration of the templates names which will use for generate Kubernetes resources according to selected replica - override top-level `chi.spec.configuration.templates`, cluster-level `chi.spec.configuration.clusters.templates`, replica-level `chi.spec.configuration.clusters.layout.replicas.templates` - # nullable: true - properties: - hostTemplate: - type: string - description: "optional, template name from chi.spec.templates.hostTemplates, which will apply to configure each `clickhouse-server` instance during render ConfigMap resources which will mount into `Pod` only for one shard" - podTemplate: - type: string - description: "optional, template name from chi.spec.templates.podTemplates, allows customization each `Pod` resource during render and reconcile each StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - dataVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse data directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - logVolumeClaimTemplate: - type: string - description: "optional, template name from chi.spec.templates.volumeClaimTemplates, allows customization each `PVC` which will mount for clickhouse log directory in each `Pod` during render and reconcile every StatefulSet.spec resource described in `chi.spec.configuration.clusters` only for one shard" - serviceTemplate: - type: string - description: "optional, fully ignores for shard-level" - clusterServiceTemplate: - type: string - description: "optional, fully ignores for shard-level" - shardServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one shard" - replicaServiceTemplate: - type: string - description: "optional, template name from chi.spec.templates.serviceTemplates, allows customization for each `Service` resource which will created by `clickhouse-operator` which cover each replica inside each shard inside clickhouse cluster described in `chi.spec.configuration.clusters` only for one shard" - volumeClaimTemplate: - type: string - description: "DEPRECATED! VolumeClaimTemplate is deprecated in favor of DataVolumeClaimTemplate and LogVolumeClaimTemplate" - templates: - type: object - description: "allows define templates which will use for render Kubernetes resources like StatefulSet, ConfigMap, Service, PVC, by default, clickhouse-operator have own templates, but you can override it" - # nullable: true - properties: - hostTemplates: - type: array - description: "hostTemplate will use during apply to generate `clickhose-server` config files" - # nullable: true - items: - type: object - #required: - # - name - properties: - name: - description: "template name, could use to link inside top-level `chi.spec.defaults.templates.hostTemplate`, cluster-level `chi.spec.configuration.clusters.templates.hostTemplate`, shard-level `chi.spec.configuration.clusters.layout.shards.temlates.hostTemplate`, replica-level `chi.spec.configuration.clusters.layout.replicas.templates.hostTemplate`" - type: string - portDistribution: - type: array - description: "define how will distribute numeric values of named ports in `Pod.spec.containers.ports` and clickhouse-server configs" - # nullable: true - items: - type: object - #required: - # - type - properties: - type: - type: string - description: "type of distribution, when `Unspecified` (default value) then all listen ports on clickhouse-server configuration in all Pods will have the same value, when `ClusterScopeIndex` then ports will increment to offset from base value depends on shard and replica index inside cluster with combination of `chi.spec.templates.podTemlates.spec.HostNetwork` it allows setup ClickHouse cluster inside Kubernetes and provide access via external network bypass Kubernetes internal network" - enum: - # List PortDistributionXXX constants - - "" - - "Unspecified" - - "ClusterScopeIndex" - spec: - # Host - type: object - properties: - name: - type: string - description: "by default, hostname will generate, but this allows define custom name for each `clickhuse-server`" - minLength: 1 - # See namePartReplicaMaxLen const - maxLength: 15 - pattern: "^[a-zA-Z0-9-]{0,15}$" - tcpPort: - type: integer - description: | - optional, setup `tcp_port` inside `clickhouse-server` settings for each Pod where current template will apply - if specified, should have equal value with `chi.spec.templates.podTemplates.spec.containers.ports[name=tcp]` - More info: https://clickhouse.tech/docs/en/interfaces/tcp/ - minimum: 1 - maximum: 65535 - httpPort: - type: integer - description: | - optional, setup `http_port` inside `clickhouse-server` settings for each Pod where current template will apply - if specified, should have equal value with `chi.spec.templates.podTemplates.spec.containers.ports[name=http]` - More info: https://clickhouse.tech/docs/en/interfaces/http/ - minimum: 1 - maximum: 65535 - interserverHTTPPort: - type: integer - description: | - optional, setup `interserver_http_port` inside `clickhouse-server` settings for each Pod where current template will apply - if specified, should have equal value with `chi.spec.templates.podTemplates.spec.containers.ports[name=interserver]` - More info: https://clickhouse.tech/docs/en/operations/server-configuration-parameters/settings/#interserver-http-port - minimum: 1 - maximum: 65535 - settings: - type: object - description: | - optional, allows configure `clickhouse-server` settings inside <yandex>...</yandex> tag in each `Pod` where this template will apply during generate `ConfigMap` which will mount in `/etc/clickhouse-server/conf.d/` - More details: https://clickhouse.tech/docs/en/operations/settings/settings/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - files: - type: object - description: | - optional, allows define content of any setting file inside each `Pod` where this template will apply during generate `ConfigMap` which will mount in `/etc/clickhouse-server/config.d/` or `/etc/clickhouse-server/conf.d/` or `/etc/clickhouse-server/users.d/` - # nullable: true - x-kubernetes-preserve-unknown-fields: true - templates: - type: object - description: "be carefull, this part of CRD allows override template inside template, don't use it if you don't understand what you do" - # nullable: true - properties: - hostTemplate: - type: string - podTemplate: - type: string - dataVolumeClaimTemplate: - type: string - logVolumeClaimTemplate: - type: string - serviceTemplate: - type: string - clusterServiceTemplate: - type: string - shardServiceTemplate: - type: string - replicaServiceTemplate: - type: string - podTemplates: - type: array - description: | - podTemplate will use during render `Pod` inside `StatefulSet.spec` and allows define rendered `Pod.spec`, pod scheduling distribution and pod zone - More information: https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#spectemplatespodtemplates - # nullable: true - items: - type: object - #required: - # - name - properties: - name: - type: string - description: "template name, could use to link inside top-level `chi.spec.defaults.templates.podTemplate`, cluster-level `chi.spec.configuration.clusters.templates.podTemplate`, shard-level `chi.spec.configuration.clusters.layout.shards.temlates.podTemplate`, replica-level `chi.spec.configuration.clusters.layout.replicas.templates.podTemplate`" - generateName: - type: string - description: "allows define format for generated `Pod` name, look to https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#spectemplatesservicetemplates for details about aviailable template variables" - zone: - type: object - description: "allows define custom zone name and will separate ClickHouse `Pods` between nodes, shortcut for `chi.spec.templates.podTemplates.spec.affinity.podAntiAffinity`" - #required: - # - values - properties: - key: - type: string - description: "optional, if defined, allows select kubernetes nodes by label with `name` equal `key`" - values: - type: array - description: "optional, if defined, allows select kubernetes nodes by label with `value` in `values`" - # nullable: true - items: - type: string - distribution: - type: string - description: "DEPRECATED, shortcut for `chi.spec.templates.podTemplates.spec.affinity.podAntiAffinity`" - enum: - - "" - - "Unspecified" - - "OnePerHost" - podDistribution: - type: array - description: "define ClickHouse Pod distibution policy between Kubernetes Nodes inside Shard, Replica, Namespace, CHI, another ClickHouse cluster" - # nullable: true - items: - type: object - #required: - # - type - properties: - type: - type: string - description: "you can define multiple affinity policy types" - enum: - # List PodDistributionXXX constants - - "" - - "Unspecified" - - "ClickHouseAntiAffinity" - - "ShardAntiAffinity" - - "ReplicaAntiAffinity" - - "AnotherNamespaceAntiAffinity" - - "AnotherClickHouseInstallationAntiAffinity" - - "AnotherClusterAntiAffinity" - - "MaxNumberPerNode" - - "NamespaceAffinity" - - "ClickHouseInstallationAffinity" - - "ClusterAffinity" - - "ShardAffinity" - - "ReplicaAffinity" - - "PreviousTailAffinity" - - "CircularReplication" - scope: - type: string - description: "scope for apply each podDistribution" - enum: - # list PodDistributionScopeXXX constants - - "" - - "Unspecified" - - "Shard" - - "Replica" - - "Cluster" - - "ClickHouseInstallation" - - "Namespace" - number: - type: integer - description: "define, how much ClickHouse Pods could be inside selected scope with selected distribution type" - minimum: 0 - maximum: 65535 - topologyKey: - type: string - description: "use for inter-pod affinity look to `pod.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.podAffinityTerm.topologyKey`, More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity" - spec: - # TODO specify PodSpec - type: object - description: "allows define whole Pod.spec inside StaefulSet.spec, look to https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates for details" - # nullable: true - x-kubernetes-preserve-unknown-fields: true - metadata: - type: object - description: | - allows pass standard object's metadata from template to Pod - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - # nullable: true - x-kubernetes-preserve-unknown-fields: true - volumeClaimTemplates: - type: array - description: "allows define template for rendering `PVC` kubernetes resource, which would use inside `Pod` for mount clickhouse `data`, clickhouse `logs` or something else" - # nullable: true - items: - type: object - #required: - # - name - # - spec - properties: - name: - description: | - template name, could use to link inside - top-level `chi.spec.defaults.templates.dataVolumeClaimTemplate` or `chi.spec.defaults.templates.logVolumeClaimTemplate`, - cluster-level `chi.spec.configuration.clusters.templates.dataVolumeClaimTemplate` or `chi.spec.configuration.clusters.templates.logVolumeClaimTemplate`, - shard-level `chi.spec.configuration.clusters.layout.shards.temlates.dataVolumeClaimTemplate` or `chi.spec.configuration.clusters.layout.shards.temlates.logVolumeClaimTemplate` - replica-level `chi.spec.configuration.clusters.layout.replicas.templates.dataVolumeClaimTemplate` or `chi.spec.configuration.clusters.layout.replicas.templates.logVolumeClaimTemplate` - type: string - reclaimPolicy: - type: string - description: "define behavior of `PVC` deletion policy during delete `Pod`, `Delete` by default, when `Retain` then `PVC` still alive even `Pod` will deleted" - enum: - - "" - - "Retain" - - "Delete" - metadata: - type: object - description: | - allows pass standard object's metadata from template to PVC - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - # nullable: true - x-kubernetes-preserve-unknown-fields: true - spec: - type: object - description: | - allows define all aspects of `PVC` resource - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims - # nullable: true - x-kubernetes-preserve-unknown-fields: true - serviceTemplates: - type: array - description: | - allows define template for rendering `Service` which would get endpoint from Pods which scoped chi-wide, cluster-wide, shard-wide, replica-wide level - # nullable: true - items: - type: object - #required: - # - name - # - spec - properties: - name: - type: string - description: | - template name, could use to link inside - chi-level `chi.spec.defaults.templates.serviceTemplate` - cluster-level `chi.spec.configuration.clusters.templates.clusterServiceTemplate` - shard-level `chi.spec.configuration.clusters.layout.shards.temlates.shardServiceTemplate` - replica-level `chi.spec.configuration.clusters.layout.replicas.templates.replicaServiceTemplate` or `chi.spec.configuration.clusters.layout.shards.replicas.replicaServiceTemplate` - generateName: - type: string - description: "allows define format for generated `Service` name, look to https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#spectemplatesservicetemplates for details about aviailable template variables" - metadata: - # TODO specify ObjectMeta - type: object - description: | - allows pass standard object's metadata from template to Service - Could be use for define specificly for Cloud Provider metadata which impact to behavior of service - More info: https://kubernetes.io/docs/concepts/services-networking/service/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - spec: - # TODO specify ServiceSpec - type: object - description: | - describe behavior of generated Service - More info: https://kubernetes.io/docs/concepts/services-networking/service/ - # nullable: true - x-kubernetes-preserve-unknown-fields: true - useTemplates: - type: array - description: "list of `ClickHouseInstallationTemplate` (chit) resource names which will merge with current `Chi` manifest during render Kubernetes resources to create related ClickHouse clusters" - # nullable: true - items: - type: object - #required: - # - name - properties: - name: - type: string - description: "name of `ClickHouseInstallationTemplate` (chit) resource" - namespace: - type: string - description: "Kubernetes namespace where need search `chit` resource, depending on `watchNamespaces` settings in `clichouse-operator`" - useType: - type: string - description: "optional, current strategy is only merge, and current `chi` settings have more priority than merged template `chit`" - enum: - # List useTypeXXX constants from model - - "" - - "merge" diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseoperatorconfigurations.clickhouse.altinity.com.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseoperatorconfigurations.clickhouse.altinity.com.yaml deleted file mode 100644 index 515a4c608..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/crds/CustomResourceDefinition-clickhouseoperatorconfigurations.clickhouse.altinity.com.yaml +++ /dev/null @@ -1,284 +0,0 @@ -# Template Parameters: -# -# NONE -# -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: clickhouseoperatorconfigurations.clickhouse.altinity.com - labels: - clickhouse.altinity.com/chop: 0.18.1 -spec: - group: clickhouse.altinity.com - scope: Namespaced - names: - kind: ClickHouseOperatorConfiguration - singular: clickhouseoperatorconfiguration - plural: clickhouseoperatorconfigurations - shortNames: - - chopconf - versions: - - name: v1 - served: true - storage: true - additionalPrinterColumns: - - name: namespaces - type: string - description: Watch namespaces - priority: 0 # show in standard view - jsonPath: .status - schema: - openAPIV3Schema: - type: object - description: "allows customize `clickhouse-operator` settings, need restart clickhouse-operator pod after adding, more details https://github.com/Altinity/clickhouse-operator/blob/master/docs/operator_configuration.md" - x-kubernetes-preserve-unknown-fields: true - properties: - status: - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - type: object - description: | - Allows to define settings of the clickhouse-operator. - More info: https://github.com/Altinity/clickhouse-operator/blob/master/config/config.yaml - Check into etc-clickhouse-operator* ConfigMaps if you need more control - x-kubernetes-preserve-unknown-fields: true - properties: - watch: - type: object - properties: - namespaces: - type: array - description: "List of namespaces where clickhouse-operator watches for events." - items: - type: string - clickhouse: - type: object - properties: - configuration: - type: object - properties: - file: - type: object - properties: - path: - type: object - properties: - common: - type: string - description: "Path to the folder where ClickHouse configuration files common for all instances within a CHI are located. Default - config.d" - host: - type: string - description: "Path to the folder where ClickHouse configuration files unique for each instance (host) within a CHI are located. Default - conf.d" - user: - type: string - description: "Path to the folder where ClickHouse configuration files with users settings are located. Files are common for all instances within a CHI." - user: - type: object - properties: - default: - type: object - properties: - profile: - type: string - description: "ClickHouse server configuration `<profile>...</profile>` for any <user>" - quota: - type: string - description: "ClickHouse server configuration `<quota>...</quota>` for any <user>" - networksIP: - type: array - description: "ClickHouse server configuration `<networks><ip>...</ip></networks>` for any <user>" - items: - type: string - password: - type: string - description: "ClickHouse server configuration `<password>...</password>` for any <user>" - network: - type: object - properties: - hostRegexpTemplate: - type: string - description: "ClickHouse server configuration `<host_regexp>...</host_regexp>` for any <user>" - access: - type: object - properties: - username: - type: string - description: "ClickHouse username to be used by operator to connect to ClickHouse instances, deprecated, use chCredentialsSecretName" - password: - type: string - description: "ClickHouse password to be used by operator to connect to ClickHouse instances, deprecated, use chCredentialsSecretName" - secret: - type: object - properties: - namespace: - type: string - description: "Location of k8s Secret with username and password to be used by operator to connect to ClickHouse instances" - name: - type: string - description: "Name of k8s Secret with username and password to be used by operator to connect to ClickHouse instances" - port: - type: integer - minimum: 1 - maximum: 65535 - description: "port to be used by operator to connect to ClickHouse instances" - template: - type: object - properties: - chi: - type: object - properties: - path: - type: string - description: "Path to folder where ClickHouseInstallationTemplate .yaml manifests are located." - reconcile: - type: object - properties: - runtime: - type: object - properties: - threadsNumber: - type: integer - minimum: 1 - maximum: 65535 - description: "How many goroutines will be used to reconcile in parallel, 10 by default" - statefulSet: - type: object - properties: - create: - type: object - properties: - onFailure: - type: string - description: | - What to do in case created StatefulSet is not in Ready after `statefulSetUpdateTimeout` seconds - Possible options: - 1. abort - do nothing, just break the process and wait for admin. - 2. delete - delete newly created problematic StatefulSet. - 3. ignore (default) - ignore error, pretend nothing happened and move on to the next StatefulSet. - update: - type: object - properties: - timeout: - type: integer - description: "How many seconds to wait for created/updated StatefulSet to be Ready" - pollInterval: - type: integer - description: "How many seconds to wait between checks for created/updated StatefulSet status" - onFailure: - type: string - description: | - What to do in case updated StatefulSet is not in Ready after `statefulSetUpdateTimeout` seconds - Possible options: - 1. abort - do nothing, just break the process and wait for admin. - 2. rollback (default) - delete Pod and rollback StatefulSet to previous Generation. Pod would be recreated by StatefulSet based on rollback-ed configuration. - 3. ignore - ignore error, pretend nothing happened and move on to the next StatefulSet. - host: - type: object - properties: - wait: - type: object - properties: - exclude: - type: boolean - include: - type: boolean - annotation: - type: object - properties: - include: - type: array - items: - type: string - exclude: - type: array - items: - type: string - label: - type: object - properties: - include: - type: array - items: - type: string - exclude: - type: array - items: - type: string - description: | - When propagating labels from the chi's `metadata.labels` section to child objects' `metadata.labels`, - exclude labels from the following list - appendScope: - type: string - description: | - Whether to append *Scope* labels to StatefulSet and Pod - - "LabelShardScopeIndex" - - "LabelReplicaScopeIndex" - - "LabelCHIScopeIndex" - - "LabelCHIScopeCycleSize" - - "LabelCHIScopeCycleIndex" - - "LabelCHIScopeCycleOffset" - - "LabelClusterScopeIndex" - - "LabelClusterScopeCycleSize" - - "LabelClusterScopeCycleIndex" - - "LabelClusterScopeCycleOffset" - enum: - # List StringBoolXXX constants from model - - "" - - "0" - - "1" - - "False" - - "false" - - "True" - - "true" - - "No" - - "no" - - "Yes" - - "yes" - - "Off" - - "off" - - "On" - - "on" - - "Disable" - - "disable" - - "Enable" - - "enable" - - "Disabled" - - "disabled" - - "Enabled" - - "enabled" - statefulSet: - type: object - properties: - revisionHistoryLimit: - type: integer - pod: - type: object - properties: - terminationGracePeriod: - type: integer - logger: - type: object - properties: - logtostderr: - type: string - description: "boolean, allows logs to stderr" - alsologtostderr: - type: string - description: "boolean allows logs to stderr and files both" - v: - type: string - description: "verbosity level of clickhouse-operator log, default - 1 max - 9" - stderrthreshold: - type: string - vmodule: - type: string - description: | - Comma-separated list of filename=N, where filename (can be a pattern) must have no .go ext, and N is a V level. - Ex.: file*=2 sets the 'V' to 2 in all files with names like file*. - log_backtrace_at: - type: string - description: | - It can be set to a file and line number with a logging line. - Ex.: file.go:123 - Each time when this line is being executed, a stack trace will be written to the Info log. diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/hacks/sync-yamls.sh b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/hacks/sync-yamls.sh deleted file mode 100644 index 12b38d39e..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/hacks/sync-yamls.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash - -# -# Script downloads manifest from altinity repo, splits it to separate files -# and puts to the corresponding folders -# NOTE: yq ( https://mikefarah.gitbook.io/yq/ ) > v4.14.x is required -# -# Usage: ./sync.sh -# - -set -o errexit -set -o nounset -set -o pipefail - -readonly repo_url="https://raw.githubusercontent.com/Altinity/clickhouse-operator" -readonly crds_dir="../crds" -readonly templates_dir="../templates/generated" -readonly manifest_path="deploy/operator/clickhouse-operator-install-bundle.yaml" -readonly chart_def="../Chart.yaml" - -function main() { - readonly manifest_url="${repo_url}/$(detect_version)/${manifest_path}" - local tmpdir - tmpdir=$(mktemp -d) - - # shellcheck disable=SC2016 - (cd "${tmpdir}" && curl -s "${manifest_url}" 2>&1 | yq e --no-doc -s '$index') - - for f in "${tmpdir}"/*.yml; do - process "${f}" - done -} - -function process() { - local file="${1}" - - local kind - kind=$(yq e '.kind' "${file}") - - local name - name=$(yq e '.metadata.name' "${file}") - - local processed_file="${kind}-${name}.yaml" - - if [[ "${kind}" == "CustomResourceDefinition" ]]; then - processed_file="${crds_dir}/${processed_file}" - else - processed_file="${templates_dir}/${processed_file}" - fi - - mv "${file}" "${processed_file}" -} - -function detect_version() { - yq e '.appVersion' ${chart_def} -} - -main diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/_helpers.tpl b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/_helpers.tpl deleted file mode 100644 index f1cd6318a..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/_helpers.tpl +++ /dev/null @@ -1,73 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "altinity-clickhouse-operator.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "altinity-clickhouse-operator.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "altinity-clickhouse-operator.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "altinity-clickhouse-operator.labels" -}} -helm.sh/chart: {{ include "altinity-clickhouse-operator.chart" . }} -{{ include "altinity-clickhouse-operator.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} - -{{/* -Selector labels -*/}} -{{- define "altinity-clickhouse-operator.selectorLabels" -}} -app.kubernetes.io/name: {{ include "altinity-clickhouse-operator.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Create the name of the service account to use -*/}} -{{- define "altinity-clickhouse-operator.serviceAccountName" -}} - {{ default (include "altinity-clickhouse-operator.fullname" .) .Values.serviceAccount.name }} -{{- end -}} - -{{/* -Create the tag for the docker image to use -*/}} -{{- define "altinity-clickhouse-operator.operator.tag" -}} -{{- .Values.operator.image.tag | default .Chart.AppVersion -}} -{{- end -}} - -{{/* -Create the tag for the docker image to use -*/}} -{{- define "altinity-clickhouse-operator.metrics.tag" -}} -{{- .Values.metrics.image.tag | default .Chart.AppVersion -}} -{{- end -}} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ClusterRole-clickhouse-operator-kube-system.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ClusterRole-clickhouse-operator-kube-system.yaml deleted file mode 100644 index 3bb1ab7cc..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ClusterRole-clickhouse-operator-kube-system.yaml +++ /dev/null @@ -1,163 +0,0 @@ -# Template Parameters: -# -# NAMESPACE=kube-system -# COMMENT=# -# ROLE_KIND=ClusterRole -# ROLE_NAME=clickhouse-operator-kube-system -# ROLE_BINDING_KIND=ClusterRoleBinding -# ROLE_BINDING_NAME=clickhouse-operator-kube-system -# -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 -rules: - - apiGroups: - - "" - resources: - - configmaps - - services - verbs: - - get - - list - - patch - - update - - watch - - create - - delete - - apiGroups: - - "" - resources: - - endpoints - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - events - verbs: - - create - - apiGroups: - - "" - resources: - - persistentvolumeclaims - verbs: - - get - - list - - patch - - update - - watch - - delete - - apiGroups: - - "" - resources: - - persistentvolumes - - pods - verbs: - - get - - list - - patch - - update - - watch - - apiGroups: - - apps - resources: - - statefulsets - verbs: - - get - - list - - patch - - update - - watch - - create - - delete - - apiGroups: - - apps - resources: - - replicasets - verbs: - - get - - patch - - update - - delete - - apiGroups: - - apps - resourceNames: - - clickhouse-operator - resources: - - deployments - verbs: - - get - - patch - - update - - delete - - apiGroups: - - policy - resources: - - poddisruptionbudgets - verbs: - - get - - list - - patch - - update - - watch - - create - - delete - - apiGroups: - - clickhouse.altinity.com - resources: - - clickhouseinstallations - verbs: - - get - - patch - - update - - delete - - apiGroups: - - clickhouse.altinity.com - resources: - - clickhouseinstallations - - clickhouseinstallationtemplates - - clickhouseoperatorconfigurations - verbs: - - get - - list - - watch - - apiGroups: - - clickhouse.altinity.com - resources: - - clickhouseinstallations/finalizers - - clickhouseinstallationtemplates/finalizers - - clickhouseoperatorconfigurations/finalizers - verbs: - - update - - apiGroups: - - clickhouse.altinity.com - resources: - - clickhouseinstallations/status - - clickhouseinstallationtemplates/status - - clickhouseoperatorconfigurations/status - verbs: - - get - - update - - patch - - create - - delete - - apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - list diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ClusterRoleBinding-clickhouse-operator-kube-system.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ClusterRoleBinding-clickhouse-operator-kube-system.yaml deleted file mode 100644 index 8c8ab1ff1..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ClusterRoleBinding-clickhouse-operator-kube-system.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# Setup ClusterRoleBinding between ClusterRole and ServiceAccount. -# ClusterRoleBinding is namespace-less and must have unique name -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "altinity-clickhouse-operator.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ include "altinity-clickhouse-operator.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-confd-files.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-confd-files.yaml deleted file mode 100644 index e8a9096f0..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-confd-files.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Template Parameters: -# -# NAME=etc-clickhouse-operator-confd-files -# NAMESPACE=kube-system -# COMMENT= -# -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-confd-files - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} -data: -{{- if .Values.configs.confdFiles }} - {{- toYaml .Values.configs.confdFiles | nindent 2 }} -{{ end }} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-configd-files.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-configd-files.yaml deleted file mode 100644 index 983602be4..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-configd-files.yaml +++ /dev/null @@ -1,59 +0,0 @@ -# Template Parameters: -# -# NAME=etc-clickhouse-operator-configd-files -# NAMESPACE=kube-system -# COMMENT= -# -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-configd-files - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} -data: -{{- if .Values.configs.configdFiles }} - {{- toYaml .Values.configs.configdFiles | nindent 2 }} -{{ else }} - 01-clickhouse-01-listen.xml: | - <yandex> - <!-- Listen wildcard address to allow accepting connections from other containers and host network. --> - <listen_host>::</listen_host> - <listen_host>0.0.0.0</listen_host> - <listen_try>1</listen_try> - </yandex> - 01-clickhouse-02-logger.xml: | - <yandex> - <logger> - <!-- Possible levels: https://github.com/pocoproject/poco/blob/develop/Foundation/include/Poco/Logger.h#L105 --> - <level>debug</level> - <log>/var/log/clickhouse-server/clickhouse-server.log</log> - <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog> - <size>1000M</size> - <count>10</count> - <!-- Default behavior is autodetection (log to console if not daemon mode and is tty) --> - <console>1</console> - </logger> - </yandex> - 01-clickhouse-03-query_log.xml: | - <yandex> - <query_log replace="1"> - <database>system</database> - <table>query_log</table> - <engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_date + interval 30 day</engine> - <flush_interval_milliseconds>7500</flush_interval_milliseconds> - </query_log> - <query_thread_log remove="1"/> - </yandex> - 01-clickhouse-04-part_log.xml: | - <yandex> - <part_log replace="1"> - <database>system</database> - <table>part_log</table> - <engine>Engine = MergeTree PARTITION BY event_date ORDER BY event_time TTL event_date + interval 30 day</engine> - <flush_interval_milliseconds>7500</flush_interval_milliseconds> - </part_log> - </yandex> - -{{ end }} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-files.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-files.yaml deleted file mode 100644 index 5ac2e1bbd..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-files.yaml +++ /dev/null @@ -1,230 +0,0 @@ -# Template Parameters: -# -# NAME=etc-clickhouse-operator-files -# NAMESPACE=kube-system -# COMMENT= -# -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-files - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} -data: -{{- if .Values.configs.files }} - {{- toYaml .Values.configs.files | nindent 2 }} -{{ else }} - config.yaml: | - # IMPORTANT - # This file is auto-generated from deploy/builder/templates-config. - # It will be overwritten upon next sources build. - # - # Template parameters available: - # watchNamespaces - # chUsername - # chPassword - # password_sha256_hex - - ################################################ - ## - ## Watch Section - ## - ################################################ - watch: - # List of namespaces where clickhouse-operator watches for events. - # Concurrently running operators should watch on different namespaces - #namespaces: ["dev", "test"] - namespaces: [] - - clickhouse: - configuration: - ################################################ - ## - ## Configuration Files Section - ## - ################################################ - file: - path: - # Path to the folder where ClickHouse configuration files common for all instances within a CHI are located. - common: config.d - # Path to the folder where ClickHouse configuration files unique for each instance (host) within a CHI are located. - host: conf.d - # Path to the folder where ClickHouse configuration files with users settings are located. - # Files are common for all instances within a CHI. - user: users.d - ################################################ - ## - ## Configuration Users Section - ## - ################################################ - user: - default: - # Default values for ClickHouse user configuration - # 1. user/profile - string - # 2. user/quota - string - # 3. user/networks/ip - multiple strings - # 4. user/password - string - profile: default - quota: default - networksIP: - - "::1" - - "127.0.0.1" - password: "default" - ################################################ - ## - ## Configuration Network Section - ## - ################################################ - network: - # Default host_regexp to limit network connectivity from outside - hostRegexpTemplate: "(chi-{chi}-[^.]+\\d+-\\d+|clickhouse\\-{chi})\\.{namespace}\\.svc\\.cluster\\.local$" - ################################################ - ## - ## Access to ClickHouse instances - ## - ################################################ - access: - # ClickHouse credentials (username, password and port) to be used by operator to connect to ClickHouse instances - # for: - # 1. Metrics requests - # 2. Schema maintenance - # 3. DROP DNS CACHE - # User with such credentials can be specified in additional ClickHouse .xml config files, - # located in `chUsersConfigsPath` folder - username: "clickhouse_operator" - password: "clickhouse_operator_password" - secret: - # Location of k8s Secret with username and password to be used by operator to connect to ClickHouse instances - # Can be used instead of explicitly specified username and password - namespace: "" - name: "" - # Port where to connect to ClickHouse instances to - port: 8123 - - ################################################ - ## - ## Templates Section - ## - ################################################ - template: - chi: - # Path to the folder where ClickHouseInstallation .yaml manifests are located. - # Manifests are applied in sorted alpha-numeric order. - path: templates.d - - ################################################ - ## - ## Reconcile Section - ## - ################################################ - reconcile: - runtime: - # Max number of concurrent reconciles in progress - threadsNumber: 10 - - statefulSet: - create: - # What to do in case created StatefulSet is not in Ready after `statefulSetUpdateTimeout` seconds - # Possible options: - # 1. abort - do nothing, just break the process and wait for admin - # 2. delete - delete newly created problematic StatefulSet - # 3. ignore - ignore error, pretend nothing happened and move on to the next StatefulSet - onFailure: ignore - - update: - # How many seconds to wait for created/updated StatefulSet to be Ready - timeout: 300 - # How many seconds to wait between checks for created/updated StatefulSet status - pollInterval: 5 - # What to do in case updated StatefulSet is not in Ready after `statefulSetUpdateTimeout` seconds - # Possible options: - # 1. abort - do nothing, just break the process and wait for admin - # 2. rollback - delete Pod and rollback StatefulSet to previous Generation. - # Pod would be recreated by StatefulSet based on rollback-ed configuration - # 3. ignore - ignore error, pretend nothing happened and move on to the next StatefulSet - onFailure: rollback - - host: - wait: - exclude: true - include: false - - ################################################ - ## - ## Annotations management - ## - ################################################ - annotation: - # Applied when: - # 1. Propagating annotations from the CHI's `metadata.annotations` to child objects' `metadata.annotations`, - # 2. Propagating annotations from the CHI Template's `metadata.annotations` to CHI's `metadata.annotations`, - # Include annotations from the following list: - # Applied only when not empty. Empty list means "include all, no selection" - include: [] - # Exclude annotations from the following list: - exclude: [] - - ################################################ - ## - ## Labels management - ## - ################################################ - label: - # Applied when: - # 1. Propagating labels from the CHI's `metadata.labels` to child objects' `metadata.labels`, - # 2. Propagating labels from the CHI Template's `metadata.labels` to CHI's `metadata.labels`, - # Include labels from the following list: - # Applied only when not empty. Empty list means "include all, no selection" - include: [] - # Exclude labels from the following list: - exclude: [] - # Whether to append *Scope* labels to StatefulSet and Pod. - # Full list of available *scope* labels check in labeler.go - # LabelShardScopeIndex - # LabelReplicaScopeIndex - # LabelCHIScopeIndex - # LabelCHIScopeCycleSize - # LabelCHIScopeCycleIndex - # LabelCHIScopeCycleOffset - # LabelClusterScopeIndex - # LabelClusterScopeCycleSize - # LabelClusterScopeCycleIndex - # LabelClusterScopeCycleOffset - appendScope: "no" - - ################################################ - ## - ## StatefulSet management - ## - ################################################ - statefulSet: - revisionHistoryLimit: 0 - - ################################################ - ## - ## Pod management - ## - ################################################ - pod: - # Grace period for Pod termination. - # How many seconds to wait between sending - # SIGTERM and SIGKILL during Pod termination process. - # Increase this number is case of slow shutdown. - terminationGracePeriod: 30 - - ################################################ - ## - ## Log parameters - ## - ################################################ - logger: - logtostderr: "true" - alsologtostderr: "false" - v: "1" - stderrthreshold: "" - vmodule: "" - log_backtrace_at: "" - -{{ end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-templatesd-files.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-templatesd-files.yaml deleted file mode 100644 index c6131c299..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-templatesd-files.yaml +++ /dev/null @@ -1,102 +0,0 @@ -# Template Parameters: -# -# NAME=etc-clickhouse-operator-templatesd-files -# NAMESPACE=kube-system -# COMMENT= -# -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-templatesd-files - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} -data: -{{- if .Values.configs.templatesdFiles }} - {{- toYaml .Values.configs.templatesdFiles | nindent 2 }} -{{ else }} - 001-templates.json.example: | - { - "apiVersion": "clickhouse.altinity.com/v1", - "kind": "ClickHouseInstallationTemplate", - "metadata": { - "name": "01-default-volumeclaimtemplate" - }, - "spec": { - "templates": { - "volumeClaimTemplates": [ - { - "name": "chi-default-volume-claim-template", - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "2Gi" - } - } - } - } - ], - "podTemplates": [ - { - "name": "chi-default-oneperhost-pod-template", - "distribution": "OnePerHost", - "spec": { - "containers" : [ - { - "name": "clickhouse", - "image": "yandex/clickhouse-server:21.3", - "ports": [ - { - "name": "http", - "containerPort": 8123 - }, - { - "name": "client", - "containerPort": 9000 - }, - { - "name": "interserver", - "containerPort": 9009 - } - ] - } - ] - } - } - ] - } - } - } - default-pod-template.yaml.example: | - apiVersion: "clickhouse.altinity.com/v1" - kind: "ClickHouseInstallationTemplate" - metadata: - name: "default-oneperhost-pod-template" - spec: - templates: - podTemplates: - - name: default-oneperhost-pod-template - distribution: "OnePerHost" - default-storage-template.yaml.example: | - apiVersion: "clickhouse.altinity.com/v1" - kind: "ClickHouseInstallationTemplate" - metadata: - name: "default-storage-template-2Gi" - spec: - templates: - volumeClaimTemplates: - - name: default-storage-template-2Gi - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - readme: | - Templates in this folder are packaged with an operator and available via 'useTemplate' - -{{ end }} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-usersd-files.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-usersd-files.yaml deleted file mode 100644 index 3f6f8f5ce..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ConfigMap-etc-clickhouse-operator-usersd-files.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# Template Parameters: -# -# NAME=etc-clickhouse-operator-usersd-files -# NAMESPACE=kube-system -# COMMENT= -# -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-usersd-files - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} -data: -{{- if .Values.configs.usersdFiles }} - {{- toYaml .Values.configs.usersdFiles | nindent 2 }} -{{ else }} - 01-clickhouse-user.xml: | - <yandex> - <users> - <clickhouse_operator> - <networks> - <ip>127.0.0.1</ip> - <ip>0.0.0.0/0</ip> - <ip>::/0</ip> - </networks> - <password_sha256_hex>716b36073a90c6fe1d445ac1af85f4777c5b7a155cea359961826a030513e448</password_sha256_hex> - <profile>clickhouse_operator</profile> - <quota>default</quota> - </clickhouse_operator> - </users> - <profiles> - <clickhouse_operator> - <log_queries>0</log_queries> - <skip_unavailable_shards>1</skip_unavailable_shards> - <http_connection_timeout>10</http_connection_timeout> - </clickhouse_operator> - </profiles> - </yandex> - 02-clickhouse-default-profile.xml: | - <yandex> - <profiles> - <default> - <log_queries>1</log_queries> - <connect_timeout_with_failover_ms>1000</connect_timeout_with_failover_ms> - <distributed_aggregation_memory_efficient>1</distributed_aggregation_memory_efficient> - <parallel_view_processing>1</parallel_view_processing> - </default> - </profiles> - </yandex> - 03-database-ordinary.xml: | - <!-- Remove it for ClickHouse versions before 20.4 --> - <yandex> - <profiles> - <default> - <default_database_engine>Ordinary</default_database_engine> - </default> - </profiles> - </yandex> - -{{ end }} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/Deployment-clickhouse-operator.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/Deployment-clickhouse-operator.yaml deleted file mode 100644 index e7109ce8c..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/Deployment-clickhouse-operator.yaml +++ /dev/null @@ -1,175 +0,0 @@ -# Template Parameters: -# -# NAMESPACE=kube-system -# COMMENT= -# OPERATOR_IMAGE=altinity/clickhouse-operator:0.18.1 -# METRICS_EXPORTER_IMAGE=altinity/metrics-exporter:0.18.1 -# -# Setup Deployment for clickhouse-operator -# Deployment would be created in kubectl-specified namespace -kind: Deployment -apiVersion: apps/v1 -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - {{- include "altinity-clickhouse-operator.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - {{- include "altinity-clickhouse-operator.selectorLabels" . | nindent 8 }} - annotations: - prometheus.io/port: '8888' - prometheus.io/scrape: 'true' - checksum/confd-files: {{ include (print $.Template.BasePath "/generated/ConfigMap-etc-clickhouse-operator-confd-files.yaml") . | sha256sum }} - checksum/configd-files: {{ include (print $.Template.BasePath "/generated/ConfigMap-etc-clickhouse-operator-configd-files.yaml") . | sha256sum }} - checksum/files: {{ include (print $.Template.BasePath "/generated/ConfigMap-etc-clickhouse-operator-files.yaml") . | sha256sum }} - checksum/templatesd-files: {{ include (print $.Template.BasePath "/generated/ConfigMap-etc-clickhouse-operator-templatesd-files.yaml") . | sha256sum }} - checksum/usersd-files: {{ include (print $.Template.BasePath "/generated/ConfigMap-etc-clickhouse-operator-usersd-files.yaml") . | sha256sum }} - {{- if .Values.podAnnotations }} - {{- toYaml .Values.podAnnotations | nindent 8 }} - {{- end }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "altinity-clickhouse-operator.serviceAccountName" . }} - volumes: - - name: etc-clickhouse-operator-folder - configMap: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-files - - name: etc-clickhouse-operator-confd-folder - configMap: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-confd-files - - name: etc-clickhouse-operator-configd-folder - configMap: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-configd-files - - name: etc-clickhouse-operator-templatesd-folder - configMap: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-templatesd-files - - name: etc-clickhouse-operator-usersd-folder - configMap: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-usersd-files - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.operator.image.repository }}:{{ include "altinity-clickhouse-operator.operator.tag" . }}" - imagePullPolicy: {{ .Values.operator.image.pullPolicy }} - {{- if .Values.operator.command }} - command: - {{- range $value := .Values.operator.command }} - - {{ $value | quote }} - {{- end }} - {{- end }} - {{- if .Values.operator.args }} - args: - {{- range $value := .Values.operator.args }} - - {{ $value | quote }} - {{- end }} - {{- end }} - volumeMounts: - - name: etc-clickhouse-operator-folder - mountPath: /etc/clickhouse-operator - - name: etc-clickhouse-operator-confd-folder - mountPath: /etc/clickhouse-operator/conf.d - - name: etc-clickhouse-operator-configd-folder - mountPath: /etc/clickhouse-operator/config.d - - name: etc-clickhouse-operator-templatesd-folder - mountPath: /etc/clickhouse-operator/templates.d - - name: etc-clickhouse-operator-usersd-folder - mountPath: /etc/clickhouse-operator/users.d - env: - # Pod-specific - # spec.nodeName: ip-172-20-52-62.ec2.internal - - name: OPERATOR_POD_NODE_NAME - valueFrom: - fieldRef: - fieldPath: spec.nodeName - # metadata.name: clickhouse-operator-6f87589dbb-ftcsf - - name: OPERATOR_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - # metadata.namespace: kube-system - - name: OPERATOR_POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - # status.podIP: 100.96.3.2 - - name: OPERATOR_POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - # spec.serviceAccount: clickhouse-operator - # spec.serviceAccountName: clickhouse-operator - - name: OPERATOR_POD_SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - # Container-specific - - name: OPERATOR_CONTAINER_CPU_REQUEST - valueFrom: - resourceFieldRef: - containerName: {{ .Chart.Name }} - resource: requests.cpu - - name: OPERATOR_CONTAINER_CPU_LIMIT - valueFrom: - resourceFieldRef: - containerName: {{ .Chart.Name }} - resource: limits.cpu - - name: OPERATOR_CONTAINER_MEM_REQUEST - valueFrom: - resourceFieldRef: - containerName: {{ .Chart.Name }} - resource: requests.memory - - name: OPERATOR_CONTAINER_MEM_LIMIT - valueFrom: - resourceFieldRef: - containerName: {{ .Chart.Name }} - resource: limits.memory - {{- with .Values.operator.env }} - {{- toYaml . | nindent 12 }} - {{- end }} - resources: - {{- toYaml .Values.operator.resources | nindent 12 }} - - name: metrics-exporter - image: "{{ .Values.metrics.image.repository }}:{{ include "altinity-clickhouse-operator.metrics.tag" . }}" - imagePullPolicy: {{ .Values.metrics.image.pullPolicy }} - {{- if .Values.metrics.command }} - command: - {{- range $value := .Values.metrics.command }} - - {{ $value | quote }} - {{- end }} - {{- end }} - {{- if .Values.metrics.args }} - args: - {{- range $value := .Values.metrics.args }} - - {{ $value | quote }} - {{- end }} - {{- end }} - volumeMounts: - - name: etc-clickhouse-operator-folder - mountPath: /etc/clickhouse-operator - - name: etc-clickhouse-operator-confd-folder - mountPath: /etc/clickhouse-operator/conf.d - - name: etc-clickhouse-operator-configd-folder - mountPath: /etc/clickhouse-operator/config.d - - name: etc-clickhouse-operator-templatesd-folder - mountPath: /etc/clickhouse-operator/templates.d - - name: etc-clickhouse-operator-usersd-folder - mountPath: /etc/clickhouse-operator/users.d - ports: - - containerPort: 8888 - name: metrics - {{- with .Values.metrics.env }} - env: - {{- toYaml . | nindent 12 }} - {{- end }} - resources: - {{- toYaml .Values.metrics.resources | nindent 12 }} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/Service-clickhouse-operator-metrics.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/Service-clickhouse-operator-metrics.yaml deleted file mode 100644 index 3b03a6715..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/Service-clickhouse-operator-metrics.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Template Parameters: -# -# NAMESPACE=kube-system -# COMMENT= -# -# Setup ClusterIP Service to provide monitoring metrics for Prometheus -# Service would be created in kubectl-specified namespace -# In order to get access outside of k8s it should be exposed as: -# kubectl --namespace prometheus port-forward service/prometheus 9090 -# and point browser to localhost:9090 -kind: Service -apiVersion: v1 -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }}-metrics - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} -spec: - ports: - - port: 8888 - name: clickhouse-operator-metrics - targetPort: metrics - selector: - {{- include "altinity-clickhouse-operator.selectorLabels" . | nindent 4 }} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ServiceAccount-clickhouse-operator.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ServiceAccount-clickhouse-operator.yaml deleted file mode 100644 index d6986674d..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/generated/ServiceAccount-clickhouse-operator.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -# Template Parameters: -# -# COMMENT= -# NAMESPACE=kube-system -# NAME=clickhouse-operator -# -# Setup ServiceAccount -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "altinity-clickhouse-operator.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} - labels: - clickhouse.altinity.com/chop: 0.18.1 - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end -}} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/servicemonitor.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/servicemonitor.yaml deleted file mode 100644 index b96a4fe2f..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/templates/servicemonitor.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "altinity-clickhouse-operator.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "altinity-clickhouse-operator.labels" . | nindent 4 }} - {{- if .Values.serviceMonitor.additionalLabels }} - {{- toYaml .Values.serviceMonitor.additionalLabels | nindent 4 }} - {{- end }} -spec: - endpoints: - - port: clickhouse-operator-metrics - selector: - matchLabels: - {{- include "altinity-clickhouse-operator.selectorLabels" . | nindent 6 }} -{{- end }} diff --git a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/values.yaml b/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/values.yaml deleted file mode 100644 index 9ad166824..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/charts/altinity-clickhouse-operator/values.yaml +++ /dev/null @@ -1,88 +0,0 @@ -operator: - image: - # operator.image.repository -- image repository - repository: altinity/clickhouse-operator - # operator.image.tag -- image tag (chart's appVersion value will be used if not set) - tag: "" - # operator.image.pullPolicy -- image pull policy - pullPolicy: IfNotPresent - # operator.resources -- custom resource configuration - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - # operator.env -- additional environment variables for the deployment - env: [ ] - # - name: SAMPLE - # value: text -metrics: - image: - # metrics.image.repository -- image repository - repository: altinity/metrics-exporter - # metrics.image.tag -- image tag (chart's appVersion value will be used if not set) - tag: "" - # metrics.image.pullPolicy -- image pull policy - pullPolicy: IfNotPresent - # metrics.resources -- custom resource configuration - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - # metrics.env -- additional environment variables for the deployment - env: [ ] - # - name: SAMPLE - # value: text - -# imagePullSecrets -- image pull secret for private images -imagePullSecrets: [] -# nameOverride -- override name of the chart -nameOverride: "" -# fullnameOverride -- full name of the chart. -fullnameOverride: "" - -serviceAccount: - # serviceAccount.create -- specifies whether a service account should be created - create: true - # serviceAccount.annotations -- annotations to add to the service account - annotations: {} - # serviceAccount.name -- the name of the service account to use; if not set and create is true, a name is generated using the fullname template - name: - -# nodeSelector -- node for scheduler pod assignment -nodeSelector: {} - -# tolerations -- tolerations for scheduler pod assignment -tolerations: [] - -# affinity -- affinity for scheduler pod assignment -affinity: {} - -serviceMonitor: - # serviceMonitor.enabled -- ServiceMonitor CRD is created for a prometheus operator - enabled: false - # serviceMonitor.additionalLabels -- additional labels for service monitor - additionalLabels: {} - -# configs -- overrides operator default configmaps -configs: - confdFiles: null -# some-file: | -# ... - configdFiles: null -# some-file: | -# ... - files: null -# some-file: | -# ... - templatesdFiles: null -# some-file: | -# ... - usersdFiles: null -# some-file: | -# ... diff --git a/scripts/helmcharts/databases/charts/clickhouse/templates/clickhouse-cluster.yaml b/scripts/helmcharts/databases/charts/clickhouse/templates/clickhouse-cluster.yaml deleted file mode 100644 index 2093b503e..000000000 --- a/scripts/helmcharts/databases/charts/clickhouse/templates/clickhouse-cluster.yaml +++ /dev/null @@ -1,113 +0,0 @@ -apiVersion: "clickhouse.altinity.com/v1" -kind: "ClickHouseInstallation" - -metadata: - name: "openreplay-clickhouse" - -spec: - defaults: - templates: - dataVolumeClaimTemplate: default - podTemplate: clickhouse:19.6 - serviceTemplate: chi-service-template - - configuration: - # Ref: https://github.com/Altinity/clickhouse-operator/issues/823 - users: - default/networks/ip: "::/0" - zookeeper: - nodes: - - host: "{{ .Values.global.kafka.zookeeperHost }}" - port: {{ .Values.global.kafka.zookeeperNonTLSPort }} - clusters: - - name: replicated - layout: - shardsCount: {{ .Values.clickhouse.replicaCount }} - replicasCount: {{ .Values.clickhouse.shardsCount }} - - templates: - volumeClaimTemplates: - - name: default - reclaimPolicy: Retain - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "{{ .Values.storage.size }}" - podTemplates: - - name: clickhouse:19.6 - spec: - containers: - - name: clickhouse-pod - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - resources: - {{ toYaml .Values.resources | nindent 16 }} - nodeSelector: - {{- toYaml .Values.nodeSelector | nindent 12}} - tolerations: - {{- toYaml .Values.tolerations | nindent 12}} - # Ref: https://github.com/Altinity/clickhouse-operator/blob/master/docs/custom_resource_explained.md#spectemplatesservicetemplates - serviceTemplates: - - name: chi-service-template - # generateName understands different sets of macroses, - # depending on the level of the object, for which Service is being created: - # - # For CHI-level Service: - # 1. {chi} - ClickHouseInstallation name - # 2. {chiID} - short hashed ClickHouseInstallation name (BEWARE, this is an experimental feature) - # - # For Cluster-level Service: - # 1. {chi} - ClickHouseInstallation name - # 2. {chiID} - short hashed ClickHouseInstallation name (BEWARE, this is an experimental feature) - # 3. {cluster} - cluster name - # 4. {clusterID} - short hashed cluster name (BEWARE, this is an experimental feature) - # 5. {clusterIndex} - 0-based index of the cluster in the CHI (BEWARE, this is an experimental feature) - # - # For Shard-level Service: - # 1. {chi} - ClickHouseInstallation name - # 2. {chiID} - short hashed ClickHouseInstallation name (BEWARE, this is an experimental feature) - # 3. {cluster} - cluster name - # 4. {clusterID} - short hashed cluster name (BEWARE, this is an experimental feature) - # 5. {clusterIndex} - 0-based index of the cluster in the CHI (BEWARE, this is an experimental feature) - # 6. {shard} - shard name - # 7. {shardID} - short hashed shard name (BEWARE, this is an experimental feature) - # 8. {shardIndex} - 0-based index of the shard in the cluster (BEWARE, this is an experimental feature) - # - # For Replica-level Service: - # 1. {chi} - ClickHouseInstallation name - # 2. {chiID} - short hashed ClickHouseInstallation name (BEWARE, this is an experimental feature) - # 3. {cluster} - cluster name - # 4. {clusterID} - short hashed cluster name (BEWARE, this is an experimental feature) - # 5. {clusterIndex} - 0-based index of the cluster in the CHI (BEWARE, this is an experimental feature) - # 6. {shard} - shard name - # 7. {shardID} - short hashed shard name (BEWARE, this is an experimental feature) - # 8. {shardIndex} - 0-based index of the shard in the cluster (BEWARE, this is an experimental feature) - # 9. {replica} - replica name - # 10. {replicaID} - short hashed replica name (BEWARE, this is an experimental feature) - # 11. {replicaIndex} - 0-based index of the replica in the shard (BEWARE, this is an experimental feature) - generateName: "clickhouse-{chi}" - # type ObjectMeta struct from k8s.io/meta/v1 - metadata: - labels: - installation: "openreplay" - spec: - ports: - - name: http - port: 8123 - - name: client - port: 9000 - type: ClusterIP - - name: cluster-template - generateName: "clickhouse" - metadata: - labels: - installation: "openreplay" - spec: - ports: - - name: http - port: 8123 - - name: client - port: 9000 - type: ClusterIP - diff --git a/scripts/helmcharts/databases/charts/clickhouse/templates/cron.yaml b/scripts/helmcharts/databases/charts/clickhouse/templates/cron.yaml new file mode 100644 index 000000000..12f0d0903 --- /dev/null +++ b/scripts/helmcharts/databases/charts/clickhouse/templates/cron.yaml @@ -0,0 +1,35 @@ +# https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: clickhouse-backup + namespace: {{ .Release.Namespace }} +spec: + schedule: "5 11 * * */4" + jobTemplate: + spec: + backoffLimit: 0 # Don't restart the failed jobs + template: + spec: + containers: + - name: clickhouse-backup + image: alpine/curl + command: + - /bin/sh + - -c + args: + - | + set -x + BACKUP_NAME=openreplay_clickhouse_backup$(date -u +%Y-%m-%dT%H-%M-%S) + curl -XPOST http://localhost:7171/backup/create?name=$BACKUP_NAME + sleep 10 + # Upload backup + # curl -XPOST http://localhost:7171/backup/upload/$BACKUP_NAME + + # Get the backup status + echo "Backup Status:" + curl http://localhost:7171/backup/status?name=$BACKUP_NAME + # List active backups + echo "Active backup in machine" + curl http://localhost:7171/backup/list + restartPolicy: Never diff --git a/ee/scripts/helm/db/clickhouse/templates/service.yaml b/scripts/helmcharts/databases/charts/clickhouse/templates/service.yaml similarity index 75% rename from ee/scripts/helm/db/clickhouse/templates/service.yaml rename to scripts/helmcharts/databases/charts/clickhouse/templates/service.yaml index 4496f556c..cce1e8280 100644 --- a/ee/scripts/helm/db/clickhouse/templates/service.yaml +++ b/scripts/helmcharts/databases/charts/clickhouse/templates/service.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Service metadata: - name: clickhouse + name: clickhouse-openreplay-clickhouse labels: {{- include "clickhouse.labels" . | nindent 4 }} spec: @@ -15,5 +15,9 @@ spec: targetPort: data protocol: TCP name: data + - port: 7171 + targetPort: backup-web + protocol: TCP + name: backup-web selector: {{- include "clickhouse.selectorLabels" . | nindent 4 }} diff --git a/ee/scripts/helm/db/clickhouse/templates/serviceaccount.yaml b/scripts/helmcharts/databases/charts/clickhouse/templates/serviceaccount.yaml similarity index 100% rename from ee/scripts/helm/db/clickhouse/templates/serviceaccount.yaml rename to scripts/helmcharts/databases/charts/clickhouse/templates/serviceaccount.yaml diff --git a/ee/scripts/helm/helm/databases/charts/clickhouse/templates/statefulset.yaml b/scripts/helmcharts/databases/charts/clickhouse/templates/statefulset.yaml similarity index 68% rename from ee/scripts/helm/helm/databases/charts/clickhouse/templates/statefulset.yaml rename to scripts/helmcharts/databases/charts/clickhouse/templates/statefulset.yaml index 392976eec..4c8e8c04a 100644 --- a/ee/scripts/helm/helm/databases/charts/clickhouse/templates/statefulset.yaml +++ b/scripts/helmcharts/databases/charts/clickhouse/templates/statefulset.yaml @@ -27,6 +27,26 @@ spec: securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: + - name: {{ .Chart.Name }}-backup + env: + - name: API_LISTEN + value: "0.0.0.0:7171" + {{- range $key, $value := .Values.backupEnv }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.backupImage.repository }}:{{ .Values.backupImage.tag }}" + imagePullPolicy: {{ .Values.backupImage.pullPolicy }} + args: + - server + ports: + - containerPort: 7171 + name: backup-web + volumeMounts: + - name: default-chi-openreplay-clickhouse-replicated-0-0-0 + mountPath: /var/lib/clickhouse - name: {{ .Chart.Name }} env: {{- range $key, $value := .Values.env }} @@ -43,8 +63,8 @@ spec: - containerPort: 8123 name: data volumeMounts: - - name: ch-volume - mountPath: /var/lib/mydata + - name: default-chi-openreplay-clickhouse-replicated-0-0-0 + mountPath: /var/lib/clickhouse resources: {{- toYaml .Values.resources | nindent 12 }} {{- with .Values.nodeSelector }} @@ -61,7 +81,7 @@ spec: {{- end }} volumeClaimTemplates: - metadata: - name: ch-volume + name: default-chi-openreplay-clickhouse-replicated-0-0-0 spec: accessModes: [ "ReadWriteOnce" ] resources: diff --git a/scripts/helmcharts/databases/charts/clickhouse/values.yaml b/scripts/helmcharts/databases/charts/clickhouse/values.yaml index 438868c9c..cb7000070 100644 --- a/scripts/helmcharts/databases/charts/clickhouse/values.yaml +++ b/scripts/helmcharts/databases/charts/clickhouse/values.yaml @@ -1,18 +1,81 @@ +# Default values for clickhouse. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + image: repository: clickhouse/clickhouse-server - tag: "22.3" + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "22.2.2.1" -storage: - size: 200Gi +backupImage: + repository: alexakulov/clickhouse-backup + pullPolicy: IfNotPresent + tag: "latest" -clickhouse: - replicaCount: 1 - shardsCount: 1 +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +env: {} +backupEnv: + BACKUPS_TO_KEEP_LOCAL: "2" +# REMOTE_STORAGE=s3 +# S3_ACCESS_KEY=key +# S3_SECRET_KEY=password +# LOG_LEVEL=debug +# ALLOW_EMPTY_BACKUPS="true" +# API_LISTEN=0.0.0.0:7171 +# API_CREATE_INTEGRATION_TABLES="true" +# BACKUPS_TO_KEEP_REMOTE="3" +# S3_ACL=private +# S3_ENDPOINT=http://minio.db.svc.cluster.local:9000 +# S3_BUCKET=clickhouse +# S3_PATH=backup +# S3_FORCE_PATH_STYLE="true" +# S3_DISABLE_SSL="true" +# S3_DEBUG="true" + + +service: + webPort: 9000 + dataPort: 8123 resources: - limits: - cpu: 2 - memory: 8Gi requests: cpu: 1 memory: 4Gi + limits: + cpu: 2 + memory: 8Gi + +nodeSelector: {} + +tolerations: [] + +affinity: {} +storageSize: 100G diff --git a/scripts/helmcharts/databases/charts/postgresql/README.md b/scripts/helmcharts/databases/charts/postgresql/README.md index 8cdb2ca13..21a04c876 100755 --- a/scripts/helmcharts/databases/charts/postgresql/README.md +++ b/scripts/helmcharts/databases/charts/postgresql/README.md @@ -689,7 +689,7 @@ This operation could take some time depending on the database size. - Once you have the backup file, you can restore it with a command like the one below: ```console -$ psql -U postgres DATABASE_NAME < /tmp/backup.sql +$ psql -v ON_ERROR_STOP=1 -U postgres DATABASE_NAME < /tmp/backup.sql ``` In this case, you are accessing to the local postgresql, so the password should be the new one (you can find it in NOTES.txt). diff --git a/ee/scripts/helm/helm/databases/charts/kafka/.helmignore b/scripts/helmcharts/databases/charts/vault/.helmignore old mode 100755 new mode 100644 similarity index 83% rename from ee/scripts/helm/helm/databases/charts/kafka/.helmignore rename to scripts/helmcharts/databases/charts/vault/.helmignore index f0c131944..4007e2435 --- a/ee/scripts/helm/helm/databases/charts/kafka/.helmignore +++ b/scripts/helmcharts/databases/charts/vault/.helmignore @@ -5,6 +5,7 @@ # Common VCS dirs .git/ .gitignore +.terraform/ .bzr/ .bzrignore .hg/ @@ -19,3 +20,9 @@ .project .idea/ *.tmproj + +# CI and test +.circleci/ +.github/ +.gitlab-ci.yml +test/ diff --git a/scripts/helmcharts/databases/charts/vault/CHANGELOG.md b/scripts/helmcharts/databases/charts/vault/CHANGELOG.md new file mode 100644 index 000000000..df958007b --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/CHANGELOG.md @@ -0,0 +1,433 @@ +## Unreleased + +## 0.22.1 (October 26th, 2022) + +Changes: +* `vault` updated to 1.12.0 [GH-803](https://github.com/hashicorp/vault-helm/pull/803) +* `vault-k8s` updated to 1.0.1 [GH-803](https://github.com/hashicorp/vault-helm/pull/803) + +## 0.22.0 (September 8th, 2022) + +Features: +* Add PrometheusOperator support for collecting Vault server metrics. [GH-772](https://github.com/hashicorp/vault-helm/pull/772) + +Changes: +* `vault-k8s` to 1.0.0 [GH-784](https://github.com/hashicorp/vault-helm/pull/784) +* Test against Kubernetes 1.25 [GH-784](https://github.com/hashicorp/vault-helm/pull/784) +* `vault` updated to 1.11.3 [GH-785](https://github.com/hashicorp/vault-helm/pull/785) + +## 0.21.0 (August 10th, 2022) + +CHANGES: +* `vault-k8s` updated to 0.17.0. [GH-771](https://github.com/hashicorp/vault-helm/pull/771) +* `vault-csi-provider` updated to 1.2.0 [GH-771](https://github.com/hashicorp/vault-helm/pull/771) +* `vault` updated to 1.11.2 [GH-771](https://github.com/hashicorp/vault-helm/pull/771) +* Start testing against Kubernetes 1.24. [GH-744](https://github.com/hashicorp/vault-helm/pull/744) +* Deprecated `injector.externalVaultAddr`. Added `global.externalVaultAddr`, which applies to both the Injector and the CSI Provider. [GH-745](https://github.com/hashicorp/vault-helm/pull/745) +* CSI Provider pods now set the `VAULT_ADDR` environment variable to either the internal Vault service or the configured external address. [GH-745](https://github.com/hashicorp/vault-helm/pull/745) + +Features: +* server: Add `server.statefulSet.securityContext` to override pod and container `securityContext`. [GH-767](https://github.com/hashicorp/vault-helm/pull/767) +* csi: Add `csi.daemonSet.securityContext` to override pod and container `securityContext`. [GH-767](https://github.com/hashicorp/vault-helm/pull/767) +* injector: Add `injector.securityContext` to override pod and container `securityContext`. [GH-750](https://github.com/hashicorp/vault-helm/pull/750) and [GH-767](https://github.com/hashicorp/vault-helm/pull/767) +* Add `server.service.activeNodePort` and `server.service.standbyNodePort` to specify the `nodePort` for active and standby services. [GH-610](https://github.com/hashicorp/vault-helm/pull/610) +* Support for setting annotations on the injector's serviceAccount [GH-753](https://github.com/hashicorp/vault-helm/pull/753) + +## 0.20.1 (May 25th, 2022) +CHANGES: +* `vault-k8s` updated to 0.16.1 [GH-739](https://github.com/hashicorp/vault-helm/pull/739) + +Improvements: +* Mutating webhook will no longer target the agent injector pod [GH-736](https://github.com/hashicorp/vault-helm/pull/736) + +Bugs: +* `vault` service account is now created even if the server is set to disabled, as per before 0.20.0 [GH-737](https://github.com/hashicorp/vault-helm/pull/737) + +## 0.20.0 (May 16th, 2022) + +CHANGES: +* `global.enabled` now works as documented, that is, setting `global.enabled` to false will disable everything, with individual components able to be turned on individually [GH-703](https://github.com/hashicorp/vault-helm/pull/703) +* Default value of `-` used for injector and server to indicate that they follow `global.enabled`. [GH-703](https://github.com/hashicorp/vault-helm/pull/703) +* Vault default image to 1.10.3 +* CSI provider default image to 1.1.0 +* Vault K8s default image to 0.16.0 +* Earliest Kubernetes version tested is now 1.16 +* Helm 3.6+ now required + +Features: +* Support topologySpreadConstraints in server and injector. [GH-652](https://github.com/hashicorp/vault-helm/pull/652) + +Improvements: +* CSI: Set `extraLabels` for daemonset, pods, and service account [GH-690](https://github.com/hashicorp/vault-helm/pull/690) +* Add namespace to injector-leader-elector role, rolebinding and secret [GH-683](https://github.com/hashicorp/vault-helm/pull/683) +* Support policy/v1 PodDisruptionBudget in Kubernetes 1.21+ for server and injector [GH-710](https://github.com/hashicorp/vault-helm/pull/710) +* Make the Cluster Address (CLUSTER_ADDR) configurable [GH-629](https://github.com/hashicorp/vault-helm/pull/709) +* server: Make `publishNotReadyAddresses` configurable for services [GH-694](https://github.com/hashicorp/vault-helm/pull/694) +* server: Allow config to be defined as a YAML object in the values file [GH-684](https://github.com/hashicorp/vault-helm/pull/684) +* Maintain default MutatingWebhookConfiguration values from `v1beta1` [GH-692](https://github.com/hashicorp/vault-helm/pull/692) + +## 0.19.0 (January 20th, 2022) + +CHANGES: +* Vault image default 1.9.2 +* Vault K8s image default 0.14.2 + +Features: +* Added configurable podDisruptionBudget for injector [GH-653](https://github.com/hashicorp/vault-helm/pull/653) +* Make terminationGracePeriodSeconds configurable for server [GH-659](https://github.com/hashicorp/vault-helm/pull/659) +* Added configurable update strategy for injector [GH-661](https://github.com/hashicorp/vault-helm/pull/661) +* csi: ability to set priorityClassName for CSI daemonset pods [GH-670](https://github.com/hashicorp/vault-helm/pull/670) + +Improvements: +* Set the namespace on the OpenShift Route [GH-679](https://github.com/hashicorp/vault-helm/pull/679) +* Add volumes and env vars to helm hook test pod [GH-673](https://github.com/hashicorp/vault-helm/pull/673) +* Make TLS configurable for OpenShift routes [GH-686](https://github.com/hashicorp/vault-helm/pull/686) + +## 0.18.0 (November 17th, 2021) + +CHANGES: +* Removed support for deploying a leader-elector container with the [vault-k8s injector](https://github.com/hashicorp/vault-k8s) injector since vault-k8s now uses an internal mechanism to determine leadership [GH-649](https://github.com/hashicorp/vault-helm/pull/649) +* Vault image default 1.9.0 +* Vault K8s image default 0.14.1 + +Improvements: +* Added templateConfig.staticSecretRenderInterval chart option for the injector [GH-621](https://github.com/hashicorp/vault-helm/pull/621) + +## 0.17.1 (October 25th, 2021) + +Improvements: + * Add option for Ingress PathType [GH-634](https://github.com/hashicorp/vault-helm/pull/634) + +## 0.17.0 (October 21st, 2021) + +KNOWN ISSUES: +* The chart will fail to deploy on Kubernetes 1.19+ with `server.ingress.enabled=true` because no `pathType` is set + +CHANGES: +* Vault image default 1.8.4 +* Vault K8s image default 0.14.0 + +Improvements: +* Support Ingress stable networking API [GH-590](https://github.com/hashicorp/vault-helm/pull/590) +* Support setting the `externalTrafficPolicy` for `LoadBalancer` and `NodePort` service types [GH-626](https://github.com/hashicorp/vault-helm/pull/626) +* Support setting ingressClassName on server Ingress [GH-630](https://github.com/hashicorp/vault-helm/pull/630) + +Bugs: +* Ensure `kubeletRootDir` volume path and mounts are the same when `csi.daemonSet.kubeletRootDir` is overridden [GH-628](https://github.com/hashicorp/vault-helm/pull/628) + +## 0.16.1 (September 29th, 2021) + +CHANGES: +* Vault image default 1.8.3 +* Vault K8s image default 0.13.1 + +## 0.16.0 (September 16th, 2021) + +CHANGES: +* Support for deploying a leader-elector container with the [vault-k8s injector](https://github.com/hashicorp/vault-k8s) injector will be removed in version 0.18.0 of this chart since vault-k8s now uses an internal mechanism to determine leadership. To enable the deployment of the leader-elector container for use with vault-k8s 0.12.0 and earlier, set `useContainer=true`. + +Improvements: + * Make CSI provider `hostPaths` configurable via `csi.daemonSet.providersDir` and `csi.daemonSet.kubeletRootDir` [GH-603](https://github.com/hashicorp/vault-helm/pull/603) + * Support vault-k8s internal leader election [GH-568](https://github.com/hashicorp/vault-helm/pull/568) [GH-607](https://github.com/hashicorp/vault-helm/pull/607) + +## 0.15.0 (August 23rd, 2021) + +Improvements: +* Add imagePullSecrets on server test [GH-572](https://github.com/hashicorp/vault-helm/pull/572) +* Add injector.webhookAnnotations chart option [GH-584](https://github.com/hashicorp/vault-helm/pull/584) + +## 0.14.0 (July 28th, 2021) + +Features: +* Added templateConfig.exitOnRetryFailure chart option for the injector [GH-560](https://github.com/hashicorp/vault-helm/pull/560) + +Improvements: +* Support configuring pod tolerations, pod affinity, and node selectors as YAML [GH-565](https://github.com/hashicorp/vault-helm/pull/565) +* Set the default vault image to come from the hashicorp organization [GH-567](https://github.com/hashicorp/vault-helm/pull/567) +* Add support for running the acceptance tests against a local `kind` cluster [GH-567](https://github.com/hashicorp/vault-helm/pull/567) +* Add `server.ingress.activeService` to configure if the ingress should use the active service [GH-570](https://github.com/hashicorp/vault-helm/pull/570) +* Add `server.route.activeService` to configure if the route should use the active service [GH-570](https://github.com/hashicorp/vault-helm/pull/570) +* Support configuring `global.imagePullSecrets` from a string array [GH-576](https://github.com/hashicorp/vault-helm/pull/576) + + +## 0.13.0 (June 17th, 2021) + +Improvements: +* Added a helm test for vault server [GH-531](https://github.com/hashicorp/vault-helm/pull/531) +* Added server.enterpriseLicense option [GH-547](https://github.com/hashicorp/vault-helm/pull/547) +* Added OpenShift overrides [GH-549](https://github.com/hashicorp/vault-helm/pull/549) + +Bugs: +* Fix ui.serviceNodePort schema [GH-537](https://github.com/hashicorp/vault-helm/pull/537) +* Fix server.ha.disruptionBudget.maxUnavailable schema [GH-535](https://github.com/hashicorp/vault-helm/pull/535) +* Added webhook-certs volume mount to sidecar injector [GH-545](https://github.com/hashicorp/vault-helm/pull/545) + +## 0.12.0 (May 25th, 2021) + +Features: +* Pass additional arguments to `vault-csi-provider` using `csi.extraArgs` [GH-526](https://github.com/hashicorp/vault-helm/pull/526) + +Improvements: +* Set chart kubeVersion and added chart-verifier tests [GH-510](https://github.com/hashicorp/vault-helm/pull/510) +* Added values json schema [GH-513](https://github.com/hashicorp/vault-helm/pull/513) +* Ability to set tolerations for CSI daemonset pods [GH-521](https://github.com/hashicorp/vault-helm/pull/521) +* UI target port is now configurable [GH-437](https://github.com/hashicorp/vault-helm/pull/437) + +Bugs: +* CSI: `global.imagePullSecrets` are now also used for CSI daemonset [GH-519](https://github.com/hashicorp/vault-helm/pull/519) + +## 0.11.0 (April 14th, 2021) + +Features: +* Added `server.enabled` to explicitly skip installing a Vault server [GH-486](https://github.com/hashicorp/vault-helm/pull/486) +* Injector now supports enabling host network [GH-471](https://github.com/hashicorp/vault-helm/pull/471) +* Injector port is now configurable [GH-489](https://github.com/hashicorp/vault-helm/pull/489) +* Injector Vault Agent resource defaults are now configurable [GH-493](https://github.com/hashicorp/vault-helm/pull/493) +* Extra paths can now be added to the Vault ingress service [GH-460](https://github.com/hashicorp/vault-helm/pull/460) +* Log level and format can now be set directly using `server.logFormat` and `server.logLevel` [GH-488](https://github.com/hashicorp/vault-helm/pull/488) + +Improvements: +* Added `https` name to injector service port [GH-495](https://github.com/hashicorp/vault-helm/pull/495) + +Bugs: +* CSI: Fix ClusterRole name and DaemonSet's service account to properly match deployment name [GH-486](https://github.com/hashicorp/vault-helm/pull/486) + +## 0.10.0 (March 25th, 2021) + +Features: +* Add support for [Vault CSI provider](https://github.com/hashicorp/vault-csi-provider) [GH-461](https://github.com/hashicorp/vault-helm/pull/461) + +Improvements: +* `objectSelector` can now be set on the mutating admission webhook [GH-456](https://github.com/hashicorp/vault-helm/pull/456) + +## 0.9.1 (February 2nd, 2021) + +Bugs: +* Injector: fix labels for default anti-affinity rule [GH-441](https://github.com/hashicorp/vault-helm/pull/441), [GH-442](https://github.com/hashicorp/vault-helm/pull/442) +* Set VAULT_DEV_LISTEN_ADDRESS in dev mode [GH-446](https://github.com/hashicorp/vault-helm/pull/446) + +## 0.9.0 (January 5th, 2021) + +Features: +* Injector now supports configurable number of replicas [GH-436](https://github.com/hashicorp/vault-helm/pull/436) +* Injector now supports auto TLS for multiple replicas using leader elections [GH-436](https://github.com/hashicorp/vault-helm/pull/436) + +Improvements: +* Dev mode now supports `server.extraArgs` [GH-421](https://github.com/hashicorp/vault-helm/pull/421) +* Dev mode root token is now configurable with `server.dev.devRootToken` [GH-415](https://github.com/hashicorp/vault-helm/pull/415) +* ClusterRoleBinding updated to `v1` [GH-395](https://github.com/hashicorp/vault-helm/pull/395) +* MutatingWebhook updated to `v1` [GH-408](https://github.com/hashicorp/vault-helm/pull/408) +* Injector service now supports `injector.service.annotations` [425](https://github.com/hashicorp/vault-helm/pull/425) +* Injector now supports `injector.extraLabels` [428](https://github.com/hashicorp/vault-helm/pull/428) +* Added `allowPrivilegeEscalation: false` to Vault and Injector containers [429](https://github.com/hashicorp/vault-helm/pull/429) +* Network Policy now supports `server.networkPolicy.egress` [389](https://github.com/hashicorp/vault-helm/pull/389) + +## 0.8.0 (October 20th, 2020) + +Improvements: +* Make server NetworkPolicy independent of OpenShift [GH-381](https://github.com/hashicorp/vault-helm/pull/381) +* Added configurables for all probe values [GH-387](https://github.com/hashicorp/vault-helm/pull/387) +* MountPath for audit and data storage is now configurable [GH-393](https://github.com/hashicorp/vault-helm/pull/393) +* Annotations can now be added to the Injector pods [GH-394](https://github.com/hashicorp/vault-helm/pull/394) +* The injector can now be configured with a failurePolicy [GH-400](https://github.com/hashicorp/vault-helm/pull/400) +* Added additional environment variables for rendering within Vault config [GH-398](https://github.com/hashicorp/vault-helm/pull/398) +* Service account for Vault K8s auth is automatically created when `injector.externalVaultAddr` is set [GH-392](https://github.com/hashicorp/vault-helm/pull/392) + +Bugs: +* Fixed install output using Helm V2 command [GH-378](https://github.com/hashicorp/vault-helm/pull/378) + +## 0.7.0 (August 24th, 2020) + +Features: +* Added `volumes` and `volumeMounts` for mounting _any_ type of volume [GH-314](https://github.com/hashicorp/vault-helm/pull/314). +* Added configurable to enable prometheus telemetery exporter for Vault Agent Injector [GH-372](https://github.com/hashicorp/vault-helm/pull/372) + +Improvements: +* Added `defaultMode` configurable to `extraVolumes`[GH-321](https://github.com/hashicorp/vault-helm/pull/321) +* Option to install and use PodSecurityPolicy's for vault server and injector [GH-177](https://github.com/hashicorp/vault-helm/pull/177) +* `VAULT_API_ADDR` is now configurable [GH-290](https://github.com/hashicorp/vault-helm/pull/290) +* Removed deprecated tolerate unready endpoint annotations [GH-363](https://github.com/hashicorp/vault-helm/pull/363) +* Add an option to set annotations on the StatefulSet [GH-199](https://github.com/hashicorp/vault-helm/pull/199) +* Make the vault server serviceAccount name a configuration option [GH-367](https://github.com/hashicorp/vault-helm/pull/367) +* Removed annotation striction from `dev` mode [GH-371](https://github.com/hashicorp/vault-helm/pull/371) +* Add an option to set annotations on PVCs [GH-364](https://github.com/hashicorp/vault-helm/pull/364) +* Added service configurables for UI [GH-285](https://github.com/hashicorp/vault-helm/pull/285) + +Bugs: +* Fix python dependency in test image [GH-337](https://github.com/hashicorp/vault-helm/pull/337) +* Fix caBundle not being quoted causing validation issues with Helm 3 [GH-352](https://github.com/hashicorp/vault-helm/pull/352) +* Fix injector network policy being rendered when injector is not enabled [GH-358](https://github.com/hashicorp/vault-helm/pull/358) + +## 0.6.0 (June 3rd, 2020) + +Features: +* Added `extraInitContainers` to define init containers for the Vault cluster [GH-258](https://github.com/hashicorp/vault-helm/pull/258) +* Added `postStart` lifecycle hook allowing users to configure commands to run on the Vault pods after they're ready [GH-315](https://github.com/hashicorp/vault-helm/pull/315) +* Beta: Added OpenShift support [GH-319](https://github.com/hashicorp/vault-helm/pull/319) + +Improvements: +* Server configs can now be defined in YAML. Multi-line string configs are still compatible [GH-213](https://github.com/hashicorp/vault-helm/pull/213) +* Removed IPC_LOCK privileges since swap is disabled on containers [[GH-198](https://github.com/hashicorp/vault-helm/pull/198)] +* Use port names that map to vault.scheme [[GH-223](https://github.com/hashicorp/vault-helm/pull/223)] +* Allow both yaml and multi-line string annotations [[GH-272](https://github.com/hashicorp/vault-helm/pull/272)] +* Added configurable to set the Raft node name to hostname [[GH-269](https://github.com/hashicorp/vault-helm/pull/269)] +* Support setting priorityClassName on pods [[GH-282](https://github.com/hashicorp/vault-helm/pull/282)] +* Added support for ingress apiVersion `networking.k8s.io/v1beta1` [[GH-310](https://github.com/hashicorp/vault-helm/pull/310)] +* Added configurable to change service type for the HA active service [GH-317](https://github.com/hashicorp/vault-helm/pull/317) + +Bugs: +* Fixed default ingress path [[GH-224](https://github.com/hashicorp/vault-helm/pull/224)] +* Fixed annotations for HA standby/active services [[GH-268](https://github.com/hashicorp/vault-helm/pull/268)] +* Updated some value defaults to match their use in templates [[GH-309](https://github.com/hashicorp/vault-helm/pull/309)] +* Use active service on ingress when ha [[GH-270](https://github.com/hashicorp/vault-helm/pull/270)] +* Fixed bug where pull secrets weren't being used for injector image [GH-298](https://github.com/hashicorp/vault-helm/pull/298) + +## 0.5.0 (April 9th, 2020) + +Features: + +* Added Raft support for HA mode [[GH-228](https://github.com/hashicorp/vault-helm/pull/229)] +* Now supports Vault Enterprise [[GH-250](https://github.com/hashicorp/vault-helm/pull/250)] +* Added K8s Service Registration for HA modes [[GH-250](https://github.com/hashicorp/vault-helm/pull/250)] + +* Option to set `AGENT_INJECT_VAULT_AUTH_PATH` for the injector [[GH-185](https://github.com/hashicorp/vault-helm/pull/185)] +* Added environment variables for logging and revocation on Vault Agent Injector [[GH-219](https://github.com/hashicorp/vault-helm/pull/219)] +* Option to set environment variables for the injector deployment [[GH-232](https://github.com/hashicorp/vault-helm/pull/232)] +* Added affinity, tolerations, and nodeSelector options for the injector deployment [[GH-234](https://github.com/hashicorp/vault-helm/pull/234)] +* Made all annotations multi-line strings [[GH-227](https://github.com/hashicorp/vault-helm/pull/227)] + +## 0.4.0 (February 21st, 2020) + +Improvements: + +* Allow process namespace sharing between Vault and sidecar containers [[GH-174](https://github.com/hashicorp/vault-helm/pull/174)] +* Added configurable to change updateStrategy [[GH-172](https://github.com/hashicorp/vault-helm/pull/172)] +* Added sleep in the preStop lifecycle step [[GH-188](https://github.com/hashicorp/vault-helm/pull/188)] +* Updated chart and tests to Helm 3 [[GH-195](https://github.com/hashicorp/vault-helm/pull/195)] +* Adds Values.injector.externalVaultAddr to use the injector with an external vault [[GH-207](https://github.com/hashicorp/vault-helm/pull/207)] + +Bugs: + +* Fix bug where Vault lifecycle was appended after extra containers. [[GH-179](https://github.com/hashicorp/vault-helm/pull/179)] + +## 0.3.3 (January 14th, 2020) + +Security: + +* Added `server.extraArgs` to allow loading of additional Vault configurations containing sensitive settings [GH-175](https://github.com/hashicorp/vault-helm/issues/175) + +Bugs: + +* Fixed injection bug where wrong environment variables were being used for manually mounted TLS files + +## 0.3.2 (January 8th, 2020) + +Bugs: + +* Fixed injection bug where TLS Skip Verify was true by default [VK8S-35] + +## 0.3.1 (January 2nd, 2020) + +Bugs: + +* Fixed injection bug causing kube-system pods to be rejected [VK8S-14] + +## 0.3.0 (December 19th, 2019) + +Features: + +* Extra containers can now be added to the Vault pods +* Added configurability of pod probes +* Added Vault Agent Injector + +Improvements: + +* Moved `global.image` to `server.image` +* Changed UI service template to route pods that aren't ready via `publishNotReadyAddresses: true` +* Added better HTTP/HTTPS scheme support to http probes +* Added configurable node port for Vault service +* `server.authDelegator` is now enabled by default + +Bugs: + +* Fixed upgrade bug by removing chart label which contained the version +* Fixed typo on `serviceAccount` (was `serviceaccount`) +* Fixed readiness/liveliness HTTP probe default to accept standbys + +## 0.2.1 (November 12th, 2019) + +Bugs: + +* Removed `readOnlyRootFilesystem` causing issues when validating deployments + +## 0.2.0 (October 29th, 2019) + +Features: + +* Added load balancer support +* Added ingress support +* Added configurable for service types (ClusterIP, NodePort, LoadBalancer, etc) +* Removed root requirements, now runs as Vault user + +Improvements: + +* Added namespace value to all rendered objects +* Made ports configurable in services +* Added the ability to add custom annotations to services +* Added docker image for running bats test in CircleCI +* Removed restrictions around `dev` mode such as annotations +* `readOnlyRootFilesystem` is now configurable +* Image Pull Policy is now configurable + +Bugs: + +* Fixed selector bugs related to Helm label updates (services, affinities, and pod disruption) +* Fixed bug where audit storage was not being mounted in HA mode +* Fixed bug where Vault pod wasn't receiving SIGTERM signals + + +## 0.1.2 (August 22nd, 2019) + +Features: + +* Added `extraSecretEnvironmentVars` to allow users to mount secrets as + environment variables +* Added `tlsDisable` configurable to change HTTP protocols from HTTP/HTTPS + depending on the value +* Added `serviceNodePort` to configure a NodePort value when setting `serviceType` + to "NodePort" + +Improvements: + +* Changed UI port to 8200 for better HTTP protocol support +* Added `path` to `extraVolumes` to define where the volume should be + mounted. Defaults to `/vault/userconfig` +* Upgraded Vault to 1.2.2 + +Bugs: + +* Fixed bug where upgrade would fail because immutable labels were being + changed (Helm Version label) +* Fixed bug where UI service used wrong selector after updating helm labels +* Added `VAULT_API_ADDR` env to Vault pod to fixed bug where Vault thinks + Consul is the active node +* Removed `step-down` preStop since it requires authentication. Shutdown signal + sent by Kube acts similar to `step-down` + + +## 0.1.1 (August 7th, 2019) + +Features: + +* Added `authDelegator` Cluster Role Binding to Vault service account for + bootstrapping Kube auth method + +Improvements: + +* Added `server.service.clusterIP` to `values.yml` so users can toggle + the Vault service to headless by using the value `None`. +* Upgraded Vault to 1.2.1 + +## 0.1.0 (August 6th, 2019) + +Initial release diff --git a/scripts/helmcharts/databases/charts/vault/CONTRIBUTING.md b/scripts/helmcharts/databases/charts/vault/CONTRIBUTING.md new file mode 100644 index 000000000..ad31ac92d --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/CONTRIBUTING.md @@ -0,0 +1,247 @@ +# Contributing to Vault Helm + +**Please note:** We take Vault's security and our users' trust very seriously. +If you believe you have found a security issue in Vault, please responsibly +disclose by contacting us at security@hashicorp.com. + +**First:** if you're unsure or afraid of _anything_, just ask or submit the +issue or pull request anyways. You won't be yelled at for giving it your best +effort. The worst that can happen is that you'll be politely asked to change +something. We appreciate any sort of contributions, and don't want a wall of +rules to get in the way of that. + +That said, if you want to ensure that a pull request is likely to be merged, +talk to us! You can find out our thoughts and ensure that your contribution +won't clash or be obviated by Vault's normal direction. A great way to do this +is via the [Vault Discussion Forum][1]. + +This document will cover what we're looking for in terms of reporting issues. +By addressing all the points we're looking for, it raises the chances we can +quickly merge or address your contributions. + +[1]: https://discuss.hashicorp.com/c/vault + +## Issues + +### Reporting an Issue + +* Make sure you test against the latest released version. It is possible + we already fixed the bug you're experiencing. Even better is if you can test + against `main`, as bugs are fixed regularly but new versions are only + released every few months. + +* Provide steps to reproduce the issue, and if possible include the expected + results as well as the actual results. Please provide text, not screen shots! + +* Respond as promptly as possible to any questions made by the Vault + team to your issue. Stale issues will be closed periodically. + +### Issue Lifecycle + +1. The issue is reported. + +2. The issue is verified and categorized by a Vault Helm collaborator. + Categorization is done via tags. For example, bugs are marked as "bugs". + +3. Unless it is critical, the issue may be left for a period of time (sometimes + many weeks), giving outside contributors -- maybe you!? -- a chance to + address the issue. + +4. The issue is addressed in a pull request or commit. The issue will be + referenced in the commit message so that the code that fixes it is clearly + linked. + +5. The issue is closed. Sometimes, valid issues will be closed to keep + the issue tracker clean. The issue is still indexed and available for + future viewers, or can be re-opened if necessary. + +## Testing + +The Helm chart ships with both unit and acceptance tests. + +The unit tests don't require any active Kubernetes cluster and complete +very quickly. These should be used for fast feedback during development. +The acceptance tests require a Kubernetes cluster with a configured `kubectl`. + +### Test Using Docker Container + +The following are the instructions for running bats tests using a Docker container. + +#### Prerequisites + +* Docker installed +* `vault-helm` checked out locally + +#### Test + +**Note:** the following commands should be run from the `vault-helm` directory. + +First, build the Docker image for running the tests: + +```shell +docker build -f ${PWD}/test/docker/Test.dockerfile ${PWD}/test/docker/ -t vault-helm-test +``` +Next, execute the tests with the following commands: +```shell +docker run -it --rm -v "${PWD}:/test" vault-helm-test bats /test/test/unit +``` +It's possible to only run specific bats tests using regular expressions. +For example, the following will run only tests with "injector" in the name: +```shell +docker run -it --rm -v "${PWD}:/test" vault-helm-test bats /test/test/unit -f "injector" +``` + +### Test Manually +The following are the instructions for running bats tests on your workstation. +#### Prerequisites +* [Bats](https://github.com/bats-core/bats-core) + ```bash + brew install bats-core + ``` +* [yq](https://pypi.org/project/yq/) + ```bash + brew install python-yq + ``` +* [helm](https://helm.sh) + ```bash + brew install kubernetes-helm + ``` + +#### Test + +To run the unit tests: + + bats ./test/unit + +To run the acceptance tests: + + bats ./test/acceptance + +If the acceptance tests fail, deployed resources in the Kubernetes cluster +may not be properly cleaned up. We recommend recycling the Kubernetes cluster to +start from a clean slate. + +**Note:** There is a Terraform configuration in the +[`test/terraform/`](https://github.com/hashicorp/vault-helm/tree/main/test/terraform) directory +that can be used to quickly bring up a GKE cluster and configure +`kubectl` and `helm` locally. This can be used to quickly spin up a test +cluster for acceptance tests. Unit tests _do not_ require a running Kubernetes +cluster. + +### Writing Unit Tests + +Changes to the Helm chart should be accompanied by appropriate unit tests. + +#### Formatting + +- Put tests in the test file in the same order as the variables appear in the `values.yaml`. +- Start tests for a chart value with a header that says what is being tested, like this: + ``` + #-------------------------------------------------------------------- + # annotations + ``` + +- Name the test based on what it's testing in the following format (this will be its first line): + ``` + @test "<section being tested>: <short description of the test case>" { + ``` + + When adding tests to an existing file, the first section will be the same as the other tests in the file. + +#### Test Details + +[Bats](https://github.com/bats-core/bats-core) provides a way to run commands in a shell and inspect the output in an automated way. +In all of the tests in this repo, the base command being run is [helm template](https://docs.helm.sh/helm/#helm-template) which turns the templated files into straight yaml output. +In this way, we're able to test that the various conditionals in the templates render as we would expect. + +Each test defines the files that should be rendered using the `--show-only` flag, then it might adjust chart values by adding `--set` flags as well. +The output from this `helm template` command is then piped to [yq](https://pypi.org/project/yq/). +`yq` allows us to pull out just the information we're interested in, either by referencing its position in the yaml file directly or giving information about it (like its length). +The `-r` flag can be used with `yq` to return a raw string instead of a quoted one which is especially useful when looking for an exact match. + +The test passes or fails based on the conditional at the end that is in square brackets, which is a comparison of our expected value and the output of `helm template` piped to `yq`. + +The `| tee /dev/stderr ` pieces direct any terminal output of the `helm template` and `yq` commands to stderr so that it doesn't interfere with `bats`. + +#### Test Examples + +Here are some examples of common test patterns: + +- Check that a value is disabled by default + + ``` + @test "ui/Service: no type by default" { + cd `chart_dir` + local actual=$(helm template \ + --show-only templates/ui-service.yaml \ + . | tee /dev/stderr | + yq -r '.spec.type' | tee /dev/stderr) + [ "${actual}" = "null" ] + } + ``` + + In this example, nothing is changed from the default templates (no `--set` flags), then we use `yq` to retrieve the value we're checking, `.spec.type`. + This output is then compared against our expected value (`null` in this case) in the assertion `[ "${actual}" = "null" ]`. + + +- Check that a template value is rendered to a specific value + ``` + @test "ui/Service: specified type" { + cd `chart_dir` + local actual=$(helm template \ + --show-only templates/ui-service.yaml \ + --set 'ui.serviceType=LoadBalancer' \ + . | tee /dev/stderr | + yq -r '.spec.type' | tee /dev/stderr) + [ "${actual}" = "LoadBalancer" ] + } + ``` + + This is very similar to the last example, except we've changed a default value with the `--set` flag and correspondingly changed the expected value. + +- Check that a template value contains several values + ``` + @test "server/standalone-StatefulSet: custom resources" { + cd `chart_dir` + local actual=$(helm template \ + --show-only templates/server-statefulset.yaml \ + --set 'server.standalone.enabled=true' \ + --set 'server.resources.requests.memory=256Mi' \ + --set 'server.resources.requests.cpu=250m' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].resources.requests.memory' | tee /dev/stderr) + [ "${actual}" = "256Mi" ] + + local actual=$(helm template \ + --show-only templates/server-statefulset.yaml \ + --set 'server.standalone.enabled=true' \ + --set 'server.resources.limits.memory=256Mi' \ + --set 'server.resources.limits.cpu=250m' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].resources.limits.memory' | tee /dev/stderr) + [ "${actual}" = "256Mi" ] + ``` + + *Note:* If testing more than two conditions, it would be good to separate the `helm template` part of the command from the `yq` sections to reduce redundant work. + +- Check that an entire template file is not rendered + ``` + @test "syncCatalog/Deployment: disabled by default" { + cd `chart_dir` + local actual=$( (helm template \ + --show-only templates/server-statefulset.yaml \ + --set 'global.enabled=false' \ + . || echo "---") | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "false" ] + } + ``` + Here we are check the length of the command output to see if the anything is rendered. + This style can easily be switched to check that a file is rendered instead. + +## Contributor License Agreement + +We require that all contributors sign our Contributor License Agreement ("CLA") +before we can accept the contribution. + +[Learn more about why HashiCorp requires a CLA and what the CLA includes](https://www.hashicorp.com/cla) diff --git a/scripts/helmcharts/databases/charts/vault/Chart.yaml b/scripts/helmcharts/databases/charts/vault/Chart.yaml new file mode 100644 index 000000000..ac1dcece8 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +appVersion: 1.12.0 +description: Official HashiCorp Vault Chart +home: https://www.vaultproject.io +icon: https://github.com/hashicorp/vault/raw/f22d202cde2018f9455dec755118a9b84586e082/Vault_PrimaryLogo_Black.png +keywords: +- vault +- security +- encryption +- secrets +- management +- automation +- infrastructure +kubeVersion: '>= 1.16.0-0' +name: vault +sources: +- https://github.com/hashicorp/vault +- https://github.com/hashicorp/vault-helm +- https://github.com/hashicorp/vault-k8s +- https://github.com/hashicorp/vault-csi-provider +version: 0.22.1 diff --git a/scripts/helmcharts/databases/charts/vault/LICENSE b/scripts/helmcharts/databases/charts/vault/LICENSE new file mode 100644 index 000000000..74f38c010 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/LICENSE @@ -0,0 +1,355 @@ +Copyright (c) 2018 HashiCorp, Inc. + +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. diff --git a/scripts/helmcharts/databases/charts/vault/Makefile b/scripts/helmcharts/databases/charts/vault/Makefile new file mode 100644 index 000000000..e423f3529 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/Makefile @@ -0,0 +1,101 @@ +TEST_IMAGE?=vault-helm-test +GOOGLE_CREDENTIALS?=vault-helm-test.json +CLOUDSDK_CORE_PROJECT?=vault-helm-dev-246514 +# set to run a single test - e.g acceptance/server-ha-enterprise-dr.bats +ACCEPTANCE_TESTS?=acceptance + +# filter bats unit tests to run. +UNIT_TESTS_FILTER?='.*' + +# set to 'true' to run acceptance tests locally in a kind cluster +LOCAL_ACCEPTANCE_TESTS?=false + +# kind cluster name +KIND_CLUSTER_NAME?=vault-helm + +# kind k8s version +KIND_K8S_VERSION?=v1.25.0 + +# Generate json schema for chart values. See test/README.md for more details. +values-schema: + helm schema-gen values.yaml > values.schema.json + +test-image: + @docker build --rm -t $(TEST_IMAGE) -f $(CURDIR)/test/docker/Test.dockerfile $(CURDIR) + +test-unit: + @docker run --rm -it -v ${PWD}:/helm-test $(TEST_IMAGE) bats -f $(UNIT_TESTS_FILTER) /helm-test/test/unit + +test-bats: test-unit test-acceptance + +test: test-image test-bats + +# run acceptance tests on GKE +# set google project/credential vars above +test-acceptance: +ifeq ($(LOCAL_ACCEPTANCE_TESTS),true) + make setup-kind acceptance +else + @docker run -it -v ${PWD}:/helm-test \ + -e GOOGLE_CREDENTIALS=${GOOGLE_CREDENTIALS} \ + -e CLOUDSDK_CORE_PROJECT=${CLOUDSDK_CORE_PROJECT} \ + -e KUBECONFIG=/helm-test/.kube/config \ + -e VAULT_LICENSE_CI=${VAULT_LICENSE_CI} \ + -w /helm-test \ + $(TEST_IMAGE) \ + make acceptance +endif + +# destroy GKE cluster using terraform +test-destroy: + @docker run -it -v ${PWD}:/helm-test \ + -e GOOGLE_CREDENTIALS=${GOOGLE_CREDENTIALS} \ + -e CLOUDSDK_CORE_PROJECT=${CLOUDSDK_CORE_PROJECT} \ + -w /helm-test \ + $(TEST_IMAGE) \ + make destroy-cluster + +# provision GKE cluster using terraform +test-provision: + @docker run -it -v ${PWD}:/helm-test \ + -e GOOGLE_CREDENTIALS=${GOOGLE_CREDENTIALS} \ + -e CLOUDSDK_CORE_PROJECT=${CLOUDSDK_CORE_PROJECT} \ + -e KUBECONFIG=/helm-test/.kube/config \ + -w /helm-test \ + $(TEST_IMAGE) \ + make provision-cluster + +# this target is for running the acceptance tests +# it is run in the docker container above when the test-acceptance target is invoked +acceptance: +ifneq ($(LOCAL_ACCEPTANCE_TESTS),true) + gcloud auth activate-service-account --key-file=${GOOGLE_CREDENTIALS} +endif + bats --tap --timing test/${ACCEPTANCE_TESTS} + +# this target is for provisioning the GKE cluster +# it is run in the docker container above when the test-provision target is invoked +provision-cluster: + gcloud auth activate-service-account --key-file=${GOOGLE_CREDENTIALS} + terraform init test/terraform + terraform apply -var project=${CLOUDSDK_CORE_PROJECT} -var init_cli=true -auto-approve test/terraform + +# this target is for removing the GKE cluster +# it is run in the docker container above when the test-destroy target is invoked +destroy-cluster: + terraform destroy -auto-approve + +# create a kind cluster for running the acceptance tests locally +setup-kind: + kind get clusters | grep -q "^${KIND_CLUSTER_NAME}$$" || \ + kind create cluster \ + --image kindest/node:${KIND_K8S_VERSION} \ + --name ${KIND_CLUSTER_NAME} \ + --config $(CURDIR)/test/kind/config.yaml + kubectl config use-context kind-${KIND_CLUSTER_NAME} + +# delete the kind cluster +delete-kind: + kind delete cluster --name ${KIND_CLUSTER_NAME} || : + +.PHONY: values-schema test-image test-unit test-bats test test-acceptance test-destroy test-provision acceptance provision-cluster destroy-cluster diff --git a/scripts/helmcharts/databases/charts/vault/README.md b/scripts/helmcharts/databases/charts/vault/README.md new file mode 100644 index 000000000..c9971ff41 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/README.md @@ -0,0 +1,43 @@ +# Vault Helm Chart + +> :warning: **Please note**: We take Vault's security and our users' trust very seriously. If +you believe you have found a security issue in Vault Helm, _please responsibly disclose_ +by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com). + +This repository contains the official HashiCorp Helm chart for installing +and configuring Vault on Kubernetes. This chart supports multiple use +cases of Vault on Kubernetes depending on the values provided. + +For full documentation on this Helm chart along with all the ways you can +use Vault with Kubernetes, please see the +[Vault and Kubernetes documentation](https://www.vaultproject.io/docs/platform/k8s/). + +## Prerequisites + +To use the charts here, [Helm](https://helm.sh/) must be configured for your +Kubernetes cluster. Setting up Kubernetes and Helm is outside the scope of +this README. Please refer to the Kubernetes and Helm documentation. + +The versions required are: + + * **Helm 3.6+** + * **Kubernetes 1.16+** - This is the earliest version of Kubernetes tested. + It is possible that this chart works with earlier versions but it is + untested. + +## Usage + +To install the latest version of this chart, add the Hashicorp helm repository +and run `helm install`: + +```console +$ helm repo add hashicorp https://helm.releases.hashicorp.com +"hashicorp" has been added to your repositories + +$ helm install vault hashicorp/vault +``` + +Please see the many options supported in the `values.yaml` file. These are also +fully documented directly on the [Vault +website](https://www.vaultproject.io/docs/platform/k8s/helm) along with more +detailed installation instructions. diff --git a/scripts/helmcharts/databases/charts/vault/templates/NOTES.txt b/scripts/helmcharts/databases/charts/vault/templates/NOTES.txt new file mode 100644 index 000000000..8e267121c --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/NOTES.txt @@ -0,0 +1,14 @@ + +Thank you for installing HashiCorp Vault! + +Now that you have deployed Vault, you should look over the docs on using +Vault with Kubernetes available here: + +https://www.vaultproject.io/docs/ + + +Your release is named {{ .Release.Name }}. To learn more about the release, try: + + $ helm status {{ .Release.Name }} + $ helm get manifest {{ .Release.Name }} + diff --git a/scripts/helmcharts/databases/charts/vault/templates/_helpers.tpl b/scripts/helmcharts/databases/charts/vault/templates/_helpers.tpl new file mode 100644 index 000000000..38973910a --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/_helpers.tpl @@ -0,0 +1,953 @@ +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to +this (by the DNS naming spec). If release name contains chart name it will +be used as a full name. +*/}} +{{- define "vault.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "vault.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "vault.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Compute if the csi driver is enabled. +*/}} +{{- define "vault.csiEnabled" -}} +{{- $_ := set . "csiEnabled" (or + (eq (.Values.csi.enabled | toString) "true") + (and (eq (.Values.csi.enabled | toString) "-") (eq (.Values.global.enabled | toString) "true"))) -}} +{{- end -}} + +{{/* +Compute if the injector is enabled. +*/}} +{{- define "vault.injectorEnabled" -}} +{{- $_ := set . "injectorEnabled" (or + (eq (.Values.injector.enabled | toString) "true") + (and (eq (.Values.injector.enabled | toString) "-") (eq (.Values.global.enabled | toString) "true"))) -}} +{{- end -}} + +{{/* +Compute if the server is enabled. +*/}} +{{- define "vault.serverEnabled" -}} +{{- $_ := set . "serverEnabled" (or + (eq (.Values.server.enabled | toString) "true") + (and (eq (.Values.server.enabled | toString) "-") (eq (.Values.global.enabled | toString) "true"))) -}} +{{- end -}} + +{{/* +Compute if the server auth delegator serviceaccount is enabled. +*/}} +{{- define "vault.serverServiceAccountEnabled" -}} +{{- $_ := set . "serverServiceAccountEnabled" + (and + (eq (.Values.server.serviceAccount.create | toString) "true" ) + (or + (eq (.Values.server.enabled | toString) "true") + (eq (.Values.global.enabled | toString) "true"))) -}} +{{- end -}} + +{{/* +Compute if the server auth delegator serviceaccount is enabled. +*/}} +{{- define "vault.serverAuthDelegator" -}} +{{- $_ := set . "serverAuthDelegator" + (and + (eq (.Values.server.authDelegator.enabled | toString) "true" ) + (or (eq (.Values.server.serviceAccount.create | toString) "true") + (not (eq .Values.server.serviceAccount.name ""))) + (or + (eq (.Values.server.enabled | toString) "true") + (eq (.Values.global.enabled | toString) "true"))) -}} +{{- end -}} + +{{/* +Compute if the server service is enabled. +*/}} +{{- define "vault.serverServiceEnabled" -}} +{{- template "vault.serverEnabled" . -}} +{{- $_ := set . "serverServiceEnabled" (and .serverEnabled (eq (.Values.server.service.enabled | toString) "true")) -}} +{{- end -}} + +{{/* +Compute if the ui is enabled. +*/}} +{{- define "vault.uiEnabled" -}} +{{- $_ := set . "uiEnabled" (or + (eq (.Values.ui.enabled | toString) "true") + (and (eq (.Values.ui.enabled | toString) "-") (eq (.Values.global.enabled | toString) "true"))) -}} +{{- end -}} + +{{/* +Compute the maximum number of unavailable replicas for the PodDisruptionBudget. +This defaults to (n/2)-1 where n is the number of members of the server cluster. +Add a special case for replicas=1, where it should default to 0 as well. +*/}} +{{- define "vault.pdb.maxUnavailable" -}} +{{- if eq (int .Values.server.ha.replicas) 1 -}} +{{ 0 }} +{{- else if .Values.server.ha.disruptionBudget.maxUnavailable -}} +{{ .Values.server.ha.disruptionBudget.maxUnavailable -}} +{{- else -}} +{{- div (sub (div (mul (int .Values.server.ha.replicas) 10) 2) 1) 10 -}} +{{- end -}} +{{- end -}} + +{{/* +Set the variable 'mode' to the server mode requested by the user to simplify +template logic. +*/}} +{{- define "vault.mode" -}} + {{- template "vault.serverEnabled" . -}} + {{- if or (.Values.injector.externalVaultAddr) (.Values.global.externalVaultAddr) -}} + {{- $_ := set . "mode" "external" -}} + {{- else if not .serverEnabled -}} + {{- $_ := set . "mode" "external" -}} + {{- else if eq (.Values.server.dev.enabled | toString) "true" -}} + {{- $_ := set . "mode" "dev" -}} + {{- else if eq (.Values.server.ha.enabled | toString) "true" -}} + {{- $_ := set . "mode" "ha" -}} + {{- else if or (eq (.Values.server.standalone.enabled | toString) "true") (eq (.Values.server.standalone.enabled | toString) "-") -}} + {{- $_ := set . "mode" "standalone" -}} + {{- else -}} + {{- $_ := set . "mode" "" -}} + {{- end -}} +{{- end -}} + +{{/* +Set's the replica count based on the different modes configured by user +*/}} +{{- define "vault.replicas" -}} + {{ if eq .mode "standalone" }} + {{- default 1 -}} + {{ else if eq .mode "ha" }} + {{- .Values.server.ha.replicas | default 3 -}} + {{ else }} + {{- default 1 -}} + {{ end }} +{{- end -}} + +{{/* +Set's up configmap mounts if this isn't a dev deployment and the user +defined a custom configuration. Additionally iterates over any +extra volumes the user may have specified (such as a secret with TLS). +*/}} +{{- define "vault.volumes" -}} + {{- if and (ne .mode "dev") (or (.Values.server.standalone.config) (.Values.server.ha.config)) }} + - name: config + configMap: + name: {{ template "vault.fullname" . }}-config + {{ end }} + {{- range .Values.server.extraVolumes }} + - name: userconfig-{{ .name }} + {{ .type }}: + {{- if (eq .type "configMap") }} + name: {{ .name }} + {{- else if (eq .type "secret") }} + secretName: {{ .name }} + {{- end }} + defaultMode: {{ .defaultMode | default 420 }} + {{- end }} + {{- if .Values.server.volumes }} + {{- toYaml .Values.server.volumes | nindent 8}} + {{- end }} + {{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey) }} + - name: vault-license + secret: + secretName: {{ .Values.server.enterpriseLicense.secretName }} + defaultMode: 0440 + {{- end }} +{{- end -}} + +{{/* +Set's the args for custom command to render the Vault configuration +file with IP addresses to make the out of box experience easier +for users looking to use this chart with Consul Helm. +*/}} +{{- define "vault.args" -}} + {{ if or (eq .mode "standalone") (eq .mode "ha") }} + - | + cp /vault/config/extraconfig-from-values.hcl /tmp/storageconfig.hcl; + [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /tmp/storageconfig.hcl; + [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /tmp/storageconfig.hcl; + [ -n "${HOSTNAME}" ] && sed -Ei "s|HOSTNAME|${HOSTNAME?}|g" /tmp/storageconfig.hcl; + [ -n "${API_ADDR}" ] && sed -Ei "s|API_ADDR|${API_ADDR?}|g" /tmp/storageconfig.hcl; + [ -n "${TRANSIT_ADDR}" ] && sed -Ei "s|TRANSIT_ADDR|${TRANSIT_ADDR?}|g" /tmp/storageconfig.hcl; + [ -n "${RAFT_ADDR}" ] && sed -Ei "s|RAFT_ADDR|${RAFT_ADDR?}|g" /tmp/storageconfig.hcl; + /usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl {{ .Values.server.extraArgs }} + {{ else if eq .mode "dev" }} + - | + /usr/local/bin/docker-entrypoint.sh vault server -dev {{ .Values.server.extraArgs }} + {{ end }} +{{- end -}} + +{{/* +Set's additional environment variables based on the mode. +*/}} +{{- define "vault.envs" -}} + {{ if eq .mode "dev" }} + - name: VAULT_DEV_ROOT_TOKEN_ID + value: {{ .Values.server.dev.devRootToken }} + - name: VAULT_DEV_LISTEN_ADDRESS + value: "[::]:8200" + {{ end }} +{{- end -}} + +{{/* +Set's which additional volumes should be mounted to the container +based on the mode configured. +*/}} +{{- define "vault.mounts" -}} + {{ if eq (.Values.server.auditStorage.enabled | toString) "true" }} + - name: audit + mountPath: {{ .Values.server.auditStorage.mountPath }} + {{ end }} + {{ if or (eq .mode "standalone") (and (eq .mode "ha") (eq (.Values.server.ha.raft.enabled | toString) "true")) }} + {{ if eq (.Values.server.dataStorage.enabled | toString) "true" }} + - name: data + mountPath: {{ .Values.server.dataStorage.mountPath }} + {{ end }} + {{ end }} + {{ if and (ne .mode "dev") (or (.Values.server.standalone.config) (.Values.server.ha.config)) }} + - name: config + mountPath: /vault/config + {{ end }} + {{- range .Values.server.extraVolumes }} + - name: userconfig-{{ .name }} + readOnly: true + mountPath: {{ .path | default "/vault/userconfig" }}/{{ .name }} + {{- end }} + {{- if .Values.server.volumeMounts }} + {{- toYaml .Values.server.volumeMounts | nindent 12}} + {{- end }} + {{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey) }} + - name: vault-license + mountPath: /vault/license + readOnly: true + {{- end }} +{{- end -}} + +{{/* +Set's up the volumeClaimTemplates when data or audit storage is required. HA +might not use data storage since Consul is likely it's backend, however, audit +storage might be desired by the user. +*/}} +{{- define "vault.volumeclaims" -}} + {{- if and (ne .mode "dev") (or .Values.server.dataStorage.enabled .Values.server.auditStorage.enabled) }} + volumeClaimTemplates: + {{- if and (eq (.Values.server.dataStorage.enabled | toString) "true") (or (eq .mode "standalone") (eq (.Values.server.ha.raft.enabled | toString ) "true" )) }} + - metadata: + name: data + {{- include "vault.dataVolumeClaim.annotations" . | nindent 6 }} + spec: + accessModes: + - {{ .Values.server.dataStorage.accessMode | default "ReadWriteOnce" }} + resources: + requests: + storage: {{ .Values.server.dataStorage.size }} + {{- if .Values.server.dataStorage.storageClass }} + storageClassName: {{ .Values.server.dataStorage.storageClass }} + {{- end }} + {{ end }} + {{- if eq (.Values.server.auditStorage.enabled | toString) "true" }} + - metadata: + name: audit + {{- include "vault.auditVolumeClaim.annotations" . | nindent 6 }} + spec: + accessModes: + - {{ .Values.server.auditStorage.accessMode | default "ReadWriteOnce" }} + resources: + requests: + storage: {{ .Values.server.auditStorage.size }} + {{- if .Values.server.auditStorage.storageClass }} + storageClassName: {{ .Values.server.auditStorage.storageClass }} + {{- end }} + {{ end }} + {{ end }} +{{- end -}} + +{{/* +Set's the affinity for pod placement when running in standalone and HA modes. +*/}} +{{- define "vault.affinity" -}} + {{- if and (ne .mode "dev") .Values.server.affinity }} + affinity: + {{ $tp := typeOf .Values.server.affinity }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.affinity . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.server.affinity | nindent 8 }} + {{- end }} + {{ end }} +{{- end -}} + +{{/* +Sets the injector affinity for pod placement +*/}} +{{- define "injector.affinity" -}} + {{- if .Values.injector.affinity }} + affinity: + {{ $tp := typeOf .Values.injector.affinity }} + {{- if eq $tp "string" }} + {{- tpl .Values.injector.affinity . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.injector.affinity | nindent 8 }} + {{- end }} + {{ end }} +{{- end -}} + +{{/* +Sets the topologySpreadConstraints when running in standalone and HA modes. +*/}} +{{- define "vault.topologySpreadConstraints" -}} + {{- if and (ne .mode "dev") .Values.server.topologySpreadConstraints }} + topologySpreadConstraints: + {{ $tp := typeOf .Values.server.topologySpreadConstraints }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.topologySpreadConstraints . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.server.topologySpreadConstraints | nindent 8 }} + {{- end }} + {{ end }} +{{- end -}} + + +{{/* +Sets the injector topologySpreadConstraints for pod placement +*/}} +{{- define "injector.topologySpreadConstraints" -}} + {{- if .Values.injector.topologySpreadConstraints }} + topologySpreadConstraints: + {{ $tp := typeOf .Values.injector.topologySpreadConstraints }} + {{- if eq $tp "string" }} + {{- tpl .Values.injector.topologySpreadConstraints . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.injector.topologySpreadConstraints | nindent 8 }} + {{- end }} + {{ end }} +{{- end -}} + +{{/* +Sets the toleration for pod placement when running in standalone and HA modes. +*/}} +{{- define "vault.tolerations" -}} + {{- if and (ne .mode "dev") .Values.server.tolerations }} + tolerations: + {{- $tp := typeOf .Values.server.tolerations }} + {{- if eq $tp "string" }} + {{ tpl .Values.server.tolerations . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.server.tolerations | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets the injector toleration for pod placement +*/}} +{{- define "injector.tolerations" -}} + {{- if .Values.injector.tolerations }} + tolerations: + {{- $tp := typeOf .Values.injector.tolerations }} + {{- if eq $tp "string" }} + {{ tpl .Values.injector.tolerations . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.injector.tolerations | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Set's the node selector for pod placement when running in standalone and HA modes. +*/}} +{{- define "vault.nodeselector" -}} + {{- if and (ne .mode "dev") .Values.server.nodeSelector }} + nodeSelector: + {{- $tp := typeOf .Values.server.nodeSelector }} + {{- if eq $tp "string" }} + {{ tpl .Values.server.nodeSelector . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.server.nodeSelector | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets the injector node selector for pod placement +*/}} +{{- define "injector.nodeselector" -}} + {{- if .Values.injector.nodeSelector }} + nodeSelector: + {{- $tp := typeOf .Values.injector.nodeSelector }} + {{- if eq $tp "string" }} + {{ tpl .Values.injector.nodeSelector . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.injector.nodeSelector | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets the injector deployment update strategy +*/}} +{{- define "injector.strategy" -}} + {{- if .Values.injector.strategy }} + strategy: + {{- $tp := typeOf .Values.injector.strategy }} + {{- if eq $tp "string" }} + {{ tpl .Values.injector.strategy . | nindent 4 | trim }} + {{- else }} + {{- toYaml .Values.injector.strategy | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra pod annotations +*/}} +{{- define "vault.annotations" -}} + {{- if .Values.server.annotations }} + annotations: + {{- $tp := typeOf .Values.server.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.annotations . | nindent 8 }} + {{- else }} + {{- toYaml .Values.server.annotations | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra injector pod annotations +*/}} +{{- define "injector.annotations" -}} + {{- if .Values.injector.annotations }} + annotations: + {{- $tp := typeOf .Values.injector.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.injector.annotations . | nindent 8 }} + {{- else }} + {{- toYaml .Values.injector.annotations | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra injector service annotations +*/}} +{{- define "injector.service.annotations" -}} + {{- if .Values.injector.service.annotations }} + annotations: + {{- $tp := typeOf .Values.injector.service.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.injector.service.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.injector.service.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +securityContext for the injector pod level. +*/}} +{{- define "injector.securityContext.pod" -}} + {{- if .Values.injector.securityContext.pod }} + securityContext: + {{- $tp := typeOf .Values.injector.securityContext.pod }} + {{- if eq $tp "string" }} + {{- tpl .Values.injector.securityContext.pod . | nindent 8 }} + {{- else }} + {{- toYaml .Values.injector.securityContext.pod | nindent 8 }} + {{- end }} + {{- else if not .Values.global.openshift }} + securityContext: + runAsNonRoot: true + runAsGroup: {{ .Values.injector.gid | default 1000 }} + runAsUser: {{ .Values.injector.uid | default 100 }} + fsGroup: {{ .Values.injector.gid | default 1000 }} + {{- end }} +{{- end -}} + +{{/* +securityContext for the injector container level. +*/}} +{{- define "injector.securityContext.container" -}} + {{- if .Values.injector.securityContext.container}} + securityContext: + {{- $tp := typeOf .Values.injector.securityContext.container }} + {{- if eq $tp "string" }} + {{- tpl .Values.injector.securityContext.container . | nindent 12 }} + {{- else }} + {{- toYaml .Values.injector.securityContext.container | nindent 12 }} + {{- end }} + {{- else if not .Values.global.openshift }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + {{- end }} +{{- end -}} + +{{/* +securityContext for the statefulset pod template. +*/}} +{{- define "server.statefulSet.securityContext.pod" -}} + {{- if .Values.server.statefulSet.securityContext.pod }} + securityContext: + {{- $tp := typeOf .Values.server.statefulSet.securityContext.pod }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.statefulSet.securityContext.pod . | nindent 8 }} + {{- else }} + {{- toYaml .Values.server.statefulSet.securityContext.pod | nindent 8 }} + {{- end }} + {{- else if not .Values.global.openshift }} + securityContext: + runAsNonRoot: true + runAsGroup: {{ .Values.server.gid | default 1000 }} + runAsUser: {{ .Values.server.uid | default 100 }} + fsGroup: {{ .Values.server.gid | default 1000 }} + {{- end }} +{{- end -}} + +{{/* +securityContext for the statefulset vault container +*/}} +{{- define "server.statefulSet.securityContext.container" -}} + {{- if .Values.server.statefulSet.securityContext.container }} + securityContext: + {{- $tp := typeOf .Values.server.statefulSet.securityContext.container }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.statefulSet.securityContext.container . | nindent 12 }} + {{- else }} + {{- toYaml .Values.server.statefulSet.securityContext.container | nindent 12 }} + {{- end }} + {{- else if not .Values.global.openshift }} + securityContext: + allowPrivilegeEscalation: false + {{- end }} +{{- end -}} + + +{{/* +Sets extra injector service account annotations +*/}} +{{- define "injector.serviceAccount.annotations" -}} + {{- if and (ne .mode "dev") .Values.injector.serviceAccount.annotations }} + annotations: + {{- $tp := typeOf .Values.injector.serviceAccount.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.injector.serviceAccount.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.injector.serviceAccount.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra injector webhook annotations +*/}} +{{- define "injector.webhookAnnotations" -}} + {{- if or (((.Values.injector.webhook)).annotations) (.Values.injector.webhookAnnotations) }} + annotations: + {{- $tp := typeOf (or (((.Values.injector.webhook)).annotations) (.Values.injector.webhookAnnotations)) }} + {{- if eq $tp "string" }} + {{- tpl (((.Values.injector.webhook)).annotations | default .Values.injector.webhookAnnotations) . | nindent 4 }} + {{- else }} + {{- toYaml (((.Values.injector.webhook)).annotations | default .Values.injector.webhookAnnotations) | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Set's the injector webhook objectSelector +*/}} +{{- define "injector.objectSelector" -}} + {{- $v := or (((.Values.injector.webhook)).objectSelector) (.Values.injector.objectSelector) -}} + {{ if $v }} + objectSelector: + {{- $tp := typeOf $v -}} + {{ if eq $tp "string" }} + {{ tpl $v . | indent 6 | trim }} + {{ else }} + {{ toYaml $v | indent 6 | trim }} + {{ end }} + {{ end }} +{{ end }} + +{{/* +Sets extra ui service annotations +*/}} +{{- define "vault.ui.annotations" -}} + {{- if .Values.ui.annotations }} + annotations: + {{- $tp := typeOf .Values.ui.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.ui.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.ui.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "vault.serviceAccount.name" -}} +{{- if .Values.server.serviceAccount.create -}} + {{ default (include "vault.fullname" .) .Values.server.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.server.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Sets extra service account annotations +*/}} +{{- define "vault.serviceAccount.annotations" -}} + {{- if and (ne .mode "dev") .Values.server.serviceAccount.annotations }} + annotations: + {{- $tp := typeOf .Values.server.serviceAccount.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.serviceAccount.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.server.serviceAccount.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra ingress annotations +*/}} +{{- define "vault.ingress.annotations" -}} + {{- if .Values.server.ingress.annotations }} + annotations: + {{- $tp := typeOf .Values.server.ingress.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.ingress.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.server.ingress.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra route annotations +*/}} +{{- define "vault.route.annotations" -}} + {{- if .Values.server.route.annotations }} + annotations: + {{- $tp := typeOf .Values.server.route.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.route.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.server.route.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra vault server Service annotations +*/}} +{{- define "vault.service.annotations" -}} + {{- if .Values.server.service.annotations }} + {{- $tp := typeOf .Values.server.service.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.service.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.server.service.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets PodSecurityPolicy annotations +*/}} +{{- define "vault.psp.annotations" -}} + {{- if .Values.global.psp.annotations }} + annotations: + {{- $tp := typeOf .Values.global.psp.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.global.psp.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.global.psp.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra statefulset annotations +*/}} +{{- define "vault.statefulSet.annotations" -}} + {{- if .Values.server.statefulSet.annotations }} + annotations: + {{- $tp := typeOf .Values.server.statefulSet.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.statefulSet.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.server.statefulSet.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets VolumeClaim annotations for data volume +*/}} +{{- define "vault.dataVolumeClaim.annotations" -}} + {{- if and (ne .mode "dev") (.Values.server.dataStorage.enabled) (.Values.server.dataStorage.annotations) }} + annotations: + {{- $tp := typeOf .Values.server.dataStorage.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.dataStorage.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.server.dataStorage.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets VolumeClaim annotations for audit volume +*/}} +{{- define "vault.auditVolumeClaim.annotations" -}} + {{- if and (ne .mode "dev") (.Values.server.auditStorage.enabled) (.Values.server.auditStorage.annotations) }} + annotations: + {{- $tp := typeOf .Values.server.auditStorage.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.server.auditStorage.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.server.auditStorage.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Set's the container resources if the user has set any. +*/}} +{{- define "vault.resources" -}} + {{- if .Values.server.resources -}} + resources: +{{ toYaml .Values.server.resources | indent 12}} + {{ end }} +{{- end -}} + +{{/* +Sets the container resources if the user has set any. +*/}} +{{- define "injector.resources" -}} + {{- if .Values.injector.resources -}} + resources: +{{ toYaml .Values.injector.resources | indent 12}} + {{ end }} +{{- end -}} + +{{/* +Sets the container resources if the user has set any. +*/}} +{{- define "csi.resources" -}} + {{- if .Values.csi.resources -}} + resources: +{{ toYaml .Values.csi.resources | indent 12}} + {{ end }} +{{- end -}} + +{{/* +Sets extra CSI daemonset annotations +*/}} +{{- define "csi.daemonSet.annotations" -}} + {{- if .Values.csi.daemonSet.annotations }} + annotations: + {{- $tp := typeOf .Values.csi.daemonSet.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.csi.daemonSet.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.csi.daemonSet.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets CSI daemonset securityContext for pod template +*/}} +{{- define "csi.daemonSet.securityContext.pod" -}} + {{- if .Values.csi.daemonSet.securityContext.pod }} + securityContext: + {{- $tp := typeOf .Values.csi.daemonSet.securityContext.pod }} + {{- if eq $tp "string" }} + {{- tpl .Values.csi.daemonSet.securityContext.pod . | nindent 8 }} + {{- else }} + {{- toYaml .Values.csi.daemonSet.securityContext.pod | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets CSI daemonset securityContext for container +*/}} +{{- define "csi.daemonSet.securityContext.container" -}} + {{- if .Values.csi.daemonSet.securityContext.container }} + securityContext: + {{- $tp := typeOf .Values.csi.daemonSet.securityContext.container }} + {{- if eq $tp "string" }} + {{- tpl .Values.csi.daemonSet.securityContext.container . | nindent 12 }} + {{- else }} + {{- toYaml .Values.csi.daemonSet.securityContext.container | nindent 12 }} + {{- end }} + {{- end }} +{{- end -}} + + +{{/* +Sets the injector toleration for pod placement +*/}} +{{- define "csi.pod.tolerations" -}} + {{- if .Values.csi.pod.tolerations }} + tolerations: + {{- $tp := typeOf .Values.csi.pod.tolerations }} + {{- if eq $tp "string" }} + {{ tpl .Values.csi.pod.tolerations . | nindent 8 | trim }} + {{- else }} + {{- toYaml .Values.csi.pod.tolerations | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra CSI provider pod annotations +*/}} +{{- define "csi.pod.annotations" -}} + {{- if .Values.csi.pod.annotations }} + annotations: + {{- $tp := typeOf .Values.csi.pod.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.csi.pod.annotations . | nindent 8 }} + {{- else }} + {{- toYaml .Values.csi.pod.annotations | nindent 8 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Sets extra CSI service account annotations +*/}} +{{- define "csi.serviceAccount.annotations" -}} + {{- if .Values.csi.serviceAccount.annotations }} + annotations: + {{- $tp := typeOf .Values.csi.serviceAccount.annotations }} + {{- if eq $tp "string" }} + {{- tpl .Values.csi.serviceAccount.annotations . | nindent 4 }} + {{- else }} + {{- toYaml .Values.csi.serviceAccount.annotations | nindent 4 }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Inject extra environment vars in the format key:value, if populated +*/}} +{{- define "vault.extraEnvironmentVars" -}} +{{- if .extraEnvironmentVars -}} +{{- range $key, $value := .extraEnvironmentVars }} +- name: {{ printf "%s" $key | replace "." "_" | upper | quote }} + value: {{ $value | quote }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Inject extra environment populated by secrets, if populated +*/}} +{{- define "vault.extraSecretEnvironmentVars" -}} +{{- if .extraSecretEnvironmentVars -}} +{{- range .extraSecretEnvironmentVars }} +- name: {{ .envName }} + valueFrom: + secretKeyRef: + name: {{ .secretName }} + key: {{ .secretKey }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* Scheme for health check and local endpoint */}} +{{- define "vault.scheme" -}} +{{- if .Values.global.tlsDisable -}} +{{ "http" }} +{{- else -}} +{{ "https" }} +{{- end -}} +{{- end -}} + +{{/* +imagePullSecrets generates pull secrets from either string or map values. +A map value must be indexable by the key 'name'. +*/}} +{{- define "imagePullSecrets" -}} +{{- with .Values.global.imagePullSecrets -}} +imagePullSecrets: +{{- range . -}} +{{- if typeIs "string" . }} + - name: {{ . }} +{{- else if index . "name" }} + - name: {{ .name }} +{{- end }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +externalTrafficPolicy sets a Service's externalTrafficPolicy if applicable. +Supported inputs are Values.server.service and Values.ui +*/}} +{{- define "service.externalTrafficPolicy" -}} +{{- $type := "" -}} +{{- if .serviceType -}} +{{- $type = .serviceType -}} +{{- else if .type -}} +{{- $type = .type -}} +{{- end -}} +{{- if and .externalTrafficPolicy (or (eq $type "LoadBalancer") (eq $type "NodePort")) }} + externalTrafficPolicy: {{ .externalTrafficPolicy }} +{{- else }} +{{- end }} +{{- end -}} + +{{/* +loadBalancer configuration for the the UI service. +Supported inputs are Values.ui +*/}} +{{- define "service.loadBalancer" -}} +{{- if eq (.serviceType | toString) "LoadBalancer" }} +{{- if .loadBalancerIP }} + loadBalancerIP: {{ .loadBalancerIP }} +{{- end }} +{{- with .loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{- range . }} + - {{ . }} +{{- end }} +{{- end -}} +{{- end }} +{{- end -}} diff --git a/scripts/helmcharts/databases/charts/vault/templates/csi-clusterrole.yaml b/scripts/helmcharts/databases/charts/vault/templates/csi-clusterrole.yaml new file mode 100644 index 000000000..ec6a3d2b9 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/csi-clusterrole.yaml @@ -0,0 +1,18 @@ +{{- template "vault.csiEnabled" . -}} +{{- if .csiEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "vault.fullname" . }}-csi-provider-clusterrole + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: +- apiGroups: + - "" + resources: + - serviceaccounts/token + verbs: + - create +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/csi-clusterrolebinding.yaml b/scripts/helmcharts/databases/charts/vault/templates/csi-clusterrolebinding.yaml new file mode 100644 index 000000000..d5b62a5f0 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/csi-clusterrolebinding.yaml @@ -0,0 +1,19 @@ +{{- template "vault.csiEnabled" . -}} +{{- if .csiEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "vault.fullname" . }}-csi-provider-clusterrolebinding + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "vault.fullname" . }}-csi-provider-clusterrole +subjects: +- kind: ServiceAccount + name: {{ template "vault.fullname" . }}-csi-provider + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/csi-daemonset.yaml b/scripts/helmcharts/databases/charts/vault/templates/csi-daemonset.yaml new file mode 100644 index 000000000..d131aac5f --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/csi-daemonset.yaml @@ -0,0 +1,100 @@ +{{- template "vault.csiEnabled" . -}} +{{- if .csiEnabled -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "vault.fullname" . }}-csi-provider + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.csi.daemonSet.extraLabels -}} + {{- toYaml .Values.csi.daemonSet.extraLabels | nindent 4 -}} + {{- end -}} + {{ template "csi.daemonSet.annotations" . }} +spec: + updateStrategy: + type: {{ .Values.csi.daemonSet.updateStrategy.type }} + {{- if .Values.csi.daemonSet.updateStrategy.maxUnavailable }} + rollingUpdate: + maxUnavailable: {{ .Values.csi.daemonSet.updateStrategy.maxUnavailable }} + {{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ template "vault.name" . }}-csi-provider + app.kubernetes.io/instance: {{ .Release.Name }} + {{- if .Values.csi.pod.extraLabels -}} + {{- toYaml .Values.csi.pod.extraLabels | nindent 8 -}} + {{- end -}} + {{ template "csi.pod.annotations" . }} + spec: + {{ template "csi.daemonSet.securityContext.pod" . }} + {{- if .Values.csi.priorityClassName }} + priorityClassName: {{ .Values.csi.priorityClassName }} + {{- end }} + serviceAccountName: {{ template "vault.fullname" . }}-csi-provider + {{- template "csi.pod.tolerations" . }} + containers: + - name: {{ include "vault.name" . }}-csi-provider + {{ template "csi.resources" . }} + {{ template "csi.daemonSet.securityContext.container" . }} + image: "{{ .Values.csi.image.repository }}:{{ .Values.csi.image.tag }}" + imagePullPolicy: {{ .Values.csi.image.pullPolicy }} + args: + - --endpoint=/provider/vault.sock + - --debug={{ .Values.csi.debug }} + {{- if .Values.csi.extraArgs }} + {{- toYaml .Values.csi.extraArgs | nindent 12 }} + {{- end }} + env: + - name: VAULT_ADDR + {{- if .Values.global.externalVaultAddr }} + value: "{{ .Values.global.externalVaultAddr }}" + {{- else }} + value: {{ include "vault.scheme" . }}://{{ template "vault.fullname" . }}.{{ .Release.Namespace }}.svc:{{ .Values.server.service.port }} + {{- end }} + volumeMounts: + - name: providervol + mountPath: "/provider" + - name: mountpoint-dir + mountPath: {{ .Values.csi.daemonSet.kubeletRootDir }}/pods + mountPropagation: HostToContainer + {{- if .Values.csi.volumeMounts }} + {{- toYaml .Values.csi.volumeMounts | nindent 12}} + {{- end }} + livenessProbe: + httpGet: + path: /health/ready + port: 8080 + failureThreshold: {{ .Values.csi.livenessProbe.failureThreshold }} + initialDelaySeconds: {{ .Values.csi.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.csi.livenessProbe.periodSeconds }} + successThreshold: {{ .Values.csi.livenessProbe.successThreshold }} + timeoutSeconds: {{ .Values.csi.livenessProbe.timeoutSeconds }} + readinessProbe: + httpGet: + path: /health/ready + port: 8080 + failureThreshold: {{ .Values.csi.readinessProbe.failureThreshold }} + initialDelaySeconds: {{ .Values.csi.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.csi.readinessProbe.periodSeconds }} + successThreshold: {{ .Values.csi.readinessProbe.successThreshold }} + timeoutSeconds: {{ .Values.csi.readinessProbe.timeoutSeconds }} + volumes: + - name: providervol + hostPath: + path: {{ .Values.csi.daemonSet.providersDir }} + - name: mountpoint-dir + hostPath: + path: {{ .Values.csi.daemonSet.kubeletRootDir }}/pods + {{- if .Values.csi.volumes }} + {{- toYaml .Values.csi.volumes | nindent 8}} + {{- end }} + {{- include "imagePullSecrets" . | nindent 6 }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/csi-serviceaccount.yaml b/scripts/helmcharts/databases/charts/vault/templates/csi-serviceaccount.yaml new file mode 100644 index 000000000..8d6fa5329 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/csi-serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- template "vault.csiEnabled" . -}} +{{- if .csiEnabled -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "vault.fullname" . }}-csi-provider + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-csi-provider + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- if .Values.csi.serviceAccount.extraLabels -}} + {{- toYaml .Values.csi.serviceAccount.extraLabels | nindent 4 -}} + {{- end -}} + {{ template "csi.serviceAccount.annotations" . }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-certs-secret.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-certs-secret.yaml new file mode 100644 index 000000000..e88685b5e --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-certs-secret.yaml @@ -0,0 +1,14 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +{{- if and (eq (.Values.injector.leaderElector.enabled | toString) "true") (gt (.Values.injector.replicas | int) 1) }} +apiVersion: v1 +kind: Secret +metadata: + name: vault-injector-certs + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-clusterrole.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-clusterrole.yaml new file mode 100644 index 000000000..6a0d6be1a --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-clusterrole.yaml @@ -0,0 +1,19 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "vault.fullname" . }}-agent-injector-clusterrole + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: + - "get" + - "list" + - "watch" + - "patch" +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-clusterrolebinding.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-clusterrolebinding.yaml new file mode 100644 index 000000000..4c193f8a2 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-clusterrolebinding.yaml @@ -0,0 +1,19 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "vault.fullname" . }}-agent-injector-binding + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "vault.fullname" . }}-agent-injector-clusterrole +subjects: +- kind: ServiceAccount + name: {{ template "vault.fullname" . }}-agent-injector + namespace: {{ .Release.Namespace }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-deployment.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-deployment.yaml new file mode 100644 index 000000000..f0605599e --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-deployment.yaml @@ -0,0 +1,156 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +# Deployment for the injector +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "vault.fullname" . }}-agent-injector + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + component: webhook +spec: + replicas: {{ .Values.injector.replicas }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + component: webhook + {{ template "injector.strategy" . }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ template "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + component: webhook + {{- if .Values.injector.extraLabels -}} + {{- toYaml .Values.injector.extraLabels | nindent 8 -}} + {{- end -}} + {{ template "injector.annotations" . }} + spec: + {{ template "injector.affinity" . }} + {{ template "injector.topologySpreadConstraints" . }} + {{ template "injector.tolerations" . }} + {{ template "injector.nodeselector" . }} + {{- if .Values.injector.priorityClassName }} + priorityClassName: {{ .Values.injector.priorityClassName }} + {{- end }} + serviceAccountName: "{{ template "vault.fullname" . }}-agent-injector" + {{ template "injector.securityContext.pod" . -}} + {{- if not .Values.global.openshift }} + hostNetwork: {{ .Values.injector.hostNetwork }} + {{- end }} + containers: + - name: sidecar-injector + {{ template "injector.resources" . }} + image: "{{ .Values.injector.image.repository }}:{{ .Values.injector.image.tag }}" + imagePullPolicy: "{{ .Values.injector.image.pullPolicy }}" + {{- template "injector.securityContext.container" . }} + env: + - name: AGENT_INJECT_LISTEN + value: {{ printf ":%v" .Values.injector.port }} + - name: AGENT_INJECT_LOG_LEVEL + value: {{ .Values.injector.logLevel | default "info" }} + - name: AGENT_INJECT_VAULT_ADDR + {{- if .Values.global.externalVaultAddr }} + value: "{{ .Values.global.externalVaultAddr }}" + {{- else if .Values.injector.externalVaultAddr }} + value: "{{ .Values.injector.externalVaultAddr }}" + {{- else }} + value: {{ include "vault.scheme" . }}://{{ template "vault.fullname" . }}.{{ .Release.Namespace }}.svc:{{ .Values.server.service.port }} + {{- end }} + - name: AGENT_INJECT_VAULT_AUTH_PATH + value: {{ .Values.injector.authPath }} + - name: AGENT_INJECT_VAULT_IMAGE + value: "{{ .Values.injector.agentImage.repository }}:{{ .Values.injector.agentImage.tag }}" + {{- if .Values.injector.certs.secretName }} + - name: AGENT_INJECT_TLS_CERT_FILE + value: "/etc/webhook/certs/{{ .Values.injector.certs.certName }}" + - name: AGENT_INJECT_TLS_KEY_FILE + value: "/etc/webhook/certs/{{ .Values.injector.certs.keyName }}" + {{- else }} + - name: AGENT_INJECT_TLS_AUTO + value: {{ template "vault.fullname" . }}-agent-injector-cfg + - name: AGENT_INJECT_TLS_AUTO_HOSTS + value: {{ template "vault.fullname" . }}-agent-injector-svc,{{ template "vault.fullname" . }}-agent-injector-svc.{{ .Release.Namespace }},{{ template "vault.fullname" . }}-agent-injector-svc.{{ .Release.Namespace }}.svc + {{- end }} + - name: AGENT_INJECT_LOG_FORMAT + value: {{ .Values.injector.logFormat | default "standard" }} + - name: AGENT_INJECT_REVOKE_ON_SHUTDOWN + value: "{{ .Values.injector.revokeOnShutdown | default false }}" + {{- if .Values.global.openshift }} + - name: AGENT_INJECT_SET_SECURITY_CONTEXT + value: "false" + {{- end }} + {{- if .Values.injector.metrics.enabled }} + - name: AGENT_INJECT_TELEMETRY_PATH + value: "/metrics" + {{- end }} + {{- if and (eq (.Values.injector.leaderElector.enabled | toString) "true") (gt (.Values.injector.replicas | int) 1) }} + - name: AGENT_INJECT_USE_LEADER_ELECTOR + value: "true" + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- end }} + - name: AGENT_INJECT_CPU_REQUEST + value: "{{ .Values.injector.agentDefaults.cpuRequest }}" + - name: AGENT_INJECT_CPU_LIMIT + value: "{{ .Values.injector.agentDefaults.cpuLimit }}" + - name: AGENT_INJECT_MEM_REQUEST + value: "{{ .Values.injector.agentDefaults.memRequest }}" + - name: AGENT_INJECT_MEM_LIMIT + value: "{{ .Values.injector.agentDefaults.memLimit }}" + - name: AGENT_INJECT_DEFAULT_TEMPLATE + value: "{{ .Values.injector.agentDefaults.template }}" + - name: AGENT_INJECT_TEMPLATE_CONFIG_EXIT_ON_RETRY_FAILURE + value: "{{ .Values.injector.agentDefaults.templateConfig.exitOnRetryFailure }}" + {{- if .Values.injector.agentDefaults.templateConfig.staticSecretRenderInterval }} + - name: AGENT_INJECT_TEMPLATE_STATIC_SECRET_RENDER_INTERVAL + value: "{{ .Values.injector.agentDefaults.templateConfig.staticSecretRenderInterval }}" + {{- end }} + {{- include "vault.extraEnvironmentVars" .Values.injector | nindent 12 }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + args: + - agent-inject + - 2>&1 + livenessProbe: + httpGet: + path: /health/ready + port: {{ .Values.injector.port }} + scheme: HTTPS + failureThreshold: 2 + initialDelaySeconds: 5 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /health/ready + port: {{ .Values.injector.port }} + scheme: HTTPS + failureThreshold: 2 + initialDelaySeconds: 5 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 5 +{{- if .Values.injector.certs.secretName }} + volumeMounts: + - name: webhook-certs + mountPath: /etc/webhook/certs + readOnly: true +{{- end }} +{{- if .Values.injector.certs.secretName }} + volumes: + - name: webhook-certs + secret: + secretName: "{{ .Values.injector.certs.secretName }}" +{{- end }} + {{- include "imagePullSecrets" . | nindent 6 }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-disruptionbudget.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-disruptionbudget.yaml new file mode 100644 index 000000000..b44fd7300 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-disruptionbudget.yaml @@ -0,0 +1,20 @@ +{{- if .Values.injector.podDisruptionBudget }} +apiVersion: {{ ge .Capabilities.KubeVersion.Minor "21" | ternary "policy/v1" "policy/v1beta1" }} +kind: PodDisruptionBudget +metadata: + name: {{ template "vault.fullname" . }}-agent-injector + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + component: webhook +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + component: webhook + {{- toYaml .Values.injector.podDisruptionBudget | nindent 2 }} +{{- end -}} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-mutating-webhook.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-mutating-webhook.yaml new file mode 100644 index 000000000..3d3fd3678 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-mutating-webhook.yaml @@ -0,0 +1,39 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +{{- if .Capabilities.APIVersions.Has "admissionregistration.k8s.io/v1" }} +apiVersion: admissionregistration.k8s.io/v1 +{{- else }} +apiVersion: admissionregistration.k8s.io/v1beta1 +{{- end }} +kind: MutatingWebhookConfiguration +metadata: + name: {{ template "vault.fullname" . }}-agent-injector-cfg + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- template "injector.webhookAnnotations" . }} +webhooks: + - name: vault.hashicorp.com + failurePolicy: {{ ((.Values.injector.webhook)).failurePolicy | default .Values.injector.failurePolicy }} + matchPolicy: {{ ((.Values.injector.webhook)).matchPolicy | default "Exact" }} + sideEffects: None + timeoutSeconds: {{ ((.Values.injector.webhook)).timeoutSeconds | default "30" }} + admissionReviewVersions: ["v1", "v1beta1"] + clientConfig: + service: + name: {{ template "vault.fullname" . }}-agent-injector-svc + namespace: {{ .Release.Namespace }} + path: "/mutate" + caBundle: {{ .Values.injector.certs.caBundle | quote }} + rules: + - operations: ["CREATE", "UPDATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] +{{- if or (.Values.injector.namespaceSelector) (((.Values.injector.webhook)).namespaceSelector) }} + namespaceSelector: +{{ toYaml (((.Values.injector.webhook)).namespaceSelector | default .Values.injector.namespaceSelector) | indent 6}} +{{ end }} +{{- template "injector.objectSelector" . -}} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-network-policy.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-network-policy.yaml new file mode 100644 index 000000000..68892d23b --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-network-policy.yaml @@ -0,0 +1,24 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +{{- if eq (.Values.global.openshift | toString) "true" }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "vault.fullname" . }}-agent-injector + labels: + app.kubernetes.io/name: {{ template "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: {{ template "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + component: webhook + ingress: + - from: + - namespaceSelector: {} + ports: + - port: 8080 + protocol: TCP +{{ end }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-psp-role.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-psp-role.yaml new file mode 100644 index 000000000..5d23c7556 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-psp-role.yaml @@ -0,0 +1,20 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +{{- if eq (.Values.global.psp.enable | toString) "true" }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "vault.fullname" . }}-agent-injector-psp + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "vault.fullname" . }}-agent-injector +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-psp-rolebinding.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-psp-rolebinding.yaml new file mode 100644 index 000000000..4f6b0a851 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-psp-rolebinding.yaml @@ -0,0 +1,21 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +{{- if eq (.Values.global.psp.enable | toString) "true" }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "vault.fullname" . }}-agent-injector-psp + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + kind: Role + name: {{ template "vault.fullname" . }}-agent-injector-psp + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ template "vault.fullname" . }}-agent-injector +{{- end }} +{{- end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-psp.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-psp.yaml new file mode 100644 index 000000000..1eee2fcd0 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-psp.yaml @@ -0,0 +1,46 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +{{- if eq (.Values.global.psp.enable | toString) "true" }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "vault.fullname" . }}-agent-injector + labels: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- template "vault.psp.annotations" . }} +spec: + privileged: false + # Required to prevent escalations to root. + allowPrivilegeEscalation: false + volumes: + - configMap + - emptyDir + - projected + - secret + - downwardAPI + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Require the container to run without root privileges. + rule: MustRunAsNonRoot + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: RunAsAny + supplementalGroups: + rule: MustRunAs + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: MustRunAs + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} +{{- end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-role.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-role.yaml new file mode 100644 index 000000000..08c8264cc --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-role.yaml @@ -0,0 +1,29 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +{{- if and (eq (.Values.injector.leaderElector.enabled | toString) "true") (gt (.Values.injector.replicas | int) 1) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "vault.fullname" . }}-agent-injector-leader-elector-role + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: + - apiGroups: [""] + resources: ["secrets", "configmaps"] + verbs: + - "create" + - "get" + - "watch" + - "list" + - "update" + - apiGroups: [""] + resources: ["pods"] + verbs: + - "get" + - "patch" + - "delete" +{{- end }} +{{- end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-rolebinding.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-rolebinding.yaml new file mode 100644 index 000000000..ea0db11b9 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-rolebinding.yaml @@ -0,0 +1,22 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +{{- if and (eq (.Values.injector.leaderElector.enabled | toString) "true") (gt (.Values.injector.replicas | int) 1) }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "vault.fullname" . }}-agent-injector-leader-elector-binding + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "vault.fullname" . }}-agent-injector-leader-elector-role +subjects: + - kind: ServiceAccount + name: {{ template "vault.fullname" . }}-agent-injector + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-service.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-service.yaml new file mode 100644 index 000000000..5e747d6f1 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-service.yaml @@ -0,0 +1,22 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "vault.fullname" . }}-agent-injector-svc + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{ template "injector.service.annotations" . }} +spec: + ports: + - name: https + port: 443 + targetPort: {{ .Values.injector.port }} + selector: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + component: webhook +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/injector-serviceaccount.yaml b/scripts/helmcharts/databases/charts/vault/templates/injector-serviceaccount.yaml new file mode 100644 index 000000000..d1919b936 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/injector-serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- template "vault.injectorEnabled" . -}} +{{- if .injectorEnabled -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "vault.fullname" . }}-agent-injector + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }}-agent-injector + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{ template "injector.serviceAccount.annotations" . }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/prometheus-prometheusrules.yaml b/scripts/helmcharts/databases/charts/vault/templates/prometheus-prometheusrules.yaml new file mode 100644 index 000000000..572f1a05a --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/prometheus-prometheusrules.yaml @@ -0,0 +1,26 @@ +{{ if and (.Values.serverTelemetry.prometheusRules.rules) + (or (.Values.global.serverTelemetry.prometheusOperator) (.Values.serverTelemetry.prometheusRules.enabled) ) +}} +--- +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "vault.fullname" . }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- /* update the selectors docs in values.yaml whenever the defaults below change. */ -}} + {{- $selectors := .Values.serverTelemetry.prometheusRules.selectors }} + {{- if $selectors }} + {{- toYaml $selectors | nindent 4 }} + {{- else }} + release: prometheus + {{- end }} +spec: + groups: + - name: {{ include "vault.fullname" . }} + rules: + {{- toYaml .Values.serverTelemetry.prometheusRules.rules | nindent 6 }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/prometheus-servicemonitor.yaml b/scripts/helmcharts/databases/charts/vault/templates/prometheus-servicemonitor.yaml new file mode 100644 index 000000000..323e51fb9 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/prometheus-servicemonitor.yaml @@ -0,0 +1,44 @@ +{{ template "vault.mode" . }} +{{ if or (.Values.global.serverTelemetry.prometheusOperator) (.Values.serverTelemetry.serviceMonitor.enabled) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "vault.fullname" . }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- /* update the selectors docs in values.yaml whenever the defaults below change. */ -}} + {{- $selectors := .Values.serverTelemetry.serviceMonitor.selectors }} + {{- if $selectors }} + {{- toYaml $selectors | nindent 4 }} + {{- else }} + release: prometheus + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- if eq .mode "ha" }} + vault-active: "true" + {{- else }} + vault-internal: "true" + {{- end }} + endpoints: + - port: {{ include "vault.scheme" . }} + interval: {{ .Values.serverTelemetry.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serverTelemetry.serviceMonitor.scrapeTimeout }} + scheme: {{ include "vault.scheme" . | lower }} + path: /v1/sys/metrics + params: + format: + - prometheus + tlsConfig: + insecureSkipVerify: true + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-clusterrolebinding.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-clusterrolebinding.yaml new file mode 100644 index 000000000..8cdd61143 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-clusterrolebinding.yaml @@ -0,0 +1,24 @@ +{{ template "vault.serverAuthDelegator" . }} +{{- if .serverAuthDelegator -}} +{{- if .Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" -}} +apiVersion: rbac.authorization.k8s.io/v1 +{{- else }} +apiVersion: rbac.authorization.k8s.io/v1beta1 +{{- end }} +kind: ClusterRoleBinding +metadata: + name: {{ template "vault.fullname" . }}-server-binding + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- kind: ServiceAccount + name: {{ template "vault.serviceAccount.name" . }} + namespace: {{ .Release.Namespace }} +{{ end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-config-configmap.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-config-configmap.yaml new file mode 100644 index 000000000..f40c69608 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-config-configmap.yaml @@ -0,0 +1,40 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- if .serverEnabled -}} +{{- if ne .mode "dev" -}} +{{ if or (.Values.server.standalone.config) (.Values.server.ha.config) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "vault.fullname" . }}-config + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +data: + extraconfig-from-values.hcl: |- + {{- if or (eq .mode "ha") (eq .mode "standalone") }} + {{- $type := typeOf (index .Values.server .mode).config }} + {{- if eq $type "string" }} + disable_mlock = true + {{- if eq .mode "standalone" }} + {{ tpl .Values.server.standalone.config . | nindent 4 | trim }} + {{- else if and (eq .mode "ha") (eq (.Values.server.ha.raft.enabled | toString) "false") }} + {{ tpl .Values.server.ha.config . | nindent 4 | trim }} + {{- else if and (eq .mode "ha") (eq (.Values.server.ha.raft.enabled | toString) "true") }} + {{ tpl .Values.server.ha.raft.config . | nindent 4 | trim }} + {{ end }} + {{- else }} + {{- if and (eq .mode "ha") (eq (.Values.server.ha.raft.enabled | toString) "true") }} +{{ merge (dict "disable_mlock" true) (index .Values.server .mode).raft.config | toPrettyJson | indent 4 }} + {{- else }} +{{ merge (dict "disable_mlock" true) (index .Values.server .mode).config | toPrettyJson | indent 4 }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-discovery-role.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-discovery-role.yaml new file mode 100644 index 000000000..9ca23dd4c --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-discovery-role.yaml @@ -0,0 +1,21 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- if .serverEnabled -}} +{{- if eq .mode "ha" }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "vault.fullname" . }}-discovery-role + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list", "update", "patch"] +{{ end }} +{{ end }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-discovery-rolebinding.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-discovery-rolebinding.yaml new file mode 100644 index 000000000..6e22e4c2b --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-discovery-rolebinding.yaml @@ -0,0 +1,29 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- if .serverEnabled -}} +{{- if eq .mode "ha" }} +{{- if .Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" -}} +apiVersion: rbac.authorization.k8s.io/v1 +{{- else }} +apiVersion: rbac.authorization.k8s.io/v1beta1 +{{- end }} +kind: RoleBinding +metadata: + name: {{ template "vault.fullname" . }}-discovery-rolebinding + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "vault.fullname" . }}-discovery-role +subjects: +- kind: ServiceAccount + name: {{ template "vault.serviceAccount.name" . }} + namespace: {{ .Release.Namespace }} +{{ end }} +{{ end }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-disruptionbudget.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-disruptionbudget.yaml new file mode 100644 index 000000000..d940fa4da --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-disruptionbudget.yaml @@ -0,0 +1,26 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" -}} +{{- if .serverEnabled -}} +{{- if and (eq .mode "ha") (eq (.Values.server.ha.disruptionBudget.enabled | toString) "true") -}} +# PodDisruptionBudget to prevent degrading the server cluster through +# voluntary cluster changes. +apiVersion: {{ ge .Capabilities.KubeVersion.Minor "21" | ternary "policy/v1" "policy/v1beta1" }} +kind: PodDisruptionBudget +metadata: + name: {{ template "vault.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + maxUnavailable: {{ template "vault.pdb.maxUnavailable" . }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + component: server +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-ha-active-service.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-ha-active-service.yaml new file mode 100644 index 000000000..ef212376d --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-ha-active-service.yaml @@ -0,0 +1,46 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- template "vault.serverServiceEnabled" . -}} +{{- if .serverServiceEnabled -}} +{{- if eq .mode "ha" }} +# Service for active Vault pod +apiVersion: v1 +kind: Service +metadata: + name: {{ template "vault.fullname" . }}-active + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + vault-active: "true" + annotations: +{{ template "vault.service.annotations" .}} +spec: + {{- if .Values.server.service.type}} + type: {{ .Values.server.service.type }} + {{- end}} + {{- if .Values.server.service.clusterIP }} + clusterIP: {{ .Values.server.service.clusterIP }} + {{- end }} + {{- include "service.externalTrafficPolicy" .Values.server.service }} + publishNotReadyAddresses: {{ .Values.server.service.publishNotReadyAddresses }} + ports: + - name: {{ include "vault.scheme" . }} + port: {{ .Values.server.service.port }} + targetPort: {{ .Values.server.service.targetPort }} + {{- if and (.Values.server.service.activeNodePort) (eq (.Values.server.service.type | toString) "NodePort") }} + nodePort: {{ .Values.server.service.activeNodePort }} + {{- end }} + - name: https-internal + port: 8201 + targetPort: 8201 + selector: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + component: server + vault-active: "true" +{{- end }} +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-ha-standby-service.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-ha-standby-service.yaml new file mode 100644 index 000000000..e6d66af84 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-ha-standby-service.yaml @@ -0,0 +1,45 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- template "vault.serverServiceEnabled" . -}} +{{- if .serverServiceEnabled -}} +{{- if eq .mode "ha" }} +# Service for standby Vault pod +apiVersion: v1 +kind: Service +metadata: + name: {{ template "vault.fullname" . }}-standby + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: +{{ template "vault.service.annotations" .}} +spec: + {{- if .Values.server.service.type}} + type: {{ .Values.server.service.type }} + {{- end}} + {{- if .Values.server.service.clusterIP }} + clusterIP: {{ .Values.server.service.clusterIP }} + {{- end }} + {{- include "service.externalTrafficPolicy" .Values.server.service }} + publishNotReadyAddresses: {{ .Values.server.service.publishNotReadyAddresses }} + ports: + - name: {{ include "vault.scheme" . }} + port: {{ .Values.server.service.port }} + targetPort: {{ .Values.server.service.targetPort }} + {{- if and (.Values.server.service.standbyNodePort) (eq (.Values.server.service.type | toString) "NodePort") }} + nodePort: {{ .Values.server.service.standbyNodePort }} + {{- end }} + - name: https-internal + port: 8201 + targetPort: 8201 + selector: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + component: server + vault-active: "false" +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-headless-service.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-headless-service.yaml new file mode 100644 index 000000000..b03f491e3 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-headless-service.yaml @@ -0,0 +1,34 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- template "vault.serverServiceEnabled" . -}} +{{- if .serverServiceEnabled -}} +# Service for Vault cluster +apiVersion: v1 +kind: Service +metadata: + name: {{ template "vault.fullname" . }}-internal + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + vault-internal: "true" + annotations: +{{ template "vault.service.annotations" .}} +spec: + clusterIP: None + publishNotReadyAddresses: {{ .Values.server.service.publishNotReadyAddresses }} + ports: + - name: "{{ include "vault.scheme" . }}" + port: {{ .Values.server.service.port }} + targetPort: {{ .Values.server.service.targetPort }} + - name: https-internal + port: 8201 + targetPort: 8201 + selector: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + component: server +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-ingress.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-ingress.yaml new file mode 100644 index 000000000..c81e5f5ce --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-ingress.yaml @@ -0,0 +1,77 @@ +{{- if not .Values.global.openshift }} +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- if .Values.server.ingress.enabled -}} +{{- $extraPaths := .Values.server.ingress.extraPaths -}} +{{- $serviceName := include "vault.fullname" . -}} +{{- template "vault.serverServiceEnabled" . -}} +{{- if .serverServiceEnabled -}} +{{- if and (eq .mode "ha" ) (eq (.Values.server.ingress.activeService | toString) "true") }} +{{- $serviceName = printf "%s-%s" $serviceName "active" -}} +{{- end }} +{{- $servicePort := .Values.server.service.port -}} +{{- $pathType := .Values.server.ingress.pathType -}} +{{- $kubeVersion := .Capabilities.KubeVersion.Version }} +{{ if semverCompare ">= 1.19.0-0" $kubeVersion }} +apiVersion: networking.k8s.io/v1 +{{ else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} +apiVersion: networking.k8s.io/v1beta1 +{{ else }} +apiVersion: extensions/v1beta1 +{{ end }} +kind: Ingress +metadata: + name: {{ template "vault.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- with .Values.server.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- template "vault.ingress.annotations" . }} +spec: +{{- if .Values.server.ingress.tls }} + tls: + {{- range .Values.server.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} +{{- if .Values.server.ingress.ingressClassName }} + ingressClassName: {{ .Values.server.ingress.ingressClassName }} +{{- end }} + rules: + {{- range .Values.server.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: +{{ if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + {{- range (.paths | default (list "/")) }} + - path: {{ . }} + {{ if semverCompare ">= 1.19.0-0" $kubeVersion }} + pathType: {{ $pathType }} + {{ end }} + backend: + {{ if semverCompare ">= 1.19.0-0" $kubeVersion }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{ else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{ end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-network-policy.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-network-policy.yaml new file mode 100644 index 000000000..5f4c21a4b --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-network-policy.yaml @@ -0,0 +1,26 @@ +{{- if eq (.Values.server.networkPolicy.enabled | toString) "true" }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "vault.fullname" . }} + labels: + app.kubernetes.io/name: {{ template "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: {{ template "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + ingress: + - from: + - namespaceSelector: {} + ports: + - port: 8200 + protocol: TCP + - port: 8201 + protocol: TCP + {{- if .Values.server.networkPolicy.egress }} + egress: + {{- toYaml .Values.server.networkPolicy.egress | nindent 4 }} + {{ end }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-psp-role.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-psp-role.yaml new file mode 100644 index 000000000..b8eb897e5 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-psp-role.yaml @@ -0,0 +1,20 @@ +{{ template "vault.mode" . }} +{{- if .serverEnabled -}} +{{- if and (ne .mode "") (eq (.Values.global.psp.enable | toString) "true") }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "vault.fullname" . }}-psp + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "vault.fullname" . }} +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-psp-rolebinding.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-psp-rolebinding.yaml new file mode 100644 index 000000000..fded9fbc6 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-psp-rolebinding.yaml @@ -0,0 +1,21 @@ +{{ template "vault.mode" . }} +{{- if .serverEnabled -}} +{{- if and (ne .mode "") (eq (.Values.global.psp.enable | toString) "true") }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "vault.fullname" . }}-psp + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + kind: Role + name: {{ template "vault.fullname" . }}-psp + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ template "vault.fullname" . }} +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-psp.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-psp.yaml new file mode 100644 index 000000000..d210af351 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-psp.yaml @@ -0,0 +1,49 @@ +{{ template "vault.mode" . }} +{{- if .serverEnabled -}} +{{- if and (ne .mode "") (eq (.Values.global.psp.enable | toString) "true") }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "vault.fullname" . }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- template "vault.psp.annotations" . }} +spec: + privileged: false + # Required to prevent escalations to root. + allowPrivilegeEscalation: false + volumes: + - configMap + - emptyDir + - projected + - secret + - downwardAPI + {{- if eq (.Values.server.dataStorage.enabled | toString) "true" }} + - persistentVolumeClaim + {{- end }} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Require the container to run without root privileges. + rule: MustRunAsNonRoot + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: RunAsAny + supplementalGroups: + rule: MustRunAs + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: MustRunAs + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-route.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-route.yaml new file mode 100644 index 000000000..e122d936b --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-route.yaml @@ -0,0 +1,34 @@ +{{- if .Values.global.openshift }} +{{- if ne .mode "external" }} +{{- if .Values.server.route.enabled -}} +{{- $serviceName := include "vault.fullname" . -}} +{{- if and (eq .mode "ha" ) (eq (.Values.server.route.activeService | toString) "true") }} +{{- $serviceName = printf "%s-%s" $serviceName "active" -}} +{{- end }} +kind: Route +apiVersion: route.openshift.io/v1 +metadata: + name: {{ template "vault.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- with .Values.server.route.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- template "vault.route.annotations" . }} +spec: + host: {{ .Values.server.route.host }} + to: + kind: Service + name: {{ $serviceName }} + weight: 100 + port: + targetPort: 8200 + tls: + {{- toYaml .Values.server.route.tls | nindent 4 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-service.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-service.yaml new file mode 100644 index 000000000..3a9b0e7e5 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-service.yaml @@ -0,0 +1,44 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- template "vault.serverServiceEnabled" . -}} +{{- if .serverServiceEnabled -}} +# Service for Vault cluster +apiVersion: v1 +kind: Service +metadata: + name: {{ template "vault.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: +{{ template "vault.service.annotations" .}} +spec: + {{- if .Values.server.service.type}} + type: {{ .Values.server.service.type }} + {{- end}} + {{- if .Values.server.service.clusterIP }} + clusterIP: {{ .Values.server.service.clusterIP }} + {{- end }} + {{- include "service.externalTrafficPolicy" .Values.server.service }} + # We want the servers to become available even if they're not ready + # since this DNS is also used for join operations. + publishNotReadyAddresses: {{ .Values.server.service.publishNotReadyAddresses }} + ports: + - name: {{ include "vault.scheme" . }} + port: {{ .Values.server.service.port }} + targetPort: {{ .Values.server.service.targetPort }} + {{- if and (.Values.server.service.nodePort) (eq (.Values.server.service.type | toString) "NodePort") }} + nodePort: {{ .Values.server.service.nodePort }} + {{- end }} + - name: https-internal + port: 8201 + targetPort: 8201 + selector: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + component: server +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-serviceaccount.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-serviceaccount.yaml new file mode 100644 index 000000000..c0d32d190 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-serviceaccount.yaml @@ -0,0 +1,14 @@ +{{ template "vault.serverServiceAccountEnabled" . }} +{{- if .serverServiceAccountEnabled -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "vault.serviceAccount.name" . }} + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{ template "vault.serviceAccount.annotations" . }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/server-statefulset.yaml b/scripts/helmcharts/databases/charts/vault/templates/server-statefulset.yaml new file mode 100644 index 000000000..fb3cbfab7 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/server-statefulset.yaml @@ -0,0 +1,210 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- if ne .mode "" }} +{{- if .serverEnabled -}} +# StatefulSet to run the actual vault server cluster. +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ template "vault.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- template "vault.statefulSet.annotations" . }} +spec: + serviceName: {{ template "vault.fullname" . }}-internal + podManagementPolicy: Parallel + replicas: {{ template "vault.replicas" . }} + updateStrategy: + type: {{ .Values.server.updateStrategyType }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + component: server + template: + metadata: + labels: + helm.sh/chart: {{ template "vault.chart" . }} + app.kubernetes.io/name: {{ template "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + component: server + {{- if .Values.server.extraLabels -}} + {{- toYaml .Values.server.extraLabels | nindent 8 -}} + {{- end -}} + {{ template "vault.annotations" . }} + spec: + {{ template "vault.affinity" . }} + {{ template "vault.topologySpreadConstraints" . }} + {{ template "vault.tolerations" . }} + {{ template "vault.nodeselector" . }} + {{- if .Values.server.priorityClassName }} + priorityClassName: {{ .Values.server.priorityClassName }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} + serviceAccountName: {{ template "vault.serviceAccount.name" . }} + {{ if .Values.server.shareProcessNamespace }} + shareProcessNamespace: true + {{ end }} + {{- template "server.statefulSet.securityContext.pod" . }} + {{- if not .Values.global.openshift }} + hostNetwork: {{ .Values.server.hostNetwork }} + {{- end }} + + volumes: + {{ template "vault.volumes" . }} + - name: home + emptyDir: {} + {{- if .Values.server.extraInitContainers }} + initContainers: + {{ toYaml .Values.server.extraInitContainers | nindent 8}} + {{- end }} + containers: + - name: vault + {{ template "vault.resources" . }} + image: {{ .Values.server.image.repository }}:{{ .Values.server.image.tag | default "latest" }} + imagePullPolicy: {{ .Values.server.image.pullPolicy }} + command: + - "/bin/sh" + - "-ec" + args: {{ template "vault.args" . }} + {{- template "server.statefulSet.securityContext.container" . }} + env: + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: VAULT_K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: VAULT_K8S_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: VAULT_ADDR + value: "{{ include "vault.scheme" . }}://127.0.0.1:8200" + - name: VAULT_API_ADDR + {{- if .Values.server.ha.apiAddr }} + value: {{ .Values.server.ha.apiAddr }} + {{- else }} + value: "{{ include "vault.scheme" . }}://$(POD_IP):8200" + {{- end }} + - name: SKIP_CHOWN + value: "true" + - name: SKIP_SETCAP + value: "true" + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: VAULT_CLUSTER_ADDR + {{- if .Values.server.ha.clusterAddr }} + value: {{ .Values.server.ha.clusterAddr }} + {{- else }} + value: "https://$(HOSTNAME).{{ template "vault.fullname" . }}-internal:8201" + {{- end }} + {{- if and (eq (.Values.server.ha.raft.enabled | toString) "true") (eq (.Values.server.ha.raft.setNodeId | toString) "true") }} + - name: VAULT_RAFT_NODE_ID + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- end }} + - name: HOME + value: "/home/vault" + {{- if .Values.server.logLevel }} + - name: VAULT_LOG_LEVEL + value: "{{ .Values.server.logLevel }}" + {{- end }} + {{- if .Values.server.logFormat }} + - name: VAULT_LOG_FORMAT + value: "{{ .Values.server.logFormat }}" + {{- end }} + {{- if (and .Values.server.enterpriseLicense.secretName .Values.server.enterpriseLicense.secretKey) }} + - name: VAULT_LICENSE_PATH + value: /vault/license/{{ .Values.server.enterpriseLicense.secretKey }} + {{- end }} + {{ template "vault.envs" . }} + {{- include "vault.extraEnvironmentVars" .Values.server | nindent 12 }} + {{- include "vault.extraSecretEnvironmentVars" .Values.server | nindent 12 }} + volumeMounts: + {{ template "vault.mounts" . }} + - name: home + mountPath: /home/vault + ports: + - containerPort: 8200 + name: {{ include "vault.scheme" . }} + - containerPort: 8201 + name: https-internal + - containerPort: 8202 + name: {{ include "vault.scheme" . }}-rep + {{- if .Values.server.readinessProbe.enabled }} + readinessProbe: + {{- if .Values.server.readinessProbe.path }} + httpGet: + path: {{ .Values.server.readinessProbe.path | quote }} + port: 8200 + scheme: {{ include "vault.scheme" . | upper }} + {{- else }} + # Check status; unsealed vault servers return 0 + # The exit code reflects the seal status: + # 0 - unsealed + # 1 - error + # 2 - sealed + exec: + command: ["/bin/sh", "-ec", "vault status -tls-skip-verify"] + {{- end }} + failureThreshold: {{ .Values.server.readinessProbe.failureThreshold }} + initialDelaySeconds: {{ .Values.server.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.server.readinessProbe.periodSeconds }} + successThreshold: {{ .Values.server.readinessProbe.successThreshold }} + timeoutSeconds: {{ .Values.server.readinessProbe.timeoutSeconds }} + {{- end }} + {{- if .Values.server.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.server.livenessProbe.path | quote }} + port: 8200 + scheme: {{ include "vault.scheme" . | upper }} + failureThreshold: {{ .Values.server.livenessProbe.failureThreshold }} + initialDelaySeconds: {{ .Values.server.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.server.livenessProbe.periodSeconds }} + successThreshold: {{ .Values.server.livenessProbe.successThreshold }} + timeoutSeconds: {{ .Values.server.livenessProbe.timeoutSeconds }} + {{- end }} + lifecycle: + # Vault container doesn't receive SIGTERM from Kubernetes + # and after the grace period ends, Kube sends SIGKILL. This + # causes issues with graceful shutdowns such as deregistering itself + # from Consul (zombie services). + preStop: + exec: + command: [ + "/bin/sh", "-c", + # Adding a sleep here to give the pod eviction a + # chance to propagate, so requests will not be made + # to this pod while it's terminating + "sleep {{ .Values.server.preStopSleepSeconds }} && kill -SIGTERM $(pidof vault)", + ] + {{- if .Values.server.postStart }} + postStart: + exec: + command: + {{- range (.Values.server.postStart) }} + - {{ . | quote }} + {{- end }} + {{- end }} + {{- if .Values.server.extraContainers }} + {{ toYaml .Values.server.extraContainers | nindent 8}} + {{- end }} + {{- include "imagePullSecrets" . | nindent 6 }} + {{ template "vault.volumeclaims" . }} +{{ end }} +{{ end }} +{{ end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/tests/server-test.yaml b/scripts/helmcharts/databases/charts/vault/templates/tests/server-test.yaml new file mode 100644 index 000000000..56dbee78c --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/tests/server-test.yaml @@ -0,0 +1,51 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- if .serverEnabled -}} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ .Release.Name }}-server-test" + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": test +spec: + {{- include "imagePullSecrets" . | nindent 2 }} + containers: + - name: {{ .Release.Name }}-server-test + image: {{ .Values.server.image.repository }}:{{ .Values.server.image.tag | default "latest" }} + imagePullPolicy: {{ .Values.server.image.pullPolicy }} + env: + - name: VAULT_ADDR + value: {{ include "vault.scheme" . }}://{{ template "vault.fullname" . }}.{{ .Release.Namespace }}.svc:{{ .Values.server.service.port }} + {{- include "vault.extraEnvironmentVars" .Values.server | nindent 8 }} + command: + - /bin/sh + - -c + - | + echo "Checking for sealed info in 'vault status' output" + ATTEMPTS=10 + n=0 + until [ "$n" -ge $ATTEMPTS ] + do + echo "Attempt" $n... + vault status -format yaml | grep -E '^sealed: (true|false)' && break + n=$((n+1)) + sleep 5 + done + if [ $n -ge $ATTEMPTS ]; then + echo "timed out looking for sealed info in 'vault status' output" + exit 1 + fi + + exit 0 + volumeMounts: + {{- if .Values.server.volumeMounts }} + {{- toYaml .Values.server.volumeMounts | nindent 8}} + {{- end }} + volumes: + {{- if .Values.server.volumes }} + {{- toYaml .Values.server.volumes | nindent 4}} + {{- end }} + restartPolicy: Never +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/templates/ui-service.yaml b/scripts/helmcharts/databases/charts/vault/templates/ui-service.yaml new file mode 100644 index 000000000..d45afdda4 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/templates/ui-service.yaml @@ -0,0 +1,37 @@ +{{ template "vault.mode" . }} +{{- if ne .mode "external" }} +{{- template "vault.uiEnabled" . -}} +{{- if .uiEnabled -}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "vault.fullname" . }}-ui + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ include "vault.chart" . }} + app.kubernetes.io/name: {{ include "vault.name" . }}-ui + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + {{- template "vault.ui.annotations" . }} +spec: + selector: + app.kubernetes.io/name: {{ include "vault.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + component: server + {{- if and (.Values.ui.activeVaultPodOnly) (eq .mode "ha") }} + vault-active: "true" + {{- end }} + publishNotReadyAddresses: {{ .Values.ui.publishNotReadyAddresses }} + ports: + - name: {{ include "vault.scheme" . }} + port: {{ .Values.ui.externalPort }} + targetPort: {{ .Values.ui.targetPort }} + {{- if .Values.ui.serviceNodePort }} + nodePort: {{ .Values.ui.serviceNodePort }} + {{- end }} + type: {{ .Values.ui.serviceType }} + {{- include "service.externalTrafficPolicy" .Values.ui }} + {{- include "service.loadBalancer" .Values.ui }} +{{- end -}} +{{- end }} diff --git a/scripts/helmcharts/databases/charts/vault/values.openshift.yaml b/scripts/helmcharts/databases/charts/vault/values.openshift.yaml new file mode 100644 index 000000000..ee0056376 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/values.openshift.yaml @@ -0,0 +1,18 @@ +# These overrides are appropriate defaults for deploying this chart on OpenShift + +global: + openshift: true + +injector: + image: + repository: "registry.connect.redhat.com/hashicorp/vault-k8s" + tag: "1.0.1-ubi" + + agentImage: + repository: "registry.connect.redhat.com/hashicorp/vault" + tag: "1.12.0-ubi" + +server: + image: + repository: "registry.connect.redhat.com/hashicorp/vault" + tag: "1.12.0-ubi" diff --git a/scripts/helmcharts/databases/charts/vault/values.schema.json b/scripts/helmcharts/databases/charts/vault/values.schema.json new file mode 100644 index 000000000..676efb7c9 --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/values.schema.json @@ -0,0 +1,1030 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "csi": { + "type": "object", + "properties": { + "daemonSet": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + }, + "extraLabels": { + "type": "object" + }, + "kubeletRootDir": { + "type": "string" + }, + "providersDir": { + "type": "string" + }, + "securityContext": { + "type": "object", + "properties": { + "container": { + "type": [ + "object", + "string" + ] + }, + "pod": { + "type": [ + "object", + "string" + ] + } + } + }, + "updateStrategy": { + "type": "object", + "properties": { + "maxUnavailable": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + } + }, + "debug": { + "type": "boolean" + }, + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "extraArgs": { + "type": "array" + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "livenessProbe": { + "type": "object", + "properties": { + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "pod": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + }, + "extraLabels": { + "type": "object" + }, + "tolerations": { + "type": [ + "null", + "array", + "string" + ] + } + } + }, + "priorityClassName": { + "type": "string" + }, + "readinessProbe": { + "type": "object", + "properties": { + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "resources": { + "type": "object" + }, + "serviceAccount": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + }, + "extraLabels": { + "type": "object" + } + } + }, + "volumeMounts": { + "type": [ + "null", + "array" + ] + }, + "volumes": { + "type": [ + "null", + "array" + ] + } + } + }, + "global": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "externalVaultAddr": { + "type": "string" + }, + "imagePullSecrets": { + "type": "array" + }, + "openshift": { + "type": "boolean" + }, + "psp": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + }, + "enable": { + "type": "boolean" + } + } + }, + "tlsDisable": { + "type": "boolean" + } + } + }, + "injector": { + "type": "object", + "properties": { + "affinity": { + "type": [ + "object", + "string" + ] + }, + "agentDefaults": { + "type": "object", + "properties": { + "cpuLimit": { + "type": "string" + }, + "cpuRequest": { + "type": "string" + }, + "memLimit": { + "type": "string" + }, + "memRequest": { + "type": "string" + }, + "template": { + "type": "string" + }, + "templateConfig": { + "type": "object", + "properties": { + "exitOnRetryFailure": { + "type": "boolean" + }, + "staticSecretRenderInterval": { + "type": "string" + } + } + } + } + }, + "agentImage": { + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "annotations": { + "type": [ + "object", + "string" + ] + }, + "authPath": { + "type": "string" + }, + "certs": { + "type": "object", + "properties": { + "caBundle": { + "type": "string" + }, + "certName": { + "type": "string" + }, + "keyName": { + "type": "string" + }, + "secretName": { + "type": [ + "null", + "string" + ] + } + } + }, + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "externalVaultAddr": { + "type": "string" + }, + "extraEnvironmentVars": { + "type": "object" + }, + "extraLabels": { + "type": "object" + }, + "failurePolicy": { + "type": "string" + }, + "hostNetwork": { + "type": "boolean" + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "leaderElector": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "logFormat": { + "type": "string" + }, + "logLevel": { + "type": "string" + }, + "metrics": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "namespaceSelector": { + "type": "object" + }, + "nodeSelector": { + "type": [ + "null", + "object", + "string" + ] + }, + "objectSelector": { + "type": [ + "object", + "string" + ] + }, + "podDisruptionBudget": { + "type": "object" + }, + "port": { + "type": "integer" + }, + "priorityClassName": { + "type": "string" + }, + "replicas": { + "type": "integer" + }, + "resources": { + "type": "object" + }, + "revokeOnShutdown": { + "type": "boolean" + }, + "securityContext": { + "type": "object", + "properties": { + "container": { + "type": [ + "object", + "string" + ] + }, + "pod": { + "type": [ + "object", + "string" + ] + } + } + }, + "service": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + } + } + }, + "strategy": { + "type": [ + "object", + "string" + ] + }, + "tolerations": { + "type": [ + "null", + "array", + "string" + ] + }, + "topologySpreadConstraints": { + "type": [ + "null", + "array", + "string" + ] + }, + "webhook": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + }, + "failurePolicy": { + "type": "string" + }, + "matchPolicy": { + "type": "string" + }, + "namespaceSelector": { + "type": "object" + }, + "objectSelector": { + "type": [ + "object", + "string" + ] + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "webhookAnnotations": { + "type": [ + "object", + "string" + ] + } + } + }, + "server": { + "type": "object", + "properties": { + "affinity": { + "type": [ + "object", + "string" + ] + }, + "annotations": { + "type": [ + "object", + "string" + ] + }, + "auditStorage": { + "type": "object", + "properties": { + "accessMode": { + "type": "string" + }, + "annotations": { + "type": [ + "object", + "string" + ] + }, + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "mountPath": { + "type": "string" + }, + "size": { + "type": "string" + }, + "storageClass": { + "type": [ + "null", + "string" + ] + } + } + }, + "authDelegator": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "dataStorage": { + "type": "object", + "properties": { + "accessMode": { + "type": "string" + }, + "annotations": { + "type": [ + "object", + "string" + ] + }, + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "mountPath": { + "type": "string" + }, + "size": { + "type": "string" + }, + "storageClass": { + "type": [ + "null", + "string" + ] + } + } + }, + "dev": { + "type": "object", + "properties": { + "devRootToken": { + "type": "string" + }, + "enabled": { + "type": "boolean" + } + } + }, + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "enterpriseLicense": { + "type": "object", + "properties": { + "secretKey": { + "type": "string" + }, + "secretName": { + "type": "string" + } + } + }, + "extraArgs": { + "type": "string" + }, + "extraContainers": { + "type": [ + "null", + "array" + ] + }, + "extraEnvironmentVars": { + "type": "object" + }, + "extraInitContainers": { + "type": [ + "null", + "array" + ] + }, + "extraLabels": { + "type": "object" + }, + "extraSecretEnvironmentVars": { + "type": "array" + }, + "extraVolumes": { + "type": "array" + }, + "ha": { + "type": "object", + "properties": { + "apiAddr": { + "type": [ + "null", + "string" + ] + }, + "clusterAddr": { + "type": [ + "null", + "string" + ] + }, + "config": { + "type": [ + "string", + "object" + ] + }, + "disruptionBudget": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "maxUnavailable": { + "type": [ + "null", + "integer" + ] + } + } + }, + "enabled": { + "type": "boolean" + }, + "raft": { + "type": "object", + "properties": { + "config": { + "type": [ + "string", + "object" + ] + }, + "enabled": { + "type": "boolean" + }, + "setNodeId": { + "type": "boolean" + } + } + }, + "replicas": { + "type": "integer" + } + } + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ingress": { + "type": "object", + "properties": { + "activeService": { + "type": "boolean" + }, + "annotations": { + "type": [ + "object", + "string" + ] + }, + "enabled": { + "type": "boolean" + }, + "extraPaths": { + "type": "array" + }, + "hosts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "paths": { + "type": "array" + } + } + } + }, + "ingressClassName": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "pathType": { + "type": "string" + }, + "tls": { + "type": "array" + } + } + }, + "livenessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "path": { + "type": "string" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "logFormat": { + "type": "string" + }, + "logLevel": { + "type": "string" + }, + "networkPolicy": { + "type": "object", + "properties": { + "egress": { + "type": "array" + }, + "enabled": { + "type": "boolean" + } + } + }, + "nodeSelector": { + "type": [ + "null", + "object", + "string" + ] + }, + "postStart": { + "type": "array" + }, + "preStopSleepSeconds": { + "type": "integer" + }, + "priorityClassName": { + "type": "string" + }, + "readinessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "resources": { + "type": "object" + }, + "route": { + "type": "object", + "properties": { + "activeService": { + "type": "boolean" + }, + "annotations": { + "type": [ + "object", + "string" + ] + }, + "enabled": { + "type": "boolean" + }, + "host": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "tls": { + "type": "object" + } + } + }, + "service": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + }, + "enabled": { + "type": "boolean" + }, + "externalTrafficPolicy": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "publishNotReadyAddresses": { + "type": "boolean" + }, + "targetPort": { + "type": "integer" + }, + "nodePort": { + "type": "integer" + }, + "activeNodePort": { + "type": "integer" + }, + "standbyNodePort": { + "type": "integer" + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + }, + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "shareProcessNamespace": { + "type": "boolean" + }, + "standalone": { + "type": "object", + "properties": { + "config": { + "type": [ + "string", + "object" + ] + }, + "enabled": { + "type": [ + "string", + "boolean" + ] + } + } + }, + "statefulSet": { + "type": "object", + "properties": { + "annotations": { + "type": [ + "object", + "string" + ] + }, + "securityContext": { + "type": "object", + "properties": { + "container": { + "type": [ + "object", + "string" + ] + }, + "pod": { + "type": [ + "object", + "string" + ] + } + } + } + } + }, + "terminationGracePeriodSeconds": { + "type": "integer" + }, + "tolerations": { + "type": [ + "null", + "array", + "string" + ] + }, + "topologySpreadConstraints": { + "type": [ + "null", + "array", + "string" + ] + }, + "updateStrategyType": { + "type": "string" + }, + "volumeMounts": { + "type": [ + "null", + "array" + ] + }, + "volumes": { + "type": [ + "null", + "array" + ] + }, + "hostNetwork": { + "type": "boolean" + } + } + }, + "ui": { + "type": "object", + "properties": { + "activeVaultPodOnly": { + "type": "boolean" + }, + "annotations": { + "type": [ + "object", + "string" + ] + }, + "enabled": { + "type": [ + "boolean", + "string" + ] + }, + "externalPort": { + "type": "integer" + }, + "externalTrafficPolicy": { + "type": "string" + }, + "publishNotReadyAddresses": { + "type": "boolean" + }, + "serviceNodePort": { + "type": [ + "null", + "integer" + ] + }, + "serviceType": { + "type": "string" + }, + "targetPort": { + "type": "integer" + } + } + } + } +} diff --git a/scripts/helmcharts/databases/charts/vault/values.yaml b/scripts/helmcharts/databases/charts/vault/values.yaml new file mode 100644 index 000000000..3d319303f --- /dev/null +++ b/scripts/helmcharts/databases/charts/vault/values.yaml @@ -0,0 +1,1121 @@ +# Available parameters and their default values for the Vault chart. + +global: + # enabled is the master enabled switch. Setting this to true or false + # will enable or disable all the components within this chart by default. + enabled: true + + # Image pull secret to use for registry authentication. + # Alternatively, the value may be specified as an array of strings. + imagePullSecrets: [] + # imagePullSecrets: + # - name: image-pull-secret + + # TLS for end-to-end encrypted transport + tlsDisable: true + + # External vault server address for the injector and CSI provider to use. + # Setting this will disable deployment of a vault server. + externalVaultAddr: "" + + # If deploying to OpenShift + openshift: false + + # Create PodSecurityPolicy for pods + psp: + enable: false + # Annotation for PodSecurityPolicy. + # This is a multi-line templated string map, and can also be set as YAML. + annotations: | + seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default,runtime/default + apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default + seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default + apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default + + serverTelemetry: + # Enable integration with the Prometheus Operator + # See the top level serverTelemetry section below before enabling this feature. + prometheusOperator: false + +injector: + # True if you want to enable vault agent injection. + # @default: global.enabled + enabled: "-" + + replicas: 1 + + # Configures the port the injector should listen on + port: 8080 + + # If multiple replicas are specified, by default a leader will be determined + # so that only one injector attempts to create TLS certificates. + leaderElector: + enabled: true + + # If true, will enable a node exporter metrics endpoint at /metrics. + metrics: + enabled: false + + # Deprecated: Please use global.externalVaultAddr instead. + externalVaultAddr: "" + + # image sets the repo and tag of the vault-k8s image to use for the injector. + image: + repository: "hashicorp/vault-k8s" + tag: "1.0.1" + pullPolicy: IfNotPresent + + # agentImage sets the repo and tag of the Vault image to use for the Vault Agent + # containers. This should be set to the official Vault image. Vault 1.3.1+ is + # required. + agentImage: + repository: "hashicorp/vault" + tag: "1.12.0" + + # The default values for the injected Vault Agent containers. + agentDefaults: + # For more information on configuring resources, see the K8s documentation: + # https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + cpuLimit: "500m" + cpuRequest: "250m" + memLimit: "128Mi" + memRequest: "64Mi" + + # Default template type for secrets when no custom template is specified. + # Possible values include: "json" and "map". + template: "map" + + # Default values within Agent's template_config stanza. + templateConfig: + exitOnRetryFailure: true + staticSecretRenderInterval: "" + + # Mount Path of the Vault Kubernetes Auth Method. + authPath: "auth/kubernetes" + + # Configures the log verbosity of the injector. + # Supported log levels include: trace, debug, info, warn, error + logLevel: "info" + + # Configures the log format of the injector. Supported log formats: "standard", "json". + logFormat: "standard" + + # Configures all Vault Agent sidecars to revoke their token when shutting down + revokeOnShutdown: false + + webhook: + # Configures failurePolicy of the webhook. The "unspecified" default behaviour depends on the + # API Version of the WebHook. + # To block pod creation while the webhook is unavailable, set the policy to `Fail` below. + # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy + # + failurePolicy: Ignore + + # matchPolicy specifies the approach to accepting changes based on the rules of + # the MutatingWebhookConfiguration. + # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy + # for more details. + # + matchPolicy: Exact + + # timeoutSeconds is the amount of seconds before the webhook request will be ignored + # or fails. + # If it is ignored or fails depends on the failurePolicy + # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#timeouts + # for more details. + # + timeoutSeconds: 30 + + # namespaceSelector is the selector for restricting the webhook to only + # specific namespaces. + # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector + # for more details. + # Example: + # namespaceSelector: + # matchLabels: + # sidecar-injector: enabled + namespaceSelector: {} + + # objectSelector is the selector for restricting the webhook to only + # specific labels. + # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector + # for more details. + # Example: + # objectSelector: + # matchLabels: + # vault-sidecar-injector: enabled + objectSelector: | + matchExpressions: + - key: app.kubernetes.io/name + operator: NotIn + values: + - {{ template "vault.name" . }}-agent-injector + + # Extra annotations to attach to the webhook + annotations: {} + + # Deprecated: please use 'webhook.failurePolicy' instead + # Configures failurePolicy of the webhook. The "unspecified" default behaviour depends on the + # API Version of the WebHook. + # To block pod creation while webhook is unavailable, set the policy to `Fail` below. + # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy + # + failurePolicy: Ignore + + # Deprecated: please use 'webhook.namespaceSelector' instead + # namespaceSelector is the selector for restricting the webhook to only + # specific namespaces. + # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector + # for more details. + # Example: + # namespaceSelector: + # matchLabels: + # sidecar-injector: enabled + namespaceSelector: {} + + # Deprecated: please use 'webhook.objectSelector' instead + # objectSelector is the selector for restricting the webhook to only + # specific labels. + # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector + # for more details. + # Example: + # objectSelector: + # matchLabels: + # vault-sidecar-injector: enabled + objectSelector: {} + + # Deprecated: please use 'webhook.annotations' instead + # Extra annotations to attach to the webhook + webhookAnnotations: {} + + certs: + # secretName is the name of the secret that has the TLS certificate and + # private key to serve the injector webhook. If this is null, then the + # injector will default to its automatic management mode that will assign + # a service account to the injector to generate its own certificates. + secretName: null + + # caBundle is a base64-encoded PEM-encoded certificate bundle for the CA + # that signed the TLS certificate that the webhook serves. This must be set + # if secretName is non-null unless an external service like cert-manager is + # keeping the caBundle updated. + caBundle: "" + + # certName and keyName are the names of the files within the secret for + # the TLS cert and private key, respectively. These have reasonable + # defaults but can be customized if necessary. + certName: tls.crt + keyName: tls.key + + # Security context for the pod template and the injector container + # The default pod securityContext is: + # runAsNonRoot: true + # runAsGroup: {{ .Values.injector.gid | default 1000 }} + # runAsUser: {{ .Values.injector.uid | default 100 }} + # fsGroup: {{ .Values.injector.gid | default 1000 }} + # and for container is + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + securityContext: + pod: {} + container: {} + + resources: {} + # resources: + # requests: + # memory: 256Mi + # cpu: 250m + # limits: + # memory: 256Mi + # cpu: 250m + + # extraEnvironmentVars is a list of extra environment variables to set in the + # injector deployment. + extraEnvironmentVars: {} + # KUBERNETES_SERVICE_HOST: kubernetes.default.svc + + # Affinity Settings for injector pods + # This can either be a multi-line string or YAML matching the PodSpec's affinity field. + # Commenting out or setting as empty the affinity variable, will allow + # deployment of multiple replicas to single node services such as Minikube. + affinity: | + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/name: {{ template "vault.name" . }}-agent-injector + app.kubernetes.io/instance: "{{ .Release.Name }}" + component: webhook + topologyKey: kubernetes.io/hostname + + # Topology settings for injector pods + # ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + # This should be either a multi-line string or YAML matching the topologySpreadConstraints array + # in a PodSpec. + topologySpreadConstraints: [] + + # Toleration Settings for injector pods + # This should be either a multi-line string or YAML matching the Toleration array + # in a PodSpec. + tolerations: [] + + # nodeSelector labels for server pod assignment, formatted as a multi-line string or YAML map. + # ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + # Example: + # nodeSelector: + # beta.kubernetes.io/arch: amd64 + nodeSelector: {} + + # Priority class for injector pods + priorityClassName: "" + + # Extra annotations to attach to the injector pods + # This can either be YAML or a YAML-formatted multi-line templated string map + # of the annotations to apply to the injector pods + annotations: {} + + # Extra labels to attach to the agent-injector + # This should be a YAML map of the labels to apply to the injector + extraLabels: {} + + # Should the injector pods run on the host network (useful when using + # an alternate CNI in EKS) + hostNetwork: false + + # Injector service specific config + service: + # Extra annotations to attach to the injector service + annotations: {} + + # Injector serviceAccount specific config + serviceAccount: + # Extra annotations to attach to the injector serviceAccount + annotations: {} + + # A disruption budget limits the number of pods of a replicated application + # that are down simultaneously from voluntary disruptions + podDisruptionBudget: {} + # podDisruptionBudget: + # maxUnavailable: 1 + + # strategy for updating the deployment. This can be a multi-line string or a + # YAML map. + strategy: {} + # strategy: | + # rollingUpdate: + # maxSurge: 25% + # maxUnavailable: 25% + # type: RollingUpdate + +server: + # If true, or "-" with global.enabled true, Vault server will be installed. + # See vault.mode in _helpers.tpl for implementation details. + enabled: "-" + + # [Enterprise Only] This value refers to a Kubernetes secret that you have + # created that contains your enterprise license. If you are not using an + # enterprise image or if you plan to introduce the license key via another + # route, then leave secretName blank ("") or set it to null. + # Requires Vault Enterprise 1.8 or later. + enterpriseLicense: + # The name of the Kubernetes secret that holds the enterprise license. The + # secret must be in the same namespace that Vault is installed into. + secretName: "" + # The key within the Kubernetes secret that holds the enterprise license. + secretKey: "license" + + # Resource requests, limits, etc. for the server cluster placement. This + # should map directly to the value of the resources field for a PodSpec. + # By default no direct resource request is made. + + image: + repository: "hashicorp/vault" + tag: "1.12.0" + # Overrides the default Image Pull Policy + pullPolicy: IfNotPresent + + # Configure the Update Strategy Type for the StatefulSet + # See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies + updateStrategyType: "OnDelete" + + # Configure the logging verbosity for the Vault server. + # Supported log levels include: trace, debug, info, warn, error + logLevel: "" + + # Configure the logging format for the Vault server. + # Supported log formats include: standard, json + logFormat: "" + + resources: {} + # resources: + # requests: + # memory: 256Mi + # cpu: 250m + # limits: + # memory: 256Mi + # cpu: 250m + + # Ingress allows ingress services to be created to allow external access + # from Kubernetes to access Vault pods. + # If deployment is on OpenShift, the following block is ignored. + # In order to expose the service, use the route section below + ingress: + enabled: false + labels: {} + # traffic: external + annotations: {} + # | + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # or + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + # Optionally use ingressClassName instead of deprecated annotation. + # See: https://kubernetes.io/docs/concepts/services-networking/ingress/#deprecated-annotation + ingressClassName: "" + + # As of Kubernetes 1.19, all Ingress Paths must have a pathType configured. The default value below should be sufficient in most cases. + # See: https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types for other possible values. + pathType: Prefix + + # When HA mode is enabled and K8s service registration is being used, + # configure the ingress to point to the Vault active service. + activeService: true + hosts: + - host: chart-example.local + paths: [] + ## Extra paths to prepend to the host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # service: + # name: ssl-redirect + # port: + # number: use-annotation + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + + # OpenShift only - create a route to expose the service + # By default the created route will be of type passthrough + route: + enabled: false + + # When HA mode is enabled and K8s service registration is being used, + # configure the route to point to the Vault active service. + activeService: true + + labels: {} + annotations: {} + host: chart-example.local + # tls will be passed directly to the route's TLS config, which + # can be used to configure other termination methods that terminate + # TLS at the router + tls: + termination: passthrough + + # authDelegator enables a cluster role binding to be attached to the service + # account. This cluster role binding can be used to setup Kubernetes auth + # method. https://www.vaultproject.io/docs/auth/kubernetes.html + authDelegator: + enabled: true + + # extraInitContainers is a list of init containers. Specified as a YAML list. + # This is useful if you need to run a script to provision TLS certificates or + # write out configuration files in a dynamic way. + extraInitContainers: null + # # This example installs a plugin pulled from github into the /usr/local/libexec/vault/oauthapp folder, + # # which is defined in the volumes value. + # - name: oauthapp + # image: "alpine" + # command: [sh, -c] + # args: + # - cd /tmp && + # wget https://github.com/puppetlabs/vault-plugin-secrets-oauthapp/releases/download/v1.2.0/vault-plugin-secrets-oauthapp-v1.2.0-linux-amd64.tar.xz -O oauthapp.xz && + # tar -xf oauthapp.xz && + # mv vault-plugin-secrets-oauthapp-v1.2.0-linux-amd64 /usr/local/libexec/vault/oauthapp && + # chmod +x /usr/local/libexec/vault/oauthapp + # volumeMounts: + # - name: plugins + # mountPath: /usr/local/libexec/vault + + # extraContainers is a list of sidecar containers. Specified as a YAML list. + extraContainers: null + + # shareProcessNamespace enables process namespace sharing between Vault and the extraContainers + # This is useful if Vault must be signaled, e.g. to send a SIGHUP for a log rotation + shareProcessNamespace: false + + # extraArgs is a string containing additional Vault server arguments. + extraArgs: "" + + # Used to define custom readinessProbe settings + readinessProbe: + enabled: true + # If you need to use a http path instead of the default exec + # path: /v1/sys/health?standbyok=true + + # When a probe fails, Kubernetes will try failureThreshold times before giving up + failureThreshold: 2 + # Number of seconds after the container has started before probe initiates + initialDelaySeconds: 5 + # How often (in seconds) to perform the probe + periodSeconds: 5 + # Minimum consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + # Number of seconds after which the probe times out. + timeoutSeconds: 3 + # Used to enable a livenessProbe for the pods + livenessProbe: + enabled: false + path: "/v1/sys/health?standbyok=true" + # When a probe fails, Kubernetes will try failureThreshold times before giving up + failureThreshold: 2 + # Number of seconds after the container has started before probe initiates + initialDelaySeconds: 60 + # How often (in seconds) to perform the probe + periodSeconds: 5 + # Minimum consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + # Number of seconds after which the probe times out. + timeoutSeconds: 3 + + # Optional duration in seconds the pod needs to terminate gracefully. + # See: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/ + terminationGracePeriodSeconds: 10 + + # Used to set the sleep time during the preStop step + preStopSleepSeconds: 5 + + # Used to define commands to run after the pod is ready. + # This can be used to automate processes such as initialization + # or boostrapping auth methods. + postStart: [] + # - /bin/sh + # - -c + # - /vault/userconfig/myscript/run.sh + + # extraEnvironmentVars is a list of extra environment variables to set with the stateful set. These could be + # used to include variables required for auto-unseal. + extraEnvironmentVars: {} + # GOOGLE_REGION: global + # GOOGLE_PROJECT: myproject + # GOOGLE_APPLICATION_CREDENTIALS: /vault/userconfig/myproject/myproject-creds.json + + # extraSecretEnvironmentVars is a list of extra environment variables to set with the stateful set. + # These variables take value from existing Secret objects. + extraSecretEnvironmentVars: [] + # - envName: AWS_SECRET_ACCESS_KEY + # secretName: vault + # secretKey: AWS_SECRET_ACCESS_KEY + + # Deprecated: please use 'volumes' instead. + # extraVolumes is a list of extra volumes to mount. These will be exposed + # to Vault in the path `/vault/userconfig/<name>/`. The value below is + # an array of objects, examples are shown below. + extraVolumes: [] + # - type: secret (or "configMap") + # name: my-secret + # path: null # default is `/vault/userconfig` + + # volumes is a list of volumes made available to all containers. These are rendered + # via toYaml rather than pre-processed like the extraVolumes value. + # The purpose is to make it easy to share volumes between containers. + volumes: null + # - name: plugins + # emptyDir: {} + + # volumeMounts is a list of volumeMounts for the main server container. These are rendered + # via toYaml rather than pre-processed like the extraVolumes value. + # The purpose is to make it easy to share volumes between containers. + volumeMounts: null + # - mountPath: /usr/local/libexec/vault + # name: plugins + # readOnly: true + + # Affinity Settings + # Commenting out or setting as empty the affinity variable, will allow + # deployment to single node services such as Minikube + # This should be either a multi-line string or YAML matching the PodSpec's affinity field. + affinity: | + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/name: {{ template "vault.name" . }} + app.kubernetes.io/instance: "{{ .Release.Name }}" + component: server + topologyKey: kubernetes.io/hostname + + # Topology settings for server pods + # ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + # This should be either a multi-line string or YAML matching the topologySpreadConstraints array + # in a PodSpec. + topologySpreadConstraints: [] + + # Toleration Settings for server pods + # This should be either a multi-line string or YAML matching the Toleration array + # in a PodSpec. + tolerations: [] + + # nodeSelector labels for server pod assignment, formatted as a multi-line string or YAML map. + # ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + # Example: + # nodeSelector: + # beta.kubernetes.io/arch: amd64 + nodeSelector: {} + + # Enables network policy for server pods + networkPolicy: + enabled: false + egress: [] + # egress: + # - to: + # - ipBlock: + # cidr: 10.0.0.0/24 + # ports: + # - protocol: TCP + # port: 443 + + # Priority class for server pods + priorityClassName: "" + + # Extra labels to attach to the server pods + # This should be a YAML map of the labels to apply to the server pods + extraLabels: {} + + # Extra annotations to attach to the server pods + # This can either be YAML or a YAML-formatted multi-line templated string map + # of the annotations to apply to the server pods + annotations: {} + + # Enables a headless service to be used by the Vault Statefulset + service: + enabled: true + # clusterIP controls whether a Cluster IP address is attached to the + # Vault service within Kubernetes. By default, the Vault service will + # be given a Cluster IP address, set to None to disable. When disabled + # Kubernetes will create a "headless" service. Headless services can be + # used to communicate with pods directly through DNS instead of a round-robin + # load balancer. + # clusterIP: None + + # Configures the service type for the main Vault service. Can be ClusterIP + # or NodePort. + #type: ClusterIP + + # Do not wait for pods to be ready + publishNotReadyAddresses: true + + # The externalTrafficPolicy can be set to either Cluster or Local + # and is only valid for LoadBalancer and NodePort service types. + # The default value is Cluster. + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-traffic-policy + externalTrafficPolicy: Cluster + + # If type is set to "NodePort", a specific nodePort value can be configured, + # will be random if left blank. + #nodePort: 30000 + + # When HA mode is enabled + # If type is set to "NodePort", a specific nodePort value can be configured, + # will be random if left blank. + #activeNodePort: 30001 + + # When HA mode is enabled + # If type is set to "NodePort", a specific nodePort value can be configured, + # will be random if left blank. + #standbyNodePort: 30002 + + # Port on which Vault server is listening + port: 8200 + # Target port to which the service should be mapped to + targetPort: 8200 + # Extra annotations for the service definition. This can either be YAML or a + # YAML-formatted multi-line templated string map of the annotations to apply + # to the service. + annotations: {} + + # This configures the Vault Statefulset to create a PVC for data + # storage when using the file or raft backend storage engines. + # See https://www.vaultproject.io/docs/configuration/storage/index.html to know more + dataStorage: + enabled: true + # Size of the PVC created + size: 10Gi + # Location where the PVC will be mounted. + mountPath: "/vault/data" + # Name of the storage class to use. If null it will use the + # configured default Storage Class. + storageClass: null + # Access Mode of the storage device being used for the PVC + accessMode: ReadWriteOnce + # Annotations to apply to the PVC + annotations: {} + + # This configures the Vault Statefulset to create a PVC for audit + # logs. Once Vault is deployed, initialized, and unsealed, Vault must + # be configured to use this for audit logs. This will be mounted to + # /vault/audit + # See https://www.vaultproject.io/docs/audit/index.html to know more + auditStorage: + enabled: false + # Size of the PVC created + size: 10Gi + # Location where the PVC will be mounted. + mountPath: "/vault/audit" + # Name of the storage class to use. If null it will use the + # configured default Storage Class. + storageClass: null + # Access Mode of the storage device being used for the PVC + accessMode: ReadWriteOnce + # Annotations to apply to the PVC + annotations: {} + + # Run Vault in "dev" mode. This requires no further setup, no state management, + # and no initialization. This is useful for experimenting with Vault without + # needing to unseal, store keys, et. al. All data is lost on restart - do not + # use dev mode for anything other than experimenting. + # See https://www.vaultproject.io/docs/concepts/dev-server.html to know more + dev: + enabled: false + + # Set VAULT_DEV_ROOT_TOKEN_ID value + devRootToken: "root" + + # Run Vault in "standalone" mode. This is the default mode that will deploy if + # no arguments are given to helm. This requires a PVC for data storage to use + # the "file" backend. This mode is not highly available and should not be scaled + # past a single replica. + standalone: + enabled: "-" + + # config is a raw string of default configuration when using a Stateful + # deployment. Default is to use a PersistentVolumeClaim mounted at /vault/data + # and store data there. This is only used when using a Replica count of 1, and + # using a stateful set. This should be HCL. + + # Note: Configuration files are stored in ConfigMaps so sensitive data + # such as passwords should be either mounted through extraSecretEnvironmentVars + # or through a Kube secret. For more information see: + # https://www.vaultproject.io/docs/platform/k8s/helm/run#protecting-sensitive-vault-configurations + config: | + ui = true + + listener "tcp" { + tls_disable = 1 + address = "[::]:8200" + cluster_address = "[::]:8201" + # Enable unauthenticated metrics access (necessary for Prometheus Operator) + #telemetry { + # unauthenticated_metrics_access = "true" + #} + } + storage "file" { + path = "/vault/data" + } + + # Example configuration for using auto-unseal, using Google Cloud KMS. The + # GKMS keys must already exist, and the cluster must have a service account + # that is authorized to access GCP KMS. + #seal "gcpckms" { + # project = "vault-helm-dev" + # region = "global" + # key_ring = "vault-helm-unseal-kr" + # crypto_key = "vault-helm-unseal-key" + #} + + # Example configuration for enabling Prometheus metrics in your config. + #telemetry { + # prometheus_retention_time = "30s", + # disable_hostname = true + #} + + # Run Vault in "HA" mode. There are no storage requirements unless the audit log + # persistence is required. In HA mode Vault will configure itself to use Consul + # for its storage backend. The default configuration provided will work the Consul + # Helm project by default. It is possible to manually configure Vault to use a + # different HA backend. + ha: + enabled: false + replicas: 3 + + # Set the api_addr configuration for Vault HA + # See https://www.vaultproject.io/docs/configuration#api_addr + # If set to null, this will be set to the Pod IP Address + apiAddr: null + + # Set the cluster_addr confuguration for Vault HA + # See https://www.vaultproject.io/docs/configuration#cluster_addr + # If set to null, this will be set to https://$(HOSTNAME).{{ template "vault.fullname" . }}-internal:8201 + clusterAddr: null + + # Enables Vault's integrated Raft storage. Unlike the typical HA modes where + # Vault's persistence is external (such as Consul), enabling Raft mode will create + # persistent volumes for Vault to store data according to the configuration under server.dataStorage. + # The Vault cluster will coordinate leader elections and failovers internally. + raft: + + # Enables Raft integrated storage + enabled: false + # Set the Node Raft ID to the name of the pod + setNodeId: false + + # Note: Configuration files are stored in ConfigMaps so sensitive data + # such as passwords should be either mounted through extraSecretEnvironmentVars + # or through a Kube secret. For more information see: + # https://www.vaultproject.io/docs/platform/k8s/helm/run#protecting-sensitive-vault-configurations + config: | + ui = true + + listener "tcp" { + tls_disable = 1 + address = "[::]:8200" + cluster_address = "[::]:8201" + # Enable unauthenticated metrics access (necessary for Prometheus Operator) + #telemetry { + # unauthenticated_metrics_access = "true" + #} + } + + storage "raft" { + path = "/vault/data" + } + + service_registration "kubernetes" {} + + # config is a raw string of default configuration when using a Stateful + # deployment. Default is to use a Consul for its HA storage backend. + # This should be HCL. + + # Note: Configuration files are stored in ConfigMaps so sensitive data + # such as passwords should be either mounted through extraSecretEnvironmentVars + # or through a Kube secret. For more information see: + # https://www.vaultproject.io/docs/platform/k8s/helm/run#protecting-sensitive-vault-configurations + config: | + ui = true + + listener "tcp" { + tls_disable = 1 + address = "[::]:8200" + cluster_address = "[::]:8201" + } + storage "consul" { + path = "vault" + address = "HOST_IP:8500" + } + + service_registration "kubernetes" {} + + # Example configuration for using auto-unseal, using Google Cloud KMS. The + # GKMS keys must already exist, and the cluster must have a service account + # that is authorized to access GCP KMS. + #seal "gcpckms" { + # project = "vault-helm-dev-246514" + # region = "global" + # key_ring = "vault-helm-unseal-kr" + # crypto_key = "vault-helm-unseal-key" + #} + + # Example configuration for enabling Prometheus metrics. + # If you are using Prometheus Operator you can enable a ServiceMonitor resource below. + # You may wish to enable unauthenticated metrics in the listener block above. + #telemetry { + # prometheus_retention_time = "30s", + # disable_hostname = true + #} + + # A disruption budget limits the number of pods of a replicated application + # that are down simultaneously from voluntary disruptions + disruptionBudget: + enabled: true + + # maxUnavailable will default to (n/2)-1 where n is the number of + # replicas. If you'd like a custom value, you can specify an override here. + maxUnavailable: null + + # Definition of the serviceAccount used to run Vault. + # These options are also used when using an external Vault server to validate + # Kubernetes tokens. + serviceAccount: + # Specifies whether a service account should be created + create: true + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + # Extra annotations for the serviceAccount definition. This can either be + # YAML or a YAML-formatted multi-line templated string map of the + # annotations to apply to the serviceAccount. + annotations: {} + + # Settings for the statefulSet used to run Vault. + statefulSet: + # Extra annotations for the statefulSet. This can either be YAML or a + # YAML-formatted multi-line templated string map of the annotations to apply + # to the statefulSet. + annotations: {} + + # Set the pod and container security contexts. + # If not set, these will default to, and for *not* OpenShift: + # pod: + # runAsNonRoot: true + # runAsGroup: {{ .Values.server.gid | default 1000 }} + # runAsUser: {{ .Values.server.uid | default 100 }} + # fsGroup: {{ .Values.server.gid | default 1000 }} + # container: + # allowPrivilegeEscalation: false + # + # If not set, these will default to, and for OpenShift: + # pod: {} + # container: {} + securityContext: + pod: {} + container: {} + + # Should the server pods run on the host network + hostNetwork: false + +# Vault UI +ui: + # True if you want to create a Service entry for the Vault UI. + # + # serviceType can be used to control the type of service created. For + # example, setting this to "LoadBalancer" will create an external load + # balancer (for supported K8S installations) to access the UI. + enabled: false + publishNotReadyAddresses: true + # The service should only contain selectors for active Vault pod + activeVaultPodOnly: false + serviceType: "ClusterIP" + serviceNodePort: null + externalPort: 8200 + targetPort: 8200 + + # The externalTrafficPolicy can be set to either Cluster or Local + # and is only valid for LoadBalancer and NodePort service types. + # The default value is Cluster. + # ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-traffic-policy + externalTrafficPolicy: Cluster + + #loadBalancerSourceRanges: + # - 10.0.0.0/16 + # - 1.78.23.3/32 + + # loadBalancerIP: + + # Extra annotations to attach to the ui service + # This can either be YAML or a YAML-formatted multi-line templated string map + # of the annotations to apply to the ui service + annotations: {} + +# secrets-store-csi-driver-provider-vault +csi: + # True if you want to install a secrets-store-csi-driver-provider-vault daemonset. + # + # Requires installing the secrets-store-csi-driver separately, see: + # https://github.com/kubernetes-sigs/secrets-store-csi-driver#install-the-secrets-store-csi-driver + # + # With the driver and provider installed, you can mount Vault secrets into volumes + # similar to the Vault Agent injector, and you can also sync those secrets into + # Kubernetes secrets. + enabled: false + + image: + repository: "hashicorp/vault-csi-provider" + tag: "1.2.0" + pullPolicy: IfNotPresent + + # volumes is a list of volumes made available to all containers. These are rendered + # via toYaml rather than pre-processed like the extraVolumes value. + # The purpose is to make it easy to share volumes between containers. + volumes: null + # - name: tls + # secret: + # secretName: vault-tls + + # volumeMounts is a list of volumeMounts for the main server container. These are rendered + # via toYaml rather than pre-processed like the extraVolumes value. + # The purpose is to make it easy to share volumes between containers. + volumeMounts: null + # - name: tls + # mountPath: "/vault/tls" + # readOnly: true + + resources: {} + # resources: + # requests: + # cpu: 50m + # memory: 128Mi + # limits: + # cpu: 50m + # memory: 128Mi + + # Settings for the daemonSet used to run the provider. + daemonSet: + updateStrategy: + type: RollingUpdate + maxUnavailable: "" + # Extra annotations for the daemonSet. This can either be YAML or a + # YAML-formatted multi-line templated string map of the annotations to apply + # to the daemonSet. + annotations: {} + # Provider host path (must match the CSI provider's path) + providersDir: "/etc/kubernetes/secrets-store-csi-providers" + # Kubelet host path + kubeletRootDir: "/var/lib/kubelet" + # Extra labels to attach to the vault-csi-provider daemonSet + # This should be a YAML map of the labels to apply to the csi provider daemonSet + extraLabels: {} + # security context for the pod template and container in the csi provider daemonSet + securityContext: + pod: {} + container: {} + + pod: + # Extra annotations for the provider pods. This can either be YAML or a + # YAML-formatted multi-line templated string map of the annotations to apply + # to the pod. + annotations: {} + + # Toleration Settings for provider pods + # This should be either a multi-line string or YAML matching the Toleration array + # in a PodSpec. + tolerations: [] + + # Extra labels to attach to the vault-csi-provider pod + # This should be a YAML map of the labels to apply to the csi provider pod + extraLabels: {} + + + + # Priority class for csi pods + priorityClassName: "" + + serviceAccount: + # Extra annotations for the serviceAccount definition. This can either be + # YAML or a YAML-formatted multi-line templated string map of the + # annotations to apply to the serviceAccount. + annotations: {} + + # Extra labels to attach to the vault-csi-provider serviceAccount + # This should be a YAML map of the labels to apply to the csi provider serviceAccount + extraLabels: {} + + # Used to configure readinessProbe for the pods. + readinessProbe: + # When a probe fails, Kubernetes will try failureThreshold times before giving up + failureThreshold: 2 + # Number of seconds after the container has started before probe initiates + initialDelaySeconds: 5 + # How often (in seconds) to perform the probe + periodSeconds: 5 + # Minimum consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + # Number of seconds after which the probe times out. + timeoutSeconds: 3 + # Used to configure livenessProbe for the pods. + livenessProbe: + # When a probe fails, Kubernetes will try failureThreshold times before giving up + failureThreshold: 2 + # Number of seconds after the container has started before probe initiates + initialDelaySeconds: 5 + # How often (in seconds) to perform the probe + periodSeconds: 5 + # Minimum consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + # Number of seconds after which the probe times out. + timeoutSeconds: 3 + + # Enables debug logging. + debug: false + + # Pass arbitrary additional arguments to vault-csi-provider. + # See https://www.vaultproject.io/docs/platform/k8s/csi/configurations#command-line-arguments + # for the available command line flags. + extraArgs: [] + +# Vault is able to collect and publish various runtime metrics. +# Enabling this feature requires setting adding `telemetry{}` stanza to +# the Vault configuration. There are a few examples included in the `config` sections above. +# +# For more information see: +# https://www.vaultproject.io/docs/configuration/telemetry +# https://www.vaultproject.io/docs/internals/telemetry +serverTelemetry: + # Enable support for the Prometheus Operator. Currently, this chart does not support + # authenticating to Vault's metrics endpoint, so the following `telemetry{}` must be included + # in the `listener "tcp"{}` stanza + # telemetry { + # unauthenticated_metrics_access = "true" + # } + # + # See the `standalone.config` for a more complete example of this. + # + # In addition, a top level `telemetry{}` stanza must also be included in the Vault configuration: + # + # example: + # telemetry { + # prometheus_retention_time = "30s", + # disable_hostname = true + # } + # + # Configuration for monitoring the Vault server. + serviceMonitor: + # The Prometheus operator *must* be installed before enabling this feature, + # if not the chart will fail to install due to missing CustomResourceDefinitions + # provided by the operator. + # + # Instructions on how to install the Helm chart can be found here: + # https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack + # More information can be found here: + # https://github.com/prometheus-operator/prometheus-operator + # https://github.com/prometheus-operator/kube-prometheus + + # Enable deployment of the Vault Server ServiceMonitor CustomResource. + enabled: false + + # Selector labels to add to the ServiceMonitor. + # When empty, defaults to: + # release: prometheus + selectors: {} + + # Interval at which Prometheus scrapes metrics + interval: 30s + + # Timeout for Prometheus scrapes + scrapeTimeout: 10s + + prometheusRules: + # The Prometheus operator *must* be installed before enabling this feature, + # if not the chart will fail to install due to missing CustomResourceDefinitions + # provided by the operator. + + # Deploy the PrometheusRule custom resource for AlertManager based alerts. + # Requires that AlertManager is properly deployed. + enabled: false + + # Selector labels to add to the PrometheusRules. + # When empty, defaults to: + # release: prometheus + selectors: {} + + # Some example rules. + rules: {} + # - alert: vault-HighResponseTime + # annotations: + # message: The response time of Vault is over 500ms on average over the last 5 minutes. + # expr: vault_core_handle_request{quantile="0.5", namespace="mynamespace"} > 500 + # for: 5m + # labels: + # severity: warning + # - alert: vault-HighResponseTime + # annotations: + # message: The response time of Vault is over 1s on average over the last 5 minutes. + # expr: vault_core_handle_request{quantile="0.5", namespace="mynamespace"} > 1000 + # for: 5m + # labels: + # severity: critical diff --git a/scripts/helmcharts/databases/values.yaml b/scripts/helmcharts/databases/values.yaml index 995ed29c7..bd2731942 100644 --- a/scripts/helmcharts/databases/values.yaml +++ b/scripts/helmcharts/databases/values.yaml @@ -137,8 +137,12 @@ kafka: # Enterprise dbs clickhouse: image: - tag: "21.9.4.35" + tag: "22.2.2.1" enabled: false postgreql: enabled: true + +# For enterpriseEdition Only +vault: + enabled: false diff --git a/scripts/helmcharts/init.sh b/scripts/helmcharts/init.sh index da9d171e7..ebbfd60c3 100644 --- a/scripts/helmcharts/init.sh +++ b/scripts/helmcharts/init.sh @@ -15,7 +15,7 @@ fatal() exit 1 } -version="v1.8.1" +version="v1.9.0" usr=`whoami` # Installing k3s @@ -59,7 +59,7 @@ usr=`whoami` which helm &> /dev/null if [[ $? -ne 0 ]]; then info "helm not installed. Installing it..." - curl -ssl https://get.helm.sh/helm-v3.4.2-linux-amd64.tar.gz -o /tmp/helm.tar.gz + curl -ssl https://get.helm.sh/helm-v3.10.1-linux-amd64.tar.gz -o /tmp/helm.tar.gz tar -xf /tmp/helm.tar.gz chmod +x linux-amd64/helm sudo cp linux-amd64/helm /usr/local/bin/helm @@ -67,6 +67,8 @@ usr=`whoami` fi } +sleep 10 + # ## Installing openssl # sudo apt update &> /dev/null # sudo apt install openssl -y &> /dev/null @@ -82,8 +84,8 @@ fatal 'DOMAIN_NAME variable is empty. Rerun the script `DOMAIN_NAME=openreplay.m } # Mac os doesn't have gnu sed, which will cause compatibility issues. -# This wrapper will help to check the sed, and use the correct version="v1.8.1" -# Ref: https://stackoverflow.com/questions/37639496/how-can-i-check-the-version="v1.8.1" +# This wrapper will help to check the sed, and use the correct version="v1.9.0" +# Ref: https://stackoverflow.com/questions/37639496/how-can-i-check-the-version="v1.9.0" function is_gnu_sed(){ sed --version >/dev/null 2>&1 } @@ -106,6 +108,7 @@ sed_i_wrapper -i "s/accessKey: \"changeMeMinioAccessKey\"/accessKey: \"$(randomP sed_i_wrapper -i "s/secretKey: \"changeMeMinioPassword\"/secretKey: \"$(randomPass)\"/g" vars.yaml sed_i_wrapper -i "s/jwt_secret: \"SetARandomStringHere\"/jwt_secret: \"$(randomPass)\"/g" vars.yaml sed_i_wrapper -i "s/assistKey: \"SetARandomStringHere\"/assistKey: \"$(randomPass)\"/g" vars.yaml +sed_i_wrapper -i "s/assistJWTSecret: \"SetARandomStringHere\"/assistJWTSecret: \"$(randomPass)\"/g" vars.yaml sed_i_wrapper -i "s/domainName: \"\"/domainName: \"${DOMAIN_NAME}\"/g" vars.yaml info "Setting proper permission for shared folder" diff --git a/scripts/helmcharts/openreplay/Chart.yaml b/scripts/helmcharts/openreplay/Chart.yaml index 5c87334d6..c409972d7 100644 --- a/scripts/helmcharts/openreplay/Chart.yaml +++ b/scripts/helmcharts/openreplay/Chart.yaml @@ -22,7 +22,7 @@ version: 0.1.0 # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. # Ref: https://github.com/helm/helm/issues/7858#issuecomment-608114589 -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" dependencies: - name: ingress-nginx diff --git a/scripts/helmcharts/openreplay/charts/alerts/Chart.yaml b/scripts/helmcharts/openreplay/charts/alerts/Chart.yaml index 1860c9115..b0e118052 100644 --- a/scripts/helmcharts/openreplay/charts/alerts/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/alerts/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/alerts/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/alerts/templates/deployment.yaml index 992f67b4d..ac01dbdac 100644 --- a/scripts/helmcharts/openreplay/charts/alerts/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/alerts/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "alerts.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -50,22 +51,47 @@ spec: value: "5432" - name: pg_dbname value: "{{ .Values.global.postgresql.postgresqlDatabase }}" + - name: ch_host + value: "{{ .Values.global.clickhouse.chHost }}" + - name: ch_port + value: "{{ .Values.global.clickhouse.service.webPort }}" - name: pg_user value: '{{ .Values.global.postgresql.postgresqlUser }}' - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: SITE_URL value: 'https://{{ .Values.global.domainName }}' - name: S3_HOST - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} value: 'https://{{ .Values.global.domainName }}:{{ .Values.global.ingress.controller.service.ports.https}}' {{- else}} value: '{{ .Values.global.s3.endpoint }}' {{- end}} - name: S3_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: S3_SECRET + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: AWS_DEFAULT_REGION value: '{{ .Values.global.s3.region }}' - name: EMAIL_HOST diff --git a/scripts/helmcharts/openreplay/charts/alerts/values.yaml b/scripts/helmcharts/openreplay/charts/alerts/values.yaml index 6562c3a46..a54418a9f 100644 --- a/scripts/helmcharts/openreplay/charts/alerts/values.yaml +++ b/scripts/helmcharts/openreplay/charts/alerts/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL @@ -90,8 +98,6 @@ autoscaling: # targetMemoryUtilizationPercentage: 80 env: - ch_host: clickhouse-openreplay-clickhouse.db.svc.cluster.local - ch_port: 9000 PYTHONUNBUFFERED: '0' diff --git a/scripts/helmcharts/openreplay/charts/assets/Chart.yaml b/scripts/helmcharts/openreplay/charts/assets/Chart.yaml index 33f7dbdb2..c12d6b251 100644 --- a/scripts/helmcharts/openreplay/charts/assets/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/assets/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/assets/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/assets/templates/deployment.yaml index 5fbd084c0..f66479475 100644 --- a/scripts/helmcharts/openreplay/charts/assets/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/assets/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "assets.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -43,9 +44,23 @@ spec: {{- end}} env: - name: AWS_ACCESS_KEY_ID + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: AWS_SECRET_ACCESS_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: S3_BUCKET_ASSETS value: {{ .Values.global.s3.assetsBucket }} - name: LICENSE_KEY @@ -54,8 +69,6 @@ spec: value: '{{ .Values.global.s3.endpoint }}' - name: AWS_REGION value: '{{ .Values.global.s3.region }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL @@ -68,9 +81,9 @@ spec: # 4. Using AWS itself. # AWS uses bucketname.endpoint/object while others use endpoint/bucketname/object - name: ASSETS_ORIGIN - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} # Local minio Installation - value: 'https://{{ .Values.global.domainName }}/{{.Values.global.s3.assetsBucket}}' + value: 'https://{{ .Values.global.domainName }}:{{.Values.global.ingress.controller.service.ports.https}}/{{.Values.global.s3.assetsBucket}}' {{- else if contains "amazonaws.com" .Values.global.s3.endpoint }} # AWS S3 # Ref: https://stackoverflow.com/questions/53634583/go-template-split-string-by-delimiter @@ -80,6 +93,7 @@ spec: # S3 compatible storage value: '{{ .Values.global.s3.endpoint }}/{{.Values.global.s3.assetsBucket}}' {{- end }} + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -90,14 +104,16 @@ spec: containerPort: {{ $val }} protocol: TCP {{- end }} - {{- with .Values.persistence.mounts }} volumeMounts: + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 12 }} + {{- with .Values.persistence.mounts }} {{- toYaml . | nindent 12 }} {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.persistence.volumes }} volumes: + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 8 }} + {{- with .Values.persistence.volumes }} {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.nodeSelector }} diff --git a/scripts/helmcharts/openreplay/charts/assets/values.yaml b/scripts/helmcharts/openreplay/charts/assets/values.yaml index 2597ed36c..f750695b7 100644 --- a/scripts/helmcharts/openreplay/charts/assets/values.yaml +++ b/scripts/helmcharts/openreplay/charts/assets/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL diff --git a/scripts/helmcharts/openreplay/charts/assist/Chart.yaml b/scripts/helmcharts/openreplay/charts/assist/Chart.yaml index 09a5ab446..022faeebf 100644 --- a/scripts/helmcharts/openreplay/charts/assist/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/assist/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/assist/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/assist/templates/deployment.yaml index b5509775d..e153e50c3 100644 --- a/scripts/helmcharts/openreplay/charts/assist/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/assist/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "assist.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -42,20 +43,38 @@ spec: {{- .Values.healthCheck | toYaml | nindent 10}} {{- end}} env: + - name: ASSIST_JWT_SECRET + value: {{ .Values.global.assistJWTSecret }} - name: ASSIST_KEY value: {{ .Values.global.assistKey }} - name: AWS_DEFAULT_REGION value: "{{ .Values.global.s3.region }}" - name: S3_HOST - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} value: 'https://{{ .Values.global.domainName }}:{{ .Values.global.ingress.controller.service.ports.https}}' {{- else}} value: '{{ .Values.global.s3.endpoint }}' {{- end}} - name: S3_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: S3_SECRET + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} + - name: REDIS_URL + value: {{ .Values.global.redis.redisHost }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' diff --git a/scripts/helmcharts/openreplay/charts/assist/values.yaml b/scripts/helmcharts/openreplay/charts/assist/values.yaml index eb9016cae..8ff07d2d0 100644 --- a/scripts/helmcharts/openreplay/charts/assist/values.yaml +++ b/scripts/helmcharts/openreplay/charts/assist/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL @@ -86,7 +94,6 @@ autoscaling: # targetMemoryUtilizationPercentage: 80 env: - REDIS_URL: "redis://redis-master.db.svc.cluster.local:6379" debug: 0 uws: false redis: false diff --git a/scripts/helmcharts/openreplay/charts/chalice/Chart.yaml b/scripts/helmcharts/openreplay/charts/chalice/Chart.yaml index 21427c490..01d5d21e1 100644 --- a/scripts/helmcharts/openreplay/charts/chalice/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/chalice/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/chalice/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/chalice/templates/deployment.yaml index 7474a7eed..30b02b563 100644 --- a/scripts/helmcharts/openreplay/charts/chalice/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/chalice/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "chalice.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -42,6 +43,16 @@ spec: {{- .Values.healthCheck | toYaml | nindent 10}} {{- end}} env: + - name: ch_host + value: "{{ .Values.global.clickhouse.chHost }}" + - name: ch_port + value: "{{ .Values.global.clickhouse.service.webPort }}" + - name: sourcemaps_reader + value: "http://sourcemaps-reader-openreplay.{{.Release.Namespace}}.{{.Values.global.clusterDomain}}:9000/sourcemaps/%s/sourcemaps" + - name: ASSIST_URL + value: "http://assist-openreplay.{{.Release.Namespace}}.{{.Values.global.clusterDomain}}:9001/assist/%s" + - name: ASSIST_JWT_SECRET + value: {{ .Values.global.assistJWTSecret }} - name: ASSIST_KEY value: {{ .Values.global.assistKey }} - name: LICENSE_KEY @@ -57,19 +68,40 @@ spec: - name: pg_user value: '{{ .Values.global.postgresql.postgresqlUser }}' - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: SITE_URL value: 'https://{{ .Values.global.domainName }}' - name: S3_HOST - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} value: 'https://{{ .Values.global.domainName }}:{{ .Values.global.ingress.controller.service.ports.https}}' {{- else}} value: '{{ .Values.global.s3.endpoint }}' {{- end}} - name: S3_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: S3_SECRET + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: AWS_DEFAULT_REGION value: '{{ .Values.global.s3.region }}' - name: sessions_region diff --git a/scripts/helmcharts/openreplay/charts/chalice/values.yaml b/scripts/helmcharts/openreplay/charts/chalice/values.yaml index 98a01ab8b..801dd26f7 100644 --- a/scripts/helmcharts/openreplay/charts/chalice/values.yaml +++ b/scripts/helmcharts/openreplay/charts/chalice/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL @@ -83,8 +91,6 @@ autoscaling: # targetMemoryUtilizationPercentage: 80 env: - ch_host: clickhouse-openreplay-clickhouse.db.svc.cluster.local - ch_port: 9000 captcha_server: '' captcha_key: '' async_Token: '' diff --git a/scripts/helmcharts/openreplay/charts/db/Chart.yaml b/scripts/helmcharts/openreplay/charts/db/Chart.yaml index 5b59f4781..1788ab793 100644 --- a/scripts/helmcharts/openreplay/charts/db/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/db/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/db/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/db/templates/deployment.yaml index f05bdd42b..039e889a1 100644 --- a/scripts/helmcharts/openreplay/charts/db/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/db/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "db.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -42,18 +43,28 @@ spec: {{- .Values.healthCheck | toYaml | nindent 10}} {{- end}} env: + - name: CLICKHOUSE_STRING + value: '{{ .Values.global.clickhouse.chHost }}:{{.Values.global.clickhouse.service.webPort}}/{{.Values.env.ch_db}}' - name: LICENSE_KEY value: '{{ .Values.global.enterpriseEditionLicense }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL value: '{{ .Values.global.kafka.kafkaUseSsl }}' - - name: POSTGRES_STRING - value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:{{ .Values.global.postgresql.postgresqlPassword }}@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} + value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: QUICKWIT_ENABLED value: '{{ .Values.global.quickwit.enabled }}' + - name: POSTGRES_STRING + value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:$(pg_password)@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -64,16 +75,18 @@ spec: containerPort: {{ $val }} protocol: TCP {{- end }} - {{- with .Values.persistence.mounts }} volumeMounts: + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 12 }} + {{- with .Values.persistence.mounts }} {{- toYaml . | nindent 12 }} {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.persistence.volumes }} volumes: + {{- with .Values.persistence.volumes }} {{- toYaml . | nindent 8 }} {{- end }} + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 8 }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/scripts/helmcharts/openreplay/charts/db/values.yaml b/scripts/helmcharts/openreplay/charts/db/values.yaml index 7d375c594..fe34eecc9 100644 --- a/scripts/helmcharts/openreplay/charts/db/values.yaml +++ b/scripts/helmcharts/openreplay/charts/db/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL @@ -90,7 +98,7 @@ autoscaling: # targetMemoryUtilizationPercentage: 80 env: - CLICKHOUSE_STRING: tcp://clickhouse-openreplay-clickhouse.db.svc.cluster.local:9000/default + ch_db: default nodeSelector: {} diff --git a/scripts/helmcharts/openreplay/charts/ender/Chart.yaml b/scripts/helmcharts/openreplay/charts/ender/Chart.yaml index 41732efc9..c15e9065f 100644 --- a/scripts/helmcharts/openreplay/charts/ender/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/ender/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/ender/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/ender/templates/deployment.yaml index a313415c8..e5b0a946b 100644 --- a/scripts/helmcharts/openreplay/charts/ender/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/ender/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "ender.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -44,14 +45,22 @@ spec: env: - name: LICENSE_KEY value: '{{ .Values.global.enterpriseEditionLicense }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL value: '{{ .Values.global.kafka.kafkaUseSsl }}' + - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} + value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: POSTGRES_STRING - value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:{{ .Values.global.postgresql.postgresqlPassword }}@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:$(pg_password)@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -62,16 +71,18 @@ spec: containerPort: {{ $val }} protocol: TCP {{- end }} - {{- with .Values.persistence.mounts }} volumeMounts: + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 12 }} + {{- with .Values.persistence.mounts }} {{- toYaml . | nindent 12 }} {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.persistence.volumes }} volumes: + {{- with .Values.persistence.volumes }} {{- toYaml . | nindent 8 }} {{- end }} + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 8 }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/scripts/helmcharts/openreplay/charts/ender/values.yaml b/scripts/helmcharts/openreplay/charts/ender/values.yaml index c751680d4..7e51481a8 100644 --- a/scripts/helmcharts/openreplay/charts/ender/values.yaml +++ b/scripts/helmcharts/openreplay/charts/ender/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL diff --git a/scripts/helmcharts/openreplay/charts/frontend/Chart.yaml b/scripts/helmcharts/openreplay/charts/frontend/Chart.yaml index e0a7e1dd6..1989cd77d 100644 --- a/scripts/helmcharts/openreplay/charts/frontend/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/frontend/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/frontend/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/frontend/templates/deployment.yaml index 7a1224e41..e5eb29441 100644 --- a/scripts/helmcharts/openreplay/charts/frontend/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/frontend/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "frontend.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -43,21 +44,42 @@ spec: {{- end}} env: - name: AWS_ACCESS_KEY_ID + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: AWS_SECRET_ACCESS_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: AWS_REGION value: '{{ .Values.global.s3.region }}' - name: LICENSE_KEY value: '{{ .Values.global.enterpriseEditionLicense }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL value: '{{ .Values.global.kafka.kafkaUseSsl }}' + - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} + value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: POSTGRES_STRING - value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:{{ .Values.global.postgresql.postgresqlPassword }}@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:$(pg_password)@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' # We need to check what is the object store endpoint. # There can be 4 options # 1. Using minio inside kube clster @@ -66,9 +88,9 @@ spec: # 4. Using AWS itself. # AWS uses bucketname.endpoint/object while others use endpoint/bucketname/object - name: ASSETS_ORIGIN - {{- if eq .Values.global.s3.endpoint "frontend://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} # Local minio Installation - value: 'frontends://{{ .Values.global.domainName }}/{{.Values.global.s3.assetsBucket}}' + value: 'frontends://{{ .Values.global.domainName }}:{{.Values.global.ingress.controller.service.ports.https}}/{{.Values.global.s3.assetsBucket}}' {{- else if contains "amazonaws.com" .Values.global.s3.endpoint }} # AWS S3 # Ref: frontends://stackoverflow.com/questions/53634583/go-template-split-string-by-delimiter @@ -78,6 +100,7 @@ spec: # S3 compatible storage value: '{{ .Values.global.s3.endpoint }}/{{.Values.global.s3.assetsBucket}}' {{- end }} + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -88,6 +111,11 @@ spec: containerPort: {{ $val }} protocol: TCP {{- end }} + volumeMounts: + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 12 }} + {{- with .Values.persistence.mounts }} + {{- toYaml . | nindent 12 }} + {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} {{- with .Values.nodeSelector }} @@ -102,3 +130,8 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} + volumes: + {{- with .Values.persistence.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 8 }} diff --git a/scripts/helmcharts/openreplay/charts/frontend/values.yaml b/scripts/helmcharts/openreplay/charts/frontend/values.yaml index 822cf6899..a34841fb2 100644 --- a/scripts/helmcharts/openreplay/charts/frontend/values.yaml +++ b/scripts/helmcharts/openreplay/charts/frontend/values.yaml @@ -25,10 +25,10 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL @@ -99,3 +99,5 @@ nodeSelector: {} tolerations: [] affinity: {} + +persistence: {} diff --git a/scripts/helmcharts/openreplay/charts/heuristics/Chart.yaml b/scripts/helmcharts/openreplay/charts/heuristics/Chart.yaml index cf70161ad..0f964f13c 100644 --- a/scripts/helmcharts/openreplay/charts/heuristics/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/heuristics/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/heuristics/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/heuristics/templates/deployment.yaml index 58059f58d..6d88fec7a 100644 --- a/scripts/helmcharts/openreplay/charts/heuristics/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/heuristics/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "heuristics.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -44,12 +45,11 @@ spec: env: - name: LICENSE_KEY value: '{{ .Values.global.enterpriseEditionLicense }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL value: '{{ .Values.global.kafka.kafkaUseSsl }}' + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -60,16 +60,18 @@ spec: containerPort: {{ $val }} protocol: TCP {{- end }} - {{- with .Values.persistence.mounts }} volumeMounts: + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 12 }} + {{- with .Values.persistence.mounts }} {{- toYaml . | nindent 12 }} {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.persistence.volumes }} volumes: + {{- with .Values.persistence.volumes }} {{- toYaml . | nindent 8 }} {{- end }} + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 8 }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/scripts/helmcharts/openreplay/charts/heuristics/values.yaml b/scripts/helmcharts/openreplay/charts/heuristics/values.yaml index ec8400866..d91bd936d 100644 --- a/scripts/helmcharts/openreplay/charts/heuristics/values.yaml +++ b/scripts/helmcharts/openreplay/charts/heuristics/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL diff --git a/scripts/helmcharts/openreplay/charts/http/Chart.yaml b/scripts/helmcharts/openreplay/charts/http/Chart.yaml index 9f4d23868..a2ed44a38 100644 --- a/scripts/helmcharts/openreplay/charts/http/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/http/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/http/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/http/templates/deployment.yaml index eaa5d7ed1..9f7d407bb 100644 --- a/scripts/helmcharts/openreplay/charts/http/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/http/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "http.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -43,21 +44,42 @@ spec: {{- end}} env: - name: AWS_ACCESS_KEY_ID + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: AWS_SECRET_ACCESS_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: AWS_REGION value: '{{ .Values.global.s3.region }}' - name: LICENSE_KEY value: '{{ .Values.global.enterpriseEditionLicense }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL value: '{{ .Values.global.kafka.kafkaUseSsl }}' + - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} + value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: POSTGRES_STRING - value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:{{ .Values.global.postgresql.postgresqlPassword }}@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:$(pg_password)@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' # We need to check what is the object store endpoint. # There can be 4 options # 1. Using minio inside kube clster @@ -66,9 +88,9 @@ spec: # 4. Using AWS itself. # AWS uses bucketname.endpoint/object while others use endpoint/bucketname/object - name: ASSETS_ORIGIN - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} # Local minio Installation - value: 'https://{{ .Values.global.domainName }}/{{.Values.global.s3.assetsBucket}}' + value: 'https://{{ .Values.global.domainName }}:{{.Values.global.ingress.controller.service.ports.https}}/{{.Values.global.s3.assetsBucket}}' {{- else if contains "amazonaws.com" .Values.global.s3.endpoint }} # AWS S3 # Ref: https://stackoverflow.com/questions/53634583/go-template-split-string-by-delimiter @@ -78,6 +100,7 @@ spec: # S3 compatible storage value: '{{ .Values.global.s3.endpoint }}/{{.Values.global.s3.assetsBucket}}' {{- end }} + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -88,14 +111,16 @@ spec: containerPort: {{ $val }} protocol: TCP {{- end }} - {{- with .Values.persistence.mounts }} volumeMounts: + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 12 }} + {{- with .Values.persistence.mounts }} {{- toYaml . | nindent 12 }} {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.persistence.volumes }} volumes: + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 8 }} + {{- with .Values.persistence.volumes }} {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.nodeSelector }} diff --git a/scripts/helmcharts/openreplay/charts/http/templates/ingress.yaml b/scripts/helmcharts/openreplay/charts/http/templates/ingress.yaml index 2097fb1cd..5188285a3 100644 --- a/scripts/helmcharts/openreplay/charts/http/templates/ingress.yaml +++ b/scripts/helmcharts/openreplay/charts/http/templates/ingress.yaml @@ -36,7 +36,7 @@ spec: path: /ingest/(.*) {{- end }} -{{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} +{{- if contains "minio" .Values.global.s3.endpoint }} ## TODO: ## Frontend service from minio will be migrated to nginx atomic container. ## This ingress is just a workaround. @@ -45,7 +45,7 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: minio - namespace: db + namespace: "{{(split "." .Values.global.s3.endpoint)._1}}" spec: ingressClassName: "{{ tpl .Values.ingress.className . }}" rules: diff --git a/scripts/helmcharts/openreplay/charts/http/values.yaml b/scripts/helmcharts/openreplay/charts/http/values.yaml index 7a96d525d..f4c0d5841 100644 --- a/scripts/helmcharts/openreplay/charts/http/values.yaml +++ b/scripts/helmcharts/openreplay/charts/http/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL diff --git a/scripts/helmcharts/openreplay/charts/integrations/Chart.yaml b/scripts/helmcharts/openreplay/charts/integrations/Chart.yaml index 6e44cf1b3..4d70e1667 100644 --- a/scripts/helmcharts/openreplay/charts/integrations/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/integrations/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/integrations/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/integrations/templates/deployment.yaml index e0f3fff60..0f9ead73c 100644 --- a/scripts/helmcharts/openreplay/charts/integrations/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/integrations/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "integrations.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -44,14 +45,22 @@ spec: env: - name: LICENSE_KEY value: '{{ .Values.global.enterpriseEditionLicense }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL value: '{{ .Values.global.kafka.kafkaUseSsl }}' + - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} + value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: POSTGRES_STRING - value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:{{ .Values.global.postgresql.postgresqlPassword }}@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:$(pg_password)@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -62,14 +71,16 @@ spec: containerPort: {{ $val }} protocol: TCP {{- end }} - {{- with .Values.persistence.mounts }} volumeMounts: + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 12 }} + {{- with .Values.persistence.mounts }} {{- toYaml . | nindent 12 }} {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.persistence.volumes }} volumes: + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 8 }} + {{- with .Values.persistence.volumes }} {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.nodeSelector }} diff --git a/scripts/helmcharts/openreplay/charts/integrations/values.yaml b/scripts/helmcharts/openreplay/charts/integrations/values.yaml index 191ed7047..dcc862a2c 100644 --- a/scripts/helmcharts/openreplay/charts/integrations/values.yaml +++ b/scripts/helmcharts/openreplay/charts/integrations/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL diff --git a/scripts/helmcharts/openreplay/charts/peers/Chart.yaml b/scripts/helmcharts/openreplay/charts/peers/Chart.yaml index 6e753e03d..6810b4353 100644 --- a/scripts/helmcharts/openreplay/charts/peers/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/peers/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/peers/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/peers/templates/deployment.yaml index 7c08dd718..2cbd395d9 100644 --- a/scripts/helmcharts/openreplay/charts/peers/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/peers/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "peers.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -45,7 +46,14 @@ spec: - name: ASSIST_KEY value: {{ .Values.global.assistKey }} - name: S3_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' diff --git a/scripts/helmcharts/openreplay/charts/peers/values.yaml b/scripts/helmcharts/openreplay/charts/peers/values.yaml index 4643a75a7..57fc30bde 100644 --- a/scripts/helmcharts/openreplay/charts/peers/values.yaml +++ b/scripts/helmcharts/openreplay/charts/peers/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL diff --git a/scripts/helmcharts/openreplay/charts/quickwit/Chart.yaml b/scripts/helmcharts/openreplay/charts/quickwit/Chart.yaml index 0c2a70eb7..651b738a8 100644 --- a/scripts/helmcharts/openreplay/charts/quickwit/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/quickwit/Chart.yaml @@ -21,4 +21,4 @@ version: 0.3.1 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/quickwit/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/quickwit/templates/deployment.yaml index df6a3181e..3ac58c215 100644 --- a/scripts/helmcharts/openreplay/charts/quickwit/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/quickwit/templates/deployment.yaml @@ -27,6 +27,7 @@ spec: serviceAccountName: {{ include "quickwit.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -47,14 +48,15 @@ spec: env: - name: AWS_DEFAULT_REGION value: "{{ .Values.global.s3.region }}" - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} - name: QW_S3_ENDPOINT - value: 'http://minio.db.svc.cluster.local:9000' + value: '{{ .Values.global.s3.endpoint }}' {{- end}} - name: AWS_ACCESS_KEY_ID value: {{ .Values.global.s3.accessKey }} - name: AWS_SECRET_ACCESS_KEY value: {{ .Values.global.s3.secretKey }} + - name: QW_DATA_DIR + value: /opt/openreplay/ ports: {{- range $key, $val := .Values.service.ports }} - name: {{ $key }} @@ -66,10 +68,14 @@ spec: volumeMounts: - name: configs mountPath: /quickwit/config/ + - name: datadir + mountPath: /opt/openreplay volumes: - name: configs configMap: name: {{ include "quickwit.fullname" . }} + - name: datadir + emptyDir: {} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/scripts/helmcharts/openreplay/charts/quickwit/templates/init.yaml b/scripts/helmcharts/openreplay/charts/quickwit/templates/init.yaml index 6739de1af..b9d102765 100644 --- a/scripts/helmcharts/openreplay/charts/quickwit/templates/init.yaml +++ b/scripts/helmcharts/openreplay/charts/quickwit/templates/init.yaml @@ -19,10 +19,8 @@ spec: env: - name: AWS_DEFAULT_REGION value: "{{ .Values.global.s3.region }}" - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} - name: QW_S3_ENDPOINT - value: 'http://minio.db.svc.cluster.local:9000' - {{- end}} + value: '{{.Values.global.s3.endpoint}}' - name: AWS_ACCESS_KEY_ID value: {{ .Values.global.s3.accessKey }} - name: AWS_SECRET_ACCESS_KEY diff --git a/scripts/helmcharts/openreplay/charts/quickwit/values.yaml b/scripts/helmcharts/openreplay/charts/quickwit/values.yaml index eaea505f8..561af61ce 100644 --- a/scripts/helmcharts/openreplay/charts/quickwit/values.yaml +++ b/scripts/helmcharts/openreplay/charts/quickwit/values.yaml @@ -43,10 +43,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL @@ -88,7 +96,6 @@ autoscaling: # targetMemoryUtilizationPercentage: 80 env: - REDIS_URL: "redis://redis-master.db.svc.cluster.local:6379" debug: 0 uws: false redis: false diff --git a/scripts/helmcharts/openreplay/charts/sink/Chart.yaml b/scripts/helmcharts/openreplay/charts/sink/Chart.yaml index 869126d87..e83ed11f2 100644 --- a/scripts/helmcharts/openreplay/charts/sink/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/sink/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/sink/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/sink/templates/deployment.yaml index 06bbad289..257af0d1a 100644 --- a/scripts/helmcharts/openreplay/charts/sink/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/sink/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "sink.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -44,8 +45,6 @@ spec: env: - name: LICENSE_KEY value: '{{ .Values.global.enterpriseEditionLicense }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL @@ -58,9 +57,9 @@ spec: # 4. Using AWS itself. # AWS uses bucketname.endpoint/object while others use endpoint/bucketname/object - name: ASSETS_ORIGIN - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} # Local minio Installation - value: 'https://{{ .Values.global.domainName }}/{{.Values.global.s3.assetsBucket}}' + value: 'https://{{ .Values.global.domainName }}:{{.Values.global.ingress.controller.service.ports.https}}/{{.Values.global.s3.assetsBucket}}' {{- else if contains "amazonaws.com" .Values.global.s3.endpoint }} # AWS S3 # Ref: https://stackoverflow.com/questions/53634583/go-template-split-string-by-delimiter @@ -70,6 +69,7 @@ spec: # S3 compatible storage value: '{{ .Values.global.s3.endpoint }}/{{.Values.global.s3.assetsBucket}}' {{- end }} + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -85,6 +85,7 @@ spec: volumeMounts: - name: datadir mountPath: /mnt/efs + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 10 }} {{- with .Values.persistence.mounts }} {{- toYaml . | nindent 10 }} {{- end }} @@ -95,6 +96,7 @@ spec: # Ensure the file directory is created. path: {{ .Values.pvc.hostMountPath }} type: DirectoryOrCreate + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 6 }} {{- with .Values.persistence.volumes }} {{- toYaml . | nindent 6 }} {{- end }} @@ -103,6 +105,7 @@ spec: - name: datadir persistentVolumeClaim: claimName: {{ .Values.pvc.name }} + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 6 }} {{- with .Values.persistence.volumes }} {{- toYaml . | nindent 8 }} {{- end }} diff --git a/scripts/helmcharts/openreplay/charts/sink/values.yaml b/scripts/helmcharts/openreplay/charts/sink/values.yaml index a37ecfa41..23ea52025 100644 --- a/scripts/helmcharts/openreplay/charts/sink/values.yaml +++ b/scripts/helmcharts/openreplay/charts/sink/values.yaml @@ -25,14 +25,16 @@ serviceAccount: podAnnotations: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 podSecurityContext: runAsUser: 1001 runAsGroup: 1001 fsGroup: 1001 fsGroupChangePolicy: "OnRootMismatch" - # fsGroup: 2000 -securityContext: {} +#securityContext: {} # capabilities: # drop: # - ALL diff --git a/ee/scripts/helm/db/clickhouse/.helmignore b/scripts/helmcharts/openreplay/charts/sourcemapreader/.helmignore similarity index 100% rename from ee/scripts/helm/db/clickhouse/.helmignore rename to scripts/helmcharts/openreplay/charts/sourcemapreader/.helmignore diff --git a/ee/scripts/helm/helm/databases/charts/clickhouse/Chart.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/Chart.yaml similarity index 85% rename from ee/scripts/helm/helm/databases/charts/clickhouse/Chart.yaml rename to scripts/helmcharts/openreplay/charts/sourcemapreader/Chart.yaml index c7a0eb3d6..1b7a7935a 100644 --- a/ee/scripts/helm/helm/databases/charts/clickhouse/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -name: clickhouse +name: sourcemapreader description: A Helm chart for Kubernetes # A chart can be either an 'application' or a 'library' chart. @@ -14,10 +14,11 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) +# Versions are expected to follow Semantic Versioning (sourcemapreaders://semver.org/) version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 1.16.0 +# It is recommended to use it with quotes. +AppVersion: "v1.9.0" diff --git a/scripts/helm/app/openreplay/templates/NOTES.txt b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/NOTES.txt similarity index 61% rename from scripts/helm/app/openreplay/templates/NOTES.txt rename to scripts/helmcharts/openreplay/charts/sourcemapreader/templates/NOTES.txt index df04fcf23..63c37cfd5 100644 --- a/scripts/helm/app/openreplay/templates/NOTES.txt +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/NOTES.txt @@ -2,21 +2,21 @@ {{- if .Values.ingress.enabled }} {{- range $host := .Values.ingress.hosts }} {{- range .paths }} - http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} + sourcemapreader{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} {{- end }} {{- end }} {{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "openreplay.fullname" . }}) + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "sourcemapreader.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT + echo sourcemapreader://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "openreplay.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "openreplay.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.port }} + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "sourcemapreader.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "sourcemapreader.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo sourcemapreader://$SERVICE_IP:{{ .Values.service.port }} {{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "openreplay.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "sourcemapreader.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") - echo "Visit http://127.0.0.1:8080 to use your application" + echo "Visit sourcemapreader://127.0.0.1:8080 to use your application" kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT {{- end }} diff --git a/scripts/helm/app/openreplay/templates/_helpers.tpl b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/_helpers.tpl similarity index 72% rename from scripts/helm/app/openreplay/templates/_helpers.tpl rename to scripts/helmcharts/openreplay/charts/sourcemapreader/templates/_helpers.tpl index ea4e67add..2a99388f1 100644 --- a/scripts/helm/app/openreplay/templates/_helpers.tpl +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/_helpers.tpl @@ -1,7 +1,7 @@ {{/* Expand the name of the chart. */}} -{{- define "openreplay.name" -}} +{{- define "sourcemapreader.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} @@ -10,7 +10,7 @@ Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "openreplay.fullname" -}} +{{- define "sourcemapreader.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} @@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name. {{/* Create chart name and version as used by the chart label. */}} -{{- define "openreplay.chart" -}} +{{- define "sourcemapreader.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} -{{- define "openreplay.labels" -}} -helm.sh/chart: {{ include "openreplay.chart" . }} -{{ include "openreplay.selectorLabels" . }} +{{- define "sourcemapreader.labels" -}} +helm.sh/chart: {{ include "sourcemapreader.chart" . }} +{{ include "sourcemapreader.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} @@ -45,17 +45,17 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} {{/* Selector labels */}} -{{- define "openreplay.selectorLabels" -}} -app.kubernetes.io/name: {{ include "openreplay.name" . }} +{{- define "sourcemapreader.selectorLabels" -}} +app.kubernetes.io/name: {{ include "sourcemapreader.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* Create the name of the service account to use */}} -{{- define "openreplay.serviceAccountName" -}} +{{- define "sourcemapreader.serviceAccountName" -}} {{- if .Values.serviceAccount.create }} -{{- default (include "openreplay.fullname" .) .Values.serviceAccount.name }} +{{- default (include "sourcemapreader.fullname" .) .Values.serviceAccount.name }} {{- else }} {{- default "default" .Values.serviceAccount.name }} {{- end }} diff --git a/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/deployment.yaml new file mode 100644 index 000000000..7abca821c --- /dev/null +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/deployment.yaml @@ -0,0 +1,105 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "sourcemapreader.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "sourcemapreader.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "sourcemapreader.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "sourcemapreader.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "sourcemapreader.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + {{- if .Values.global.enterpriseEditionLicense }} + image: "{{ tpl .Values.image.repository . }}:{{ .Values.image.tag | default .Chart.AppVersion }}-ee" + {{- else }} + image: "{{ tpl .Values.image.repository . }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.healthCheck}} + {{- .Values.healthCheck | toYaml | nindent 10}} + {{- end}} + env: + - name: AWS_ACCESS_KEY_ID + value: {{ .Values.global.s3.accessKey }} + - name: AWS_SECRET_ACCESS_KEY + value: {{ .Values.global.s3.secretKey }} + - name: AWS_REGION + value: '{{ .Values.global.s3.region }}' + - name: LICENSE_KEY + value: '{{ .Values.global.enterpriseEditionLicense }}' + - name: REDIS_STRING + value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' + - name: KAFKA_SERVERS + value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' + - name: KAFKA_USE_SSL + value: '{{ .Values.global.kafka.kafkaUseSsl }}' + - name: POSTGRES_STRING + value: 'postgres://{{ .Values.global.postgresql.postgresqlUser }}:{{ .Values.global.postgresql.postgresqlPassword }}@{{ .Values.global.postgresql.postgresqlHost }}:{{ .Values.global.postgresql.postgresqlPort }}/{{ .Values.global.postgresql.postgresqlDatabase }}' + # We need to check what is the object store endpoint. + # There can be 4 options + # 1. Using minio inside kube clster + # 2. Using minio managed external cluster, like aws minio offering + # 3. Using GCP or other object stores compatible with s3 apis + # 4. Using AWS itself. + # AWS uses bucketname.endpoint/object while others use endpoint/bucketname/object + - name: ASSETS_ORIGIN + {{- if contains "minio" .Values.global.s3.endpoint }} + # Local minio Installation + value: 'sourcemapreaders://{{ .Values.global.domainName }}:{{.Values.global.ingress.controller.service.ports.https}}/{{.Values.global.s3.assetsBucket}}' + {{- else if contains "amazonaws.com" .Values.global.s3.endpoint }} + # AWS S3 + # Ref: sourcemapreaders://stackoverflow.com/questions/53634583/go-template-split-string-by-delimiter + # We need sourcemapreaders://bucketname.s3endpoint + value: {{ (split "://" .Values.global.s3.endpoint)._0 }}://{{.Values.global.s3.assetsBucket}}.{{ (split "://" .Values.global.s3.endpoint)._1 }} + {{- else }} + # S3 compatible storage + value: '{{ .Values.global.s3.endpoint }}/{{.Values.global.s3.assetsBucket}}' + {{- end }} + {{- range $key, $val := .Values.env }} + - name: {{ $key }} + value: '{{ $val }}' + {{- end}} + ports: + {{- range $key, $val := .Values.service.ports }} + - name: {{ $key }} + containerPort: {{ $val }} + protocol: TCP + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/scripts/helm/nginx-ingress/nginx-ingress/templates/hpa.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/hpa.yaml similarity index 79% rename from scripts/helm/nginx-ingress/nginx-ingress/templates/hpa.yaml rename to scripts/helmcharts/openreplay/charts/sourcemapreader/templates/hpa.yaml index 9af6c1b79..85d6f30ac 100644 --- a/scripts/helm/nginx-ingress/nginx-ingress/templates/hpa.yaml +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/hpa.yaml @@ -2,14 +2,15 @@ apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: - name: {{ include "nginx.fullname" . }} + name: {{ include "sourcemapreader.fullname" . }} + namespace: {{ .Release.Namespace }} labels: - {{- include "nginx.labels" . | nindent 4 }} + {{- include "sourcemapreader.labels" . | nindent 4 }} spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment - name: {{ include "nginx.fullname" . }} + name: {{ include "sourcemapreader.fullname" . }} minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: diff --git a/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/ingress.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/ingress.yaml new file mode 100644 index 000000000..62983d0e6 --- /dev/null +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/ingress.yaml @@ -0,0 +1,40 @@ +{{- if .Values.ingress.enabled }} +{{- $fullName := include "sourcemapreader.fullname" . -}} +{{- $svcPort := .Values.service.ports.sourcemapreader -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "sourcemapreader.labels" . | nindent 4 }} + annotations: + {{- with .Values.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + nginx.ingress.kubernetes.io/configuration-snippet: | + index /index.html; + rewrite ^((?!.(js|css|png|svg|jpg|woff|woff2)).)*$ /index.html break; + proxy_intercept_errors on; # see sourcemapreader://nginx.org/en/docs/sourcemapreader/ngx_sourcemapreader_proxy_module.html#proxy_intercept_errors + error_page 404 =200 /index.html; + {{- .Values.ingress.cspSnippet | nindent 6}} +spec: + ingressClassName: "{{ tpl .Values.ingress.className . }}" + tls: + - hosts: + - {{ .Values.global.domainName }} + {{- if .Values.ingress.tls.secretName}} + secretName: {{ .Values.ingress.tls.secretName }} + {{- end}} + rules: + - host: {{ .Values.global.domainName }} + http: + paths: + - pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + path: /(.*) +{{- end }} diff --git a/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/service.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/service.yaml new file mode 100644 index 000000000..feef56bc5 --- /dev/null +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "sourcemapreader.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "sourcemapreader.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + {{- range $key, $val := .Values.service.ports }} + - port: {{ $val }} + targetPort: {{ $key }} + protocol: TCP + name: {{ $key }} + {{- end}} + selector: + {{- include "sourcemapreader.selectorLabels" . | nindent 4 }} diff --git a/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/serviceMonitor.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/serviceMonitor.yaml new file mode 100644 index 000000000..62410c9de --- /dev/null +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/serviceMonitor.yaml @@ -0,0 +1,18 @@ +{{- if and ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) ( .Values.serviceMonitor.enabled ) }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "sourcemapreader.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "sourcemapreader.labels" . | nindent 4 }} + {{- if .Values.serviceMonitor.additionalLabels }} + {{- toYaml .Values.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} +spec: + endpoints: + {{- .Values.serviceMonitor.scrapeConfigs | toYaml | nindent 4 }} + selector: + matchLabels: + {{- include "sourcemapreader.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/ee/scripts/helm/helm/databases/charts/clickhouse/templates/serviceaccount.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/serviceaccount.yaml similarity index 58% rename from ee/scripts/helm/helm/databases/charts/clickhouse/templates/serviceaccount.yaml rename to scripts/helmcharts/openreplay/charts/sourcemapreader/templates/serviceaccount.yaml index 1f1183598..ace4000aa 100644 --- a/ee/scripts/helm/helm/databases/charts/clickhouse/templates/serviceaccount.yaml +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/serviceaccount.yaml @@ -2,9 +2,10 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: {{ include "clickhouse.serviceAccountName" . }} + name: {{ include "sourcemapreader.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} labels: - {{- include "clickhouse.labels" . | nindent 4 }} + {{- include "sourcemapreader.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} annotations: {{- toYaml . | nindent 4 }} diff --git a/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/tests/test-connection.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/tests/test-connection.yaml new file mode 100644 index 000000000..08c4a5f46 --- /dev/null +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "sourcemapreader.fullname" . }}-test-connection" + labels: + {{- include "sourcemapreader.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "sourcemapreader.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/scripts/helm/app/openreplay/values.yaml b/scripts/helmcharts/openreplay/charts/sourcemapreader/values.yaml similarity index 56% rename from scripts/helm/app/openreplay/values.yaml rename to scripts/helmcharts/openreplay/charts/sourcemapreader/values.yaml index 498f88801..d7a0341a5 100644 --- a/scripts/helm/app/openreplay/values.yaml +++ b/scripts/helmcharts/openreplay/charts/sourcemapreader/values.yaml @@ -1,20 +1,18 @@ -# Default values for OpenReplay. +# Default values for openreplay. # This is a YAML-formatted file. # Declare variables to be passed into your templates. replicaCount: 1 -namespace: default image: - repository: "" - name: nginx + repository: "{{ .Values.global.openReplayContainerRegistry }}/sourcemaps-reader" pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "" imagePullSecrets: [] -nameOverride: "" -fullnameOverride: "" +nameOverride: "sourcemapreader" +fullnameOverride: "sourcemapreader-openreplay" serviceAccount: # Specifies whether a service account should be created @@ -27,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL @@ -40,20 +46,35 @@ securityContext: {} service: type: ClusterIP - port: 80 + ports: + sourcemapreader: 9000 + +serviceMonitor: + enabled: false + additionalLabels: + release: observability + scrapeConfigs: + - port: metrics + honorLabels: true + interval: 15s + path: /metrics + scheme: sourcemapreader + scrapeTimeout: 10s ingress: enabled: false - annotations: {} + className: "{{ .Values.global.ingress.controller.ingressClassResource.name }}" + cspSnippet: |- + # Custom CSP snippet here. + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "120" + nginx.ingress.kubernetes.io/proxy-send-timeout: "300" + nginx.ingress.kubernetes.io/proxy-read-timeout: "300" # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: [] - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local + tls: + secretName: openreplay-ssl resources: {} # We usually recommend not to specify default resources and to leave this as a conscious @@ -70,10 +91,12 @@ resources: {} autoscaling: enabled: false minReplicas: 1 - maxReplicas: 100 + maxReplicas: 5 targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 80 +env: {} + nodeSelector: {} tolerations: [] diff --git a/scripts/helmcharts/openreplay/charts/storage/Chart.yaml b/scripts/helmcharts/openreplay/charts/storage/Chart.yaml index 09ebf3ef6..3f6ed0843 100644 --- a/scripts/helmcharts/openreplay/charts/storage/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/storage/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/storage/templates/deployment.yaml b/scripts/helmcharts/openreplay/charts/storage/templates/deployment.yaml index 5a2e8c73d..d20059fdc 100644 --- a/scripts/helmcharts/openreplay/charts/storage/templates/deployment.yaml +++ b/scripts/helmcharts/openreplay/charts/storage/templates/deployment.yaml @@ -28,6 +28,7 @@ spec: serviceAccountName: {{ include "storage.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + shareProcessNamespace: true containers: - name: {{ .Chart.Name }} securityContext: @@ -43,9 +44,23 @@ spec: {{- end}} env: - name: AWS_ACCESS_KEY_ID + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: AWS_SECRET_ACCESS_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: AWS_ENDPOINT value: '{{ .Values.global.s3.endpoint }}' - name: AWS_REGION_WEB @@ -58,12 +73,11 @@ spec: value: {{ .Values.global.s3.recordingsBucket }} - name: LICENSE_KEY value: '{{ .Values.global.enterpriseEditionLicense }}' - - name: REDIS_STRING - value: '{{ .Values.global.redis.redisHost }}:{{ .Values.global.redis.redisPort }}' - name: KAFKA_SERVERS value: '{{ .Values.global.kafka.kafkaHost }}:{{ .Values.global.kafka.kafkaPort }}' - name: KAFKA_USE_SSL value: '{{ .Values.global.kafka.kafkaUseSsl }}' + {{- include "openreplay.env.redis_string" .Values.global.redis | nindent 12 }} {{- range $key, $val := .Values.env }} - name: {{ $key }} value: '{{ $val }}' @@ -79,6 +93,7 @@ spec: volumeMounts: - name: datadir mountPath: /mnt/efs + {{- include "openreplay.volume.redis_ca_certificate.mount" .Values.global.redis | nindent 10 }} {{- with .Values.persistence.mounts }} {{- toYaml . | nindent 10 }} {{- end }} @@ -101,6 +116,7 @@ spec: persistentVolumeClaim: claimName: {{ .Values.pvc.name }} {{- end }} + {{- include "openreplay.volume.redis_ca_certificate" .Values.global.redis | nindent 6 }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/scripts/helmcharts/openreplay/charts/storage/values.yaml b/scripts/helmcharts/openreplay/charts/storage/values.yaml index b73c2cf1e..85fa7ea65 100644 --- a/scripts/helmcharts/openreplay/charts/storage/values.yaml +++ b/scripts/helmcharts/openreplay/charts/storage/values.yaml @@ -25,14 +25,16 @@ serviceAccount: podAnnotations: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 podSecurityContext: runAsUser: 1001 runAsGroup: 1001 fsGroup: 1001 fsGroupChangePolicy: "OnRootMismatch" - # fsGroup: 2000 -securityContext: {} +#securityContext: {} # capabilities: # drop: # - ALL diff --git a/scripts/helmcharts/openreplay/charts/utilities/Chart.yaml b/scripts/helmcharts/openreplay/charts/utilities/Chart.yaml index cde8fd180..b92bba869 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.8.1" +AppVersion: "v1.9.0" diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml index f4f3ea409..e88aabe80 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml @@ -22,9 +22,9 @@ spec: - -c args: - | - # Delete all the files older than 7 days + # Delete all the files older than {{.Values.efsCleaner.retention}} days set -x - echo "Cleaning NFS strorage for data older than 7 days" + echo "Cleaning NFS strorage for data older than {{.Values.efsCleaner.retention}} days" storage=`du -sh /mnt/efs` find /mnt/efs -type f -mtime +{{.Values.efsCleaner.retention}} -delete echo "Storage before cleaning" diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/report-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/report-cron.yaml index 0685c7ad2..17fa52720 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/report-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/report-cron.yaml @@ -31,19 +31,40 @@ spec: - name: pg_user value: '{{ .Values.global.postgresql.postgresqlUser }}' - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: SITE_URL value: 'https://{{ .Values.global.domainName }}' - name: S3_HOST - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} value: 'https://{{ .Values.global.domainName }}:{{ .Values.global.ingress.controller.service.ports.https}}' {{- else}} value: '{{ .Values.global.s3.endpoint }}' {{- end}} - name: S3_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: S3_SECRET + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: AWS_DEFAULT_REGION value: '{{ .Values.global.s3.region }}' - name: sessions_region diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/sessions-cleaner-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/sessions-cleaner-cron.yaml index 7441ca106..49bc8cfed 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/sessions-cleaner-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/sessions-cleaner-cron.yaml @@ -31,19 +31,40 @@ spec: - name: pg_user value: '{{ .Values.global.postgresql.postgresqlUser }}' - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: SITE_URL value: 'https://{{ .Values.global.domainName }}' - name: S3_HOST - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} value: 'https://{{ .Values.global.domainName }}:{{ .Values.global.ingress.controller.service.ports.https}}' {{- else}} value: '{{ .Values.global.s3.endpoint }}' {{- end}} - name: S3_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: S3_SECRET + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: AWS_DEFAULT_REGION value: '{{ .Values.global.s3.region }}' - name: sessions_region diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/telemetry-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/telemetry-cron.yaml index 92ed861ff..b9044664f 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/telemetry-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/telemetry-cron.yaml @@ -31,19 +31,40 @@ spec: - name: pg_user value: '{{ .Values.global.postgresql.postgresqlUser }}' - name: pg_password + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} - name: SITE_URL value: 'https://{{ .Values.global.domainName }}' - name: S3_HOST - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} value: 'https://{{ .Values.global.domainName }}:{{ .Values.global.ingress.controller.service.ports.https}}' {{- else}} value: '{{ .Values.global.s3.endpoint }}' {{- end}} - name: S3_KEY + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: access-key + {{- else }} value: {{ .Values.global.s3.accessKey }} + {{- end }} - name: S3_SECRET + {{- if .Values.global.s3.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.s3.existingSecret }} + key: secret-key + {{- else }} value: {{ .Values.global.s3.secretKey }} + {{- end }} - name: AWS_DEFAULT_REGION value: '{{ .Values.global.s3.region }}' - name: sessions_region diff --git a/scripts/helmcharts/openreplay/charts/utilities/values.yaml b/scripts/helmcharts/openreplay/charts/utilities/values.yaml index 90632b4c2..2076f8349 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/values.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/values.yaml @@ -55,7 +55,6 @@ sessionsCleaner: # Common env values are from chalice for the crons chalice: env: - ch_host: clickhouse-openreplay-clickhouse.db.svc.cluster.local ch_port: 9000 captcha_server: '' captcha_key: '' @@ -84,3 +83,13 @@ fullnameOverride: "utilities-openreplay" # refer: https://crontab.guru/#5_3_*_*_1 cron: "5 3 */3 * *" +# Pod configurations + +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" diff --git a/scripts/helmcharts/openreplay/files/clickhouse.sh b/scripts/helmcharts/openreplay/files/clickhouse.sh index 3e29cf2df..5b11f4e91 100644 --- a/scripts/helmcharts/openreplay/files/clickhouse.sh +++ b/scripts/helmcharts/openreplay/files/clickhouse.sh @@ -2,7 +2,7 @@ set -ex -clickhousedir=/opt/openreplay/openreplay/scripts/helm/db/init_dbs/clickhouse +clickhousedir=/opt/openreplay/openreplay/scripts/schema/db/init_dbs/clickhouse function migrate() { echo "Starting clickhouse migration" @@ -11,7 +11,7 @@ function migrate() { echo "Migrating clickhouse version $version" # For now, we can ignore the clickhouse db inject errors. # TODO: Better error handling in script - clickhouse-client -h clickhouse-openreplay-clickhouse.db.svc.cluster.local --port 9000 --multiquery < ${clickhousedir}/${version}/${version}.sql || true + clickhouse-client -h ${CH_HOST} --port ${CH_PORT} --multiquery < ${clickhousedir}/${version}/${version}.sql || true done } @@ -19,7 +19,7 @@ function init() { echo "Initializing clickhouse" for file in `ls ${clickhousedir}/create/*.sql`; do echo "Injecting $file" - clickhouse-client -h clickhouse-openreplay-clickhouse.db.svc.cluster.local --port 9000 --multiquery < $file || true + clickhouse-client -h ${CH_HOST} --port ${CH_PORT} --multiquery < $file || true done } diff --git a/scripts/helmcharts/openreplay/files/dbops.sh b/scripts/helmcharts/openreplay/files/dbops.sh index fd238471e..21ace9d2c 100644 --- a/scripts/helmcharts/openreplay/files/dbops.sh +++ b/scripts/helmcharts/openreplay/files/dbops.sh @@ -32,7 +32,7 @@ function migration() { fi # Checking migration versions - cd /opt/openreplay/openreplay/scripts/helm + cd /opt/openreplay/openreplay/scripts/schema migration_versions=(`ls -l db/init_dbs/$db | grep -E ^d | awk -v number=${PREVIOUS_APP_VERSION} '$NF > number {print $NF}' | grep -v create`) echo "Migration version: ${migration_versions[*]}" # Can't pass the space seperated array to ansible for migration. So joining them with , diff --git a/scripts/helmcharts/openreplay/files/minio.sh b/scripts/helmcharts/openreplay/files/minio.sh index 31502ae39..34229572c 100644 --- a/scripts/helmcharts/openreplay/files/minio.sh +++ b/scripts/helmcharts/openreplay/files/minio.sh @@ -5,9 +5,10 @@ set -e cd /tmp -buckets=("mobs" "sessions-assets" "static" "sourcemaps" "sessions-mobile-assets" "quickwit") +buckets=("mobs" "sessions-assets" "sourcemaps" "sessions-mobile-assets" "quickwit" "vault-data") -mc alias set minio http://minio.db.svc.cluster.local:9000 $MINIO_ACCESS_KEY $MINIO_SECRET_KEY + +mc alias set minio $MINIO_HOST $MINIO_ACCESS_KEY $MINIO_SECRET_KEY function init() { echo "Initializing minio" @@ -31,11 +32,14 @@ mc mb minio/${bucket} || true done mc ilm import minio/mobs < /tmp/lifecycle.json || true -# Creating frontend bucket +##################################################### +# Creating frontend bucket; Do not change this block! +# !! PUBLIC BUCKETS !! +##################################################### mc mb minio/frontend || true mc policy set download minio/frontend || true mc policy set download minio/sessions-assets || true -mc policy set download minio/static || true + } # /bin/bash kafka.sh migrate $migration_versions diff --git a/scripts/helmcharts/openreplay/files/postgresql.sh b/scripts/helmcharts/openreplay/files/postgresql.sh index a641e4650..673f1b5c4 100644 --- a/scripts/helmcharts/openreplay/files/postgresql.sh +++ b/scripts/helmcharts/openreplay/files/postgresql.sh @@ -2,7 +2,7 @@ set -ex -pgdir=/opt/openreplay/openreplay/scripts/helm/db/init_dbs/postgresql +pgdir=/opt/openreplay/openreplay/scripts/schema/db/init_dbs/postgresql # ENV variables # Ref: https://www.postgresql.org/docs/current/libpq-envars.html @@ -17,13 +17,13 @@ function migrate() { IFS=',' read -r -a migration_versions <<< "$1" for version in ${migration_versions[*]}; do echo "Migrating postgresql version $version" - psql -f ${pgdir}/${version}/${version}.sql 2>&1 + psql -v ON_ERROR_STOP=1 -f ${pgdir}/${version}/${version}.sql 2>&1 done } function init() { echo "Initializing postgresql" - psql -f ${pgdir}/init_schema.sql 2>&1 + psql -v ON_ERROR_STOP=1 -f ${pgdir}/init_schema.sql 2>&1 } # /bin/bash postgresql.sh migrate $migration_versions diff --git a/scripts/helmcharts/openreplay/files/vault.sh b/scripts/helmcharts/openreplay/files/vault.sh new file mode 100644 index 000000000..87670acde --- /dev/null +++ b/scripts/helmcharts/openreplay/files/vault.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +# This script will initialize vault + +# VERBOSE=1 for verbose logging +if [ "x$VERBOSE" == "x1" ]; then + set -x +fi + +export VAULT_ADDR=${VAULT_ADDR} + + +# Check vault is already initialized, if so return + +# initialize vault +vault_output=$(vault operator init) 2> /opt/openreplay/err.txt || { + err_code=$? + (cat /opt/openreplay/err.txt | grep -i "vault is already initialized") && { + echo "Vault already initialized." + err_code=0 + } + exit $err_code +} + +# Writting output to a file +echo $vault_output > /opt/openreplay/vault_creds.txt + +# Unsealing vault +for i in 1 2 3; do + vault operator unseal `echo $vault_output | grep -Eio "unseal key $i: \S+" | awk '{print $4}'` +done + +# Logging in to vault +vault login `echo $vault_output | grep -Eio "initial root token: \S+" | awk '{print $4}'` + +# Confguration + +vault secrets enable database + +vault write database/roles/db-app \ + db_name=postgres \ + creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \ + GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \ + revocation_statements="ALTER ROLE \"{{name}}\" NOLOGIN;"\ + default_ttl="1h" \ + max_ttl="1d" + +vault write database/config/postgres \ + plugin_name=postgresql-database-plugin \ + allowed_roles="*" \ + connection_url="postgresql://{{username}}:{{password}}@$PGHOST:$PGPORT/$PGDATABASE" \ + username="${PGUSER}" \ + password="${PGPASSWORD}" + +vault auth enable kubernetes + +vault write auth/kubernetes/config \ + kubernetes_host=https://${KUBERNETES_PORT_443_TCP_ADDR}:443 \ + kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt + + +# Allow apps to create credentials for the policy db-app +cat <<EOF >/opt/openreplay/pgaccess-policy.hcl +path "database/creds/db-app" { + capabilities = ["read"] +} +EOF + +vault policy write pgaccess /opt/openreplay/pgaccess-policy.hcl + +vault write auth/kubernetes/role/pgaccess \ + bound_service_account_names="*-openreplay" \ + bound_service_account_namespaces=app \ + policies=pgaccess \ + ttl=1h diff --git a/scripts/helmcharts/openreplay/templates/_helpers.tpl b/scripts/helmcharts/openreplay/templates/_helpers.tpl index ea4e67add..400ff0366 100644 --- a/scripts/helmcharts/openreplay/templates/_helpers.tpl +++ b/scripts/helmcharts/openreplay/templates/_helpers.tpl @@ -60,3 +60,45 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +Create the environment configuration for REDIS_STRING +*/}} +{{- define "openreplay.env.redis_string" -}} +{{- $scheme := (eq (.tls | default dict).enabled true) | ternary "rediss" "redis" -}} +{{- $auth := "" -}} +{{- if or .existingSecret .redisPassword -}} + {{- $auth = printf "%s:$(REDIS_PASSWORD)@" (.redisUsername | default "") -}} +{{- end -}} +{{- if .existingSecret -}} +- name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .existingSecret }} + key: redis-password +{{- else if .redisPassword }} +- name: REDIS_PASSWORD + value: {{ .redisPassword }} +{{- end}} +- name: REDIS_STRING + value: '{{ $scheme }}://{{ $auth }}{{ .redisHost }}:{{ .redisPort }}' +{{- end }} + +{{/* +Create the volume mount config for redis TLS certificates +*/}} +{{- define "openreplay.volume.redis_ca_certificate" -}} +{{- if and ((.tls | default dict).enabled) (.tls.certificatesSecret) (.tls.certCAFilename) -}} +- name: redis-ca-certificate + secret: + secretName: {{ .tls.certificatesSecret }} +{{- end }} +{{- end }} + +{{- define "openreplay.volume.redis_ca_certificate.mount" -}} +{{- if and ((.tls |default dict).enabled) (.tls.certificatesSecret) (.tls.certCAFilename) -}} +- name: redis-ca-certificate + mountPath: /etc/ssl/certs/redis-ca-certificate.pem + subPath: {{ .tls.certCAFilename }} +{{- end }} +{{- end }} diff --git a/scripts/helmcharts/openreplay/templates/job.yaml b/scripts/helmcharts/openreplay/templates/job.yaml index c0d7f0a45..aaadc2eb7 100644 --- a/scripts/helmcharts/openreplay/templates/job.yaml +++ b/scripts/helmcharts/openreplay/templates/job.yaml @@ -50,7 +50,7 @@ spec: error_connection=1 while [ $exit_count -le 20 ];do - nc -zv clickhouse-openreplay-clickhouse.db.svc.cluster.local 9000 -w 1 + nc -zv {{.Values.global.clickhouse.chHost}} 9000 -w 1 if [ $? -ne 0 ]; then echo "[info] clickhouse is not up; retrying in 5 seconds" sleep 4 @@ -91,7 +91,14 @@ spec: - name: PGUSER value: "{{ .Values.global.postgresql.postgresqlUser }}" - name: PGPASSWORD - value: "{{ .Values.global.postgresql.postgresqlPassword }}" + {{- if .Values.global.postgresql.existingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.global.postgresql.existingSecret }} + key: postgresql-postgres-password + {{- else }} + value: '{{ .Values.global.postgresql.postgresqlPassword }}' + {{- end}} image: bitnami/postgresql:13.3.0-debian-10-r53 command: - /bin/bash @@ -103,7 +110,7 @@ spec: mountPath: /opt/openreplay - name: dbmigrationscript mountPath: /opt/migrations/ - {{- if eq .Values.global.s3.endpoint "http://minio.db.svc.cluster.local:9000" }} + {{- if contains "minio" .Values.global.s3.endpoint }} - name: minio image: bitnami/minio:2020.10.9-debian-10-r6 env: @@ -119,6 +126,8 @@ spec: value: "{{ .Values.minio.global.minio.accessKey }}" - name: MINIO_SECRET_KEY value: "{{ .Values.minio.global.minio.secretKey }}" + - name: MINIO_HOST + value: "{{ .Values.global.s3.endpoint }}" command: - /bin/bash - /opt/migrations/dbops.sh @@ -132,6 +141,75 @@ spec: {{- end}} {{- if .Values.global.enterpriseEditionLicense }} # Enterprise migration + {{- if .Values.vault.enabled }} + - name: vault + env: + - name: FORCE_MIGRATION + value: "{{ .Values.forceMigration }}" + - name: PGHOST + value: "{{ .Values.global.postgresql.postgresqlHost }}" + - name: PGPORT + value: "{{ .Values.global.postgresql.postgresqlPort }}" + - name: PGDATABASE + value: "{{ .Values.global.postgresql.postgresqlDatabase }}" + - name: PGUSER + value: "{{ .Values.global.postgresql.postgresqlUser }}" + - name: PGPASSWORD + value: "{{ .Values.global.postgresql.postgresqlPassword }}" + - name: VAULT_ADDR + value: "{{ .Values.global.vault.vaultHost }}" + image: hashicorp/vault:1.12.0 + command: + - /bin/sh + - /opt/migrations/vault.sh + volumeMounts: + - name: shared + mountPath: /opt/openreplay + - name: dbmigrationscript + mountPath: /opt/migrations/ + - name: vault-s3-upload + env: + - name: AWS_ACCESS_KEY_ID + value: "{{ .Values.global.s3.accessKey }}" + - name: AWS_SECRET_ACCESS_KEY + value: "{{ .Values.global.s3.secretKey }}" + - name: AWS_DEFAULT_REGION + value: "{{ .Values.global.s3.region }}" + - name: AWS_ENDPOINT + value: "{{ .Values.global.s3.endpoint }}" + - name: VAULT_BUCKET + value: "{{ .Values.global.s3.vaultBucket }}" + image: amazon/aws-cli + command: + - /bin/bash + - -c + args: + - | + while true; do + [[ -f /opt/openreplay/vault_creds.txt ]] && { + aws s3 cp --endpoint ${AWS_ENDPOINT} /opt/openreplay/vault_creds.txt s3://${VAULT_BUCKET}/vault/ + exit 0 + } || { + [[ -f /opt/openreplay/err.txt ]] && { + (cat /opt/openreplay/err.txt | grep -i "vault is already initialized") && { + cat /opt/openreplay/err.txt + echo vault already initialized + exit 0 + } || { + echo Unknown error + cat /opt/openreplay/err.txt + exit 2 + } + } + } || { + echo vault not yet initialized; + sleep 2 + }; + done + volumeMounts: + - name: shared + mountPath: /opt/openreplay + {{- end }} - name: clickhouse image: yandex/clickhouse-client:21.9.4.35 env: @@ -141,6 +219,10 @@ spec: value: "{{ .Values.fromVersion }}" - name: CHART_APP_VERSION value: "{{ .Chart.AppVersion }}" + - name: CH_HOST + value: "{{.Values.global.clickhouse.chHost}}" + - name: CH_PORT + value: "{{.Values.global.clickhouse.service.webPort}}" command: - /bin/bash - /opt/migrations/dbops.sh diff --git a/scripts/helmcharts/openreplay/values.yaml b/scripts/helmcharts/openreplay/values.yaml index 24f358283..33cc3e178 100644 --- a/scripts/helmcharts/openreplay/values.yaml +++ b/scripts/helmcharts/openreplay/values.yaml @@ -25,10 +25,18 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +securityContext: + runAsUser: 1001 + runAsGroup: 1001 +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: {} # fsGroup: 2000 -securityContext: {} +# securityContext: {} # capabilities: # drop: # - ALL @@ -36,26 +44,6 @@ securityContext: {} # runAsNonRoot: true # runAsUser: 1000 -service: - type: ClusterIP - port: 80 - -ingress: - enabled: false - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - resources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little @@ -81,45 +69,6 @@ tolerations: [] affinity: {} -nginx-ingress: - fullnameOverride: nginx-ingress - image: - # Using openresty because we need lua support, - # and dynamic resolve config from local. - # Ref: https://serverfault.com/questions/638822/nginx-resolver-address-from-etc-resolv-conf - repository: rg.fr-par.scw.cloud/foss/openresty - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "buster" - -# By default http listens to 80 port, and for v1.7.0 http listens in 80 -http: - podSecurityContext: - runAsUser: 0 - runAsGroup: 0 - fsGroup: 0 - fsGroupChangePolicy: "OnRootMismatch" -# Running sink and storage as non root users, because of existing volume permission change will take time -sink: - podSecurityContext: - runAsUser: 0 - runAsGroup: 0 - fsGroup: 0 - fsGroupChangePolicy: "OnRootMismatch" -storage: - podSecurityContext: - runAsUser: 0 - runAsGroup: 0 - fsGroup: 0 - fsGroupChangePolicy: "OnRootMismatch" - -chalice: - podSecurityContext: - runAsUser: 0 - runAsGroup: 0 - fsGroup: 0 - fsGroupChangePolicy: "OnRootMismatch" - ingress-nginx: enabled: true controller: @@ -132,3 +81,26 @@ ingress-nginx: ## repository: tag: "v1.3.0" digest: "" + +# For enterpriseEdition Only +vault: &vault + vaultHost: databases-vault.db.svc.cluster.local:8200 + annotations: + vault.hashicorp.com/agent-cache-enable: "true" + vault.hashicorp.com/agent-inject: "true" + vault.hashicorp.com/agent-inject-token: "true" + vault.hashicorp.com/template-static-secret-render-interval: 2m + # vault.hashicorp.com/log-level: debug + vault.hashicorp.com/agent-run-as-same-user: "true" + vault.hashicorp.com/agent-inject-command-processor.properties: | + pkill -TERM openreplay + vault.hashicorp.com/role: pgaccess + vault.hashicorp.com/agent-inject-secret-processor.properties: database/creds/db-app + vault.hashicorp.com/agent-inject-template-processor.properties: | + {{- with secret "database/creds/db-app" -}} + POSTGRES_STRING=postgres://{{.Data.username}}:{{.Data.password}}@postgresql.db.svc.cluster.local:5432/postgres + {{- end -}} + +global: + vault: *vault + clusterDomain: "svc.cluster.local" diff --git a/scripts/helmcharts/vars.yaml b/scripts/helmcharts/vars.yaml index dd1f36883..c77881963 100644 --- a/scripts/helmcharts/vars.yaml +++ b/scripts/helmcharts/vars.yaml @@ -1,4 +1,4 @@ -fromVersion: "v1.8.1" +fromVersion: "v1.9.0" # Databases specific variables postgresql: &postgres # For generating passwords @@ -17,9 +17,12 @@ postgresql: &postgres # asdf # cpu: 2 -clickhouse: +clickhouse: &clickhouse # For enterpriseEdition enabled: false + chHost: clickhouse-openreplay-clickhouse.db.svc.cluster.local + service: + webPort: 9000 quickwit: &quickwit # For enterpriseEdition @@ -91,6 +94,7 @@ ingress-nginx: &ingress-nginx force-ssl-redirect: false proxy-body-size: 10m + # Application specific variables global: ingress: *ingress-nginx @@ -98,15 +102,19 @@ global: kafka: *kafka redis: *redis quickwit: *quickwit + clickhouse: *clickhouse + # Registry URL from where the OR images should be pulled. openReplayContainerRegistry: "public.ecr.aws/p1t3u8a3" # secret key to inject to assist and peers service assistKey: "SetARandomStringHere" + assistJWTSecret: "SetARandomStringHere" s3: region: "us-east-1" endpoint: "http://minio.db.svc.cluster.local:9000" assetsBucket: "sessions-assets" recordingsBucket: "mobs" sourcemapsBucket: "sourcemaps" + vaultBucket: "vault-data" # This is only for enterpriseEdition quickwitBucket: "quickwit" # if you're using one node installation, where @@ -138,6 +146,9 @@ global: # storage: # pvc: # name: mysharedpersistence +# chalice: +# pvc: +# name: mysharedpersistence chalice: env: @@ -166,3 +177,4 @@ chalice: # requests: # cpu: 512m # memory: 2056Mi + diff --git a/scripts/helmcharts/vars_template.yaml b/scripts/helmcharts/vars_template.yaml deleted file mode 100644 index 1e008250d..000000000 --- a/scripts/helmcharts/vars_template.yaml +++ /dev/null @@ -1,111 +0,0 @@ -fromVersion: "{{ openreplay_version }}" -# Databases specific variables -postgresql: &postgres - # For generating passwords - # `openssl rand -hex 20` - postgresqlPassword: "{{ postgres_db_password }}" - postgresqlHost: "{{ postgres_endpoint }}" - postgresqlPort: "5432" - postgresqlUser: "{{ postgres_db_user }}" - postgresqlDatabase: "{{ postgres_db_name }}" - # resources: - # requests: - # memory: 256Mi - # cpu: 250m - # limits: - # memory: 3000Mi - # cpu: 2 - -clickhouse: {} - # For enterpriseEdition - # enabled: true - -kafka: &kafka - # For enterpriseEdition - # enabled: true - - kafkaHost: "{{ kafka_endpoint.split(':')[0] }}" - kafkaPort: "{{ kafka_endpoint.split(':')[-1] }}" - kafkaUseSsl: "{{ kafka_ssl }}" - -redis: &redis - # For enterpriseEdition - # enabled: false - redisHost: "{{ redis_endpoint.split(':')[0] }}" - redisPort: "{{ redis_endpoint.split(':')[-1] }}" - -minio: - global: - minio: - # For generating passwords - # `openssl rand -hex 20` - accessKey: "{{ minio_access_key }}" - secretKey: "{{ minio_secret_key }}" - -# Application specific variables -global: - postgresql: *postgres - kafka: *kafka - redis: *redis - s3: - region: "{{ aws_region }}" - endpoint: "{{ s3_endpoint }}" - assetsBucket: "{{ assets_bucket }}" - recordingsBucket: "{{ recordings_bucket }}" - sourcemapsBucket: "{{ sourcemaps_bucket }}" - # if you're using one node installation, where - # you're using local s3, make sure these variables - # are same as minio.global.minio.accesskey and secretKey - accessKey: "{{ minio_access_key }}" - secretKey: "{{ minio_secret_key }}" - email: - emailHost: '{{ email_host }}' - emailPort: '{{ email_port }}' - emailUser: '{{ email_user }}' - emailPassword: '{{ email_password }}' - emailUseTls: '{{ email_use_tls }}' - emailUseSsl: '{{ email_use_ssl }}' - emailSslKey: '{{ email_ssl_key }}' - emailSslCert: '{{ email_ssl_cert }}' - emailFrom: '{{ email_from }}' - - enterpriseEditionLicense: "{{ enterprise_edition_license }}" - domainName: "{{ domain_name }}" - -chalice: - env: - jwt_secret: "{{ jwt_secret_key }}" - # captcha_server: '' - # captcha_key: '' - # SAML2_MD_URL: '' - # idp_entityId: '' - # idp_sso_url: '' - # idp_x509cert: '' - # idp_sls_url: '' - # idp_name: '' - # idp_tenantKey: '' - - -# If you want to override something -# chartname: -# filedFrom chart/Values.yaml: -# key: value - -# For example: -# -# http: -# resources: -# limits: -# cpu: 1024m -# memory: 4096Mi -# requests: -# cpu: 512m -# memory: 2056Mi - -## Changes to nginx -# -# nginx-ingress: -# customServerConfigs: | -# # Redirecting http to https -# return 301 https://$host$request_uri; -# diff --git a/scripts/helmcharts/versionUpdater.sh b/scripts/helmcharts/versionUpdater.sh index 5fc8230a2..70c388dcc 100644 --- a/scripts/helmcharts/versionUpdater.sh +++ b/scripts/helmcharts/versionUpdater.sh @@ -7,4 +7,4 @@ currentVersion=$1 } find ./openreplay -type f -iname chart.yaml -exec sed -i "s/AppVersion.*/AppVersion: \"$currentVersion\"/g" {} \; sed -i "s/fromVersion.*/fromVersion: \"$currentVersion\"/g" vars.yaml -sed -i "s/version.*/version=\"$currentVersion\"/g" init.sh +sed -i "s/version=.*/version=\"$currentVersion\"/g" init.sh diff --git a/scripts/helm/db/init_dbs/postgresql/1.2.0/1.2.0.sql b/scripts/schema/db/init_dbs/postgresql/1.2.0/1.2.0.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.2.0/1.2.0.sql rename to scripts/schema/db/init_dbs/postgresql/1.2.0/1.2.0.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.3.0/1.3.0.sql b/scripts/schema/db/init_dbs/postgresql/1.3.0/1.3.0.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.3.0/1.3.0.sql rename to scripts/schema/db/init_dbs/postgresql/1.3.0/1.3.0.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.3.5/1.3.5.sql b/scripts/schema/db/init_dbs/postgresql/1.3.5/1.3.5.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.3.5/1.3.5.sql rename to scripts/schema/db/init_dbs/postgresql/1.3.5/1.3.5.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.3.6/1.3.6.sql b/scripts/schema/db/init_dbs/postgresql/1.3.6/1.3.6.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.3.6/1.3.6.sql rename to scripts/schema/db/init_dbs/postgresql/1.3.6/1.3.6.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.4.0/1.4.0.sql b/scripts/schema/db/init_dbs/postgresql/1.4.0/1.4.0.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.4.0/1.4.0.sql rename to scripts/schema/db/init_dbs/postgresql/1.4.0/1.4.0.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.5.0/1.5.0.sql b/scripts/schema/db/init_dbs/postgresql/1.5.0/1.5.0.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.5.0/1.5.0.sql rename to scripts/schema/db/init_dbs/postgresql/1.5.0/1.5.0.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.5.1/1.5.1.sql b/scripts/schema/db/init_dbs/postgresql/1.5.1/1.5.1.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.5.1/1.5.1.sql rename to scripts/schema/db/init_dbs/postgresql/1.5.1/1.5.1.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.5.2/1.5.2.sql b/scripts/schema/db/init_dbs/postgresql/1.5.2/1.5.2.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.5.2/1.5.2.sql rename to scripts/schema/db/init_dbs/postgresql/1.5.2/1.5.2.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql b/scripts/schema/db/init_dbs/postgresql/1.5.3/1.5.3.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql rename to scripts/schema/db/init_dbs/postgresql/1.5.3/1.5.3.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.5.4/1.5.4.sql b/scripts/schema/db/init_dbs/postgresql/1.5.4/1.5.4.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.5.4/1.5.4.sql rename to scripts/schema/db/init_dbs/postgresql/1.5.4/1.5.4.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.6.0/1.6.0.sql b/scripts/schema/db/init_dbs/postgresql/1.6.0/1.6.0.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.6.0/1.6.0.sql rename to scripts/schema/db/init_dbs/postgresql/1.6.0/1.6.0.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql b/scripts/schema/db/init_dbs/postgresql/1.7.0/1.7.0.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql rename to scripts/schema/db/init_dbs/postgresql/1.7.0/1.7.0.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.8.0/1.8.0.sql b/scripts/schema/db/init_dbs/postgresql/1.8.0/1.8.0.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.8.0/1.8.0.sql rename to scripts/schema/db/init_dbs/postgresql/1.8.0/1.8.0.sql diff --git a/scripts/helm/db/init_dbs/postgresql/1.8.1/1.8.1.sql b/scripts/schema/db/init_dbs/postgresql/1.8.1/1.8.1.sql similarity index 100% rename from scripts/helm/db/init_dbs/postgresql/1.8.1/1.8.1.sql rename to scripts/schema/db/init_dbs/postgresql/1.8.1/1.8.1.sql diff --git a/scripts/schema/db/init_dbs/postgresql/1.9.0/1.9.0.sql b/scripts/schema/db/init_dbs/postgresql/1.9.0/1.9.0.sql new file mode 100644 index 000000000..5850be8ba --- /dev/null +++ b/scripts/schema/db/init_dbs/postgresql/1.9.0/1.9.0.sql @@ -0,0 +1,72 @@ +BEGIN; +CREATE OR REPLACE FUNCTION openreplay_version() + RETURNS text AS +$$ +SELECT 'v1.9.0' +$$ LANGUAGE sql IMMUTABLE; + +ALTER TABLE IF EXISTS public.tenants + ADD COLUMN IF NOT EXISTS last_telemetry bigint NOT NULL DEFAULT CAST(EXTRACT(epoch FROM date_trunc('day', now())) * 1000 AS BIGINT), + DROP COLUMN IF EXISTS version_number; + +CREATE TABLE IF NOT EXISTS sessions_notes +( + note_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, + message text NOT NULL, + created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), + user_id integer NULL REFERENCES users (user_id) ON DELETE SET NULL, + deleted_at timestamp without time zone NULL DEFAULT NULL, + tag text NULL, + session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, + project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, + timestamp integer NOT NULL DEFAULT -1, + is_public boolean NOT NULL DEFAULT FALSE +); + +CREATE TABLE IF NOT EXISTS errors_tags +( + key text NOT NULL, + value text NOT NULL, + created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), + error_id text NOT NULL REFERENCES errors (error_id) ON DELETE CASCADE, + session_id bigint NOT NULL, + message_id bigint NOT NULL, + FOREIGN KEY (session_id, message_id) REFERENCES events.errors (session_id, message_id) ON DELETE CASCADE +); + +CREATE INDEX IF NOT EXISTS errors_tags_error_id_idx ON errors_tags (error_id); +CREATE INDEX IF NOT EXISTS errors_tags_session_id_idx ON errors_tags (session_id); +CREATE INDEX IF NOT EXISTS errors_tags_message_id_idx ON errors_tags (message_id); + +UPDATE metrics +SET default_config=default_config || '{"col":4}' +WHERE metric_type = 'funnel'; + +UPDATE dashboard_widgets +SET config=config || '{"col":4}' +WHERE metric_id IN (SELECT metric_id FROM metrics WHERE metric_type = 'funnel'); + +CREATE OR REPLACE FUNCTION notify_integration() RETURNS trigger AS +$$ +BEGIN + IF NEW IS NULL THEN + PERFORM pg_notify('integration', + jsonb_build_object('project_id', OLD.project_id, 'provider', OLD.provider, 'options', + null)::text); + ELSIF (OLD IS NULL) OR (OLD.options <> NEW.options) THEN + PERFORM pg_notify('integration', row_to_json(NEW)::text); + END IF; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +DROP INDEX IF EXISTS events_common.requests_url_idx; +DROP INDEX IF EXISTS events_common.requests_url_gin_idx; +DROP INDEX IF EXISTS events_common.requests_url_gin_idx2; + +DROP INDEX IF EXISTS events.resources_url_gin_idx; +DROP INDEX IF EXISTS events.resources_url_idx; + +COMMIT; + +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_session_id_status_code_nn_idx ON events_common.requests (session_id, status_code) WHERE status_code IS NOT NULL; \ No newline at end of file diff --git a/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/scripts/schema/db/init_dbs/postgresql/init_schema.sql similarity index 96% rename from scripts/helm/db/init_dbs/postgresql/init_schema.sql rename to scripts/schema/db/init_dbs/postgresql/init_schema.sql index 94bfa04e2..79b0b649c 100644 --- a/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/scripts/schema/db/init_dbs/postgresql/init_schema.sql @@ -6,7 +6,7 @@ CREATE SCHEMA IF NOT EXISTS events; CREATE OR REPLACE FUNCTION openreplay_version() RETURNS text AS $$ -SELECT 'v1.8.1' +SELECT 'v1.9.0' $$ LANGUAGE sql IMMUTABLE; -- --- accounts.sql --- @@ -60,7 +60,9 @@ CREATE OR REPLACE FUNCTION notify_integration() RETURNS trigger AS $$ BEGIN IF NEW IS NULL THEN - PERFORM pg_notify('integration', (row_to_json(OLD)::text || '{"options": null, "request_data": null}'::text)); + PERFORM pg_notify('integration', + jsonb_build_object('project_id', OLD.project_id, 'provider', OLD.provider, 'options', + null)::text); ELSIF (OLD IS NULL) OR (OLD.options <> NEW.options) THEN PERFORM pg_notify('integration', row_to_json(NEW)::text); END IF; @@ -121,14 +123,14 @@ $$ name text NOT NULL, api_key text NOT NULL DEFAULT generate_api_key(20), created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'), - version_number text NOT NULL, license text NULL, opt_out bool NOT NULL DEFAULT FALSE, t_projects integer NOT NULL DEFAULT 1, t_sessions bigint NOT NULL DEFAULT 0, t_users integer NOT NULL DEFAULT 1, t_integrations integer NOT NULL DEFAULT 0, - CONSTRAINT onerow_uni CHECK (tenant_id = 1) + last_telemetry bigint NOT NULL DEFAULT CAST(EXTRACT(epoch FROM date_trunc('day', now())) * 1000 AS BIGINT) + CONSTRAINT onerow_uni CHECK (tenant_id = 1) ); CREATE TYPE user_role AS ENUM ('owner', 'admin', 'member'); @@ -167,7 +169,7 @@ $$ provider_user_id text NOT NULL, token text NOT NULL ); - CREATE UNIQUE INDEX oauth_authentication_unique_user_id_provider_idx ON oauth_authentication(user_id,provider); + CREATE UNIQUE INDEX oauth_authentication_unique_user_id_provider_idx ON oauth_authentication (user_id, provider); -- --- projects.sql --- @@ -594,21 +596,14 @@ $$ query text NULL, PRIMARY KEY (session_id, timestamp, seq_index) ); - CREATE INDEX requests_url_idx ON events_common.requests (url); + CREATE INDEX requests_duration_idx ON events_common.requests (duration); - CREATE INDEX requests_url_gin_idx ON events_common.requests USING GIN (url gin_trgm_ops); CREATE INDEX requests_timestamp_idx ON events_common.requests (timestamp); - CREATE INDEX requests_url_gin_idx2 ON events_common.requests USING GIN (RIGHT(url, length(url) - (CASE - WHEN url LIKE 'http://%' - THEN 7 - WHEN url LIKE 'https://%' - THEN 8 - ELSE 0 END)) - gin_trgm_ops); CREATE INDEX requests_timestamp_session_id_failed_idx ON events_common.requests (timestamp, session_id) WHERE success = FALSE; CREATE INDEX requests_request_body_nn_gin_idx ON events_common.requests USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; CREATE INDEX requests_response_body_nn_gin_idx ON events_common.requests USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; CREATE INDEX requests_status_code_nn_idx ON events_common.requests (status_code) WHERE status_code IS NOT NULL; + CREATE INDEX requests_session_id_status_code_nn_idx ON events_common.requests (session_id, status_code) WHERE status_code IS NOT NULL; CREATE INDEX requests_host_nn_idx ON events_common.requests (host) WHERE host IS NOT NULL; CREATE INDEX requests_host_nn_gin_idx ON events_common.requests USING GIN (host gin_trgm_ops) WHERE host IS NOT NULL; CREATE INDEX requests_path_nn_idx ON events_common.requests (path) WHERE path IS NOT NULL; @@ -734,6 +729,21 @@ $$ CREATE INDEX errors_error_id_timestamp_session_id_idx ON events.errors (error_id, timestamp, session_id); CREATE INDEX errors_error_id_idx ON events.errors (error_id); + CREATE TABLE errors_tags + ( + key text NOT NULL, + value text NOT NULL, + created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), + error_id text NOT NULL REFERENCES errors (error_id) ON DELETE CASCADE, + session_id bigint NOT NULL, + message_id bigint NOT NULL, + FOREIGN KEY (session_id, message_id) REFERENCES events.errors (session_id, message_id) ON DELETE CASCADE + ); + + CREATE INDEX errors_tags_error_id_idx ON errors_tags (error_id); + CREATE INDEX errors_tags_session_id_idx ON errors_tags (session_id); + CREATE INDEX errors_tags_message_id_idx ON errors_tags (message_id); + CREATE TABLE events.graphql ( session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, @@ -999,6 +1009,20 @@ $$ FOR EACH ROW EXECUTE PROCEDURE notify_alert(); + CREATE TABLE sessions_notes + ( + note_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, + message text NOT NULL, + created_at timestamp without time zone NOT NULL default (now() at time zone 'utc'), + user_id integer NULL REFERENCES users (user_id) ON DELETE SET NULL, + deleted_at timestamp without time zone NULL DEFAULT NULL, + tag text NULL, + session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, + project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, + timestamp integer NOT NULL DEFAULT -1, + is_public boolean NOT NULL DEFAULT FALSE + ); + raise notice 'DB created'; END IF; END; diff --git a/sourcemap-reader/Dockerfile b/sourcemap-reader/Dockerfile new file mode 100644 index 000000000..493317ba2 --- /dev/null +++ b/sourcemap-reader/Dockerfile @@ -0,0 +1,24 @@ +FROM node:18-alpine +LABEL Maintainer="KRAIEM Taha Yassine<tahayk2@gmail.com>" +RUN apk add --no-cache tini + +ARG envarg +ENV SOURCE_MAP_VERSION=0.7.4 \ + APP_NAME=sourcemaps-reader \ + LISTEN_PORT=9000 \ + MAPPING_WASM=/work/mappings.wasm \ + PRIVATE_ENDPOINTS=true \ + ENTERPRISE_BUILD=${envarg} + +ADD https://unpkg.com/source-map@${SOURCE_MAP_VERSION}/lib/mappings.wasm ${MAPPING_WASM} +WORKDIR /work +COPY *.json ./ +RUN npm install && chmod 644 ${MAPPING_WASM} + +COPY . . + +RUN adduser -u 1001 openreplay -D +USER 1001 + +ENTRYPOINT ["/sbin/tini", "--"] +CMD ./entrypoint.sh diff --git a/sourcemap-reader/build.sh b/sourcemap-reader/build.sh new file mode 100644 index 000000000..9767512f3 --- /dev/null +++ b/sourcemap-reader/build.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Script to build api module +# flags to accept: +# envarg: build for enterprise edition. +# Default will be OSS build. + +# Usage: IMAGE_TAG=latest DOCKER_REPO=myDockerHubID bash build.sh <ee> +set -e + +image_name="sourcemaps-reader" + +git_sha1=${IMAGE_TAG:-$(git rev-parse HEAD)} +envarg="default-foss" +tmp_folder_name="${image_name}_${RANDOM}" + +check_prereq() { + which docker || { + echo "Docker not installed, please install docker." + exit 1 + } + return +} + +function build_api(){ + destination="_smr" + [[ $1 == "ee" ]] && { + destination="_smr_ee" + } + cp -R ../sourcemap-reader ../${destination} + cd ../${destination} + cp -R ../utilities/utils . + tag="" + # Copy enterprise code + [[ $1 == "ee" ]] && { + cp -rf ../ee/sourcemap-reader/* ./ + envarg="default-ee" + tag="ee-" + } + docker build -f ./Dockerfile --build-arg envarg=$envarg -t ${DOCKER_REPO:-'local'}/${image_name}:${git_sha1} . + cd ../sourcemap-reader + rm -rf ../${destination} + [[ $PUSH_IMAGE -eq 1 ]] && { + docker push ${DOCKER_REPO:-'local'}/${image_name}:${git_sha1} + docker tag ${DOCKER_REPO:-'local'}/${image_name}:${git_sha1} ${DOCKER_REPO:-'local'}/${image_name}:${tag}latest + docker push ${DOCKER_REPO:-'local'}/${image_name}:${tag}latest + } + echo "${image_name} docker build completed" +} + +check_prereq +build_api $1 +echo buil_complete diff --git a/sourcemap-reader/entrypoint.sh b/sourcemap-reader/entrypoint.sh new file mode 100755 index 000000000..d1bcb4adf --- /dev/null +++ b/sourcemap-reader/entrypoint.sh @@ -0,0 +1,2 @@ +#!/bin/sh +npm start \ No newline at end of file diff --git a/sourcemap-reader/package-lock.json b/sourcemap-reader/package-lock.json index eb866a247..ef9d38162 100644 --- a/sourcemap-reader/package-lock.json +++ b/sourcemap-reader/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "aws-sdk": "^2.1172.0", "express": "^4.18.1", + "request": "^2.88.2", "source-map": "^0.7.4" } }, @@ -26,11 +27,47 @@ "node": ">= 0.6" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/aws-sdk": { "version": "2.1172.0", "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1172.0.tgz", @@ -50,6 +87,19 @@ "node": ">= 10.0.0" } }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -69,6 +119,14 @@ } ] }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -122,6 +180,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -154,6 +228,22 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -162,6 +252,14 @@ "ms": "2.0.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -179,6 +277,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -254,6 +361,29 @@ "node": ">= 0.10.0" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -271,6 +401,27 @@ "node": ">= 0.8" } }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -305,6 +456,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -342,6 +522,20 @@ "node": ">= 0.8" } }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -371,11 +565,21 @@ "node": ">= 0.10" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, "node_modules/jmespath": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", @@ -384,6 +588,40 @@ "node": ">= 0.6.0" } }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -448,6 +686,14 @@ "node": ">= 0.6" } }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, "node_modules/object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -480,6 +726,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -492,6 +743,11 @@ "node": ">= 0.10" } }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, "node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", @@ -542,6 +798,54 @@ "node": ">= 0.8" } }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -639,6 +943,30 @@ "node": ">= 8" } }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -655,6 +983,42 @@ "node": ">=0.6" } }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -675,6 +1039,22 @@ "node": ">= 0.8" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, "node_modules/url": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", @@ -708,6 +1088,19 @@ "node": ">= 0.8" } }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -736,11 +1129,40 @@ "negotiator": "0.6.3" } }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "aws-sdk": { "version": "2.1172.0", "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1172.0.tgz", @@ -757,11 +1179,29 @@ "xml2js": "0.4.19" } }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "requires": { + "tweetnacl": "^0.14.3" + } + }, "body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -805,6 +1245,19 @@ "get-intrinsic": "^1.0.2" } }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -828,6 +1281,19 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "requires": { + "assert-plus": "^1.0.0" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -836,6 +1302,11 @@ "ms": "2.0.0" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -846,6 +1317,15 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -909,6 +1389,26 @@ "vary": "~1.1.2" } }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, "finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -923,6 +1423,21 @@ "unpipe": "~1.0.0" } }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -948,6 +1463,28 @@ "has-symbols": "^1.0.3" } }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -973,6 +1510,16 @@ "toidentifier": "1.0.1" } }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -996,16 +1543,57 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, "jmespath": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1049,6 +1637,11 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, "object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -1072,6 +1665,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1081,6 +1679,11 @@ "ipaddr.js": "1.9.1" } }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, "punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", @@ -1115,6 +1718,45 @@ "unpipe": "1.0.0" } }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1188,6 +1830,22 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" }, + "sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -1198,6 +1856,35 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1212,6 +1899,21 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, "url": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", @@ -1236,6 +1938,16 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", diff --git a/sourcemap-reader/package.json b/sourcemap-reader/package.json index ad24a481d..bf0a60d44 100644 --- a/sourcemap-reader/package.json +++ b/sourcemap-reader/package.json @@ -20,6 +20,7 @@ "dependencies": { "aws-sdk": "^2.1172.0", "express": "^4.18.1", + "request": "^2.88.2", "source-map": "^0.7.4" } } diff --git a/sourcemap-reader/run-dev.sh b/sourcemap-reader/run-dev.sh index 3c80807dd..19ba781ce 100755 --- a/sourcemap-reader/run-dev.sh +++ b/sourcemap-reader/run-dev.sh @@ -1,3 +1,3 @@ #!/bin/zsh -MAPPING_WASM=./mappings.wasm npm start \ No newline at end of file +MAPPING_WASM=./mappings.wasm PREFIX=/abc npm start \ No newline at end of file diff --git a/sourcemap-reader/server.js b/sourcemap-reader/server.js index b58128992..02f63475b 100644 --- a/sourcemap-reader/server.js +++ b/sourcemap-reader/server.js @@ -23,4 +23,12 @@ const server = app.listen(PORT, HOST, () => { console.log(`SR App listening on http://${HOST}:${PORT}`); console.log('Press Ctrl+C to quit.'); }); -module.exports = {server}; \ No newline at end of file +module.exports = {server}; + +app.get('/private/shutdown', (req, res) => { + console.log("Requested shutdown"); + res.statusCode = 200; + res.end("ok!"); + process.kill(1, "SIGTERM"); + } +); \ No newline at end of file diff --git a/sourcemap-reader/servers/sourcemaps-handler.js b/sourcemap-reader/servers/sourcemaps-handler.js index 96e9efe01..86c93df7b 100644 --- a/sourcemap-reader/servers/sourcemaps-handler.js +++ b/sourcemap-reader/servers/sourcemaps-handler.js @@ -3,6 +3,7 @@ const fs = require('fs'); const sourceMap = require('source-map'); const AWS = require('aws-sdk'); const URL = require('url'); +const request = require('request'); const wasm = fs.readFileSync(process.env.MAPPING_WASM || '/mappings.wasm'); sourceMap.SourceMapConsumer.initialize({ "lib/mappings.wasm": wasm @@ -10,102 +11,141 @@ sourceMap.SourceMapConsumer.initialize({ console.log(`>sourceMap initialised using ${process.env.MAPPING_WASM || '/mappings.wasm'}`); -module.exports.sourcemapReader = async event => { - let s3; - - if (process.env.S3_HOST) { - s3 = new AWS.S3({ - endpoint: process.env.S3_HOST, - accessKeyId: process.env.S3_KEY, - secretAccessKey: process.env.S3_SECRET, - s3ForcePathStyle: true, // needed with minio? - signatureVersion: 'v4' - }); - } else { - s3 = new AWS.S3({ - 'AccessKeyID': process.env.aws_access_key_id, - 'SecretAccessKey': process.env.aws_secret_access_key, - 'Region': process.env.aws_region - }); - } - - var options = { - Bucket: event.bucket, - Key: event.key - }; - return new Promise(function (resolve, reject) { - const getObjectStart = Date.now(); - s3.getObject(options, (err, data) => { - if (err) { - console.error("[SR] Get S3 object failed"); - console.error(err); - return reject(err); - } - const getObjectEnd = Date.now(); - const fileSize = (data.ContentLength / 1024) / 1024; - options.fileSize = `${fileSize} Mb`; - const downloadTime = (getObjectEnd - getObjectStart) / 1000; - options.downloadTime = `${downloadTime} s`; - if (fileSize >= 3) { - console.log("[SR] large file:" + JSON.stringify(options)); - } - let sourcemap = data.Body.toString(); - - return new sourceMap.SourceMapConsumer(sourcemap) - .then(consumer => { - let results = []; - for (let i = 0; i < event.positions.length; i++) { - let original = consumer.originalPositionFor({ +function parseSourcemap(sourcemap, event, options, resolve, reject) { + const getObjectEnd = Date.now(); + try { + return new sourceMap.SourceMapConsumer(sourcemap) + .then(consumer => { + let results = []; + for (let i = 0; i < event.positions.length; i++) { + let original = consumer.originalPositionFor({ + line: event.positions[i].line, + column: event.positions[i].column + }); + let url = URL.parse(""); + let preview = []; + if (original.source) { + preview = consumer.sourceContentFor(original.source, true); + if (preview !== null) { + preview = preview.split("\n") + .map((line, i) => [i + 1, line]); + if (event.padding) { + let start = original.line < event.padding ? 0 : original.line - event.padding; + preview = preview.slice(start, original.line + event.padding); + } + } else { + console.log(`[SR] source not found, null preview for: ${original.source}`); + preview = [] + } + url = URL.parse(original.source); + } else { + console.log("[SR] couldn't find original position of: " + JSON.stringify({ line: event.positions[i].line, column: event.positions[i].column - }); - let url = URL.parse(""); - let preview = []; - if (original.source) { - preview = consumer.sourceContentFor(original.source, true); - if (preview !== null) { - preview = preview.split("\n") - .map((line, i) => [i + 1, line]); - if (event.padding) { - let start = original.line < event.padding ? 0 : original.line - event.padding; - preview = preview.slice(start, original.line + event.padding); - } - } else { - console.log(`[SR] source not found, null preview for: ${original.source}`); - preview = [] - } - url = URL.parse(original.source); - } else { - console.log("[SR] couldn't find original position of: " + JSON.stringify({ - line: event.positions[i].line, - column: event.positions[i].column - })); - } - let result = { - "absPath": url.href, - "filename": url.pathname, - "lineNo": original.line, - "colNo": original.column, - "function": original.name, - "context": preview - }; - // console.log(result); - results.push(result); + })); } - consumer = undefined; + let result = { + "absPath": url.href, + "filename": url.pathname, + "lineNo": original.line, + "colNo": original.column, + "function": original.name, + "context": preview + }; + // console.log(result); + results.push(result); + } + consumer = undefined; - const sourcemapProcessingTime = (Date.now() - getObjectEnd) / 1000; - options.sourcemapProcessingTime = `${sourcemapProcessingTime} s` - if (fileSize >= 3 || sourcemapProcessingTime > 2) { - console.log("[SR] " + JSON.stringify(options)); + options.sourcemapProcessingTime = (Date.now() - getObjectEnd) / 1000; + options.sourcemapProcessingTimeUnit = 's'; + if (options.fileSize >= 3 || options.sourcemapProcessingTime > 2) { + console.log("[SR] " + JSON.stringify(options)); + } + // Use this code if you don't use the http event with the LAMBDA-PROXY integration + return resolve(results); + }) + .catch(err => { + return reject(err); + }) + .finally(() => { + sourcemap = undefined; + }); + } catch (err) { + reject(err); + } +} + +module.exports.sourcemapReader = async event => { + if (event.isURL) { + let options = { + URL: event.key + }; + return new Promise(function (resolve, reject) { + const getObjectStart = Date.now(); + return request.get(options.URL, (err, response, sourcemap) => { + if (err || response.statusCode !== 200) { + console.error("[SR] Getting file from URL failed"); + console.error("err:"); + console.error(err); + console.error("response:"); + if (err) { + return reject(err); } - // Use this code if you don't use the http event with the LAMBDA-PROXY integration - return resolve(results); - }) - .finally(() => { - sourcemap = undefined; - }) - + return reject(response); + } + const getObjectEnd = Date.now(); + options.fileSize = (response.headers['content-length'] / 1024) / 1024; + options.fileSizeUnit = 'Mb'; + options.downloadTime = (getObjectEnd - getObjectStart) / 1000; + options.downloadTimeUnit = 's'; + if (options.fileSize >= 3) { + console.log("[SR] large file:" + JSON.stringify(options)); + } + return parseSourcemap(sourcemap, event, options, resolve, reject); + }); }); - }); + } else { + let s3; + if (process.env.S3_HOST) { + s3 = new AWS.S3({ + endpoint: process.env.S3_HOST, + accessKeyId: process.env.S3_KEY, + secretAccessKey: process.env.S3_SECRET, + s3ForcePathStyle: true, // needed with minio? + signatureVersion: 'v4' + }); + } else { + s3 = new AWS.S3({ + 'AccessKeyID': process.env.aws_access_key_id, + 'SecretAccessKey': process.env.aws_secret_access_key, + 'Region': process.env.aws_region + }); + } + + let options = { + Bucket: event.bucket, + Key: event.key + }; + return new Promise(function (resolve, reject) { + const getObjectStart = Date.now(); + s3.getObject(options, (err, data) => { + if (err) { + console.error("[SR] Get S3 object failed"); + console.error(err); + return reject(err); + } + const getObjectEnd = Date.now(); + options.fileSize = (data.ContentLength / 1024) / 1024; + options.fileSizeUnit = 'Mb'; + options.downloadTime = (getObjectEnd - getObjectStart) / 1000; + options.downloadTimeUnit = 's'; + if (options.fileSize >= 3) { + console.log("[SR] large file:" + JSON.stringify(options)); + } + let sourcemap = data.Body.toString(); + return parseSourcemap(sourcemap, event, options, resolve, reject); + }); + }); + } }; \ No newline at end of file diff --git a/sourcemap-reader/servers/sourcemaps-server.js b/sourcemap-reader/servers/sourcemaps-server.js index 7ac6da992..da70f6b3b 100644 --- a/sourcemap-reader/servers/sourcemaps-server.js +++ b/sourcemap-reader/servers/sourcemaps-server.js @@ -9,7 +9,7 @@ router.post('/', (req, res) => { }); req.on('end', function () { data = JSON.parse(data); - console.log("[SR] Starting parser for: " + data.key); + console.log(`[SR] Starting parser for ${data.isURL ? "URL: " : "file: "}${data.key}`); // process.env = {...process.env, ...data.bucket_config}; handler.sourcemapReader(data) .then((results) => { @@ -20,8 +20,8 @@ router.post('/', (req, res) => { .catch((e) => { console.error("[SR] Something went wrong"); console.error(e); - res.statusCode(500); - res.end(e); + res.statusCode = 500; + res.end(e.toString()); }); }) diff --git a/sourcemap-uploader/package.json b/sourcemap-uploader/package.json index e8da522a1..ee495605e 100644 --- a/sourcemap-uploader/package.json +++ b/sourcemap-uploader/package.json @@ -1,6 +1,6 @@ { "name": "@openreplay/sourcemap-uploader", - "version": "3.0.6", + "version": "3.0.7", "description": "NPM module to upload your JS sourcemaps files to OpenReplay", "bin": "cli.js", "main": "index.js", diff --git a/third-party.md b/third-party.md index 0e6e3d210..186ad8817 100644 --- a/third-party.md +++ b/third-party.md @@ -1,4 +1,4 @@ -## Licenses (as of June 30, 2022) +## Licenses (as of November 04, 2022) Below is the list of dependencies used in OpenReplay software. Licenses may change between versions, so please keep this up to date with every new library you use. @@ -53,6 +53,7 @@ Below is the list of dependencies used in OpenReplay software. Licenses may chan | classnames | MIT | JavaScript | | codemirror | MIT | JavaScript | | copy-to-clipboard | MIT | JavaScript | +| jsonwebtoken | MIT | JavaScript | | datamaps | MIT | JavaScript | | deep-diff | MIT | JavaScript | | immutable | MIT | JavaScript | @@ -112,3 +113,4 @@ Below is the list of dependencies used in OpenReplay software. Licenses may chan | clickhouse | Apache2 | Infrastructure | | redis | BSD3 | Infrastructure | | yq | MIT | Infrastructure | +| html2canvas | MIT | JavaScript | diff --git a/tracker/README.md b/tracker/README.md index f283ee3a8..64a06f51e 100644 --- a/tracker/README.md +++ b/tracker/README.md @@ -7,16 +7,16 @@ In order to build locally any of the javascript packages located under this dire cd tracker # or any tracker-* plugin ``` -Then run +Then run ```sh -yarn -yarn build +yarn +yarn build ``` OR ```sh -npm i -npm run build +npm i +npm run build ``` You can then use it as a local javascript package by executing the folowing line under your local project location: @@ -29,3 +29,7 @@ OR npm install --save ../path/to/openreplay/monorepo/tracker/tracker ``` + +## Contributing notes + +Please use `dev` branch as base and target branch. diff --git a/tracker/tracker-assist/layout/index.html b/tracker/tracker-assist/layout/index.html index 6c1995e3d..cf62a9789 100644 --- a/tracker/tracker-assist/layout/index.html +++ b/tracker/tracker-assist/layout/index.html @@ -62,7 +62,6 @@ z-index: 99; bottom: 5px; right: 5px; - border: thin solid rgba(255, 255, 255, .3); } @@ -70,11 +69,19 @@ display: none; } + #audio-btn, #video-btn { + color: #cc0000; + } + #audio-btn:after { text-transform: capitalize; content: 'Mute' } + #audio-btn.muted, #video-btn.off { + color: #888; + } + #audio-btn.muted .bi-mic-mute { display: inline-block; } @@ -117,6 +124,10 @@ padding: 8px 16px; } + #title-span { + font-weight: 500; + } + </style> <link href="css/bootstrap.min.css" rel="stylesheet"> @@ -130,7 +141,7 @@ <div id="controls"> <div class="card-header d-flex justify-content-between"> <div class="user-info"> - <span>Call with</span> + <span id="title-span">Call with</span> <!-- User Name --> <span id="agent-name" class="person-name fw-light">Support Agent</span> </div> @@ -142,7 +153,6 @@ </div> <div id="video-container" class="card-body bg-dark p-0 d-flex align-items-center position-relative"> <div id="local-stream" class="ratio ratio-4x3 rounded m-0 p-0 shadow"> - <p class="text-white m-auto text-center">Starting video...</p> <video id="video-local" autoplay muted></video> </div> diff --git a/tracker/tracker-assist/package.json b/tracker/tracker-assist/package.json index 5591c0731..7c6b40138 100644 --- a/tracker/tracker-assist/package.json +++ b/tracker/tracker-assist/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker-assist", "description": "Tracker plugin for screen assistance through the WebRTC", - "version": "4.0.2", + "version": "4.1.3", "keywords": [ "WebRTC", "assistance", diff --git a/tracker/tracker-assist/src/Assist.ts b/tracker/tracker-assist/src/Assist.ts index d79e008f3..a742c4fbd 100644 --- a/tracker/tracker-assist/src/Assist.ts +++ b/tracker/tracker-assist/src/Assist.ts @@ -15,24 +15,25 @@ import type { Options as ConfirmOptions, } from './ConfirmWindow/defaults.js' // TODO: fully specified strict check with no-any (everywhere) -type StartEndCallback = () => ((()=>Record<string, unknown>) | void) +type StartEndCallback = (agentInfo?: Record<string, any>) => ((() => any) | void) export interface Options { - onAgentConnect: StartEndCallback, - onCallStart: StartEndCallback, - onRemoteControlStart: StartEndCallback, - session_calling_peer_key: string, - session_control_peer_key: string, - callConfirm: ConfirmOptions, - controlConfirm: ConfirmOptions, + onAgentConnect: StartEndCallback; + onCallStart: StartEndCallback; + onRemoteControlStart: StartEndCallback; + session_calling_peer_key: string; + session_control_peer_key: string; + callConfirm: ConfirmOptions; + controlConfirm: ConfirmOptions; // @depricated - confirmText?: string, + confirmText?: string; // @depricated - confirmStyle?: Properties, + confirmStyle?: Properties; - config: RTCConfiguration, - callUITemplate?: string, + config: RTCConfiguration; + serverURL: string + callUITemplate?: string; } @@ -48,10 +49,11 @@ type OptionalCallback = (()=>Record<string, unknown>) | void type Agent = { onDisconnect?: OptionalCallback, onControlReleased?: OptionalCallback, - //name?: string + agentInfo: Record<string, string> | undefined // } + export default class Assist { readonly version = 'PACKAGE_VERSION' @@ -59,6 +61,7 @@ export default class Assist { private peer: Peer | null = null private assistDemandedRestart = false private callingState: CallingState = CallingState.False + private remoteControl: RemoteControl | null = null; private agents: Record<string, Agent> = {} private readonly options: Options @@ -71,6 +74,7 @@ export default class Assist { session_calling_peer_key: '__openreplay_calling_peer', session_control_peer_key: '__openreplay_control_peer', config: null, + serverURL: null, onCallStart: ()=>{}, onAgentConnect: ()=>{}, onRemoteControlStart: ()=>{}, @@ -125,7 +129,18 @@ export default class Assist { private readonly setCallingState = (newState: CallingState): void => { this.callingState = newState } - + private getHost():string{ + if (this.options.serverURL){ + return new URL(this.options.serverURL).host + } + return this.app.getHost() + } + private getBasePrefixUrl(): string{ + if (this.options.serverURL){ + return new URL(this.options.serverURL).pathname + } + return '' + } private onStart() { const app = this.app const sessionId = app.getSessionID() @@ -135,8 +150,8 @@ export default class Assist { const peerID = `${app.getProjectKey()}-${sessionId}` // SocketIO - const socket = this.socket = connect(app.getHost(), { - path: '/ws-assist/socket', + const socket = this.socket = connect(this.getHost(), { + path: this.getBasePrefixUrl()+'/ws-assist/socket', query: { 'peerId': peerID, 'identity': 'session', @@ -150,14 +165,16 @@ export default class Assist { }) socket.onAny((...args) => app.debug.log('Socket:', ...args)) - const remoteControl = new RemoteControl( + this.remoteControl = new RemoteControl( this.options, id => { if (!callUI) { callUI = new CallWindow(app.debug.error, this.options.callUITemplate) } - callUI?.showRemoteControl(remoteControl.releaseControl) - this.agents[id].onControlReleased = this.options.onRemoteControlStart() + if (this.remoteControl){ + callUI?.showRemoteControl(this.remoteControl.releaseControl) + } + this.agents[id].onControlReleased = this.options.onRemoteControlStart(this.agents[id].agentInfo) this.emit('control_granted', id) annot = new AnnotationCanvas() annot.mount() @@ -183,18 +200,18 @@ export default class Assist { ) // TODO: check incoming args - socket.on('request_control', remoteControl.requestControl) - socket.on('release_control', remoteControl.releaseControl) - socket.on('scroll', remoteControl.scroll) - socket.on('click', remoteControl.click) - socket.on('move', remoteControl.move) + socket.on('request_control', this.remoteControl.requestControl) + socket.on('release_control', this.remoteControl.releaseControl) + socket.on('scroll', this.remoteControl.scroll) + socket.on('click', this.remoteControl.click) + socket.on('move', this.remoteControl.move) socket.on('focus', (clientID, nodeID) => { const el = app.nodes.getNode(nodeID) - if (el instanceof HTMLElement) { - remoteControl.focus(clientID, el) + if (el instanceof HTMLElement && this.remoteControl) { + this.remoteControl.focus(clientID, el) } }) - socket.on('input', remoteControl.input) + socket.on('input', this.remoteControl.input) let annot: AnnotationCanvas | null = null socket.on('moveAnnotation', (_, p) => annot && annot.move(p)) // TODO: restrict by id @@ -203,8 +220,8 @@ export default class Assist { socket.on('NEW_AGENT', (id: string, info) => { this.agents[id] = { - onDisconnect: this.options.onAgentConnect?.(), - ...info, // TODO + onDisconnect: this.options.onAgentConnect?.(info), + agentInfo: info, // TODO ? } this.assistDemandedRestart = true this.app.stop() @@ -212,19 +229,21 @@ export default class Assist { }) socket.on('AGENTS_CONNECTED', (ids: string[]) => { ids.forEach(id =>{ + const agentInfo = this.agents[id]?.agentInfo this.agents[id] = { - onDisconnect: this.options.onAgentConnect?.(), + agentInfo, + onDisconnect: this.options.onAgentConnect?.(agentInfo), } }) this.assistDemandedRestart = true this.app.stop() this.app.start().then(() => { this.assistDemandedRestart = false }).catch(e => app.debug.error(e)) - remoteControl.reconnect(ids) + this.remoteControl?.reconnect(ids) }) socket.on('AGENT_DISCONNECTED', (id) => { - remoteControl.releaseControl() + this.remoteControl?.releaseControl() this.agents[id]?.onDisconnect?.() delete this.agents[id] @@ -247,6 +266,9 @@ export default class Assist { callingAgents.set(id, name) updateCallerNames() }) + socket.on('videofeed', (id, feedState) => { + callUI?.toggleVideoStream(feedState) + }) const callingAgents: Map<string, string> = new Map() // !! uses socket.io ID // TODO: merge peerId & socket.io id (simplest way - send peerId with the name) @@ -265,8 +287,8 @@ export default class Assist { // PeerJS call (todo: use native WebRTC) const peerOptions = { - host: app.getHost(), - path: '/assist', + host: this.getHost(), + path: this.getBasePrefixUrl()+'/assist', port: location.protocol === 'http:' && this.noSecureMode ? 80 : 443, //debug: appOptions.__debug_log ? 2 : 0, // 0 Print nothing //1 Prints only errors. / 2 Prints errors and warnings. / 3 Prints all logs. } @@ -316,10 +338,9 @@ export default class Assist { }) Object.values(lStreams).forEach((stream) => { stream.stop() }) Object.keys(lStreams).forEach((peerId: string) => { delete lStreams[peerId] }) - // UI closeCallConfirmWindow() - if (remoteControl.status === RCStatus.Disabled) { + if (this.remoteControl?.status === RCStatus.Disabled) { callUI?.remove() annot?.remove() callUI = null @@ -338,6 +359,7 @@ export default class Assist { this.emit('call_end') handleCallEnd() } + const updateVideoFeed = ({ enabled, }) => this.emit('videofeed', { streamId: this.peer?.id, enabled, }) peer.on('call', (call) => { app.debug.log('Incoming call: ', call) @@ -379,6 +401,7 @@ export default class Assist { // UI if (!callUI) { callUI = new CallWindow(app.debug.error, this.options.callUITemplate) + callUI.setVideoToggleCallback(updateVideoFeed) } callUI.showControls(initiateCallEnd) @@ -394,7 +417,7 @@ export default class Assist { initiateCallEnd() }) call.on('stream', (rStream) => { - callUI?.addRemoteStream(rStream) + callUI?.addRemoteStream(rStream, call.peer) const onInteraction = () => { // do only if document.hidden ? callUI?.playRemote() document.removeEventListener('click', onInteraction) @@ -437,6 +460,7 @@ export default class Assist { } private clean() { + this.remoteControl?.releaseControl() if (this.peer) { this.peer.destroy() this.app.debug.log('Peer destroyed') diff --git a/tracker/tracker-assist/src/CallWindow.ts b/tracker/tracker-assist/src/CallWindow.ts index 32ceaff38..d561a2ba7 100644 --- a/tracker/tracker-assist/src/CallWindow.ts +++ b/tracker/tracker-assist/src/CallWindow.ts @@ -4,6 +4,7 @@ import attachDND from './dnd.js' const SS_START_TS_KEY = '__openreplay_assist_call_start_ts' export default class CallWindow { + private remoteVideoId: string private readonly iframe: HTMLIFrameElement private vRemote: HTMLVideoElement | null = null private vLocal: HTMLVideoElement | null = null @@ -16,8 +17,11 @@ export default class CallWindow { private remoteControlContainer: HTMLElement | null = null private remoteControlEndBtn: HTMLElement | null = null private controlsContainer: HTMLElement | null = null - + private remoteVideoOn = false + private localVideoOn = false + private onToggleVideo: (args: any) => void private tsInterval: ReturnType<typeof setInterval> + private remoteVideo: MediaStreamTrack private readonly load: Promise<void> @@ -27,7 +31,7 @@ export default class CallWindow { position: 'fixed', zIndex: 2147483647 - 1, border: 'none', - bottom: '10px', + bottom: '50px', right: '10px', height: '200px', width: '200px', @@ -44,8 +48,9 @@ export default class CallWindow { return } - //const baseHref = "https://static.openreplay.com/tracker-assist/test" + // const baseHref = "https://static.openreplay.com/tracker-assist/test" const baseHref = 'https://static.openreplay.com/tracker-assist/4.0.0' + // this.load = fetch(this.callUITemplate || baseHref + '/index2.html') this.load = fetch(this.callUITemplate || baseHref + '/index.html') .then((r) => r.text()) .then((text) => { @@ -98,7 +103,7 @@ export default class CallWindow { const secsFull = ~~(ellapsed / 1000) const mins = ~~(secsFull / 60) const secs = secsFull - mins * 60 - tsElem.innerText = `${mins}:${secs < 10 ? 0 : ''}${secs}` + tsElem.innerText = `${mins > 0 ? `${mins}m` : ''}${secs < 10 ? 0 : ''}${secs}s` }, 500) } @@ -124,12 +129,14 @@ export default class CallWindow { private checkRemoteVideoInterval: ReturnType<typeof setInterval> private audioContainer: HTMLDivElement | null = null - addRemoteStream(rStream: MediaStream) { + addRemoteStream(rStream: MediaStream, peerId: string) { this.load .then(() => { // Video if (this.vRemote && !this.vRemote.srcObject) { this.vRemote.srcObject = rStream + this.remoteVideo = rStream.getVideoTracks()[0] + this.remoteVideoId = peerId if (this.vPlaceholder) { this.vPlaceholder.innerText = 'Video has been paused. Click anywhere to resume.' @@ -141,9 +148,8 @@ export default class CallWindow { } // just in case let enabled = false this.checkRemoteVideoInterval = setInterval(() => { - const settings = rStream.getVideoTracks()[0]?.getSettings() - const isDummyVideoTrack = - !!settings && (settings.width === 2 || settings.frameRate === 0) + const settings = this.remoteVideo?.getSettings() + const isDummyVideoTrack = !this.remoteVideo.enabled || (!!settings && (settings.width === 2 || settings.frameRate === 0)) const shouldBeEnabled = !isDummyVideoTrack if (enabled !== shouldBeEnabled) { this.toggleRemoteVideoUI((enabled = shouldBeEnabled)) @@ -171,6 +177,7 @@ export default class CallWindow { this.load .then(() => { if (this.videoContainer) { + this.remoteVideoOn = enable if (enable) { this.videoContainer.classList.add('remote') } else { @@ -228,6 +235,7 @@ export default class CallWindow { if (!this.videoBtn || !this.videoContainer) { return } + this.localVideoOn = enabled if (enabled) { this.videoContainer.classList.add('local') this.videoBtn.classList.remove('off') @@ -243,6 +251,7 @@ export default class CallWindow { stream .toggleVideo() .then((enabled) => { + this.onToggleVideo?.({ streamId: stream.stream.id, enabled, }) this.toggleVideoUI(enabled) this.load .then(() => { @@ -298,6 +307,10 @@ export default class CallWindow { this.adjustIframeSize() } + public setVideoToggleCallback(cb) { + this.onToggleVideo = cb + } + remove() { clearInterval(this.tsInterval) clearInterval(this.checkRemoteVideoInterval) @@ -311,4 +324,11 @@ export default class CallWindow { sessionStorage.removeItem(SS_START_TS_KEY) this.localStreams = [] } + + toggleVideoStream({ streamId, enabled, }: { streamId: string, enabled: boolean }) { + if (this.remoteVideoId === streamId) { + this.remoteVideo.enabled = enabled + this.toggleRemoteVideoUI(enabled) + } + } } diff --git a/tracker/tracker-assist/src/ConfirmWindow/ConfirmWindow.ts b/tracker/tracker-assist/src/ConfirmWindow/ConfirmWindow.ts index d5e3d98cc..9e263111f 100644 --- a/tracker/tracker-assist/src/ConfirmWindow/ConfirmWindow.ts +++ b/tracker/tracker-assist/src/ConfirmWindow/ConfirmWindow.ts @@ -50,16 +50,22 @@ export default class ConfirmWindow { const wrapper = document.createElement('div') const popup = document.createElement('div') const p = document.createElement('p') + wrapper.id = 'openreplay-confirm-window-wrapper' + popup.id = 'openreplay-confirm-window-popup' + p.id = 'openreplay-confirm-window-p' p.innerText = options.text const buttons = document.createElement('div') + buttons.id = 'openreplay-confirm-window-buttons' const confirmBtn = makeButton(options.confirmBtn, { background: 'rgba(0, 167, 47, 1)', color: 'white', }) + confirmBtn.id = 'openreplay-confirm-window-confirm-btn' const declineBtn = makeButton(options.declineBtn, { background: '#FFE9E9', color: '#CC0000', }) + declineBtn.id = 'openreplay-confirm-window-decline-btn' buttons.appendChild(confirmBtn) buttons.appendChild(declineBtn) popup.appendChild(p) diff --git a/tracker/tracker-assist/src/Mouse.ts b/tracker/tracker-assist/src/Mouse.ts index 35f1b1dde..c0bf86f12 100644 --- a/tracker/tracker-assist/src/Mouse.ts +++ b/tracker/tracker-assist/src/Mouse.ts @@ -31,6 +31,7 @@ export default class Mouse { Object.assign(this.mouse.style, { position: 'absolute', zIndex: '999998', + pointerEvents: 'none', }) } @@ -47,10 +48,8 @@ export default class Mouse { this.position = pos Object.assign(this.mouse.style, { - // we're moving it off by few pixels - // so the doc.elementFromPoint works - left: `${(pos[0] || 0) + 3}px`, - top: `${(pos[1] || 0) + 3}px`, + left: `${pos[0] || 0}px`, + top: `${pos[1] || 0}px`, }) } diff --git a/tracker/tracker-vuex/package.json b/tracker/tracker-vuex/package.json index 97c9831ce..b4fa2ff50 100644 --- a/tracker/tracker-vuex/package.json +++ b/tracker/tracker-vuex/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker-vuex", "description": "Tracker plugin for Vuex state recording", - "version": "4.0.2", + "version": "4.0.3", "keywords": [ "vuex", "logging", diff --git a/tracker/tracker-vuex/src/index.ts b/tracker/tracker-vuex/src/index.ts index 380be9081..a4ca0a676 100644 --- a/tracker/tracker-vuex/src/index.ts +++ b/tracker/tracker-vuex/src/index.ts @@ -25,7 +25,8 @@ function processMutationAndState( const _table = encoder.commit(); for (let key in _table) app.send(Messages.OTable(key, _table[key])); app.send(Messages.Vuex(_mutation, _state)); - } catch { + } catch (e) { + console.error(e) encoder.clear(); } } @@ -49,6 +50,7 @@ export default function(opts: Partial<Options> = {}) { return (storeName: string) => (store) => { // Vuex if (store.subscribe) { + app.debug.log('Hooked to vuex store') const randomId = Math.random().toString(36).substring(2, 9) store.subscribe((mutation, storeState) => { state[storeName || randomId] = storeState @@ -58,6 +60,7 @@ export default function(opts: Partial<Options> = {}) { // Pinia if (store.$onAction) { + app.debug.log('Hooked to pinia store') store.$onAction(({ name, store, args }) => { try { state[storeName || store.$id] = store.$state; diff --git a/tracker/tracker-zustand/src/index.ts b/tracker/tracker-zustand/src/index.ts index bf9186fb1..79c6a984e 100644 --- a/tracker/tracker-zustand/src/index.ts +++ b/tracker/tracker-zustand/src/index.ts @@ -1,62 +1,68 @@ -import { App, Messages } from "@openreplay/tracker"; -import { Encoder, sha1 } from "./syncod/index.js"; +import { App, Messages } from '@openreplay/tracker' +import { Encoder, sha1 } from './syncod/index.js' export interface Options { - filter: (mutation: any, state: any) => boolean; - transformer: (state: any) => any; - mutationTransformer: (mutation: any) => any; + filter: (mutation: any, state: any) => boolean + transformer: (state: any) => any + mutationTransformer: (mutation: any) => any } function processMutationAndState( - app: App, - options: Options, - encoder: Encoder, - mutation: string[], - state: Record<string, any> + app: App, + options: Options, + encoder: Encoder, + mutation: string[], + state: Record<string, any>, ) { - if (options.filter(mutation, state)) { - try { - const _mutation = encoder.encode(options.mutationTransformer(mutation)); - const _state = encoder.encode(options.transformer(state)); - const _table = encoder.commit(); - for (let key in _table) app.send(Messages.OTable(key, _table[key])); - app.send(Messages.Zustand(_mutation, _state)); - } catch (e) { - encoder.clear(); - app.debug.error(e) - } - } + if (options.filter(mutation, state)) { + try { + const _mutation = encoder.encode(options.mutationTransformer(mutation)) + const _state = encoder.encode(options.transformer(state)) + const _table = encoder.commit() + for (let key in _table) app.send(Messages.OTable(key, _table[key])) + app.send(Messages.Zustand(_mutation, _state)) + } catch (e) { + encoder.clear() + app.debug.error(e) + } + } } export default function(opts: Partial<Options> = {}) { - const options: Options = Object.assign( - { - filter: () => true, - transformer: state => state, - mutationTransformer: mutation => mutation, - }, - opts - ); - return (app: App | null) => { - if (app === null) { - return Function.prototype; - } - const encoder = new Encoder(sha1, 50); - const state = {}; - return (storeName: string = Math.random().toString(36).substring(2, 9)) => - (config: Function) => - (set: (...args: any) => void, get: () => Record<string, any>, api: any) => - config( - (...args) => { - set(...args) - const newState = get(); - state[storeName] = newState - const triggeredActions = args.map(action => action.toString?.()) + const options: Options = Object.assign( + { + filter: () => true, + transformer: (state) => state, + mutationTransformer: (mutation) => mutation, + }, + opts, + ) + return (app: App | null) => { + if (app === null) { + return Function.prototype + } + const encoder = new Encoder(sha1, 50) + const state = {} + return ( + storeName: string = Math.random() + .toString(36) + .substring(2, 9), + ) => (config: Function) => ( + set: (...args: any) => void, + get: () => Record<string, any>, + api: any, + ) => + config( + (...args) => { + set(...args) + const newState = get() + state[storeName] = newState + const triggeredActions = args.map((action) => action.toString?.()) - processMutationAndState(app, options, encoder, triggeredActions, state) - }, - get, - api - ) - }; + processMutationAndState(app, options, encoder, triggeredActions, state) + }, + get, + api, + ) + } } diff --git a/tracker/tracker/package.json b/tracker/tracker/package.json index 3d30d9917..6cf707862 100644 --- a/tracker/tracker/package.json +++ b/tracker/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker", "description": "The OpenReplay tracker main package", - "version": "4.0.2", + "version": "4.1.9", "keywords": [ "logging", "replay" diff --git a/tracker/tracker/src/common/interaction.ts b/tracker/tracker/src/common/interaction.ts index 19d8fa906..0720bf2a8 100644 --- a/tracker/tracker/src/common/interaction.ts +++ b/tracker/tracker/src/common/interaction.ts @@ -19,4 +19,11 @@ type Auth = { beaconSizeLimit?: number } -export type WorkerMessageData = null | 'stop' | Start | Auth | Array<Message> +export type ToWorkerData = null | 'stop' | Start | Auth | Array<Message> + +type Failure = { + type: 'failure' + reason: string +} + +export type FromWorkerData = 'restart' | Failure diff --git a/tracker/tracker/src/common/messages.gen.ts b/tracker/tracker/src/common/messages.gen.ts index 4e2afe778..e5f7fe28c 100644 --- a/tracker/tracker/src/common/messages.gen.ts +++ b/tracker/tracker/src/common/messages.gen.ts @@ -24,7 +24,7 @@ export declare const enum Type { ConsoleLog = 22, PageLoadTiming = 23, PageRenderTiming = 24, - JSException = 25, + JSExceptionDeprecated = 25, RawCustomEvent = 27, UserID = 28, UserAnonymousID = 29, @@ -44,6 +44,8 @@ export declare const enum Type { ResourceTiming = 53, ConnectionInformation = 54, SetPageVisibility = 55, + LoadFontFace = 57, + SetNodeFocus = 58, LongTask = 59, SetNodeAttributeURLBased = 60, SetCSSDataURLBased = 61, @@ -58,6 +60,7 @@ export declare const enum Type { AdoptedSSAddOwner = 76, AdoptedSSRemoveOwner = 77, Zustand = 79, + JSException = 78, } @@ -210,8 +213,8 @@ export type PageRenderTiming = [ /*timeToInteractive:*/ number, ] -export type JSException = [ - /*type:*/ Type.JSException, +export type JSExceptionDeprecated = [ + /*type:*/ Type.JSExceptionDeprecated, /*name:*/ string, /*message:*/ string, /*payload:*/ string, @@ -347,6 +350,19 @@ export type SetPageVisibility = [ /*hidden:*/ boolean, ] +export type LoadFontFace = [ + /*type:*/ Type.LoadFontFace, + /*parentID:*/ number, + /*family:*/ string, + /*source:*/ string, + /*descriptors:*/ string, +] + +export type SetNodeFocus = [ + /*type:*/ Type.SetNodeFocus, + /*id:*/ number, +] + export type LongTask = [ /*type:*/ Type.LongTask, /*timestamp:*/ number, @@ -446,6 +462,14 @@ export type Zustand = [ /*state:*/ string, ] +export type JSException = [ + /*type:*/ Type.JSException, + /*name:*/ string, + /*message:*/ string, + /*payload:*/ string, + /*metadata:*/ string, +] -type Message = BatchMetadata | PartitionedMessage | Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | ConsoleLog | PageLoadTiming | PageRenderTiming | JSException | RawCustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | ResourceTiming | ConnectionInformation | SetPageVisibility | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | Zustand + +type Message = BatchMetadata | PartitionedMessage | Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | ConsoleLog | PageLoadTiming | PageRenderTiming | JSExceptionDeprecated | RawCustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | ResourceTiming | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | Zustand | JSException export default Message diff --git a/tracker/tracker/src/main/app/guards.ts b/tracker/tracker/src/main/app/guards.ts index e4cfa8116..56366a2cf 100644 --- a/tracker/tracker/src/main/app/guards.ts +++ b/tracker/tracker/src/main/app/guards.ts @@ -25,6 +25,7 @@ export function isRootNode(node: Node): node is Document | DocumentFragment { type TagTypeMap = { HTML: HTMLHtmlElement + BODY: HTMLBodyElement IMG: HTMLImageElement INPUT: HTMLInputElement TEXTAREA: HTMLTextAreaElement diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index 769cc8672..bec00d01b 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -1,6 +1,6 @@ import type Message from './messages.gen.js' import { Timestamp, Metadata, UserID } from './messages.gen.js' -import { timestamp as now, deprecationWarn } from '../utils.js' +import { now, adjustTimeOrigin, deprecationWarn } from '../utils.js' import Nodes from './nodes.js' import Observer from './observer/top_observer.js' import Sanitizer from './sanitizer.js' @@ -14,7 +14,15 @@ import type { Options as ObserverOptions } from './observer/top_observer.js' import type { Options as SanitizerOptions } from './sanitizer.js' import type { Options as LoggerOptions } from './logger.js' import type { Options as SessOptions } from './session.js' -import type { Options as WebworkerOptions, WorkerMessageData } from '../../common/interaction.js' +import type { + Options as WebworkerOptions, + ToWorkerData, + FromWorkerData, +} from '../../common/interaction.js' + +interface TypedWorker extends Omit<Worker, 'postMessage'> { + postMessage(data: ToWorkerData): void +} // TODO: Unify and clearly describe options logic export interface StartOptions { @@ -94,7 +102,7 @@ export default class App { private readonly revID: string private activityState: ActivityState = ActivityState.NotActive private readonly version = 'TRACKER_VERSION' // TODO: version compatability check inside each plugin. - private readonly worker?: Worker + private readonly worker?: TypedWorker constructor(projectKey: string, sessionToken: string | undefined, options: Partial<Options>) { // if (options.onStart !== undefined) { // deprecationWarn("'onStart' option", "tracker.start().then(/* handle session info */)") @@ -114,13 +122,15 @@ export default class App { verbose: false, __is_snippet: false, __debug_report_edp: null, - localStorage: window?.localStorage, - sessionStorage: window?.sessionStorage, + localStorage: null, + sessionStorage: null, }, options, ) this.revID = this.options.revID + this.localStorage = this.options.localStorage ?? window.localStorage + this.sessionStorage = this.options.sessionStorage ?? window.sessionStorage this.sanitizer = new Sanitizer(this, options) this.nodes = new Nodes(this.options.node_id) this.observer = new Observer(this, options) @@ -128,8 +138,6 @@ export default class App { this.ticker.attach(() => this.commit()) this.debug = new Logger(this.options.__debug__) this.notify = new Logger(this.options.verbose ? LogLevel.Warnings : LogLevel.Silent) - this.localStorage = this.options.localStorage || window.localStorage - this.sessionStorage = this.options.sessionStorage || window.sessionStorage this.session = new Session(this, this.options) this.session.attachUpdateCallback(({ userID, metadata }) => { if (userID != null) { @@ -153,13 +161,13 @@ export default class App { this.worker.onerror = (e) => { this._debug('webworker_error', e) } - this.worker.onmessage = ({ data }: MessageEvent) => { - if (data === 'failed') { + this.worker.onmessage = ({ data }: MessageEvent<FromWorkerData>) => { + if (data === 'restart') { this.stop(false) - this._debug('worker_failed', {}) // add context (from worker) - } else if (data === 'restart') { + this.start({}, true) + } else if (data.type === 'failure') { this.stop(false) - this.start({ forceNew: true }) + this._debug('worker_failed', data.reason) } } const alertWorker = () => { @@ -179,7 +187,7 @@ export default class App { private _debug(context: string, e: any) { if (this.options.__debug_report_edp !== null) { - fetch(this.options.__debug_report_edp, { + void fetch(this.options.__debug_report_edp, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ @@ -197,22 +205,28 @@ export default class App { } this.messages.push(message) // TODO: commit on start if there were `urgent` sends; - // Clearify where urgent can be used for; - // Clearify workflow for each type of message in case it was sent before start + // Clarify where urgent can be used for; + // Clarify workflow for each type of message in case it was sent before start // (like Fetch before start; maybe add an option "preCapture: boolean" or sth alike) + // Careful: `this.delay` is equal to zero before start hense all Timestamp-s will have to be updated on start if (this.activityState === ActivityState.Active && urgent) { this.commit() } } private commit(): void { if (this.worker && this.messages.length) { - this.messages.unshift(Timestamp(now())) + this.messages.unshift(Timestamp(this.timestamp())) this.worker.postMessage(this.messages) this.commitCallbacks.forEach((cb) => cb(this.messages)) this.messages.length = 0 } } + private delay = 0 + timestamp(): number { + return now() + this.delay + } + safe<T extends (this: any, ...args: any[]) => void>(fn: T): T { const app = this return function (this: any, ...args: any[]) { @@ -220,7 +234,7 @@ export default class App { fn.apply(this, args) } catch (e) { app._debug('safe_fn_call', e) - // time: now(), + // time: this.timestamp(), // name: e.name, // message: e.message, // stack: e.stack @@ -254,8 +268,8 @@ export default class App { if (useSafe) { listener = this.safe(listener) } - this.attachStartCallback(() => target.addEventListener(type, listener, useCapture), useSafe) - this.attachStopCallback(() => target.removeEventListener(type, listener, useCapture), useSafe) + this.attachStartCallback(() => target?.addEventListener(type, listener, useCapture), useSafe) + this.attachStopCallback(() => target?.removeEventListener(type, listener, useCapture), useSafe) } // TODO: full correct semantic @@ -304,8 +318,12 @@ export default class App { this.debug.error('OpenReplay error: Unable to build session URL') return undefined } + const ingest = this.options.ingestPoint + const isSaas = ingest === DEFAULT_INGEST_POINT - return this.options.ingestPoint.replace(/ingest$/, `${projectID}/session/${sessionID}`) + const projectPath = isSaas ? ingest.replace('api', 'app') : ingest + + return projectPath.replace(/ingest$/, `${projectID}/session/${sessionID}`) } getHost(): string { @@ -351,7 +369,8 @@ export default class App { this.sessionStorage.removeItem(this.options.session_reset_key) } } - private _start(startOpts: StartOptions): Promise<StartPromiseReturn> { + + private _start(startOpts: StartOptions = {}, resetByWorker = false): Promise<StartPromiseReturn> { if (!this.worker) { return Promise.resolve(UnsuccessfulStart('No worker found: perhaps, CSP is not set.')) } @@ -363,12 +382,23 @@ export default class App { ) } this.activityState = ActivityState.Starting + adjustTimeOrigin() + if (startOpts.sessionHash) { this.session.applySessionHash(startOpts.sessionHash) } + if (startOpts.forceNew) { + // Reset session metadata only if requested directly + this.session.reset() + } + this.session.assign({ + // MBTODO: maybe it would make sense to `forceNew` if the `userID` was changed + userID: startOpts.userID, + metadata: startOpts.metadata, + }) const timestamp = now() - const startWorkerMsg: WorkerMessageData = { + this.worker.postMessage({ type: 'start', pageNo: this.session.incPageNo(), ingestPoint: this.options.ingestPoint, @@ -376,20 +406,11 @@ export default class App { url: document.URL, connAttemptCount: this.options.connAttemptCount, connAttemptGap: this.options.connAttemptGap, - } - this.worker.postMessage(startWorkerMsg) - - this.session.update({ - // TODO: transparent "session" module logic AND explicit internal api for plugins. - // "updating" with old metadata in order to trigger session's UpdateCallbacks. - // (for the case of internal .start() calls, like on "restart" webworker signal or assistent connection in tracker-assist ) - metadata: startOpts.metadata || this.session.getInfo().metadata, - userID: startOpts.userID, }) - const sReset = this.sessionStorage.getItem(this.options.session_reset_key) + const lsReset = this.sessionStorage.getItem(this.options.session_reset_key) !== null this.sessionStorage.removeItem(this.options.session_reset_key) - const shouldReset = startOpts.forceNew || sReset !== null + const needNewSessionID = startOpts.forceNew || lsReset || resetByWorker return window .fetch(this.options.ingestPoint + '/v1/web/start', { @@ -401,7 +422,7 @@ export default class App { ...this.getTrackerInfo(), timestamp, userID: this.session.getInfo().userID, - token: shouldReset ? undefined : this.session.getSessionToken(), + token: needNewSessionID ? undefined : this.session.getSessionToken(), deviceMemory, jsHeapSizeLimit, }), @@ -429,37 +450,45 @@ export default class App { const { token, userUUID, - sessionID, projectID, beaconSizeLimit, - startTimestamp, // real startTS, derived from sessionID + delay, // derived from token + sessionID, // derived from token + startTimestamp, // real startTS (server time), derived from sessionID } = r if ( typeof token !== 'string' || typeof userUUID !== 'string' || - //typeof startTimestamp !== 'number' || - //typeof sessionID !== 'string' || + (typeof startTimestamp !== 'number' && typeof startTimestamp !== 'undefined') || + typeof sessionID !== 'string' || + typeof delay !== 'number' || (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined') ) { return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`) } - if (sessionID !== this.session.getInfo().sessionID) { - this.session.reset() - } + this.delay = delay this.session.setSessionToken(token) - this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }) // TODO: no no-explicit 'any' + this.session.assign({ + sessionID, + timestamp: startTimestamp || timestamp, + projectID, + }) + // (Re)send Metadata for the case of a new session + Object.entries(this.session.getInfo().metadata).forEach(([key, value]) => + this.send(Metadata(key, value)), + ) this.localStorage.setItem(this.options.local_uuid_key, userUUID) - const startWorkerMsg: WorkerMessageData = { + this.worker.postMessage({ type: 'auth', token, beaconSizeLimit, - } - this.worker.postMessage(startWorkerMsg) + }) const onStartInfo = { sessionToken: token, userUUID, sessionID } - this.startCallbacks.forEach((cb) => cb(onStartInfo)) // TODO: start as early as possible (before receiving the token) + // TODO: start as early as possible (before receiving the token) + this.startCallbacks.forEach((cb) => cb(onStartInfo)) // MBTODO: callbacks after DOM "mounted" (observed) this.observer.observe() this.ticker.start() this.activityState = ActivityState.Active @@ -484,15 +513,15 @@ export default class App { }) } - start(options: StartOptions = {}): Promise<StartPromiseReturn> { + start(...args: Parameters<App['_start']>): Promise<StartPromiseReturn> { if (!document.hidden) { - return this._start(options) + return this._start(...args) } else { return new Promise((resolve) => { const onVisibilityChange = () => { if (!document.hidden) { document.removeEventListener('visibilitychange', onVisibilityChange) - resolve(this._start(options)) + resolve(this._start(...args)) } } document.addEventListener('visibilitychange', onVisibilityChange) @@ -516,8 +545,4 @@ export default class App { } } } - restart() { - this.stop(false) - this.start({ forceNew: false }) - } } diff --git a/tracker/tracker/src/main/app/messages.gen.ts b/tracker/tracker/src/main/app/messages.gen.ts index ce924a918..b9f235588 100644 --- a/tracker/tracker/src/main/app/messages.gen.ts +++ b/tracker/tracker/src/main/app/messages.gen.ts @@ -281,13 +281,13 @@ export function PageRenderTiming( ] } -export function JSException( +export function JSExceptionDeprecated( name: string, message: string, payload: string, -): Messages.JSException { +): Messages.JSExceptionDeprecated { return [ - Messages.Type.JSException, + Messages.Type.JSExceptionDeprecated, name, message, payload, @@ -535,6 +535,30 @@ export function SetPageVisibility( ] } +export function LoadFontFace( + parentID: number, + family: string, + source: string, + descriptors: string, +): Messages.LoadFontFace { + return [ + Messages.Type.LoadFontFace, + parentID, + family, + source, + descriptors, + ] +} + +export function SetNodeFocus( + id: number, +): Messages.SetNodeFocus { + return [ + Messages.Type.SetNodeFocus, + id, + ] +} + export function LongTask( timestamp: number, duration: number, @@ -719,3 +743,18 @@ export function Zustand( ] } +export function JSException( + name: string, + message: string, + payload: string, + metadata: string, +): Messages.JSException { + return [ + Messages.Type.JSException, + name, + message, + payload, + metadata, + ] +} + diff --git a/tracker/tracker/src/main/app/messages.ts b/tracker/tracker/src/main/app/messages.ts index f76d434a8..4b740eddb 100644 --- a/tracker/tracker/src/main/app/messages.ts +++ b/tracker/tracker/src/main/app/messages.ts @@ -140,8 +140,13 @@ export function PageRenderTiming( return [Messages.Type.PageRenderTiming, speedIndex, visuallyComplete, timeToInteractive] } -export function JSException(name: string, message: string, payload: string): Messages.JSException { - return [Messages.Type.JSException, name, message, payload] +export function JSException( + name: string, + message: string, + payload: string, + metadata: string, +): Messages.JSException { + return [Messages.Type.JSException, name, message, payload, metadata] } export function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent { diff --git a/tracker/tracker/src/main/app/nodes.ts b/tracker/tracker/src/main/app/nodes.ts index 8bff1c760..387679380 100644 --- a/tracker/tracker/src/main/app/nodes.ts +++ b/tracker/tracker/src/main/app/nodes.ts @@ -1,5 +1,5 @@ type NodeCallback = (node: Node, isStart: boolean) => void -type ElementListener = [string, EventListener] +type ElementListener = [string, EventListener, boolean] export default class Nodes { private nodes: Array<Node | void> = [] @@ -12,18 +12,18 @@ export default class Nodes { attachNodeCallback(nodeCallback: NodeCallback): void { this.nodeCallbacks.push(nodeCallback) } - attachNodeListener(node: Node, type: string, listener: EventListener): void { + attachNodeListener(node: Node, type: string, listener: EventListener, useCapture = true): void { const id = this.getID(node) if (id === undefined) { return } - node.addEventListener(type, listener) + node.addEventListener(type, listener, useCapture) let listeners = this.elementListeners.get(id) if (listeners === undefined) { listeners = [] this.elementListeners.set(id, listeners) } - listeners.push([type, listener]) + listeners.push([type, listener, useCapture]) } registerNode(node: Node): [/*id:*/ number, /*isNew:*/ boolean] { @@ -44,7 +44,9 @@ export default class Nodes { const listeners = this.elementListeners.get(id) if (listeners !== undefined) { this.elementListeners.delete(id) - listeners.forEach((listener) => node.removeEventListener(listener[0], listener[1])) + listeners.forEach((listener) => + node.removeEventListener(listener[0], listener[1], listener[2]), + ) } } return id diff --git a/tracker/tracker/src/main/app/observer/top_observer.ts b/tracker/tracker/src/main/app/observer/top_observer.ts index 1e69e5bbd..be1a1ce33 100644 --- a/tracker/tracker/src/main/app/observer/top_observer.ts +++ b/tracker/tracker/src/main/app/observer/top_observer.ts @@ -129,6 +129,8 @@ export default class TopObserver extends Observer { window.document, () => { this.app.send(CreateDocument()) + // it has no node_id here + this.app.nodes.callNodeCallbacks(document, true) }, window.document.documentElement, ) diff --git a/tracker/tracker/src/main/app/session.ts b/tracker/tracker/src/main/app/session.ts index 5c3db5ac5..4682bcc43 100644 --- a/tracker/tracker/src/main/app/session.ts +++ b/tracker/tracker/src/main/app/session.ts @@ -37,7 +37,7 @@ export default class Session { this.callbacks.forEach((cb) => cb(newInfo)) } - update(newInfo: Partial<SessionInfo>): void { + assign(newInfo: Partial<SessionInfo>): void { if (newInfo.userID !== undefined) { // TODO clear nullable/undefinable types this.userID = newInfo.userID diff --git a/tracker/tracker/src/main/index.ts b/tracker/tracker/src/main/index.ts index af84730b0..069336ef7 100644 --- a/tracker/tracker/src/main/index.ts +++ b/tracker/tracker/src/main/index.ts @@ -20,6 +20,8 @@ import Performance from './modules/performance.js' import Scroll from './modules/scroll.js' import Viewport from './modules/viewport.js' import CSSRules from './modules/cssrules.js' +import Focus from './modules/focus.js' +import Fonts from './modules/fonts.js' import ConstructedStyleSheets from './modules/constructedStyleSheets.js' import { IN_BROWSER, deprecationWarn, DOCS_HOST } from './utils.js' @@ -123,6 +125,8 @@ export default class API { Timing(app, options) Performance(app, options) Scroll(app) + Focus(app) + Fonts(app) ;(window as any).__OPENREPLAY__ = this if (options.autoResetOnWindowOpen) { @@ -245,7 +249,7 @@ export default class API { this.setMetadata(key, value) } - event(key: string, payload: any, issue = false): void { + event(key: string, payload: any = null, issue = false): void { if (typeof key === 'string' && this.app !== null) { if (issue) { return this.issue(key, payload) @@ -260,7 +264,7 @@ export default class API { } } - issue(key: string, payload: any): void { + issue(key: string, payload: any = null): void { if (typeof key === 'string' && this.app !== null) { try { payload = JSON.stringify(payload) @@ -271,17 +275,21 @@ export default class API { } } - handleError = (e: Error | ErrorEvent | PromiseRejectionEvent) => { + handleError = ( + e: Error | ErrorEvent | PromiseRejectionEvent, + metadata: Record<string, any> = {}, + ) => { if (this.app === null) { return } if (e instanceof Error) { - this.app.send(getExceptionMessage(e, [])) + const msg = getExceptionMessage(e, [], metadata) + this.app.send(msg) } else if ( e instanceof ErrorEvent || ('PromiseRejectionEvent' in window && e instanceof PromiseRejectionEvent) ) { - const msg = getExceptionMessageFromEvent(e) + const msg = getExceptionMessageFromEvent(e, undefined, metadata) if (msg != null) { this.app.send(msg) } diff --git a/tracker/tracker/src/main/modules/constructedStyleSheets.ts b/tracker/tracker/src/main/modules/constructedStyleSheets.ts index 5a25352de..246b1cdf2 100644 --- a/tracker/tracker/src/main/modules/constructedStyleSheets.ts +++ b/tracker/tracker/src/main/modules/constructedStyleSheets.ts @@ -31,54 +31,58 @@ export default function (app: App | null) { return } if (!hasAdoptedSS(document)) { - app.attachStartCallback(() => { - // MBTODO: pre-start sendQueue app - app.send(TechnicalInfo('no_adopted_stylesheets', '')) - }) return } const styleSheetIDMap: Map<CSSStyleSheet, number> = new Map() const adoptedStyleSheetsOwnings: Map<number, number[]> = new Map() - const sendAdoptedStyleSheetsUpdate = (root: StyleSheetOwner) => { - let nodeID = app.nodes.getID(root) - if (root === document) { - nodeID = 0 // main document doesn't have nodeID. ID count starts from the documentElement - } - if (!nodeID) { - return - } - let pastOwning = adoptedStyleSheetsOwnings.get(nodeID) - if (!pastOwning) { - pastOwning = [] - } - const nowOwning: number[] = [] - const styleSheets = root.adoptedStyleSheets - for (const s of styleSheets) { - let sheetID = styleSheetIDMap.get(s) - const init = !sheetID - if (!sheetID) { - sheetID = nextID() + const sendAdoptedStyleSheetsUpdate = (root: StyleSheetOwner) => + setTimeout(() => { + let nodeID = app.nodes.getID(root) + if (root === document) { + nodeID = 0 // main document doesn't have nodeID. ID count starts from the documentElement } - nowOwning.push(sheetID) - if (!pastOwning.includes(sheetID)) { - app.send(AdoptedSSAddOwner(sheetID, nodeID)) + if (nodeID === undefined) { + return } - if (init) { - const rules = s.cssRules - for (let i = 0; i < rules.length; i++) { - app.send(AdoptedSSInsertRuleURLBased(sheetID, rules[i].cssText, i, app.getBaseHref())) + let pastOwning = adoptedStyleSheetsOwnings.get(nodeID) + if (!pastOwning) { + pastOwning = [] + } + const nowOwning: number[] = [] + const styleSheets = root.adoptedStyleSheets + for (const s of styleSheets) { + let sheetID = styleSheetIDMap.get(s) + const init = !sheetID + if (!sheetID) { + sheetID = nextID() + styleSheetIDMap.set(s, sheetID) + } + if (!pastOwning.includes(sheetID)) { + app.send(AdoptedSSAddOwner(sheetID, nodeID)) + } + if (init) { + const rules = s.cssRules + for (let i = 0; i < rules.length; i++) { + app.send(AdoptedSSInsertRuleURLBased(sheetID, rules[i].cssText, i, app.getBaseHref())) + } + } + nowOwning.push(sheetID) + } + for (const sheetID of pastOwning) { + if (!nowOwning.includes(sheetID)) { + app.send(AdoptedSSRemoveOwner(sheetID, nodeID)) } } - } - for (const sheetID of pastOwning) { - if (!nowOwning.includes(sheetID)) { - app.send(AdoptedSSRemoveOwner(sheetID, nodeID)) - } - } - adoptedStyleSheetsOwnings.set(nodeID, nowOwning) - } + adoptedStyleSheetsOwnings.set(nodeID, nowOwning) + }, 20) // Misterious bug: + /* On the page https://explore.fast.design/components/fast-accordion + the only rule inside the only adoptedStyleSheet of the iframe-s document + gets changed during first milliseconds after the load. + Howerer, none of the documented methods (replace, insertRule) is triggered. + The rule is not substituted (remains the same object), however the text gets changed. + */ function patchAdoptedStyleSheets( prototype: typeof Document.prototype | typeof ShadowRoot.prototype, @@ -111,8 +115,8 @@ export default function (app: App | null) { patchAdoptedStyleSheets(context.Document.prototype) patchAdoptedStyleSheets(context.ShadowRoot.prototype) - //@ts-ignore TODO: configure ts (use necessary lib) - const { insertRule, deleteRule, replace, replaceSync } = context.CSSStyleSheet.prototype + //@ts-ignore TODO: upgrade ts to 4.8+ + const { replace, replaceSync } = context.CSSStyleSheet.prototype //@ts-ignore context.CSSStyleSheet.prototype.replace = function (text: string) { @@ -135,7 +139,7 @@ export default function (app: App | null) { } patchContext(window) - app.observer.attachContextCallback(patchContext) + app.observer.attachContextCallback(app.safe(patchContext)) app.attachStopCallback(() => { styleSheetIDMap.clear() diff --git a/tracker/tracker/src/main/modules/cssrules.ts b/tracker/tracker/src/main/modules/cssrules.ts index c4fce0fb7..08db23af8 100644 --- a/tracker/tracker/src/main/modules/cssrules.ts +++ b/tracker/tracker/src/main/modules/cssrules.ts @@ -17,7 +17,7 @@ export default function (app: App | null) { return } - const sendInserDeleteRule = app.safe((sheet: CSSStyleSheet, index: number, rule?: string) => { + const sendInsertDeleteRule = app.safe((sheet: CSSStyleSheet, index: number, rule?: string) => { const sheetID = styleSheetIDMap.get(sheet) if (!sheetID) { // OK-case. Sheet haven't been registered yet. Rules will be sent on registration. @@ -57,17 +57,17 @@ export default function (app: App | null) { } }) - const patchContext = (context: typeof globalThis) => { + const patchContext = app.safe((context: typeof globalThis) => { const { insertRule, deleteRule } = context.CSSStyleSheet.prototype const { insertRule: groupInsertRule, deleteRule: groupDeleteRule } = context.CSSGroupingRule.prototype context.CSSStyleSheet.prototype.insertRule = function (rule: string, index = 0): number { - sendInserDeleteRule(this, index, rule) + sendInsertDeleteRule(this, index, rule) return insertRule.call(this, rule, index) } context.CSSStyleSheet.prototype.deleteRule = function (index: number): void { - sendInserDeleteRule(this, index) + sendInsertDeleteRule(this, index) return deleteRule.call(this, index) } @@ -81,7 +81,7 @@ export default function (app: App | null) { sendReplaceGroupingRule(this) return result } - } + }) patchContext(window) app.observer.attachContextCallback(patchContext) @@ -105,7 +105,7 @@ export default function (app: App | null) { const rules = sheet.cssRules for (let i = 0; i < rules.length; i++) { - sendInserDeleteRule(sheet, i, rules[i].cssText) + sendInsertDeleteRule(sheet, i, rules[i].cssText) } }) } diff --git a/tracker/tracker/src/main/modules/exception.ts b/tracker/tracker/src/main/modules/exception.ts index 8d286349f..0db10afca 100644 --- a/tracker/tracker/src/main/modules/exception.ts +++ b/tracker/tracker/src/main/modules/exception.ts @@ -27,32 +27,42 @@ function getDefaultStack(e: ErrorEvent): Array<StackFrame> { ] } -export function getExceptionMessage(error: Error, fallbackStack: Array<StackFrame>): Message { +export function getExceptionMessage( + error: Error, + fallbackStack: Array<StackFrame>, + metadata: Record<string, any> = {}, +): Message { let stack = fallbackStack try { stack = ErrorStackParser.parse(error) } catch (e) {} - return JSException(error.name, error.message, JSON.stringify(stack)) + return JSException(error.name, error.message, JSON.stringify(stack), JSON.stringify(metadata)) } export function getExceptionMessageFromEvent( e: ErrorEvent | PromiseRejectionEvent, context: typeof globalThis = window, + metadata: Record<string, any> = {}, ): Message | null { if (e instanceof ErrorEvent) { if (e.error instanceof Error) { - return getExceptionMessage(e.error, getDefaultStack(e)) + return getExceptionMessage(e.error, getDefaultStack(e), metadata) } else { let [name, message] = e.message.split(':') if (!message) { name = 'Error' message = e.message } - return JSException(name, message, JSON.stringify(getDefaultStack(e))) + return JSException( + name, + message, + JSON.stringify(getDefaultStack(e)), + JSON.stringify(metadata), + ) } } else if ('PromiseRejectionEvent' in context && e instanceof context.PromiseRejectionEvent) { if (e.reason instanceof Error) { - return getExceptionMessage(e.reason, []) + return getExceptionMessage(e.reason, [], metadata) } else { let message: string try { @@ -60,7 +70,7 @@ export function getExceptionMessageFromEvent( } catch (_) { message = String(e.reason) } - return JSException('Unhandled Promise Rejection', message, '[]') + return JSException('Unhandled Promise Rejection', message, '[]', JSON.stringify(metadata)) } } return null @@ -84,7 +94,7 @@ export default function (app: App, opts: Partial<Options>): void { app.attachEventListener(context, 'error', handler) } if (options.captureExceptions) { - app.observer.attachContextCallback(patchContext) + app.observer.attachContextCallback(patchContext) // TODO: attach once-per-iframe (?) patchContext(window) } } diff --git a/tracker/tracker/src/main/modules/focus.ts b/tracker/tracker/src/main/modules/focus.ts new file mode 100644 index 000000000..d9db865db --- /dev/null +++ b/tracker/tracker/src/main/modules/focus.ts @@ -0,0 +1,45 @@ +import type App from '../app/index.js' +import { isNode, hasTag } from '../app/guards.js' +import { SetNodeFocus } from '../app/messages.gen.js' + +export default function (app: App): void { + function sendSetNodeFocus(n: Node) { + const id = app.nodes.getID(n) + if (id !== undefined) { + app.send(SetNodeFocus(id)) + } + } + + let blurred = false + app.nodes.attachNodeCallback((node) => { + if (!hasTag(node, 'BODY')) { + return + } + app.nodes.attachNodeListener(node, 'focus', (e: FocusEvent): void => { + if (!isNode(e.target)) { + return + } + sendSetNodeFocus(e.target) + blurred = false + }) + app.nodes.attachNodeListener(node, 'blur', (e: FocusEvent): void => { + if (e.relatedTarget === null) { + blurred = true + setTimeout(() => { + if (blurred) { + app.send(SetNodeFocus(-1)) + } + }, 0) + } + }) + }) + app.attachStartCallback(() => { + let elem = document.activeElement + while (elem && hasTag(elem, 'IFRAME') && elem.contentDocument) { + elem = elem.contentDocument.activeElement + } + if (elem && elem !== elem.ownerDocument.body) { + sendSetNodeFocus(elem) + } + }, true) +} diff --git a/tracker/tracker/src/main/modules/fonts.ts b/tracker/tracker/src/main/modules/fonts.ts new file mode 100644 index 000000000..1dfb6069c --- /dev/null +++ b/tracker/tracker/src/main/modules/fonts.ts @@ -0,0 +1,66 @@ +import type App from '../app/index.js' +import { isDocument } from '../app/guards.js' +import { LoadFontFace } from '../app/messages.gen.js' + +type FFData = [string, string, string] + +export default function (app: App) { + if (!window.FontFace) { + return + } + + const docFonts: Map<Document, FFData[]> = new Map() + + const patchWindow = (wnd: typeof globalThis) => { + class FontFaceInterceptor extends wnd.FontFace { + constructor(...args: ConstructorParameters<typeof FontFace>) { + //maybe do this on load(). In this case check if the document.fonts.load(...) function calls the font's load() + if (typeof args[1] === 'string') { + let desc = '' + if (args[2]) { + app.safe(() => { + desc = JSON.stringify(args[2]) + }) + } + + const ffData: FFData = [args[0], args[1], desc] + const ffDataArr = docFonts.get(wnd.document) || [] + ffDataArr.push(ffData) + docFonts.set(wnd.document, ffDataArr) + + const parentID = wnd === window ? 0 : app.nodes.getID(wnd.document) + if (parentID === undefined) { + return + } + + if (app.active()) { + app.send(LoadFontFace(parentID, ...ffData)) + } + } + super(...args) + } + } + wnd.FontFace = FontFaceInterceptor + } + app.observer.attachContextCallback(patchWindow) + patchWindow(window) + + app.nodes.attachNodeCallback((node) => { + if (!isDocument(node)) { + return + } + const ffDataArr = docFonts.get(node) + if (!ffDataArr) { + return + } + + const parentID = node.defaultView === window ? 0 : app.nodes.getID(node) + if (parentID === undefined) { + return + } + + ffDataArr.forEach((ffData) => { + app.send(LoadFontFace(parentID, ...ffData)) + }) + }) +} diff --git a/tracker/tracker/src/main/modules/img.ts b/tracker/tracker/src/main/modules/img.ts index b2c699167..c6dedc6e0 100644 --- a/tracker/tracker/src/main/modules/img.ts +++ b/tracker/tracker/src/main/modules/img.ts @@ -1,5 +1,5 @@ import type App from '../app/index.js' -import { timestamp, isURL, IS_FIREFOX, MAX_STR_LEN } from '../utils.js' +import { isURL, IS_FIREFOX, MAX_STR_LEN } from '../utils.js' import { ResourceTiming, SetNodeAttributeURLBased, SetNodeAttribute } from '../app/messages.gen.js' import { hasTag } from '../app/guards.js' @@ -59,7 +59,7 @@ export default function (app: App): void { const sendImgError = app.safe(function (img: HTMLImageElement): void { const resolvedSrc = resolveURL(img.src || '') // Src type is null sometimes. - is it true? if (isURL(resolvedSrc)) { - app.send(ResourceTiming(timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img')) + app.send(ResourceTiming(app.timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img')) } }) diff --git a/tracker/tracker/src/main/modules/timing.ts b/tracker/tracker/src/main/modules/timing.ts index 2cb1e1767..f2d2cbf11 100644 --- a/tracker/tracker/src/main/modules/timing.ts +++ b/tracker/tracker/src/main/modules/timing.ts @@ -226,13 +226,13 @@ export default function (app: App, opts: Partial<Options>): void { paintBlocks === null ? 0 : calculateSpeedIndex(firstContentfulPaint || firstPaint, paintBlocks) + const { domContentLoadedEventEnd, navigationStart } = performance.timing const timeToInteractive = interactiveWindowTickTime === null ? Math.max( interactiveWindowStartTime, firstContentfulPaint, - performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart || - 0, + domContentLoadedEventEnd - navigationStart || 0, ) : 0 app.send( diff --git a/tracker/tracker/src/main/modules/viewport.ts b/tracker/tracker/src/main/modules/viewport.ts index e17a70359..9541f085e 100644 --- a/tracker/tracker/src/main/modules/viewport.ts +++ b/tracker/tracker/src/main/modules/viewport.ts @@ -1,9 +1,10 @@ import type App from '../app/index.js' +import { getTimeOrigin } from '../utils.js' import { SetPageLocation, SetViewportSize, SetPageVisibility } from '../app/messages.gen.js' export default function (app: App): void { let url: string, width: number, height: number - let navigationStart = performance.timing.navigationStart + let navigationStart: number const sendSetPageLocation = app.safe(() => { const { URL } = document @@ -30,6 +31,7 @@ export default function (app: App): void { app.attachStartCallback(() => { url = '' + navigationStart = getTimeOrigin() width = height = -1 sendSetPageLocation() sendSetViewportSize() diff --git a/tracker/tracker/src/main/utils.ts b/tracker/tracker/src/main/utils.ts index 0bbe09e33..739821ea9 100644 --- a/tracker/tracker/src/main/utils.ts +++ b/tracker/tracker/src/main/utils.ts @@ -6,12 +6,19 @@ export const IS_FIREFOX = IN_BROWSER && navigator.userAgent.match(/firefox|fxios export const MAX_STR_LEN = 1e5 -const navigationStart: number | false = - (IN_BROWSER && performance.timing.navigationStart) || performance.timeOrigin -// performance.now() is buggy in some browsers -export const timestamp: () => number = - IN_BROWSER && performance.now() && navigationStart - ? () => Math.round(performance.now() + navigationStart) +// Buggy to use `performance.timeOrigin || performance.timing.navigationStart` +// https://github.com/mdn/content/issues/4713 +// Maybe move to timer/ticker +let timeOrigin: number = IN_BROWSER ? Date.now() - performance.now() : 0 +export function adjustTimeOrigin() { + timeOrigin = Date.now() - performance.now() +} +export function getTimeOrigin() { + return timeOrigin +} +export const now: () => number = + IN_BROWSER && !!performance.now + ? () => Math.round(performance.now() + timeOrigin) : () => Date.now() export const stars: (str: string) => string = diff --git a/tracker/tracker/src/webworker/MessageEncoder.gen.ts b/tracker/tracker/src/webworker/MessageEncoder.gen.ts index b646fd6ff..c4e2d70d6 100644 --- a/tracker/tracker/src/webworker/MessageEncoder.gen.ts +++ b/tracker/tracker/src/webworker/MessageEncoder.gen.ts @@ -98,7 +98,7 @@ export default class MessageEncoder extends PrimitiveEncoder { return this.uint(msg[1]) && this.uint(msg[2]) && this.uint(msg[3]) break - case Messages.Type.JSException: + case Messages.Type.JSExceptionDeprecated: return this.string(msg[1]) && this.string(msg[2]) && this.string(msg[3]) break @@ -178,6 +178,14 @@ export default class MessageEncoder extends PrimitiveEncoder { return this.boolean(msg[1]) break + case Messages.Type.LoadFontFace: + return this.uint(msg[1]) && this.string(msg[2]) && this.string(msg[3]) && this.string(msg[4]) + break + + case Messages.Type.SetNodeFocus: + return this.int(msg[1]) + break + case Messages.Type.LongTask: return this.uint(msg[1]) && this.uint(msg[2]) && this.uint(msg[3]) && this.uint(msg[4]) && this.string(msg[5]) && this.string(msg[6]) && this.string(msg[7]) break @@ -234,6 +242,10 @@ export default class MessageEncoder extends PrimitiveEncoder { return this.string(msg[1]) && this.string(msg[2]) break + case Messages.Type.JSException: + return this.string(msg[1]) && this.string(msg[2]) && this.string(msg[3]) && this.string(msg[4]) + break + } } diff --git a/tracker/tracker/src/webworker/QueueSender.ts b/tracker/tracker/src/webworker/QueueSender.ts index 6082e222b..aa1ff4589 100644 --- a/tracker/tracker/src/webworker/QueueSender.ts +++ b/tracker/tracker/src/webworker/QueueSender.ts @@ -29,7 +29,7 @@ export default class QueueSender { constructor( ingestBaseURL: string, private readonly onUnauthorised: () => any, - private readonly onFailure: () => any, + private readonly onFailure: (reason: string) => any, private readonly MAX_ATTEMPTS_COUNT = 10, private readonly ATTEMPT_TIMEOUT = 1000, ) { @@ -50,7 +50,7 @@ export default class QueueSender { private retry(batch: Uint8Array): void { if (this.attemptsCount >= this.MAX_ATTEMPTS_COUNT) { - this.onFailure() + this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`) return } this.attemptsCount++ diff --git a/tracker/tracker/src/webworker/index.ts b/tracker/tracker/src/webworker/index.ts index 4faaf1395..6cddb8a6b 100644 --- a/tracker/tracker/src/webworker/index.ts +++ b/tracker/tracker/src/webworker/index.ts @@ -1,10 +1,12 @@ import type Message from '../common/messages.gen.js' import { Type as MType } from '../common/messages.gen.js' -import { WorkerMessageData } from '../common/interaction.js' +import { ToWorkerData, FromWorkerData } from '../common/interaction.js' import QueueSender from './QueueSender.js' import BatchWriter from './BatchWriter.js' +declare function postMessage(message: FromWorkerData): void + enum WorkerStatus { NotActive, Starting, @@ -51,18 +53,18 @@ function reset(): void { } function initiateRestart(): void { - self.postMessage('restart') + postMessage('restart') reset() } -function initiateFailure(): void { - self.postMessage('failed') +function initiateFailure(reason: string): void { + postMessage({ type: 'failure', reason }) reset() } let sendIntervalID: ReturnType<typeof setInterval> | null = null let restartTimeoutID: ReturnType<typeof setTimeout> -self.onmessage = ({ data }: MessageEvent<WorkerMessageData>): any => { +self.onmessage = ({ data }: MessageEvent<ToWorkerData>): any => { if (data == null) { finalize() return @@ -101,9 +103,9 @@ self.onmessage = ({ data }: MessageEvent<WorkerMessageData>): any => { // onUnauthorised initiateRestart() }, - () => { + (reason) => { // onFailure - initiateFailure() + initiateFailure(reason) }, data.connAttemptCount, data.connAttemptGap, diff --git a/utilities/.gitignore b/utilities/.gitignore index 4486f0a7f..7a6a01b6e 100644 --- a/utilities/.gitignore +++ b/utilities/.gitignore @@ -3,4 +3,6 @@ node_modules npm-debug.log .cache test.html -.local \ No newline at end of file +.local + +*.mmdb \ No newline at end of file diff --git a/utilities/Dockerfile b/utilities/Dockerfile index e3d5d4a0a..08ccba56f 100644 --- a/utilities/Dockerfile +++ b/utilities/Dockerfile @@ -5,6 +5,7 @@ RUN apk add --no-cache tini git libc6-compat && ln -s /lib/libc.musl-x86_64.so.1 ARG envarg ENV ENTERPRISE_BUILD=${envarg} \ MAXMINDDB_FILE=/home/openreplay/geoip.mmdb \ + PRIVATE_ENDPOINTS=false \ LISTEN_PORT=9001 WORKDIR /work COPY package.json . diff --git a/utilities/build.sh b/utilities/build.sh index b6ee774f8..98f244749 100644 --- a/utilities/build.sh +++ b/utilities/build.sh @@ -15,8 +15,12 @@ check_prereq() { } function build_api(){ - cp -R ../utilities ../_utilities - cd ../_utilities + destination="_utilities" + [[ $1 == "ee" ]] && { + destination="_utilities_ee" + } + cp -R ../utilities ../${destination} + cd ../${destination} # Copy enterprise code [[ $1 == "ee" ]] && { @@ -25,7 +29,7 @@ function build_api(){ docker build -f ./Dockerfile -t ${DOCKER_REPO:-'local'}/assist:${git_sha1} . cd ../utilities - rm -rf ../_utilities + rm -rf ../${destination} [[ $PUSH_IMAGE -eq 1 ]] && { docker push ${DOCKER_REPO:-'local'}/assist:${git_sha1} docker tag ${DOCKER_REPO:-'local'}/assist:${git_sha1} ${DOCKER_REPO:-'local'}/assist:latest diff --git a/utilities/package-lock.json b/utilities/package-lock.json index f4eb45944..66bee4b50 100644 --- a/utilities/package-lock.json +++ b/utilities/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@maxmind/geoip2-node": "^3.4.0", "express": "^4.18.1", + "jsonwebtoken": "^8.5.1", "socket.io": "^4.5.1", "ua-parser-js": "^1.0.2" } @@ -102,6 +103,11 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -229,6 +235,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -487,6 +501,32 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -501,6 +541,60 @@ "verror": "1.10.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -726,6 +820,14 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -1060,6 +1162,11 @@ "unpipe": "1.0.0" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1150,6 +1257,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1351,6 +1466,30 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -1362,6 +1501,60 @@ "verror": "1.10.0" } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -1505,6 +1698,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, "send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", diff --git a/utilities/package.json b/utilities/package.json index 41859ebc6..f798e73dd 100644 --- a/utilities/package.json +++ b/utilities/package.json @@ -20,6 +20,7 @@ "dependencies": { "@maxmind/geoip2-node": "^3.4.0", "express": "^4.18.1", + "jsonwebtoken": "^8.5.1", "socket.io": "^4.5.1", "ua-parser-js": "^1.0.2" } diff --git a/utilities/run-dev.sh b/utilities/run-dev.sh new file mode 100755 index 000000000..00e8d5a4b --- /dev/null +++ b/utilities/run-dev.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -a +source .env +set +a + +npm start \ No newline at end of file diff --git a/utilities/server.js b/utilities/server.js index 0b300f47b..d71aca65d 100644 --- a/utilities/server.js +++ b/utilities/server.js @@ -31,4 +31,12 @@ const wsserver = wsapp.listen(PORT, HOST, () => { }); wsapp.enable('trust proxy'); socket.start(wsserver); -module.exports = {wsserver}; \ No newline at end of file +module.exports = {wsserver}; + +wsapp.get('/private/shutdown', (req, res) => { + console.log("Requested shutdown"); + res.statusCode = 200; + res.end("ok!"); + process.kill(1, "SIGTERM"); + } +); \ No newline at end of file diff --git a/utilities/servers/websocket.js b/utilities/servers/websocket.js index d93ef671a..615390996 100644 --- a/utilities/servers/websocket.js +++ b/utilities/servers/websocket.js @@ -16,7 +16,8 @@ const { EVENTS_DEFINITION, extractSessionInfo, socketConnexionTimeout, - errorHandler + errorHandler, + authorizer } = require('../utils/assistHelper'); const wsRouter = express.Router(); @@ -241,6 +242,7 @@ module.exports = { wsRouter, start: (server, prefix) => { createSocketIOServer(server, prefix); + io.use(async (socket, next) => await authorizer.check(socket, next)); io.on('connection', async (socket) => { socket.on(EVENTS_DEFINITION.listen.ERROR, err => errorHandler(EVENTS_DEFINITION.listen.ERROR, err)); debug && console.log(`WS started:${socket.id}, Query:${JSON.stringify(socket.handshake.query)}`); @@ -364,4 +366,4 @@ module.exports = { socketsLive, socketsLiveByProject } -}; \ No newline at end of file +}; diff --git a/utilities/utils/assistHelper.js b/utilities/utils/assistHelper.js index 212a3b93d..ece1ea0f3 100644 --- a/utilities/utils/assistHelper.js +++ b/utilities/utils/assistHelper.js @@ -1,7 +1,9 @@ +const jwt = require('jsonwebtoken'); const uaParser = require('ua-parser-js'); const {geoip} = require('./geoIP'); +const {extractPeerId} = require('./helper'); -let debug = process.env.debug === "1" || false; +let debug = process.env.debug === "1"; const IDENTITIES = {agent: 'agent', session: 'session'}; const EVENTS_DEFINITION = { listen: { @@ -92,7 +94,6 @@ function socketConnexionTimeout(io) { console.error(e); } }, 0.5 * 60 * 1000, io); - // }, 2.5 * 60 * 1000, io); } else { debug && console.log(`WS no manually disconnecting sockets.`); } @@ -103,6 +104,56 @@ function errorHandler(listenerName, error) { console.error(error); } + +function generateAccessToken(payload) { + return jwt.sign(payload, process.env.ASSIST_JWT_SECRET, {expiresIn: process.env.ASSIST_JWT_EXPIRATION || '30m'}); +} + + +const JWT_TOKEN_PREFIX = "Bearer "; + +function check(socket, next) { + if (socket.handshake.query.identity === IDENTITIES.session) { + return next(); + } + if (socket.handshake.query.peerId && socket.handshake.auth && socket.handshake.auth.token) { + let token = socket.handshake.auth.token; + if (token.startsWith(JWT_TOKEN_PREFIX)) { + token = token.substring(JWT_TOKEN_PREFIX.length); + } + jwt.verify(token, process.env.ASSIST_JWT_SECRET, (err, decoded) => { + debug && console.log("JWT payload:"); + debug && console.log(decoded); + if (err) { + debug && console.error(err); + return next(new Error('Authentication error')); + } + const {projectKey, sessionId} = extractPeerId(socket.handshake.query.peerId); + if (!projectKey || !sessionId) { + debug && console.error("Missing attribute:"); + debug && console.error(`projectKey:${projectKey}, sessionId:${sessionId}`); + return next(new Error('Authentication error')); + } + if (String(projectKey) !== String(decoded.projectKey) || String(sessionId) !== String(decoded.sessionId)) { + debug && console.error(`Trying to access projectKey:${projectKey} instead of ${decoded.projectKey}\nor`); + debug && console.error(`Trying to access sessionId:${sessionId} instead of ${decoded.sessionId}`); + return next(new Error('Authorization error')); + } + socket.decoded = decoded; + return next(); + }); + } else { + debug && console.error("something missing in:"); + debug && console.error(socket.handshake); + return next(new Error('Authentication error')); + } +} + module.exports = { - extractSessionInfo, EVENTS_DEFINITION, IDENTITIES, socketConnexionTimeout, errorHandler + extractSessionInfo, + EVENTS_DEFINITION, + IDENTITIES, + socketConnexionTimeout, + errorHandler, + authorizer: {generateAccessToken, check} }; \ No newline at end of file