diff --git a/.github/workflows/gcp_apps_js.yml b/.github/workflows/gcp_apps_js.yml new file mode 100644 index 000000000..1da788dfd --- /dev/null +++ b/.github/workflows/gcp_apps_js.yml @@ -0,0 +1,76 @@ +name: Deploy Apps-Js to Cloud RUN + +on: + push: + branches: [ "main", "development" ] + paths: + - 'plugins/apps-js/**' + workflow_dispatch: + inputs: + environment: + description: 'Select the environment to deploy to' + required: true + default: 'development' + branch: + description: 'Branch to deploy from' + required: true + default: 'main' + +env: + SERVICE: apps-js + REGION: us-central1 + +jobs: + deploy: + environment: ${{ (github.ref == 'refs/heads/development' && 'development') || (github.ref == 'refs/heads/main' && 'prod') }} + permissions: + contents: 'read' + id-token: 'write' + + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Google Auth + id: auth + uses: 'google-github-actions/auth@v2' + with: + credentials_json: ${{ secrets.GCP_CREDENTIALS }} + + - run: gcloud auth configure-docker + + - name: Build and Push Docker image + run: | + docker build \ + --build-arg OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} \ + --build-arg OPENROUTER_API_KEY=${{ secrets.OPENROUTER_API_KEY }} \ + --build-arg UPSTASH_REDIS_HOST=${{ secrets.UPSTASH_REDIS_HOST }} \ + --build-arg UPSTASH_REDIS_PASSWORD=${{ secrets.UPSTASH_REDIS_PASSWORD }} \ + --build-arg UPSTASH_REDIS_PORT=${{ secrets.UPSTASH_REDIS_PORT }} \ + --build-arg JWT_SECRET=${{ secrets.JWT_SECRET }} \ + --build-arg GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }} \ + --build-arg GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET }} \ + --build-arg GOOGLE_REDIRECT_URI=${{ secrets.GOOGLE_REDIRECT_URI }} \ + --build-arg GOOGLE_CALLBACK_URL=${{ secrets.GOOGLE_CALLBACK_URL }} \ + --build-arg BASE_URL=${{ secrets.BASE_URL }} \ + --build-arg SUPABASE_URL=${{ secrets.SUPABASE_URL }} \ + --build-arg SUPABASE_KEY=${{ secrets.SUPABASE_KEY }} \ + --build-arg OMI_APP_ID=${{ secrets.OMI_APP_ID }} \ + --build-arg OMI_APP_SECRET=${{ secrets.OMI_APP_SECRET }} \ + --build-arg DECK_APP_ID=${{ secrets.DECK_APP_ID }} \ + --build-arg DECK_APP_SECRET=${{ secrets.DECK_APP_SECRET }} \ + --build-arg SLIDESGPT_API_KEY=${{ secrets.SLIDESGPT_API_KEY }} \ + -t gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} -f plugins/apps-js/Dockerfile.datadog . + docker push gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} + + - name: Deploy to Cloud Run + id: deploy + uses: google-github-actions/deploy-cloudrun@v2 + with: + service: ${{ env.SERVICE }} + region: ${{ env.REGION }} + image: gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} + + - name: Show Output + run: echo ${{ steps.deploy.outputs.url }} \ No newline at end of file diff --git a/.github/workflows/gcp_backend.yml b/.github/workflows/gcp_backend.yml index 9474522da..c9cb728b2 100644 --- a/.github/workflows/gcp_backend.yml +++ b/.github/workflows/gcp_backend.yml @@ -84,13 +84,16 @@ jobs: region: ${{ env.REGION }} image: gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} - - name: Deploy ${{ env.SERVICE }}-listen to Cloud Run - id: deploy-backend-listen - uses: google-github-actions/deploy-cloudrun@v2 - with: - service: ${{ env.SERVICE }}-listen - region: ${{ env.REGION }} - image: gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} + - name: Connect to GKE cluster + run: | + curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg + echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list + sudo apt-get update && sudo apt-get install google-cloud-cli-gke-gcloud-auth-plugin -y + gcloud container clusters get-credentials ${{ vars.GKE_CLUSTER }} --region ${{ env.REGION }} --project ${{ vars.GCP_PROJECT_ID }} + + - name: Deploy ${{ env.SERVICE }}-listen to GKE + run: | + kubectl -n ${{ vars.ENV }}-omi-backend rollout restart deploy ${{ vars.ENV }}-omi-backend-listen - name: Deploy ${{ env.SERVICE }}-integration to Cloud Run id: deploy-backend-integration diff --git a/.github/workflows/gcp_frontend.yml b/.github/workflows/gcp_frontend.yml index 9e2526bc3..49b906f79 100644 --- a/.github/workflows/gcp_frontend.yml +++ b/.github/workflows/gcp_frontend.yml @@ -36,7 +36,16 @@ jobs: - run: gcloud auth configure-docker - name: Build and Push Docker image run: | - docker build -t gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} -f web/frontend/Dockerfile.datadog . + docker build \ + --build-arg NEXT_PUBLIC_FIREBASE_API_KEY=${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }} \ + --build-arg NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }} \ + --build-arg NEXT_PUBLIC_FIREBASE_PROJECT_ID=${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }} \ + --build-arg NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }} \ + --build-arg NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }} \ + --build-arg NEXT_PUBLIC_FIREBASE_APP_ID=${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }} \ + --build-arg NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=${{ secrets.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID }} \ + -t gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} -f web/frontend/Dockerfile.datadog . + docker push gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} - name: Deploy to Cloud Run id: deploy diff --git a/.gitignore b/.gitignore index a9a7798aa..31940381a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,10 +25,9 @@ build/ dist/ .build/ .swiftpm/ -# VS Code - exclude everything except specific files + +# VS Code .vscode/* -!.vscode/launch.json -!.vscode/extensions.json # Android specific **/android/**/build/ @@ -88,6 +87,8 @@ dist/ **/web/.dart_tool/ # Miscellaneous +!app/pubspec.lock +!app/ios/Podfile.lock *.lock *.log *.swo @@ -186,3 +187,4 @@ omiGlass/.expo # Logs /backend/logs/ +app/.fvm/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 7f40c923e..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Uvicorn (backend)", - "type": "python", - "request": "launch", - "module": "uvicorn", - "cwd": "${workspaceFolder}/backend", - "args": [ - "main:app", - "--reload", - "--env-file", ".dev.env", - // "--host", "0.0.0.0", - "--port", "8000", - // "--log-level", "debug", - // "--log-config", "logging_config.json" - ], - "jinja": true, - "python": "${workspaceFolder}/backend/venv/bin/python", - "justMyCode": false, - "env": { - "PYTHONPATH": "${workspaceFolder}/backend", - "LD_LIBRARY_PATH": "/usr/local/lib:/opt/homebrew/lib:${env:LD_LIBRARY_PATH}", - "DYLD_LIBRARY_PATH": "/opt/homebrew/lib:${env:DYLD_LIBRARY_PATH}", - "LIBRARY_PATH": "/opt/homebrew/lib:${env:LIBRARY_PATH}", - "PKG_CONFIG_PATH": "/opt/homebrew/lib/pkgconfig:${env:PKG_CONFIG_PATH}" - } - }, - { - "name": "Flutter (dev)", - "type": "dart", - "request": "launch", - "program": "${workspaceFolder}/app/lib/main.dart", - "cwd": "${workspaceFolder}/app", - "flutterMode": "debug", - "args": [ - "--flavor", - "dev" - ] - }, - { - "name": "Flutter (dev) - iOS Specific Device", - "type": "dart", - "request": "launch", - "program": "${workspaceFolder}/app/lib/main.dart", - "cwd": "${workspaceFolder}/app", - "flutterMode": "debug", - "args": [ - "--flavor", - "dev", - "-d", - "00008130-000C5196386B8D3A" - ] - }, - { - "name": "Flutter Run (Terminal)", - "type": "node", - "request": "launch", - "runtimeExecutable": "flutter", - "cwd": "${workspaceFolder}/app", - "args": [ - "run", - "--flavor", - "dev", - "-d", - "00008130-000C5196386B8D3A" - ], - "console": "integratedTerminal" - } - ] -} \ No newline at end of file diff --git a/README.md b/README.md index c576fdb62..e13322302 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ transcriptions of meetings, chats, and voice memos wherever you are.

-[Homepage](https://omi.me/) | [Documentation](https://docs.omi.me/) | [Buy Consumer device](https://www.omi.me/cart/50230946562340:1) | [Buy Developer Kit](https://www.omi.me/products/omi-dev-kit-2) +[Homepage](https://omi.me/) | [Documentation](https://docs.omi.me/) | [Buy omi Developer Kit](https://www.omi.me/products/omi-dev-kit-2) | [Buy Omi Glass Dev Kit](https://www.omi.me/glass)

diff --git a/app/.fvmrc b/app/.fvmrc new file mode 100644 index 000000000..e1504264f --- /dev/null +++ b/app/.fvmrc @@ -0,0 +1,3 @@ +{ + "flutter": "3.24.1" +} \ No newline at end of file diff --git a/app/README.md b/app/README.md index 40cd56f88..ac0858933 100644 --- a/app/README.md +++ b/app/README.md @@ -6,6 +6,8 @@ The Omi App is a Flutter-based mobile application that serves as the companion a ### Quick Setup +Before getting started, make sure your device is connected and unlocked. If you're using an iPhone, ensure that Developer Mode is enabled โ€” you can toggle this in the iPhone settings. For Android devices, make sure the device is connected and USB debugging is enabled in Developer Options + 1. Navigate to the app directory: ```bash cd app @@ -19,12 +21,18 @@ The Omi App is a Flutter-based mobile application that serves as the companion a # For Android bash setup.sh android ``` + +3. Ensure GitHub SSH access is set up correctly for pulling certificates from repositories. After running the command below, if you're prompted for a passphrase, enter your SSH passphrase โ€” or simply press Enter/Return if you haven't set one. + ```bash + cd ~/.ssh; ssh-add + ``` -3. Run the app: +4. To run the app, navigate to the app directory and use the following command: ```bash flutter run --flavor dev ``` + ### Building and Deploying to iPhone To build and deploy the app to an iPhone so it can run independently from your laptop: diff --git a/app/android/settings.gradle b/app/android/settings.gradle index 591e609fb..63dbc5016 100644 --- a/app/android/settings.gradle +++ b/app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.1.4" apply false + id "com.android.application" version "8.6.0" apply false // START: FlutterFire Configuration id "com.google.gms.google-services" version "4.3.15" apply false // END: FlutterFire Configuration diff --git a/app/ios/Podfile.lock b/app/ios/Podfile.lock new file mode 100644 index 000000000..6a61049e5 --- /dev/null +++ b/app/ios/Podfile.lock @@ -0,0 +1,517 @@ +PODS: + - app_links (0.0.2): + - Flutter + - AppAuth (1.7.6): + - AppAuth/Core (= 1.7.6) + - AppAuth/ExternalUserAgent (= 1.7.6) + - AppAuth/Core (1.7.6) + - AppAuth/ExternalUserAgent (1.7.6): + - AppAuth/Core + - audio_session (0.0.1): + - Flutter + - awesome_notifications (0.10.0): + - Flutter + - IosAwnCore (~> 0.10.0) + - awesome_notifications_core (0.0.1): + - Flutter + - connectivity_plus (0.0.1): + - Flutter + - device_info_plus (0.0.1): + - Flutter + - DKImagePickerController/Core (4.3.9): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.9) + - DKImagePickerController/PhotoGallery (4.3.9): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.9) + - DKPhotoGallery (0.0.19): + - DKPhotoGallery/Core (= 0.0.19) + - DKPhotoGallery/Model (= 0.0.19) + - DKPhotoGallery/Preview (= 0.0.19) + - DKPhotoGallery/Resource (= 0.0.19) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.19): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.19): + - SDWebImage + - SwiftyGif + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter + - Firebase/Auth (11.10.0): + - Firebase/CoreOnly + - FirebaseAuth (~> 11.10.0) + - Firebase/CoreOnly (11.10.0): + - FirebaseCore (~> 11.10.0) + - Firebase/Messaging (11.10.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 11.10.0) + - firebase_auth (5.5.3): + - Firebase/Auth (= 11.10.0) + - firebase_core + - Flutter + - firebase_core (3.13.0): + - Firebase/CoreOnly (= 11.10.0) + - Flutter + - firebase_messaging (15.2.5): + - Firebase/Messaging (= 11.10.0) + - firebase_core + - Flutter + - FirebaseAppCheckInterop (11.13.0) + - FirebaseAuth (11.10.0): + - FirebaseAppCheckInterop (~> 11.0) + - FirebaseAuthInterop (~> 11.0) + - FirebaseCore (~> 11.10.0) + - FirebaseCoreExtension (~> 11.10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.0) + - GoogleUtilities/Environment (~> 8.0) + - GTMSessionFetcher/Core (< 5.0, >= 3.4) + - RecaptchaInterop (~> 101.0) + - FirebaseAuthInterop (11.13.0) + - FirebaseCore (11.10.0): + - FirebaseCoreInternal (~> 11.10.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Logger (~> 8.0) + - FirebaseCoreExtension (11.10.0): + - FirebaseCore (~> 11.10.0) + - FirebaseCoreInternal (11.10.0): + - "GoogleUtilities/NSData+zlib (~> 8.0)" + - FirebaseInstallations (11.10.0): + - FirebaseCore (~> 11.10.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - PromisesObjC (~> 2.4) + - FirebaseMessaging (11.10.0): + - FirebaseCore (~> 11.10.0) + - FirebaseInstallations (~> 11.0) + - GoogleDataTransport (~> 10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Reachability (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - nanopb (~> 3.30910.0) + - Flutter (1.0.0) + - flutter_archive (0.0.1): + - Flutter + - ZIPFoundation (= 0.9.19) + - flutter_background_service_ios (0.0.3): + - Flutter + - flutter_blue_plus (0.0.1): + - Flutter + - flutter_foreground_task (0.0.1): + - Flutter + - flutter_native_splash (2.4.3): + - Flutter + - flutter_silero_vad (0.0.1): + - Flutter + - onnxruntime-objc (= 1.15.0) + - flutter_sound (9.28.0): + - Flutter + - flutter_sound_core (= 9.28.0) + - flutter_sound_core (9.28.0) + - flutter_timezone (0.0.1): + - Flutter + - frame_sdk (0.0.2): + - Flutter + - geolocator_apple (1.2.0): + - Flutter + - FlutterMacOS + - google_sign_in_ios (0.0.1): + - Flutter + - FlutterMacOS + - GoogleSignIn (~> 7.0.0) + - GoogleDataTransport (10.1.0): + - nanopb (~> 3.30910.0) + - PromisesObjC (~> 2.4) + - GoogleSignIn (7.0.0): + - AppAuth (~> 1.5) + - GTMAppAuth (< 3.0, >= 1.3) + - GTMSessionFetcher/Core (< 4.0, >= 1.1) + - GoogleUtilities/AppDelegateSwizzler (8.1.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (8.1.0): + - GoogleUtilities/Privacy + - GoogleUtilities/Logger (8.1.0): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Network (8.1.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (8.1.0)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (8.1.0) + - GoogleUtilities/Reachability (8.1.0): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (8.1.0): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GTMAppAuth (2.0.0): + - AppAuth/Core (~> 1.6) + - GTMSessionFetcher/Core (< 4.0, >= 1.5) + - GTMSessionFetcher/Core (3.5.0) + - image_picker_ios (0.0.1): + - Flutter + - Instabug (14.3.0) + - instabug_flutter (14.3.1): + - Flutter + - Instabug (= 14.3.0) + - integration_test (0.0.1): + - Flutter + - Intercom (18.7.2) + - intercom_flutter (9.0.0): + - Flutter + - Intercom (= 18.7.2) + - IosAwnCore (0.10.0) + - iOSDFULibrary (4.15.3): + - ZIPFoundation (= 0.9.19) + - iOSMcuManagerLibrary (1.6): + - SwiftCBOR (= 0.4.4) + - just_audio (0.0.1): + - Flutter + - FlutterMacOS + - location (0.0.1): + - Flutter + - manage_calendar_events (0.0.1): + - Flutter + - map_launcher (0.0.1): + - Flutter + - mcumgr_flutter (0.0.2): + - Flutter + - iOSMcuManagerLibrary (= 1.6) + - SwiftProtobuf + - Mixpanel-swift (5.0.0): + - Mixpanel-swift/Complete (= 5.0.0) + - Mixpanel-swift/Complete (5.0.0) + - mixpanel_flutter (2.4.1): + - Flutter + - Mixpanel-swift (= 5.0.0) + - nanopb (3.30910.0): + - nanopb/decode (= 3.30910.0) + - nanopb/encode (= 3.30910.0) + - nanopb/decode (3.30910.0) + - nanopb/encode (3.30910.0) + - nordic_dfu (1.0.0): + - Flutter + - iOSDFULibrary (~> 4.15.3) + - onnxruntime-c (1.15.0) + - onnxruntime-objc (1.15.0): + - onnxruntime-objc/Core (= 1.15.0) + - onnxruntime-objc/Core (1.15.0): + - onnxruntime-c (= 1.15.0) + - opus_flutter_ios (1.4.0): + - Flutter + - package_info_plus (0.4.5): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - permission_handler_apple (9.3.0): + - Flutter + - PostHog (3.26.0) + - posthog_flutter (0.0.1): + - Flutter + - FlutterMacOS + - PostHog (~> 3.22) + - PromisesObjC (2.4.0) + - RecaptchaInterop (101.0.0) + - SDWebImage (5.21.0): + - SDWebImage/Core (= 5.21.0) + - SDWebImage/Core (5.21.0) + - share_plus (0.0.1): + - Flutter + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sign_in_with_apple (0.0.1): + - Flutter + - sqflite_darwin (0.0.4): + - Flutter + - FlutterMacOS + - SwiftCBOR (0.4.4) + - SwiftProtobuf (1.29.0) + - SwiftyGif (5.4.5) + - url_launcher_ios (0.0.1): + - Flutter + - webview_flutter_wkwebview (0.0.1): + - Flutter + - FlutterMacOS + - ZIPFoundation (0.9.19) + +DEPENDENCIES: + - app_links (from `.symlinks/plugins/app_links/ios`) + - audio_session (from `.symlinks/plugins/audio_session/ios`) + - awesome_notifications (from `.symlinks/plugins/awesome_notifications/ios`) + - awesome_notifications_core (from `.symlinks/plugins/awesome_notifications_core/ios`) + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) + - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) + - file_picker (from `.symlinks/plugins/file_picker/ios`) + - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - Flutter (from `Flutter`) + - flutter_archive (from `.symlinks/plugins/flutter_archive/ios`) + - flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`) + - flutter_blue_plus (from `.symlinks/plugins/flutter_blue_plus/ios`) + - flutter_foreground_task (from `.symlinks/plugins/flutter_foreground_task/ios`) + - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) + - flutter_silero_vad (from `.symlinks/plugins/flutter_silero_vad/ios`) + - flutter_sound (from `.symlinks/plugins/flutter_sound/ios`) + - flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`) + - frame_sdk (from `.symlinks/plugins/frame_sdk/ios`) + - geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`) + - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - instabug_flutter (from `.symlinks/plugins/instabug_flutter/ios`) + - integration_test (from `.symlinks/plugins/integration_test/ios`) + - intercom_flutter (from `.symlinks/plugins/intercom_flutter/ios`) + - just_audio (from `.symlinks/plugins/just_audio/darwin`) + - location (from `.symlinks/plugins/location/ios`) + - manage_calendar_events (from `.symlinks/plugins/manage_calendar_events/ios`) + - map_launcher (from `.symlinks/plugins/map_launcher/ios`) + - mcumgr_flutter (from `.symlinks/plugins/mcumgr_flutter/ios`) + - mixpanel_flutter (from `.symlinks/plugins/mixpanel_flutter/ios`) + - nordic_dfu (from `.symlinks/plugins/nordic_dfu/ios`) + - opus_flutter_ios (from `.symlinks/plugins/opus_flutter_ios/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - posthog_flutter (from `.symlinks/plugins/posthog_flutter/ios`) + - share_plus (from `.symlinks/plugins/share_plus/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`) + - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`) + +SPEC REPOS: + trunk: + - AppAuth + - DKImagePickerController + - DKPhotoGallery + - Firebase + - FirebaseAppCheckInterop + - FirebaseAuth + - FirebaseAuthInterop + - FirebaseCore + - FirebaseCoreExtension + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging + - flutter_sound_core + - GoogleDataTransport + - GoogleSignIn + - GoogleUtilities + - GTMAppAuth + - GTMSessionFetcher + - Instabug + - Intercom + - IosAwnCore + - iOSDFULibrary + - iOSMcuManagerLibrary + - Mixpanel-swift + - nanopb + - onnxruntime-c + - onnxruntime-objc + - PostHog + - PromisesObjC + - RecaptchaInterop + - SDWebImage + - SwiftCBOR + - SwiftProtobuf + - SwiftyGif + - ZIPFoundation + +EXTERNAL SOURCES: + app_links: + :path: ".symlinks/plugins/app_links/ios" + audio_session: + :path: ".symlinks/plugins/audio_session/ios" + awesome_notifications: + :path: ".symlinks/plugins/awesome_notifications/ios" + awesome_notifications_core: + :path: ".symlinks/plugins/awesome_notifications_core/ios" + connectivity_plus: + :path: ".symlinks/plugins/connectivity_plus/ios" + device_info_plus: + :path: ".symlinks/plugins/device_info_plus/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/ios" + firebase_auth: + :path: ".symlinks/plugins/firebase_auth/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + Flutter: + :path: Flutter + flutter_archive: + :path: ".symlinks/plugins/flutter_archive/ios" + flutter_background_service_ios: + :path: ".symlinks/plugins/flutter_background_service_ios/ios" + flutter_blue_plus: + :path: ".symlinks/plugins/flutter_blue_plus/ios" + flutter_foreground_task: + :path: ".symlinks/plugins/flutter_foreground_task/ios" + flutter_native_splash: + :path: ".symlinks/plugins/flutter_native_splash/ios" + flutter_silero_vad: + :path: ".symlinks/plugins/flutter_silero_vad/ios" + flutter_sound: + :path: ".symlinks/plugins/flutter_sound/ios" + flutter_timezone: + :path: ".symlinks/plugins/flutter_timezone/ios" + frame_sdk: + :path: ".symlinks/plugins/frame_sdk/ios" + geolocator_apple: + :path: ".symlinks/plugins/geolocator_apple/darwin" + google_sign_in_ios: + :path: ".symlinks/plugins/google_sign_in_ios/darwin" + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" + instabug_flutter: + :path: ".symlinks/plugins/instabug_flutter/ios" + integration_test: + :path: ".symlinks/plugins/integration_test/ios" + intercom_flutter: + :path: ".symlinks/plugins/intercom_flutter/ios" + just_audio: + :path: ".symlinks/plugins/just_audio/darwin" + location: + :path: ".symlinks/plugins/location/ios" + manage_calendar_events: + :path: ".symlinks/plugins/manage_calendar_events/ios" + map_launcher: + :path: ".symlinks/plugins/map_launcher/ios" + mcumgr_flutter: + :path: ".symlinks/plugins/mcumgr_flutter/ios" + mixpanel_flutter: + :path: ".symlinks/plugins/mixpanel_flutter/ios" + nordic_dfu: + :path: ".symlinks/plugins/nordic_dfu/ios" + opus_flutter_ios: + :path: ".symlinks/plugins/opus_flutter_ios/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + posthog_flutter: + :path: ".symlinks/plugins/posthog_flutter/ios" + share_plus: + :path: ".symlinks/plugins/share_plus/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + sign_in_with_apple: + :path: ".symlinks/plugins/sign_in_with_apple/ios" + sqflite_darwin: + :path: ".symlinks/plugins/sqflite_darwin/darwin" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + webview_flutter_wkwebview: + :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin" + +SPEC CHECKSUMS: + app_links: f3e17e4ee5e357b39d8b95290a9b2c299fca71c6 + AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73 + audio_session: 19e9480dbdd4e5f6c4543826b2e8b0e4ab6145fe + awesome_notifications: dd5518ff1c80be03d4f1c40f04da9d9cc2a37af5 + awesome_notifications_core: d02eed89738fa362d56cbd372850e9adcd2c6bef + connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d + device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 + file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49 + Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2 + firebase_auth: 3f532201cbdc7cd6dfc3bfa89affc0c294111e20 + firebase_core: 432718558359a8c08762151b5f49bb0f093eb6e0 + firebase_messaging: 3b99522baf7480dfb4b7683d2b34e842d577c362 + FirebaseAppCheckInterop: 72066489c209823649a997132bcd9269bc33a4bb + FirebaseAuth: c4146bdfdc87329f9962babd24dae89373f49a32 + FirebaseAuthInterop: 4fa327ec3c551a80a6929561f83af80b1dd44937 + FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7 + FirebaseCoreExtension: 6f357679327f3614e995dc7cf3f2d600bdc774ac + FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679 + FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3 + FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_archive: cb3e0219e555897ba4b36f166baa1eca394890b9 + flutter_background_service_ios: e30e0d3ee69e4cee66272d0c78eacd48c2e94aac + flutter_blue_plus: 4837da7d00cf5d441fdd6635b3a57f936778ea96 + flutter_foreground_task: 21ef182ab0a29a3005cc72cd70e5f45cb7f7f817 + flutter_native_splash: f71420956eb811e6d310720fee915f1d42852e7a + flutter_silero_vad: bcad5bcce50bd7f63b772ad3f46f9ce1995dd833 + flutter_sound: 82aba29055d6feba684d08906e0623217b87bcd3 + flutter_sound_core: 427465f72d07ab8c3edbe8ffdde709ddacd3763c + flutter_timezone: ffb07bdad3c6276af8dada0f11978d8a1f8a20bb + frame_sdk: 5d4d7ba36cf53cfdb6aebf563dc0a69e7920a727 + geolocator_apple: 66b711889fd333205763b83c9dcf0a57a28c7afd + google_sign_in_ios: 7c205d44fdc266640375c6ac33d96ba3983dbe02 + GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 + GoogleSignIn: b232380cf495a429b8095d3178a8d5855b42e842 + GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 + GTMAppAuth: 99fb010047ba3973b7026e45393f51f27ab965ae + GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 + image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 + Instabug: 97a4e694731f46bbc02dbe49ab29cc552c5e2f41 + instabug_flutter: 1d2781ee0b451dc2102fbe94802e310866d03e01 + integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 + Intercom: bb29786287d8b4e23d171ccbe9ceeb5b74c38b36 + intercom_flutter: 80e3f8f15cbee60ff772faa16f502368d10274f6 + IosAwnCore: 653786a911089012092ce831f2945cd339855a89 + iOSDFULibrary: 198c36ebe5a31bf2ca04ee8fb40837176a423e85 + iOSMcuManagerLibrary: 4102a4595be1c69e5286d7f1520a733c82c30b0a + just_audio: a42c63806f16995daf5b219ae1d679deb76e6a79 + location: d5cf8598915965547c3f36761ae9cc4f4e87d22e + manage_calendar_events: 9b2889799340398027b3e3f5c4891d41599ec257 + map_launcher: 5fde49ac9a52672bf99da746599f507b4490d7b5 + mcumgr_flutter: 097e59bec5917b527ba6d095da57bdaed2de1fa2 + Mixpanel-swift: e9bef28a9648faff384d5ba6f48ecc2787eb24c0 + mixpanel_flutter: 56a3d296d12ec2b7902792cb3266bdec15d434e8 + nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 + nordic_dfu: 963e2e4e6afb04e515ff43c546e6f8abf3e04ed5 + onnxruntime-c: e87399683ec19e3b812e13c6692882609a802b86 + onnxruntime-objc: 57ae8f83779a4c32731065d50d02d042af581114 + opus_flutter_ios: 0c103338d4f4316034e082857749a3514b9540d3 + package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 + PostHog: 77fa0e762ced56862eb9a520c46bda206ccf5f23 + posthog_flutter: 6d1041c7da77eb2032c27b72df103439af64cb8c + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + RecaptchaInterop: 11e0b637842dfb48308d242afc3f448062325aba + SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 + share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440 + sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d + SwiftCBOR: ce5354ec8b660da2d6fc754462881119dbe1f963 + SwiftProtobuf: b7aa08087e2ab6d162862d143020091254095f69 + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + webview_flutter_wkwebview: a4af96a051138e28e29f60101d094683b9f82188 + ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c + +PODFILE CHECKSUM: 0ff3dedbc65a62aff6be5119a19cb4fd9e15742d + +COCOAPODS: 1.15.2 diff --git a/app/ios/Runner.xcodeproj/project.pbxproj b/app/ios/Runner.xcodeproj/project.pbxproj index 9cf59c0a9..8141bb493 100644 --- a/app/ios/Runner.xcodeproj/project.pbxproj +++ b/app/ios/Runner.xcodeproj/project.pbxproj @@ -15,9 +15,9 @@ 29B635C199B3BDE0F2BE8EC5 /* devRelease.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 79B00761CB247C7EC7C8983B /* devRelease.xcconfig */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 426B89AD2C46919D00E24442 /* Config in Resources */ = {isa = PBXBuildFile; fileRef = 426B89AC2C46919D00E24442 /* Config */; }; - 63AF53B7F1AB365736C79AB8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C69A653D709374662CCB075E /* Pods_Runner.framework */; }; 6436409A27A31CD800820AF7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6436409C27A31CD800820AF7 /* InfoPlist.strings */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 8ECFBE4905FB83E862F3F961 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BA3E73408D04A71ABEA5167 /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -52,14 +52,16 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 072872AC24251C3536B9BABF /* Pods-Runner.debug-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-dev.xcconfig"; sourceTree = ""; }; 08E3947A4217EF205E22BD44 /* prodDebug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = prodDebug.xcconfig; path = Flutter/prodDebug.xcconfig; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 17DD34CA2CFE6F3845E13C99 /* devDebug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = devDebug.xcconfig; path = Flutter/devDebug.xcconfig; sourceTree = ""; }; + 18FFC3626FAEB6C0E2F8B8AC /* Pods-Runner.release-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-dev.xcconfig"; sourceTree = ""; }; 35656BCB5CBAA7C0BB162EE0 /* prodRelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = prodRelease.xcconfig; path = Flutter/prodRelease.xcconfig; sourceTree = ""; }; - 3724F354CEEDF26CAA89DE63 /* Pods-Runner.release-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-prod.xcconfig"; sourceTree = ""; }; + 3A57DC804B7F6C11D18054D4 /* Pods-Runner.profile-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-dev.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B84245E7DA0251DE76CA384 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 3BA3E73408D04A71ABEA5167 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 42127D962C283C250005AB40 /* OneSignalCore.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:J3J28YJX9L:OneSignal, Inc."; lastKnownFileType = wrapper.xcframework; name = OneSignalCore.xcframework; path = Pods/OneSignalXCFramework/iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework; sourceTree = ""; }; 42127D9A2C283C310005AB40 /* OneSignalExtension.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:J3J28YJX9L:OneSignal, Inc."; lastKnownFileType = wrapper.xcframework; name = OneSignalExtension.xcframework; path = Pods/OneSignalXCFramework/iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework; sourceTree = ""; }; 42127D9D2C283C400005AB40 /* OneSignalOSCore.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:J3J28YJX9L:OneSignal, Inc."; lastKnownFileType = wrapper.xcframework; name = OneSignalOSCore.xcframework; path = Pods/OneSignalXCFramework/iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework; sourceTree = ""; }; @@ -67,7 +69,6 @@ 42476A832C5E369200426330 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; 426B89AC2C46919D00E24442 /* Config */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Config; sourceTree = ""; }; 556416C8748DD3DD2C06A9DB /* devProfile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = devProfile.xcconfig; path = Flutter/devProfile.xcconfig; sourceTree = ""; }; - 5CC54DB1539C2E32157E773D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 5F7FD4162BF1232500923839 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 5FCEB2FA2C27586C00B17EE8 /* RunnerDebug-prod.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerDebug-prod.entitlements"; sourceTree = ""; }; 5FCEB2FB2C27587100B17EE8 /* RunnerProfile-prod.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerProfile-prod.entitlements"; sourceTree = ""; }; @@ -75,12 +76,11 @@ 5FCEB2FD2C2758BA00B17EE8 /* RunnerDebug-dev.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerDebug-dev.entitlements"; sourceTree = ""; }; 5FCEB2FE2C2758BD00B17EE8 /* RunnerProfile-dev.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerProfile-dev.entitlements"; sourceTree = ""; }; 5FCEB2FF2C2758C000B17EE8 /* RunnerRelease-dev.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerRelease-dev.entitlements"; sourceTree = ""; }; + 6F1A7E959CF9BBEC39BA4471 /* Pods-Runner.debug-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-prod.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 79A3E5C306D624AE31145607 /* Pods-Runner.profile-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-prod.xcconfig"; sourceTree = ""; }; 79B00761CB247C7EC7C8983B /* devRelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = devRelease.xcconfig; path = Flutter/devRelease.xcconfig; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 92800DE2DBE33C9182F3F582 /* Pods-Runner.profile-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-dev.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -88,15 +88,15 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9E42219331AC03D460762ACB /* Pods-Runner.release-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-dev.xcconfig"; sourceTree = ""; }; + 9D6DA65A5DFCF877576F2AEC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9F07595217A5DEEA0729C7FE /* Pods-Runner.release-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-prod.xcconfig"; sourceTree = ""; }; ACE7BEFB9654B6DF5B9E1790 /* prodLaunchScreen.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; name = prodLaunchScreen.storyboard; path = Runner/prodLaunchScreen.storyboard; sourceTree = ""; }; B52E83A1CC630E163A04DC50 /* prodProfile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = prodProfile.xcconfig; path = Flutter/prodProfile.xcconfig; sourceTree = ""; }; - C69A653D709374662CCB075E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CAA9769D950FF08AFB9038AC /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + B91448D531463AC31409FBDE /* Pods-Runner.profile-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-prod.xcconfig"; sourceTree = ""; }; + C797F1462626E744BA8F2F4B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; CF0FE6142D61FDC10072C10D /* Custom.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Custom.xcconfig; path = Flutter/Custom.xcconfig; sourceTree = ""; }; - D03DCC70D4791528CB0929E7 /* Pods-Runner.debug-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-prod.xcconfig"; sourceTree = ""; }; - E4D40465AE1C862B18960D63 /* Pods-Runner.debug-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-dev.xcconfig"; sourceTree = ""; }; E7A9F5F37DDF9FA87AC8A5CD /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; + E8303C81065F720515309566 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; EF770A936DE2AA63387FD198 /* devLaunchScreen.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; name = devLaunchScreen.storyboard; path = Runner/devLaunchScreen.storyboard; sourceTree = ""; }; /* End PBXFileReference section */ @@ -105,7 +105,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 63AF53B7F1AB365736C79AB8 /* Pods_Runner.framework in Frameworks */, + 8ECFBE4905FB83E862F3F961 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -120,7 +120,7 @@ 42127D9D2C283C400005AB40 /* OneSignalOSCore.xcframework */, 42127D9A2C283C310005AB40 /* OneSignalExtension.xcframework */, 42127D962C283C250005AB40 /* OneSignalCore.xcframework */, - C69A653D709374662CCB075E /* Pods_Runner.framework */, + 3BA3E73408D04A71ABEA5167 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -128,15 +128,15 @@ 68E21E60C4FBF7F520F1D656 /* Pods */ = { isa = PBXGroup; children = ( - 3B84245E7DA0251DE76CA384 /* Pods-Runner.debug.xcconfig */, - 5CC54DB1539C2E32157E773D /* Pods-Runner.release.xcconfig */, - CAA9769D950FF08AFB9038AC /* Pods-Runner.profile.xcconfig */, - D03DCC70D4791528CB0929E7 /* Pods-Runner.debug-prod.xcconfig */, - 79A3E5C306D624AE31145607 /* Pods-Runner.profile-prod.xcconfig */, - 3724F354CEEDF26CAA89DE63 /* Pods-Runner.release-prod.xcconfig */, - E4D40465AE1C862B18960D63 /* Pods-Runner.debug-dev.xcconfig */, - 92800DE2DBE33C9182F3F582 /* Pods-Runner.profile-dev.xcconfig */, - 9E42219331AC03D460762ACB /* Pods-Runner.release-dev.xcconfig */, + E8303C81065F720515309566 /* Pods-Runner.debug.xcconfig */, + 9D6DA65A5DFCF877576F2AEC /* Pods-Runner.release.xcconfig */, + C797F1462626E744BA8F2F4B /* Pods-Runner.profile.xcconfig */, + 6F1A7E959CF9BBEC39BA4471 /* Pods-Runner.debug-prod.xcconfig */, + B91448D531463AC31409FBDE /* Pods-Runner.profile-prod.xcconfig */, + 9F07595217A5DEEA0729C7FE /* Pods-Runner.release-prod.xcconfig */, + 072872AC24251C3536B9BABF /* Pods-Runner.debug-dev.xcconfig */, + 3A57DC804B7F6C11D18054D4 /* Pods-Runner.profile-dev.xcconfig */, + 18FFC3626FAEB6C0E2F8B8AC /* Pods-Runner.release-dev.xcconfig */, ); path = Pods; sourceTree = ""; @@ -212,7 +212,7 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - F9F8C4175EB80A90DC64548E /* [CP] Check Pods Manifest.lock */, + 850DCFF539DDE60719A1CB47 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 426B89AB2C46885100E24442 /* Copy Google Plist file */, 97C146EA1CF9000F007C117D /* Sources */, @@ -221,8 +221,8 @@ 42127D8A2C2839B60005AB40 /* Embed Foundation Extensions */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 2F67A041E3B0519B462D484D /* [CP] Embed Pods Frameworks */, - 1DD18D9D2FBAA8A200EFCE7E /* [CP] Copy Pods Resources */, + 1696D7B5D702A72B207AC179 /* [CP] Embed Pods Frameworks */, + C78E0E14E2A1712A91339475 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -294,24 +294,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 1DD18D9D2FBAA8A200EFCE7E /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 2F67A041E3B0519B462D484D /* [CP] Embed Pods Frameworks */ = { + 1696D7B5D702A72B207AC179 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -362,6 +345,28 @@ shellPath = /bin/sh; shellScript = "# Type a script or drag a sc# Type a script or drag a script file from your workspace to insert its path.\nDEV_GOOGLE_PLIST=\"${PROJECT_DIR}/Config/Dev\"\nPROD_GOOGLE_PLIST=\"${PROJECT_DIR}/Config/Prod\"\n\necho \"build config is ${CONFIGURATION}\"\n\ncase \"${CONFIGURATION}\" in\n\n \"Debug-dev\" | \"AdHoc_Staging\" | \"Release-dev\" | \"Debug\")\n cp -r \"$DEV_GOOGLE_PLIST/GoogleService-Info.plist\" \"${PROJECT_DIR}/Runner/GoogleService-Info.plist\" ;;\n \"Debug-prod\" | \"Profile\" |\"Release-prod\" |\"Release\")\n cp -r \"$PROD_GOOGLE_PLIST/GoogleService-Info.plist\" \"${PROJECT_DIR}/Runner/GoogleService-Info.plist\" ;;\n\n *)\n ;;\nesac\n"; }; + 850DCFF539DDE60719A1CB47 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -377,26 +382,21 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; - F9F8C4175EB80A90DC64548E /* [CP] Check Pods Manifest.lock */ = { + C78E0E14E2A1712A91339475 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -442,7 +442,7 @@ /* Begin XCBuildConfiguration section */ 0CE6142D2C21F36000559F1E /* Debug-prod */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D03DCC70D4791528CB0929E7 /* Pods-Runner.debug-prod.xcconfig */; + baseConfigurationReference = 6F1A7E959CF9BBEC39BA4471 /* Pods-Runner.debug-prod.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; @@ -459,7 +459,7 @@ }; 0CE6142E2C21F36000559F1E /* Profile-prod */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 79A3E5C306D624AE31145607 /* Pods-Runner.profile-prod.xcconfig */; + baseConfigurationReference = B91448D531463AC31409FBDE /* Pods-Runner.profile-prod.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; @@ -476,7 +476,7 @@ }; 0CE6142F2C21F36000559F1E /* Release-prod */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3724F354CEEDF26CAA89DE63 /* Pods-Runner.release-prod.xcconfig */; + baseConfigurationReference = 9F07595217A5DEEA0729C7FE /* Pods-Runner.release-prod.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; @@ -493,7 +493,7 @@ }; 0CE614302C21F36000559F1E /* Debug-dev */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E4D40465AE1C862B18960D63 /* Pods-Runner.debug-dev.xcconfig */; + baseConfigurationReference = 072872AC24251C3536B9BABF /* Pods-Runner.debug-dev.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; @@ -510,7 +510,7 @@ }; 0CE614312C21F36000559F1E /* Profile-dev */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 92800DE2DBE33C9182F3F582 /* Pods-Runner.profile-dev.xcconfig */; + baseConfigurationReference = 3A57DC804B7F6C11D18054D4 /* Pods-Runner.profile-dev.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; @@ -527,7 +527,7 @@ }; 0CE614322C21F36000559F1E /* Release-dev */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9E42219331AC03D460762ACB /* Pods-Runner.release-dev.xcconfig */; + baseConfigurationReference = 18FFC3626FAEB6C0E2F8B8AC /* Pods-Runner.release-dev.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; @@ -546,7 +546,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -644,7 +644,7 @@ baseConfigurationReference = 08E3947A4217EF205E22BD44 /* prodDebug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; ASSETCATALOG_COMPILER_APPICON_NAME = "$(ASSET_PREFIX)AppIcon"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; @@ -719,7 +719,7 @@ baseConfigurationReference = 35656BCB5CBAA7C0BB162EE0 /* prodRelease.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; ASSETCATALOG_COMPILER_APPICON_NAME = "$(ASSET_PREFIX)AppIcon"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; @@ -789,7 +789,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -846,7 +846,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -991,7 +991,7 @@ baseConfigurationReference = 79B00761CB247C7EC7C8983B /* devRelease.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; ASSETCATALOG_COMPILER_APPICON_NAME = "$(ASSET_PREFIX)AppIcon"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; @@ -1062,7 +1062,7 @@ baseConfigurationReference = 556416C8748DD3DD2C06A9DB /* devProfile.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; ASSETCATALOG_COMPILER_APPICON_NAME = "$(ASSET_PREFIX)AppIcon"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; @@ -1132,7 +1132,7 @@ baseConfigurationReference = B52E83A1CC630E163A04DC50 /* prodProfile.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; ASSETCATALOG_COMPILER_APPICON_NAME = "$(ASSET_PREFIX)AppIcon"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; @@ -1202,7 +1202,7 @@ baseConfigurationReference = 17DD34CA2CFE6F3845E13C99 /* devDebug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = $ARCHS_STANDARD_64_BIT; + ARCHS = "$ARCHS_STANDARD_64_BIT"; ASSETCATALOG_COMPILER_APPICON_NAME = "$(ASSET_PREFIX)AppIcon"; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; CLANG_ANALYZER_NONNULL = YES; diff --git a/app/lib/backend/auth.dart b/app/lib/backend/auth.dart index 165a360fa..e318362a4 100644 --- a/app/lib/backend/auth.dart +++ b/app/lib/backend/auth.dart @@ -55,6 +55,7 @@ Future signInWithApple() async { final oauthCredential = OAuthProvider("apple.com").credential( idToken: appleCredential.identityToken, rawNonce: rawNonce, + accessToken: appleCredential.authorizationCode, ); debugPrint('OAuth Credential created.'); @@ -110,7 +111,9 @@ Future signInWithGoogle() async { try { debugPrint('Signing in with Google'); // Trigger the authentication flow - final GoogleSignInAccount? googleUser = await GoogleSignIn(scopes: ['profile', 'email']).signIn(); + final GoogleSignInAccount? googleUser = await GoogleSignIn( + scopes: ['profile', 'email'], + ).signIn(); debugPrint('Google User: $googleUser'); // Obtain the auth details from the request diff --git a/app/lib/backend/http/api/apps.dart b/app/lib/backend/http/api/apps.dart index 1e8b8a3d4..908842370 100644 --- a/app/lib/backend/http/api/apps.dart +++ b/app/lib/backend/http/api/apps.dart @@ -7,10 +7,10 @@ import 'package:omi/backend/http/shared.dart'; import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/app.dart'; import 'package:omi/env/env.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:http/http.dart' as http; import 'package:omi/utils/logger.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; import 'package:path/path.dart'; Future> retrieveApps() async { @@ -29,7 +29,7 @@ Future> retrieveApps() async { return apps; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return SharedPreferencesUtil().appsList; } } @@ -52,7 +52,7 @@ Future> retrievePopularApps() async { return apps; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return SharedPreferencesUtil().appsList; } } @@ -287,7 +287,7 @@ Future> getAppCategories() async { return Category.fromJsonList(res); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return []; } } @@ -306,7 +306,7 @@ Future> getAppCapabilitiesServer() async { return AppCapability.fromJsonList(res); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return []; } } @@ -325,7 +325,7 @@ Future> getNotificationScopesServer() async { return NotificationScope.fromJsonList(res); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return []; } } @@ -343,7 +343,7 @@ Future changeAppVisibilityServer(String appId, bool makePublic) async { return true; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return false; } } @@ -361,7 +361,7 @@ Future deleteAppServer(String appId) async { return true; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return false; } } @@ -379,7 +379,7 @@ Future?> getAppDetailsServer(String appId) async { return jsonDecode(response.body); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return null; } } @@ -397,7 +397,7 @@ Future> getPaymentPlansServer() async { return PaymentPlan.fromJsonList(jsonDecode(response.body)); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return []; } } @@ -415,7 +415,7 @@ Future getGenratedDescription(String name, String description) async { return jsonDecode(response.body)['description']; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return ''; } } @@ -434,7 +434,7 @@ Future> listApiKeysServer(String appId) async { return AppApiKey.fromJsonList(jsonDecode(response.body)); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return []; } } @@ -454,7 +454,7 @@ Future> createApiKeyServer(String appId) async { return jsonDecode(response.body); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); throw Exception('Failed to create API key: ${e.toString()}'); } } @@ -474,7 +474,7 @@ Future deleteApiKeyServer(String appId, String keyId) async { return true; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); throw Exception('Failed to delete API key: ${e.toString()}'); } } @@ -546,7 +546,7 @@ Future checkPersonaUsername(String username) async { return jsonDecode(response.body)['is_taken']; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return true; } } @@ -564,7 +564,7 @@ Future getTwitterProfileData(String handle) async { return jsonDecode(response.body); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return null; } } @@ -590,7 +590,7 @@ Future<(bool, String?)> verifyTwitterOwnership(String username, String handle, S ); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return (false, null); } } @@ -608,7 +608,7 @@ Future getPersonaInitialMessage(String username) async { return jsonDecode(response.body)['message']; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return ''; } } @@ -627,7 +627,7 @@ Future getUserPersonaServer() async { return App.fromJson(res); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return null; } } @@ -646,7 +646,7 @@ Future generateUsername(String handle) async { return res['username']; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return null; } } @@ -664,7 +664,7 @@ Future migrateAppOwnerId(String oldId) async { return true; } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return false; } } @@ -682,7 +682,7 @@ Future?> getUpsertUserPersonaServer() async { return jsonDecode(response.body); } catch (e, stackTrace) { debugPrint(e.toString()); - CrashReporting.reportHandledCrash(e, stackTrace); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return null; } } diff --git a/app/lib/backend/http/api/conversations.dart b/app/lib/backend/http/api/conversations.dart index 252dbfada..63e6d172d 100644 --- a/app/lib/backend/http/api/conversations.dart +++ b/app/lib/backend/http/api/conversations.dart @@ -3,12 +3,12 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:omi/backend/http/shared.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; import 'package:omi/backend/schema/conversation.dart'; import 'package:omi/backend/schema/structured.dart'; import 'package:omi/backend/schema/transcript_segment.dart'; import 'package:omi/env/env.dart'; import 'package:http/http.dart' as http; -import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:path/path.dart'; Future processInProgressConversation() async { @@ -24,14 +24,8 @@ Future processInProgressConversation() async { return CreateConversationResponse.fromJson(jsonDecode(response.body)); } else { // TODO: Server returns 304 doesn't recover - CrashReporting.reportHandledCrash( - Exception('Failed to create conversation'), - StackTrace.current, - level: NonFatalExceptionLevel.info, - userAttributes: { - 'response': response.body, - }, - ); + PlatformManager.instance.instabug.reportCrash(Exception('Failed to create conversation'), StackTrace.current, + userAttributes: {'response': response.body}); } return null; } @@ -283,6 +277,23 @@ Future setConversationActionItemState( return response.statusCode == 200; } +Future updateActionItemDescription( + String conversationId, String oldDescription, String newDescription, int idx) async { + var body = { + 'old_description': oldDescription, + 'description': newDescription, + }; + var response = await makeApiCall( + url: '${Env.apiBaseUrl}v1/conversations/$conversationId/action-items/$idx', + headers: {}, + method: 'PATCH', + body: jsonEncode(body), + ); + if (response == null) return false; + debugPrint('updateActionItemDescription: ${response.body}'); + return response.statusCode == 200; +} + Future deleteConversationActionItem(String conversationId, ActionItem item) async { var response = await makeApiCall( url: '${Env.apiBaseUrl}v1/conversations/$conversationId/action-items', @@ -381,7 +392,6 @@ Future<(List, int, int)> searchConversationsServer( return ([], 0, 0); } - Future testConversationPrompt(String prompt, String conversationId) async { var response = await makeApiCall( url: '${Env.apiBaseUrl}v1/conversations/$conversationId/test-prompt', @@ -392,9 +402,9 @@ Future testConversationPrompt(String prompt, String conversationId) asyn }), ); if (response == null) return ''; - if (response.statusCode == 200){ + if (response.statusCode == 200) { return jsonDecode(response.body)['summary']; - }else { + } else { return ''; } } diff --git a/app/lib/backend/http/api/messages.dart b/app/lib/backend/http/api/messages.dart index d804ab6a0..2e01d1962 100644 --- a/app/lib/backend/http/api/messages.dart +++ b/app/lib/backend/http/api/messages.dart @@ -8,7 +8,6 @@ import 'package:omi/env/env.dart'; import 'package:omi/utils/logger.dart'; import 'package:omi/utils/other/string_utils.dart'; import 'package:http/http.dart' as http; -import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:path/path.dart'; Future> getMessagesServer({ @@ -40,7 +39,7 @@ Future> getMessagesServer({ Future> clearChatServer({String? pluginId}) async { if (pluginId == 'no_selected') pluginId = null; var response = await makeApiCall( - url: '${Env.apiBaseUrl}v1/messages?plugin_id=${pluginId ?? ''}', + url: '${Env.apiBaseUrl}v2/messages?plugin_id=${pluginId ?? ''}', headers: {}, method: 'DELETE', body: '', @@ -53,32 +52,6 @@ Future> clearChatServer({String? pluginId}) async { } } -Future sendMessageServer(String text, {String? appId, List? fileIds}) { - var url = '${Env.apiBaseUrl}v1/messages?plugin_id=$appId'; - if (appId == null || appId.isEmpty || appId == 'null' || appId == 'no_selected') { - url = '${Env.apiBaseUrl}v1/messages'; - } - return makeApiCall( - url: url, - headers: {}, - method: 'POST', - body: jsonEncode({'text': text, 'file_ids': fileIds}), - ).then((response) { - if (response == null) throw Exception('Failed to send message'); - if (response.statusCode == 200) { - return ServerMessage.fromJson(jsonDecode(response.body)); - } else { - Logger.error('Failed to send message ${response.body}'); - CrashReporting.reportHandledCrash( - Exception('Failed to send message ${response.body}'), - StackTrace.current, - level: NonFatalExceptionLevel.error, - ); - return ServerMessage.failedMessage(); - } - }); -} - ServerMessageChunk? parseMessageChunk(String line, String messageId) { if (line.startsWith('think: ')) { return ServerMessageChunk(messageId, line.substring(7).replaceAll("__CRLF__", "\n"), MessageChunkType.think); @@ -164,7 +137,7 @@ Stream sendMessageStreamServer(String text, {String? appId, Future getInitialAppMessage(String? appId) { return makeApiCall( - url: '${Env.apiBaseUrl}v1/initial-message?plugin_id=$appId', + url: '${Env.apiBaseUrl}v2/initial-message?app_id=$appId', headers: {}, method: 'POST', body: '', @@ -235,36 +208,10 @@ Stream sendVoiceMessageStreamServer(List files) async* } } -Future> sendVoiceMessageServer(List files) async { - var request = http.MultipartRequest( - 'POST', - Uri.parse('${Env.apiBaseUrl}v1/voice-messages'), - ); - for (var file in files) { - request.files.add(await http.MultipartFile.fromPath('files', file.path, filename: basename(file.path))); - } - request.headers.addAll({'Authorization': await getAuthHeader()}); - - try { - var streamedResponse = await request.send(); - var response = await http.Response.fromStream(streamedResponse); - if (response.statusCode == 200) { - debugPrint('sendVoiceMessageServer response body: ${jsonDecode(response.body)}'); - return ((jsonDecode(response.body) ?? []) as List).map((m) => ServerMessage.fromJson(m)).toList(); - } else { - debugPrint('Failed to upload sample. Status code: ${response.statusCode} ${response.body}'); - throw Exception('Failed to upload sample. Status code: ${response.statusCode}'); - } - } catch (e) { - debugPrint('An error occurred uploadSample: $e'); - throw Exception('An error occurred uploadSample: $e'); - } -} - Future?> uploadFilesServer(List files, {String? appId}) async { - var url = '${Env.apiBaseUrl}v1/files?plugin_id=$appId'; + var url = '${Env.apiBaseUrl}v2/files?app_id=$appId'; if (appId == null || appId.isEmpty || appId == 'null' || appId == 'no_selected') { - url = '${Env.apiBaseUrl}v1/files'; + url = '${Env.apiBaseUrl}v2/files'; } var request = http.MultipartRequest( 'POST', @@ -301,7 +248,7 @@ Future?> uploadFilesServer(List files, {String? appId}) Future reportMessageServer(String messageId) async { var response = await makeApiCall( - url: '${Env.apiBaseUrl}v1/messages/$messageId/report', + url: '${Env.apiBaseUrl}v2/messages/$messageId/report', headers: {}, method: 'POST', body: '', @@ -312,20 +259,19 @@ Future reportMessageServer(String messageId) async { } } - Future transcribeVoiceMessage(File audioFile) async { try { var request = http.MultipartRequest( 'POST', - Uri.parse('${Env.apiBaseUrl}v1/voice-message/transcribe'), + Uri.parse('${Env.apiBaseUrl}v2/voice-message/transcribe'), ); - + request.headers.addAll({'Authorization': await getAuthHeader()}); request.files.add(await http.MultipartFile.fromPath('files', audioFile.path)); - + var streamedResponse = await request.send(); var response = await http.Response.fromStream(streamedResponse); - + if (response.statusCode == 200) { final data = jsonDecode(response.body); return data['transcript'] ?? ''; diff --git a/app/lib/backend/http/api/users.dart b/app/lib/backend/http/api/users.dart index e2591c229..e18397468 100644 --- a/app/lib/backend/http/api/users.dart +++ b/app/lib/backend/http/api/users.dart @@ -6,7 +6,7 @@ import 'package:omi/backend/http/shared.dart'; import 'package:omi/backend/schema/geolocation.dart'; import 'package:omi/backend/schema/person.dart'; import 'package:omi/env/env.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; Future updateUserGeolocation({required Geolocation geolocation}) async { var response = await makeApiCall( @@ -17,12 +17,8 @@ Future updateUserGeolocation({required Geolocation geolocation}) async { ); if (response == null) return false; if (response.statusCode == 200) return true; - CrashReporting.reportHandledCrash( - Exception('Failed to update user geolocation'), - StackTrace.current, - level: NonFatalExceptionLevel.info, - userAttributes: {'response': response.body}, - ); + PlatformManager.instance.instabug.reportCrash(Exception('Failed to update user geolocation'), StackTrace.current, + userAttributes: {'response': response.body}); return false; } @@ -183,7 +179,6 @@ Future> getAllPeople({bool includeSpeechSamples = true}) async { body: '', ); if (response == null) return []; - debugPrint('getAllPeople response: ${response.body}'); if (response.statusCode == 200) { List peopleJson = jsonDecode(response.body); List people = peopleJson.mapIndexed((idx, json) { diff --git a/app/lib/backend/http/shared.dart b/app/lib/backend/http/shared.dart index ad90be3aa..9831e1842 100644 --- a/app/lib/backend/http/shared.dart +++ b/app/lib/backend/http/shared.dart @@ -6,7 +6,7 @@ import 'package:omi/backend/preferences.dart'; import 'package:omi/env/env.dart'; import 'package:omi/utils/logger.dart'; import 'package:http/http.dart' as http; -import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; Future getAuthHeader() async { DateTime? expiry = DateTime.fromMillisecondsSinceEpoch(SharedPreferencesUtil().tokenExpirationTime); @@ -72,12 +72,7 @@ Future makeApiCall({ return response; } catch (e, stackTrace) { debugPrint('HTTP request failed: $e, $stackTrace'); - CrashReporting.reportHandledCrash( - e, - stackTrace, - userAttributes: {'url': url, 'method': method}, - level: NonFatalExceptionLevel.warning, - ); + PlatformManager.instance.instabug.reportCrash(e, stackTrace, userAttributes: {'url': url, 'method': method}); return null; } finally {} } @@ -131,17 +126,13 @@ dynamic extractContentFromResponse( } else { debugPrint('Error fetching data: ${response?.statusCode}'); // TODO: handle error, better specially for script migration - CrashReporting.reportHandledCrash( - Exception('Error fetching data: ${response?.statusCode}'), - StackTrace.current, - userAttributes: { - 'response_null': (response == null).toString(), - 'response_status_code': response?.statusCode.toString() ?? '', - 'is_embedding': isEmbedding.toString(), - 'is_function_calling': isFunctionCalling.toString(), - }, - level: NonFatalExceptionLevel.warning, - ); + PlatformManager.instance.instabug + .reportCrash(Exception('Error fetching data: ${response?.statusCode}'), StackTrace.current, userAttributes: { + 'response_null': (response == null).toString(), + 'response_status_code': response?.statusCode.toString() ?? '', + 'is_embedding': isEmbedding.toString(), + 'is_function_calling': isFunctionCalling.toString(), + }); return null; } } diff --git a/app/lib/backend/preferences.dart b/app/lib/backend/preferences.dart index b6ac3c500..fe0aaf372 100644 --- a/app/lib/backend/preferences.dart +++ b/app/lib/backend/preferences.dart @@ -213,6 +213,10 @@ class SharedPreferencesUtil { set showConversationDeleteConfirmation(bool value) => saveBool("showConversationDeleteConfirmation", value); + bool get showActionItemDeleteConfirmation => getBool('showActionItemDeleteConfirmation') ?? true; + + set showActionItemDeleteConfirmation(bool value) => saveBool('showActionItemDeleteConfirmation', value); + List get appsList { final List apps = getStringList('appsList') ?? []; return App.fromJsonList(apps.map((e) => jsonDecode(e)).toList()); diff --git a/app/lib/backend/schema/conversation.dart b/app/lib/backend/schema/conversation.dart index 5e3202fb9..ed9fdd575 100644 --- a/app/lib/backend/schema/conversation.dart +++ b/app/lib/backend/schema/conversation.dart @@ -220,6 +220,21 @@ class ServerConversation { return transcript; } } + + /// Calculates the conversation duration in seconds based on transcript segments + int getDurationInSeconds() { + if (transcriptSegments.isEmpty) return 0; + + // Find the last segment's end time + double lastEndTime = 0; + for (var segment in transcriptSegments) { + if (segment.end > lastEndTime) { + lastEndTime = segment.end; + } + } + + return lastEndTime.toInt(); + } } class SyncLocalFilesResponse { diff --git a/app/lib/backend/schema/memory.dart b/app/lib/backend/schema/memory.dart index 85ef9caf8..53aee7084 100644 --- a/app/lib/backend/schema/memory.dart +++ b/app/lib/backend/schema/memory.dart @@ -1,4 +1,4 @@ -enum MemoryCategory { core, lifestyle, hobbies, interests, habits, work, skills, learnings, other } +enum MemoryCategory { interesting, system } enum MemoryVisibility { private, public } @@ -40,7 +40,7 @@ class Memory { content: json['content'], category: MemoryCategory.values.firstWhere( (e) => e.toString().split('.').last == json['category'], - orElse: () => MemoryCategory.other, + orElse: () => MemoryCategory.interesting, ), createdAt: DateTime.parse(json['created_at']).toLocal(), updatedAt: DateTime.parse(json['updated_at']).toLocal(), @@ -50,9 +50,7 @@ class Memory { manuallyAdded: json['manually_added'] ?? false, edited: json['edited'] ?? false, deleted: json['deleted'] ?? false, - visibility: json['visibility'] != null - ? (MemoryVisibility.values.asNameMap()[json['visibility']] ?? MemoryVisibility.public) - : MemoryVisibility.public, + visibility: json['visibility'] != null ? (MemoryVisibility.values.asNameMap()[json['visibility']] ?? MemoryVisibility.public) : MemoryVisibility.public, ); } diff --git a/app/lib/main.dart b/app/lib/main.dart index 81c9c86ea..770d3bc3a 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -1,5 +1,5 @@ import 'dart:async'; - +import 'dart:io'; import 'package:app_links/app_links.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -43,8 +43,6 @@ import 'package:omi/services/notifications.dart'; import 'package:omi/services/services.dart'; import 'package:omi/utils/alerts/app_snackbar.dart'; import 'package:omi/utils/analytics/growthbook.dart'; -import 'package:omi/utils/analytics/intercom.dart'; -import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/features/calendar.dart'; import 'package:omi/utils/logger.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; @@ -53,6 +51,8 @@ import 'package:opus_flutter/opus_flutter.dart' as opus_flutter; import 'package:posthog_flutter/posthog_flutter.dart'; import 'package:provider/provider.dart'; import 'package:talker_flutter/talker_flutter.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; +import 'package:omi/utils/debugging/instabug_manager.dart'; Future _init() async { // Service manager @@ -65,17 +65,16 @@ Future _init() async { await Firebase.initializeApp(options: dev.DefaultFirebaseOptions.currentPlatform, name: 'dev'); } - await IntercomManager().initIntercom(); + await PlatformManager.initializeServices(); await NotificationService.instance.initialize(); await SharedPreferencesUtil.init(); - await MixpanelManager.init(); // TODO: thinh, move to app start await ServiceManager.instance().start(); bool isAuth = (await getIdToken()) != null; - if (isAuth) MixpanelManager().identify(); - initOpus(await opus_flutter.load()); + if (isAuth) PlatformManager.instance.mixpanel.identify(); + if (!Platform.isMacOS) initOpus(await opus_flutter.load()); await GrowthbookUtil.init(); CalendarUtil.init(); @@ -105,15 +104,15 @@ void main() async { // _setupAudioSession(); bool isAuth = await _init(); if (Env.instabugApiKey != null) { - await Instabug.setWelcomeMessageMode(WelcomeMessageMode.disabled); + await PlatformManager.instance.instabug.setWelcomeMessageMode(WelcomeMessageMode.disabled); runZonedGuarded( () async { - Instabug.init( + await InstabugManager.init( token: Env.instabugApiKey!, invocationEvents: [InvocationEvent.none], ); if (isAuth) { - Instabug.identifyUser( + PlatformManager.instance.instabug.identifyUser( FirebaseAuth.instance.currentUser?.email ?? '', SharedPreferencesUtil().fullName, SharedPreferencesUtil().uid, @@ -122,7 +121,7 @@ void main() async { FlutterError.onError = (FlutterErrorDetails details) { Zone.current.handleUncaughtError(details.exception, details.stack ?? StackTrace.empty); }; - Instabug.setColorTheme(ColorTheme.dark); + PlatformManager.instance.instabug.setColorTheme(ColorTheme.dark); runApp(const MyApp()); }, CrashReporting.reportCrash, @@ -220,7 +219,8 @@ class _MyAppState extends State with WidgetsBindingObserver { return WithForegroundTask( child: MaterialApp( navigatorObservers: [ - if (Env.instabugApiKey != null) InstabugNavigatorObserver(), + if (Env.instabugApiKey != null && PlatformManager.instance.instabug.getNavigatorObserver() != null) + PlatformManager.instance.instabug.getNavigatorObserver()!, if (Env.posthogApiKey != null) PosthogObserver(), ], debugShowCheckedModeBanner: F.env == Environment.dev, @@ -315,7 +315,7 @@ class _DeciderWidgetState extends State { if (mounted) { var app = await context.read().getAppFromId(uri.pathSegments[1]); if (app != null) { - MixpanelManager().track('App Opened From DeepLink', properties: {'appId': app.id}); + PlatformManager.instance.mixpanel.track('App Opened From DeepLink', properties: {'appId': app.id}); if (mounted) { Navigator.of(context).push(MaterialPageRoute(builder: (context) => AppDetailPage(app: app))); } @@ -341,9 +341,7 @@ class _DeciderWidgetState extends State { context.read().setupHasSpeakerProfile(); context.read().setupUserPrimaryLanguage(); try { - await IntercomManager.instance.intercom.loginIdentifiedUser( - userId: SharedPreferencesUtil().uid, - ); + await PlatformManager.instance.intercom.loginIdentifiedUser(SharedPreferencesUtil().uid); } catch (e) { debugPrint('Failed to login to Intercom: $e'); } @@ -352,9 +350,11 @@ class _DeciderWidgetState extends State { context.read().setAppsFromCache(); context.read().refreshMessages(); } else { - await IntercomManager.instance.intercom.loginUnidentifiedUser(); + if (!PlatformManager.instance.isMacOS) { + await PlatformManager.instance.intercom.intercom.loginUnidentifiedUser(); + } } - IntercomManager.instance.setUserAttributes(); + PlatformManager.instance.intercom.setUserAttributes(); }); super.initState(); } diff --git a/app/lib/pages/action_items/action_items_page.dart b/app/lib/pages/action_items/action_items_page.dart new file mode 100644 index 000000000..a6fdf3918 --- /dev/null +++ b/app/lib/pages/action_items/action_items_page.dart @@ -0,0 +1,354 @@ +import 'package:flutter/material.dart'; +import 'package:omi/providers/conversation_provider.dart'; +import 'package:provider/provider.dart'; +import 'widgets/action_item_title_widget.dart'; +import 'widgets/convo_action_items_group_widget.dart'; +import 'package:omi/backend/schema/conversation.dart'; +import 'package:omi/backend/schema/structured.dart'; +import 'package:omi/utils/analytics/mixpanel.dart'; + +class ActionItemsPage extends StatefulWidget { + const ActionItemsPage({super.key}); + + @override + State createState() => _ActionItemsPageState(); +} + +class _ActionItemsPageState extends State with AutomaticKeepAliveClientMixin { + bool _showGroupedView = false; + + @override + bool get wantKeepAlive => true; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + MixpanelManager().actionItemsPageOpened(); + }); + } + + // Get all action items as a flat list + List _getFlattenedActionItems(Map> itemsByConversation) { + final result = []; + + for (final entry in itemsByConversation.entries) { + for (final item in entry.value) { + if (item.deleted) continue; + result.add( + ActionItemData( + actionItem: item, + conversation: entry.key, + itemIndex: entry.key.structured.actionItems.indexOf(item), + ), + ); + } + } + + // Sort by completion status (incomplete first) + result.sort((a, b) { + if (a.actionItem.completed == b.actionItem.completed) return 0; + return a.actionItem.completed ? 1 : -1; + }); + + return result; + } + + @override + Widget build(BuildContext context) { + super.build(context); + return Consumer( + builder: (context, convoProvider, child) { + final Map> itemsByConversation = + convoProvider.conversationsWithActiveActionItems; + + // Sort conversations by date (most recent first) + final sortedEntries = itemsByConversation.entries.toList() + ..sort((a, b) => b.key.createdAt.compareTo(a.key.createdAt)); + + // Get flattened list for non-grouped view + final flattenedItems = _getFlattenedActionItems(itemsByConversation); + + return Scaffold( + backgroundColor: Theme.of(context).colorScheme.primary, + body: CustomScrollView( + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + // Main Content + if (convoProvider.isLoadingConversations && sortedEntries.isEmpty) + const SliverFillRemaining( + child: Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.white), + ), + ), + ) + else if (sortedEntries.isEmpty) + SliverFillRemaining( + child: Center( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.check_circle_outline, + size: 72, + color: Colors.grey.shade400, + ), + const SizedBox(height: 24), + Text( + 'No Action Items', + style: Theme.of(context).textTheme.headlineSmall?.copyWith( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 12), + Text( + 'Tasks and to-dos from your conversations will appear here once they are created.', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.grey.shade400, + fontSize: 16, + height: 1.5, + ), + ), + ], + ), + ), + ), + ) + else + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.fromLTRB(16.0, 24.0, 16.0, 0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'To-Do\'s (${flattenedItems.where((item) => !item.actionItem.completed).length})', + style: const TextStyle( + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.w600, + ), + ), + const Row( + children: [ + // Settings button + // TODO: Add settings once we have more stuff for action items + // Container( + // width: 44, + // height: 44, + // margin: const EdgeInsets.only(right: 8), + // decoration: BoxDecoration( + // color: Colors.grey.shade700.withOpacity(0.3), + // borderRadius: BorderRadius.circular(12), + // ), + // child: IconButton( + // icon: const Icon(Icons.tune, size: 20), + // color: Colors.white, + // onPressed: () { + // // Filter settings + // }, + // ), + // ), + // Group/Ungroup toggle button hidden for now + // Container( + // width: 44, + // height: 44, + // decoration: BoxDecoration( + // color: _showGroupedView + // ? Colors.deepPurpleAccent.withOpacity(0.3) + // : Colors.grey.shade700.withOpacity(0.3), + // borderRadius: BorderRadius.circular(12), + // border: _showGroupedView + // ? Border.all(color: Colors.deepPurpleAccent, width: 1.5) + // : null, + // ), + // child: IconButton( + // icon: Icon( + // _showGroupedView ? Icons.view_agenda_outlined : Icons.view_list_outlined, + // size: 20, + // ), + // color: _showGroupedView ? Colors.deepPurpleAccent : Colors.white, + // onPressed: () { + // setState(() { + // _showGroupedView = !_showGroupedView; + // }); + // MixpanelManager().actionItemsViewToggled(_showGroupedView); + // }, + // ), + // ), + ], + ), + ], + ), + const SizedBox(height: 16), + ], + ), + ), + ), + + if (sortedEntries.isNotEmpty) + _showGroupedView ? _buildGroupedView(sortedEntries) : _buildFlatView(flattenedItems), + + if (sortedEntries.isNotEmpty) + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.fromLTRB(16.0, 24.0, 16.0, 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + const Text( + 'Completed', + style: TextStyle( + color: Colors.white, + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey[800], + borderRadius: BorderRadius.circular(12), + ), + child: Text( + '${flattenedItems.where((item) => item.actionItem.completed).length}', + style: const TextStyle( + color: Colors.grey, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + // Text( + // 'Hide', + // style: TextStyle( + // color: Colors.grey.shade400, + // fontSize: 14, + // fontWeight: FontWeight.w500, + // ), + // ), + ], + ), + ], + ), + ), + ), + + if (sortedEntries.isNotEmpty && flattenedItems.any((item) => item.actionItem.completed)) + SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + final completedItems = flattenedItems.where((item) => item.actionItem.completed).toList(); + if (index < completedItems.length) { + final item = completedItems[index]; + // Simple container for proper spacing + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + child: ActionItemTileWidget( + actionItem: item.actionItem, + conversationId: item.conversation.id, + itemIndexInConversation: item.itemIndex, + ), + ); + } + return null; + }, + childCount: flattenedItems.where((item) => item.actionItem.completed).length, + ), + ) + else if (sortedEntries.isNotEmpty) + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Container( + height: 52, + decoration: BoxDecoration( + color: Colors.grey[900], + borderRadius: BorderRadius.circular(16), + ), + child: Center( + child: Text( + 'No completed items yet', + style: TextStyle( + color: Colors.grey.shade400, + fontSize: 14, + ), + ), + ), + ), + ), + ), + + const SliverPadding(padding: EdgeInsets.only(bottom: 100)), + ], + ), + ); + }, + ); + } + + Widget _buildGroupedView(List>> sortedEntries) { + return SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + final entry = sortedEntries[index]; + return ConversationActionItemsGroupWidget( + conversation: entry.key, + actionItems: entry.value, + ); + }, + childCount: sortedEntries.length, + ), + ); + } + + Widget _buildFlatView(List items) { + final incompleteItems = items.where((item) => !item.actionItem.completed).toList(); + + return SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + final item = incompleteItems[index]; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + child: ActionItemTileWidget( + actionItem: item.actionItem, + conversationId: item.conversation.id, + itemIndexInConversation: item.itemIndex, + ), + ); + }, + childCount: incompleteItems.length, + ), + ); + } +} + +class ActionItemData { + final ActionItem actionItem; + final ServerConversation conversation; + final int itemIndex; + + ActionItemData({ + required this.actionItem, + required this.conversation, + required this.itemIndex, + }); +} diff --git a/app/lib/pages/action_items/widgets/action_item_title_widget.dart b/app/lib/pages/action_items/widgets/action_item_title_widget.dart new file mode 100644 index 000000000..f6aa26198 --- /dev/null +++ b/app/lib/pages/action_items/widgets/action_item_title_widget.dart @@ -0,0 +1,312 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:omi/backend/schema/structured.dart'; +import 'package:omi/providers/conversation_provider.dart'; +import 'package:provider/provider.dart'; +import 'package:omi/utils/analytics/mixpanel.dart'; + +import 'edit_action_item_sheet.dart'; +import 'package:omi/widgets/confirmation_dialog.dart'; +import 'package:omi/backend/preferences.dart'; + +class ActionItemTileWidget extends StatefulWidget { + final ActionItem actionItem; + final String conversationId; + final int itemIndexInConversation; + final bool hasRoundedCorners; + final bool isLastInGroup; + final bool isInGroup; + + const ActionItemTileWidget({ + super.key, + required this.actionItem, + required this.conversationId, + required this.itemIndexInConversation, + this.hasRoundedCorners = true, + this.isLastInGroup = false, + this.isInGroup = false, + }); + + @override + State createState() => _ActionItemTileWidgetState(); +} + +class _ActionItemTileWidgetState extends State { + // Assume SharedPreferencesUtil is available and has these methods: + // bool get dontAskAgainDeleteActionItem => _prefs.getBool('dont_ask_again_delete_action_item') ?? false; + // Future setDontAskAgainDeleteActionItem(bool value) async => await _prefs.setBool('dont_ask_again_delete_action_item', value); + + @override + Widget build(BuildContext context) { + final provider = Provider.of(context, listen: false); + final conversation = provider.conversations.firstWhere( + (c) => c.id == widget.conversationId, + orElse: () => provider.searchedConversations.firstWhere((c) => c.id == widget.conversationId), + ); + + BorderRadius borderRadius; + if (widget.hasRoundedCorners) { + borderRadius = BorderRadius.circular(16); + } else if (widget.isLastInGroup) { + borderRadius = const BorderRadius.only( + bottomLeft: Radius.circular(16), + bottomRight: Radius.circular(16), + ); + } else { + borderRadius = BorderRadius.zero; + } + + return Container( + decoration: BoxDecoration( + color: Colors.grey[900], + borderRadius: borderRadius, + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + // ClipRRect to enforce rounded corners throughout the dismissible animation + clipBehavior: Clip.antiAlias, + child: Dismissible( + key: Key("${widget.conversationId}_${widget.itemIndexInConversation}"), + // Allow horizontal swipe in both directions + direction: DismissDirection.horizontal, + + // Background for complete action (swipe right, startToEnd) + background: Container( + alignment: Alignment.centerLeft, + color: Colors.green, + child: const Padding( + padding: EdgeInsets.only(left: 20), + child: Row( + children: [ + Icon( + Icons.check_circle, + color: Colors.white, + size: 30, + ), + ], + ), + ), + ), + + // Background for delete action (swipe left, endToStart) + secondaryBackground: Container( + alignment: Alignment.centerRight, + color: Colors.red, + child: const Padding( + padding: EdgeInsets.only(right: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Icon( + Icons.delete, + color: Colors.white, + size: 30, + ), + ], + ), + ), + ), + + confirmDismiss: (direction) async { + if (direction == DismissDirection.endToStart) { + final prefsUtil = SharedPreferencesUtil(); + bool dontAskAgain = !(prefsUtil.showActionItemDeleteConfirmation); + + if (dontAskAgain) { + context.read().deleteActionItemAndUpdateLocally( + widget.conversationId, + widget.itemIndexInConversation, + widget.actionItem, + ); + return true; + } + + // Delete action (swipe left) - show confirmation dialog + return await showDialog( + context: context, + builder: (context) => ConfirmationDialog( + title: 'Delete Action Item', + description: 'Are you sure you want to delete this action item?', + checkboxText: "Don't ask again", + checkboxValue: dontAskAgain, + onCheckboxChanged: (value) { + prefsUtil.showActionItemDeleteConfirmation = !value; + }, + confirmText: 'Delete', + cancelText: 'Cancel', + onConfirm: () { + context.read().deleteActionItemAndUpdateLocally( + widget.conversationId, + widget.itemIndexInConversation, + widget.actionItem, + ); + Navigator.pop(context, true); + }, + onCancel: () => Navigator.pop(context, false), + ), + ) ?? + false; + } else if (direction == DismissDirection.startToEnd) { + // Complete action (swipe right) - toggle completed state + final newValue = !widget.actionItem.completed; + context.read().updateGlobalActionItemState( + conversation, + widget.itemIndexInConversation, + newValue, + ); + return false; + } + return false; + }, + + onDismissed: (direction) {}, + + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + HapticFeedback.lightImpact(); + MixpanelManager().actionItemTappedForEditOnActionItemsPage( + conversationId: widget.conversationId, + actionItemDescription: widget.actionItem.description, + ); + _showEditActionItemBottomSheet(context, widget.actionItem); + }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Transform.translate( + offset: const Offset(0, 2), + child: GestureDetector( + onTap: () { + HapticFeedback.lightImpact(); + final newValue = !widget.actionItem.completed; + MixpanelManager().actionItemToggledCompletionOnActionItemsPage( + conversationId: widget.conversationId, + actionItemDescription: widget.actionItem.description, + isCompleted: newValue, + ); + context.read().updateGlobalActionItemState( + conversation, + widget.itemIndexInConversation, + newValue, + ); + }, + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + height: 20, + width: 20, + decoration: BoxDecoration( + color: widget.actionItem.completed ? Colors.deepPurpleAccent : Colors.transparent, + border: Border.all( + color: widget.actionItem.completed ? Colors.deepPurpleAccent : Colors.grey[400]!, + width: 1.5, + ), + borderRadius: BorderRadius.circular(5), + ), + child: widget.actionItem.completed + ? const Icon( + Icons.check, + size: 14, + color: Colors.white, + ) + : null, + ), + ), + ), + ), + + // Content + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 14.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + widget.actionItem.description, + style: TextStyle( + color: widget.actionItem.completed ? Colors.grey.shade500 : Colors.white, + decoration: widget.actionItem.completed ? TextDecoration.lineThrough : null, + decorationColor: Colors.grey.shade600, + fontSize: 16, + height: 1.3, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + + // Optional date/time for tasks + if (widget.actionItem.description.toLowerCase().contains('february') || + widget.actionItem.description.toLowerCase().contains('masterclass')) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + decoration: BoxDecoration( + color: Colors.grey.shade800, + borderRadius: BorderRadius.circular(16), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.notifications_outlined, + size: 14, + color: Colors.grey.shade400, + ), + const SizedBox(width: 6), + Text( + 'February 28 - 11:00am', + style: TextStyle( + color: Colors.grey.shade400, + fontSize: 13, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ); + } + + void _showEditActionItemBottomSheet(BuildContext context, ActionItem item) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) { + return EditActionItemBottomSheet( + actionItem: item, + conversationId: widget.conversationId, + itemIndex: widget.itemIndexInConversation, + ); + }, + ); + } +} diff --git a/app/lib/pages/action_items/widgets/convo_action_items_group_widget.dart b/app/lib/pages/action_items/widgets/convo_action_items_group_widget.dart new file mode 100644 index 000000000..00ad6cca2 --- /dev/null +++ b/app/lib/pages/action_items/widgets/convo_action_items_group_widget.dart @@ -0,0 +1,135 @@ +import 'package:flutter/material.dart'; +import 'package:omi/backend/schema/conversation.dart'; +import 'package:omi/backend/schema/structured.dart'; +import 'package:omi/pages/conversation_detail/page.dart'; +import 'package:omi/pages/conversation_detail/conversation_detail_provider.dart'; +import 'package:omi/providers/conversation_provider.dart'; +import 'package:omi/utils/other/temp.dart'; +import 'package:provider/provider.dart'; + +import 'action_item_title_widget.dart'; + +class ConversationActionItemsGroupWidget extends StatelessWidget { + final ServerConversation conversation; + final List actionItems; + + const ConversationActionItemsGroupWidget({ + super.key, + required this.conversation, + required this.actionItems, + }); + + @override + Widget build(BuildContext context) { + final sortedItems = [...actionItems]..sort((a, b) { + if (a.completed == b.completed) return 0; + return a.completed ? 1 : -1; + }); + + return Container( + margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 6.0), + decoration: BoxDecoration( + color: Colors.grey[900], + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 8, + offset: const Offset(0, 3), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InkWell( + onTap: () { + _navigateToConversationDetail(context); + }, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + conversation.structured.title.isNotEmpty + ? conversation.structured.title + : 'Untitled Conversation', + style: const TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 4), + Text( + '${sortedItems.where((item) => !item.completed).length} remaining', + style: TextStyle( + color: Colors.grey[400], + fontSize: 14, + ), + ), + ], + ), + ), + Icon( + Icons.chevron_right, + color: Colors.grey[400], + ), + ], + ), + ), + ), + + // Action Items List + ...sortedItems.asMap().entries.map((entry) { + final index = entry.key; + final item = entry.value; + final isLastItem = index == sortedItems.length - 1; + + return ActionItemTileWidget( + actionItem: item, + conversationId: conversation.id, + itemIndexInConversation: conversation.structured.actionItems.indexOf(item), + hasRoundedCorners: false, + isLastInGroup: isLastItem, + isInGroup: true, + ); + }), + const SizedBox(height: 8), + ], + ), + ); + } + + void _navigateToConversationDetail(BuildContext context) async { + final convoProvider = Provider.of(context, listen: false); + + DateTime? date; + int? index; + + for (final entry in convoProvider.groupedConversations.entries) { + final foundIndex = entry.value.indexWhere((c) => c.id == conversation.id); + if (foundIndex != -1) { + date = entry.key; + index = foundIndex; + break; + } + } + + if (date != null && index != null) { + final detailProvider = Provider.of(context, listen: false); + detailProvider.updateConversation(index, date); + + convoProvider.onConversationTap(index); + + await routeToPage( + context, + ConversationDetailPage(conversation: conversation), + ); + } + } +} diff --git a/app/lib/pages/action_items/widgets/edit_action_item_sheet.dart b/app/lib/pages/action_items/widgets/edit_action_item_sheet.dart new file mode 100644 index 000000000..8331762b4 --- /dev/null +++ b/app/lib/pages/action_items/widgets/edit_action_item_sheet.dart @@ -0,0 +1,252 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:omi/backend/http/api/conversations.dart'; +import 'package:omi/backend/schema/conversation.dart'; +import 'package:omi/backend/schema/structured.dart'; +import 'package:omi/providers/conversation_provider.dart'; +import 'package:provider/provider.dart'; + +class EditActionItemBottomSheet extends StatefulWidget { + final ActionItem actionItem; + final String conversationId; + final int itemIndex; + + const EditActionItemBottomSheet({ + super.key, + required this.actionItem, + required this.conversationId, + required this.itemIndex, + }); + + @override + State createState() => _EditActionItemBottomSheetState(); +} + +class _EditActionItemBottomSheetState extends State { + late TextEditingController _textController; + late bool _isCompleted; + + @override + void initState() { + super.initState(); + _textController = TextEditingController(text: widget.actionItem.description); + _textController.selection = TextSelection.fromPosition( + TextPosition(offset: _textController.text.length), + ); + _isCompleted = widget.actionItem.completed; + } + + @override + void dispose() { + _textController.dispose(); + super.dispose(); + } + + void _saveActionItem() async { + if (_textController.text.trim().isEmpty) { + // Optionally, show a message that description can't be empty + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Action item description cannot be empty.'), + backgroundColor: Colors.red, + ), + ); + return; + } + + String oldDescription = widget.actionItem.description; + String newDescription = _textController.text.trim(); + + updateActionItemDescription(widget.conversationId, oldDescription, newDescription, widget.itemIndex); + + final convoProvider = Provider.of(context, listen: false); + convoProvider.updateActionItemDescriptionInConversation( + widget.conversationId, + widget.itemIndex, // This should be the index of the item in the conversation's list + newDescription, + ); + + if (mounted) { + Navigator.pop(context); + } + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: Container( + decoration: BoxDecoration( + color: Colors.grey.shade900, + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), + ), + padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Completed status toggle + Row( + children: [ + SizedBox( + height: 24, + width: 24, + child: Checkbox( + value: _isCompleted, + activeColor: Colors.deepPurpleAccent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + onChanged: (bool? value) { + HapticFeedback.lightImpact(); + if (value == null) return; + + final convoProvider = Provider.of(context, listen: false); + ServerConversation? conversation = convoProvider.conversations.firstWhere( + (c) => c.id == widget.conversationId, + orElse: () => throw Exception('Conversation not found for ID: ${widget.conversationId}'), + ); + + convoProvider.updateGlobalActionItemState( + conversation, + widget.itemIndex, + value, + ); + + setState(() { + _isCompleted = value; + }); + }, + ), + ), + const SizedBox(width: 8), + Text( + _isCompleted ? 'Completed' : 'Mark complete', + style: TextStyle( + color: Colors.grey.shade300, + fontSize: 14, + ), + ), + ], + ), + // Delete button + IconButton( + icon: const Icon(Icons.delete_outline, color: Colors.red), + onPressed: () { + // Show delete confirmation dialog + showDialog( + context: context, + builder: (context) => AlertDialog( + backgroundColor: Colors.grey.shade900, + title: const Text( + 'Delete Action Item', + style: TextStyle(color: Colors.white), + ), + content: Text( + 'Are you sure you want to delete this action item?', + style: TextStyle(color: Colors.grey.shade300), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context, false), + child: Text( + 'Cancel', + style: TextStyle(color: Colors.grey.shade400), + ), + ), + TextButton( + onPressed: () { + Navigator.pop(context, true); // Close dialog + Navigator.pop(context); // Close bottom sheet + + // Show confirmation + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Action item deleted'), + duration: Duration(seconds: 2), + ), + ); + }, + child: const Text( + 'Delete', + style: TextStyle(color: Colors.red), + ), + ), + ], + ), + ); + }, + ), + ], + ), + const SizedBox(height: 12), + // Text field for editing the action item + TextField( + controller: _textController, + autofocus: true, + maxLines: null, + textInputAction: TextInputAction.done, + style: const TextStyle( + color: Colors.white, + fontSize: 16, + height: 1.4, + ), + decoration: const InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.zero, + isDense: true, + ), + onSubmitted: (value) { + if (value.trim().isNotEmpty) { + _saveActionItem(); + } + }, + ), + const SizedBox(height: 18), + // Bottom row with helper text and character count + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.05), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.keyboard_return, + size: 13, + color: Colors.grey.shade400, + ), + const SizedBox(width: 4), + Text( + 'Press done to save', + style: TextStyle( + color: Colors.grey.shade400, + fontSize: 11, + ), + ), + ], + ), + ), + Text( + '${_textController.text.length}/200', + style: TextStyle( + color: Colors.grey.shade500, + fontSize: 11, + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/app/lib/pages/apps/app_detail/app_detail.dart b/app/lib/pages/apps/app_detail/app_detail.dart index 9775d2cf5..f2d10ff65 100644 --- a/app/lib/pages/apps/app_detail/app_detail.dart +++ b/app/lib/pages/apps/app_detail/app_detail.dart @@ -49,7 +49,6 @@ class _AppDetailPageState extends State { bool isLoading = false; Timer? _paymentCheckTimer; late App app; - late bool showInstallAppConfirmation; checkSetupCompleted() { // TODO: move check to backend @@ -69,7 +68,6 @@ class _AppDetailPageState extends State { @override void initState() { app = widget.app; - showInstallAppConfirmation = SharedPreferencesUtil().showInstallAppConfirmation; WidgetsBinding.instance.addPostFrameCallback((_) async { // Automatically open app home page if conditions are met if (app.enabled && app.externalIntegration?.appHomeUrl?.isNotEmpty == true) { @@ -92,8 +90,10 @@ class _AppDetailPageState extends State { } setIsLoading(false); - context.read().checkIsAppOwner(app.uid); - context.read().setIsAppPublicToggled(!app.private); + if (mounted){ + context.read().checkIsAppOwner(app.uid); + context.read().setIsAppPublicToggled(!app.private); + } }); if (app.worksExternally()) { if (app.externalIntegration!.setupInstructionsFilePath?.isNotEmpty == true) { @@ -458,14 +458,6 @@ class _AppDetailPageState extends State { title: 'Data Access Notice', description: 'This app will access your data. Omi AI is not responsible for how your data is used, modified, or deleted by this app', - checkboxText: "Don't show it again", - checkboxValue: !showInstallAppConfirmation, - onCheckboxChanged: (value) { - setState(() { - showInstallAppConfirmation = !value; - SharedPreferencesUtil().showInstallAppConfirmation = !value; - }); - }, onConfirm: () { _toggleApp(app.id, true); Navigator.pop(context); diff --git a/app/lib/pages/apps/app_home_web_page.dart b/app/lib/pages/apps/app_home_web_page.dart index 77c67a747..c9f196150 100644 --- a/app/lib/pages/apps/app_home_web_page.dart +++ b/app/lib/pages/apps/app_home_web_page.dart @@ -45,9 +45,11 @@ class _AppHomeWebPageState extends State with SingleTickerProvid ..setNavigationDelegate( NavigationDelegate( onPageFinished: (String url) { - setState(() { - _isLoading = false; - }); + if (mounted) { + setState(() { + _isLoading = false; + }); + } }, onWebResourceError: (WebResourceError error) { setState(() { diff --git a/app/lib/pages/apps/providers/add_app_provider.dart b/app/lib/pages/apps/providers/add_app_provider.dart index 87f8809b9..d2c8a687f 100644 --- a/app/lib/pages/apps/providers/add_app_provider.dart +++ b/app/lib/pages/apps/providers/add_app_provider.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -663,6 +664,9 @@ class AddAppProvider extends ChangeNotifier { var file = await imagePicker.pickImage(source: ImageSource.gallery); if (file != null) { imageFile = File(file.path); + if (imageUrl != null) { + await CachedNetworkImage.evictFromCache(imageUrl!, cacheKey: imageUrl); + } imageUrl = null; } notifyListeners(); diff --git a/app/lib/pages/apps/widgets/api_keys_widget.dart b/app/lib/pages/apps/widgets/api_keys_widget.dart index 845c6bab5..310502e98 100644 --- a/app/lib/pages/apps/widgets/api_keys_widget.dart +++ b/app/lib/pages/apps/widgets/api_keys_widget.dart @@ -40,9 +40,11 @@ class _ApiKeysWidgetState extends State { try { await Provider.of(context, listen: false).loadApiKeys(widget.appId); } finally { - setState(() { - _isLoading = false; - }); + if(mounted){ + setState(() { + _isLoading = false; + }); + } } } diff --git a/app/lib/pages/apps/widgets/app_section_card.dart b/app/lib/pages/apps/widgets/app_section_card.dart index c527ed9a7..7242f9ac6 100644 --- a/app/lib/pages/apps/widgets/app_section_card.dart +++ b/app/lib/pages/apps/widgets/app_section_card.dart @@ -7,6 +7,7 @@ import 'package:omi/pages/apps/app_detail/app_detail.dart'; import 'package:omi/providers/app_provider.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/other/temp.dart'; +import 'package:omi/widgets/extensions/string.dart'; import 'package:provider/provider.dart'; class AppSectionCard extends StatelessWidget { @@ -146,7 +147,7 @@ class SectionAppItemCard extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 2.0), child: Text( - app.getCategoryName(), + app.description.decodeString, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(color: Colors.grey, fontSize: 13), diff --git a/app/lib/pages/apps/widgets/create_options_sheet.dart b/app/lib/pages/apps/widgets/create_options_sheet.dart index 00141f6df..a65157b54 100644 --- a/app/lib/pages/apps/widgets/create_options_sheet.dart +++ b/app/lib/pages/apps/widgets/create_options_sheet.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:omi/pages/apps/add_app.dart'; +import 'package:omi/pages/persona/persona_profile.dart'; import 'package:omi/pages/persona/persona_provider.dart'; import 'package:omi/providers/home_provider.dart'; import 'package:provider/provider.dart'; @@ -64,8 +65,16 @@ class CreateOptionsSheet extends StatelessWidget { MixpanelManager().pageOpened('Create Persona'); // Set routing in provider and navigate to Persona Profile page Provider.of(context, listen: false).setRouting(PersonaProfileRouting.create_my_clone); - Provider.of(context, listen: false).setIndex(3); - Provider.of(context, listen: false).onSelectedIndexChanged!(3); + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const PersonaProfilePage(), + settings: const RouteSettings( + arguments: 'from_settings', + ), + ), + ); + // Provider.of(context, listen: false).setIndex(3); + // Provider.of(context, listen: false).onSelectedIndexChanged!(3); }, ), ), diff --git a/app/lib/pages/apps/widgets/filter_sheet.dart b/app/lib/pages/apps/widgets/filter_sheet.dart index d097b9fad..27f3288c7 100644 --- a/app/lib/pages/apps/widgets/filter_sheet.dart +++ b/app/lib/pages/apps/widgets/filter_sheet.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:omi/providers/app_provider.dart'; +import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:provider/provider.dart'; class FilterBottomSheet extends StatelessWidget { @@ -50,6 +51,8 @@ class FilterBottomSheet extends StatelessWidget { label: 'Installed Apps', onTap: () { provider.addOrRemoveFilter('Installed Apps', 'Apps'); + MixpanelManager().appsTypeFilter( + 'Installed Apps', provider.isFilterSelected('Installed Apps', 'Apps')); }, isSelected: provider.isFilterSelected('Installed Apps', 'Apps'), ), @@ -57,6 +60,7 @@ class FilterBottomSheet extends StatelessWidget { label: 'My Apps', onTap: () { provider.addOrRemoveFilter('My Apps', 'Apps'); + MixpanelManager().appsTypeFilter('My Apps', provider.isFilterSelected('My Apps', 'Apps')); }, isSelected: provider.isFilterSelected('My Apps', 'Apps'), ), @@ -71,6 +75,7 @@ class FilterBottomSheet extends StatelessWidget { label: 'A-Z', onTap: () { provider.addOrRemoveFilter('A-Z', 'Sort'); + MixpanelManager().appsSortFilter('A-Z', provider.isFilterSelected('A-Z', 'Sort')); }, isSelected: provider.isFilterSelected('A-Z', 'Sort'), ), @@ -78,6 +83,7 @@ class FilterBottomSheet extends StatelessWidget { label: 'Z-A', onTap: () { provider.addOrRemoveFilter('Z-A', 'Sort'); + MixpanelManager().appsSortFilter('Z-A', provider.isFilterSelected('Z-A', 'Sort')); }, isSelected: provider.isFilterSelected('Z-A', 'Sort'), ), @@ -85,6 +91,8 @@ class FilterBottomSheet extends StatelessWidget { label: 'Highest Rating', onTap: () { provider.addOrRemoveFilter('Highest Rating', 'Sort'); + MixpanelManager().appsSortFilter( + 'Highest Rating', provider.isFilterSelected('Highest Rating', 'Sort')); }, isSelected: provider.isFilterSelected('Highest Rating', 'Sort'), ), @@ -92,6 +100,8 @@ class FilterBottomSheet extends StatelessWidget { label: 'Lowest Rating', onTap: () { provider.addOrRemoveFilter('Lowest Rating', 'Sort'); + MixpanelManager() + .appsSortFilter('Lowest Rating', provider.isFilterSelected('Lowest Rating', 'Sort')); }, isSelected: provider.isFilterSelected('Lowest Rating', 'Sort'), ), @@ -106,6 +116,8 @@ class FilterBottomSheet extends StatelessWidget { label: category.title, onTap: () { provider.addOrRemoveCategoryFilter(category); + MixpanelManager().appsCategoryFilter( + category.title, provider.isCategoryFilterSelected(category)); }, isSelected: provider.isCategoryFilterSelected(category), )) @@ -120,24 +132,32 @@ class FilterBottomSheet extends StatelessWidget { label: '1+ Stars', onTap: () { provider.addOrRemoveFilter('1+ Stars', 'Rating'); + MixpanelManager() + .appsRatingFilter('1+ Stars', provider.isFilterSelected('1+ Stars', 'Rating')); }, isSelected: provider.isFilterSelected('1+ Stars', 'Rating')), FilterOption( label: '2+ Stars', onTap: () { provider.addOrRemoveFilter('2+ Stars', 'Rating'); + MixpanelManager() + .appsRatingFilter('2+ Stars', provider.isFilterSelected('2+ Stars', 'Rating')); }, isSelected: provider.isFilterSelected('2+ Stars', 'Rating')), FilterOption( label: '3+ Stars', onTap: () { provider.addOrRemoveFilter('3+ Stars', 'Rating'); + MixpanelManager() + .appsRatingFilter('3+ Stars', provider.isFilterSelected('3+ Stars', 'Rating')); }, isSelected: provider.isFilterSelected('3+ Stars', 'Rating')), FilterOption( label: '4+ Stars', onTap: () { provider.addOrRemoveFilter('4+ Stars', 'Rating'); + MixpanelManager() + .appsRatingFilter('4+ Stars', provider.isFilterSelected('4+ Stars', 'Rating')); }, isSelected: provider.isFilterSelected('4+ Stars', 'Rating')), ], @@ -151,6 +171,8 @@ class FilterBottomSheet extends StatelessWidget { label: capability.title, onTap: () { provider.addOrRemoveCapabilityFilter(capability); + MixpanelManager().appsCapabilityFilter( + capability.title, provider.isCapabilityFilterSelected(capability)); }, isSelected: provider.isCapabilityFilterSelected(capability), )) @@ -167,6 +189,7 @@ class FilterBottomSheet extends StatelessWidget { child: ElevatedButton( onPressed: () { provider.clearFilters(); + MixpanelManager().appsClearFilters(); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[300], diff --git a/app/lib/pages/chat/clone_chat_page.dart b/app/lib/pages/chat/clone_chat_page.dart index cbe624e28..f1752e556 100644 --- a/app/lib/pages/chat/clone_chat_page.dart +++ b/app/lib/pages/chat/clone_chat_page.dart @@ -32,6 +32,10 @@ class CloneChatPageState extends State { if (provider.userPersona != null) { App selectedApp = provider.userPersona!; + if (!mounted){ + return; + } + var appProvider = Provider.of(context, listen: false); SharedPreferencesUtil().appsList = [selectedApp]; appProvider.setApps(); diff --git a/app/lib/pages/chat/page.dart b/app/lib/pages/chat/page.dart index 3b8a1b724..2e3acbd54 100644 --- a/app/lib/pages/chat/page.dart +++ b/app/lib/pages/chat/page.dart @@ -84,6 +84,10 @@ class ChatPageState extends State with AutomaticKeepAliveClientMixin { } }); SchedulerBinding.instance.addPostFrameCallback((_) async { + var provider = context.read(); + if (provider.messages.isEmpty) { + provider.refreshMessages(); + } scrollToBottom(); }); super.initState(); @@ -499,6 +503,7 @@ class ChatPageState extends State with AutomaticKeepAliveClientMixin { setState(() { textController.text = transcript; _showVoiceRecorder = false; + context.read().setNextMessageOriginIsVoice(true); }); }, onClose: () { @@ -518,12 +523,12 @@ class ChatPageState extends State with AutomaticKeepAliveClientMixin { focusNode: home.chatFieldFocusNode, textAlign: TextAlign.start, textAlignVertical: TextAlignVertical.top, - decoration: InputDecoration( + decoration: const InputDecoration( hintText: 'Message', - hintStyle: const TextStyle(fontSize: 14.0, color: Colors.grey), + hintStyle: TextStyle(fontSize: 14.0, color: Colors.grey), focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, - contentPadding: const EdgeInsets.only(top: 8, bottom: 10), + contentPadding: EdgeInsets.only(top: 8, bottom: 10), ), maxLines: null, keyboardType: TextInputType.multiline, @@ -600,7 +605,6 @@ class ChatPageState extends State with AutomaticKeepAliveClientMixin { _sendMessageUtil(String text) { var provider = context.read(); - MixpanelManager().chatMessageSent(text); provider.setSendingMessage(true); provider.addMessageLocally(text); scrollToBottom(); diff --git a/app/lib/pages/conversation_detail/page.dart b/app/lib/pages/conversation_detail/page.dart index 4167d06c7..c6a2e0578 100644 --- a/app/lib/pages/conversation_detail/page.dart +++ b/app/lib/pages/conversation_detail/page.dart @@ -10,7 +10,6 @@ import 'package:omi/pages/conversation_detail/widgets.dart'; import 'package:omi/pages/settings/people.dart'; import 'package:omi/providers/connectivity_provider.dart'; import 'package:omi/providers/conversation_provider.dart'; -import 'package:omi/utils/alerts/app_snackbar.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/other/temp.dart'; import 'package:omi/widgets/conversation_bottom_bar.dart'; @@ -49,10 +48,23 @@ class _ConversationDetailPageState extends State with Ti void initState() { super.initState(); - _controller = TabController(length: 2, vsync: this, initialIndex: 1); // Start with summary tab + _controller = TabController(length: 3, vsync: this, initialIndex: 1); // Start with summary tab _controller!.addListener(() { setState(() { - selectedTab = _controller!.index == 0 ? ConversationTab.transcript : ConversationTab.summary; + switch (_controller!.index) { + case 0: + selectedTab = ConversationTab.transcript; + break; + case 1: + selectedTab = ConversationTab.summary; + break; + case 2: + selectedTab = ConversationTab.actionItems; + break; + default: + debugPrint('Invalid tab index: ${_controller!.index}'); + selectedTab = ConversationTab.summary; + } }); }); @@ -188,6 +200,7 @@ class _ConversationDetailPageState extends State with Ti }, ), const SummaryTab(), + const ActionItemsTab(), ], ); }), @@ -210,7 +223,21 @@ class _ConversationDetailPageState extends State with Ti hasSegments: conversation.transcriptSegments.isNotEmpty || conversation.externalIntegration != null, onTabSelected: (tab) { - int index = tab == ConversationTab.transcript ? 0 : 1; + int index; + switch (tab) { + case ConversationTab.transcript: + index = 0; + break; + case ConversationTab.summary: + index = 1; + break; + case ConversationTab.actionItems: + index = 2; + break; + default: + debugPrint('Invalid tab selected: $tab'); + index = 1; // Default to summary tab + } _controller!.animateTo(index); }, onStopPressed: () { @@ -556,3 +583,62 @@ class EditSegmentWidget extends StatelessWidget { }); } } + +class ActionItemsTab extends StatelessWidget { + const ActionItemsTab({super.key}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Consumer( + builder: (context, provider, child) { + final hasActionItems = provider.conversation.structured.actionItems.where((item) => !item.deleted).isNotEmpty; + + return ListView( + shrinkWrap: true, + children: [ + const SizedBox(height: 24), + if (hasActionItems) const ActionItemsListWidget() else _buildEmptyState(context), + const SizedBox(height: 150) + ], + ); + }, + ), + ); + } + + Widget _buildEmptyState(BuildContext context) { + return Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 40.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.check_circle_outline, + size: 72, + color: Colors.grey, + ), + const SizedBox(height: 24), + Text( + 'No Action Items', + style: Theme.of(context).textTheme.headlineSmall?.copyWith( + color: Colors.white, + ), + ), + const SizedBox(height: 12), + Text( + 'This memory doesn\'t have any action items yet. They\'ll appear here when your conversations include tasks or to-dos.', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.grey.shade400, + fontSize: 16, + ), + ), + ], + ), + ), + ); + } +} diff --git a/app/lib/pages/conversation_detail/widgets.dart b/app/lib/pages/conversation_detail/widgets.dart index a7df53d0e..f75dd9a5e 100644 --- a/app/lib/pages/conversation_detail/widgets.dart +++ b/app/lib/pages/conversation_detail/widgets.dart @@ -21,6 +21,7 @@ import 'package:omi/providers/connectivity_provider.dart'; import 'package:omi/providers/conversation_provider.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/other/temp.dart'; +import 'package:omi/utils/other/time_utils.dart'; import 'package:omi/widgets/dialog.dart'; import 'package:omi/widgets/extensions/string.dart'; import 'package:provider/provider.dart'; @@ -42,6 +43,15 @@ class GetSummaryWidgets extends StatelessWidget { return startedAt == null ? dateTimeFormat('h:mm a', createdAt) : dateTimeFormat('h:mm a', startedAt); } + String _getDuration(ServerConversation conversation) { + if (conversation.transcriptSegments.isEmpty) return ''; + + int durationSeconds = conversation.getDurationInSeconds(); + if (durationSeconds <= 0) return ''; + + return secondsToHumanReadable(durationSeconds); + } + @override Widget build(BuildContext context) { return Selector>( @@ -72,6 +82,20 @@ class GetSummaryWidgets extends StatelessWidget { : '${dateTimeFormat('MMM d, yyyy', conversation.createdAt)} ${conversation.startedAt == null ? 'at' : 'from'} ${setTime(conversation.startedAt, conversation.createdAt, conversation.finishedAt)}', style: const TextStyle(color: Colors.grey, fontSize: 16), ), + if (conversation.transcriptSegments.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 4.0), + child: Row( + children: [ + const Icon(Icons.access_time, color: Colors.grey, size: 14), + const SizedBox(width: 4), + Text( + 'Duration: ${_getDuration(conversation)}', + style: const TextStyle(color: Colors.grey, fontSize: 14), + ), + ], + ), + ), const SizedBox(height: 16), conversation.discarded ? const SizedBox.shrink() : const SizedBox(height: 8), ], @@ -134,27 +158,29 @@ class ActionItemsListWidget extends StatelessWidget { var tempItem = provider.conversation.structured.actionItems[idx]; var tempIdx = idx; provider.deleteActionItem(idx); - ScaffoldMessenger.of(context) - .showSnackBar( - SnackBar( - content: const Text('Action Item deleted successfully ๐Ÿ—‘๏ธ'), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - action: SnackBarAction( - label: 'Undo', - textColor: Colors.white, - onPressed: () { - provider.undoDeleteActionItem(idx); - }, - ), - ), - ) - .closed - .then((reason) { - if (reason != SnackBarClosedReason.action) { - provider.deleteActionItemPermanently(tempItem, tempIdx); - MixpanelManager().deletedActionItem(provider.conversation); - } - }); + provider.deleteActionItemPermanently(tempItem, tempIdx); + MixpanelManager().deletedActionItem(provider.conversation); + // ScaffoldMessenger.of(context) + // .showSnackBar( + // SnackBar( + // content: const Text('Action Item deleted successfully ๐Ÿ—‘๏ธ'), + // padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), + // action: SnackBarAction( + // label: 'Undo', + // textColor: Colors.white, + // onPressed: () { + // provider.undoDeleteActionItem(idx); + // }, + // ), + // ), + // ) + // .closed + // .then((reason) { + // if (reason != SnackBarClosedReason.action) { + // provider.deleteActionItemPermanently(tempItem, tempIdx); + // MixpanelManager().deletedActionItem(provider.conversation); + // } + // }); }, child: Padding( padding: const EdgeInsets.only(top: 10, bottom: 2), @@ -878,7 +904,7 @@ class _GetShareOptionsState extends State { changeLoadingShareTranscript(true); String content = ''' ${widget.conversation.structured.title} - + ${widget.conversation.getTranscript(generate: true)} ''' .replaceAll(' ', '') diff --git a/app/lib/pages/conversation_detail/widgets/summarized_apps_sheet.dart b/app/lib/pages/conversation_detail/widgets/summarized_apps_sheet.dart index c51903acb..61b73623d 100644 --- a/app/lib/pages/conversation_detail/widgets/summarized_apps_sheet.dart +++ b/app/lib/pages/conversation_detail/widgets/summarized_apps_sheet.dart @@ -24,6 +24,12 @@ class SummarizedAppsBottomSheet extends StatelessWidget { builder: (context, provider, _) { final summarizedApp = provider.getSummarizedApp(); final currentAppId = summarizedApp?.appId; + final conversationId = provider.conversation.id; + + MixpanelManager().summarizedAppSheetViewed( + conversationId: conversationId, + currentSummarizedAppId: currentAppId, + ); return _SheetContainer( scrollController: scrollController, @@ -146,6 +152,15 @@ class _AppsList extends StatelessWidget { void _handleAutoAppTap(BuildContext context) async { Navigator.pop(context); final provider = context.read(); + final previousAppId = provider.getSummarizedApp()?.appId; + final conversationId = provider.conversation.id; + + MixpanelManager().summarizedAppSelected( + conversationId: conversationId, + selectedAppId: 'auto', + previousAppId: previousAppId, + ); + provider.clearSelectedAppForReprocessing(); await provider.reprocessConversation(); return; @@ -153,9 +168,18 @@ class _AppsList extends StatelessWidget { void _handleAppTap(BuildContext context, App app) async { // If this is a different app than currently selected, reprocess with this app + final provider = context.read(); + final previousAppId = provider.getSummarizedApp()?.appId; + final conversationId = provider.conversation.id; + if (app.id != currentAppId) { + MixpanelManager().summarizedAppSelected( + conversationId: conversationId, + selectedAppId: app.id, + previousAppId: previousAppId, + ); + Navigator.pop(context); - final provider = context.read(); provider.setSelectedAppForReprocessing(app); provider.setPreferredSummarizationApp(app.id); await provider.reprocessConversation(appId: app.id); @@ -277,6 +301,10 @@ class _EnableAppsListItem extends StatelessWidget { trailing: const Icon(Icons.arrow_forward_ios, color: Colors.white, size: 16), onTap: () { Navigator.pop(context); + final conversationId = context.read().conversation?.id; + if (conversationId != null) { + MixpanelManager().summarizedAppEnableAppsClicked(conversationId: conversationId); + } routeToPage(context, const AppsPage(showAppBar: true)); MixpanelManager().pageOpened('Detail Apps'); }, diff --git a/app/lib/pages/conversations/conversations_page.dart b/app/lib/pages/conversations/conversations_page.dart index 05a7603b4..7ec0535b4 100644 --- a/app/lib/pages/conversations/conversations_page.dart +++ b/app/lib/pages/conversations/conversations_page.dart @@ -4,6 +4,7 @@ import 'package:omi/pages/capture/widgets/widgets.dart'; import 'package:omi/pages/conversations/widgets/processing_capture.dart'; import 'package:omi/pages/conversations/widgets/search_result_header_widget.dart'; import 'package:omi/pages/conversations/widgets/search_widget.dart'; +import 'package:omi/providers/capture_provider.dart'; import 'package:omi/providers/conversation_provider.dart'; import 'package:provider/provider.dart'; import 'package:visibility_detector/visibility_detector.dart'; @@ -43,7 +44,9 @@ class _ConversationsPageState extends State with AutomaticKee backgroundColor: Colors.black, color: Colors.white, onRefresh: () async { - return await convoProvider.getInitialConversations(); + Provider.of(context, listen: false).refreshInProgressConversations(); + await convoProvider.getInitialConversations(); + return; }, child: CustomScrollView( slivers: [ diff --git a/app/lib/pages/conversations/widgets/conversation_list_item.dart b/app/lib/pages/conversations/widgets/conversation_list_item.dart index 5510e6046..31f7bb4f1 100644 --- a/app/lib/pages/conversations/widgets/conversation_list_item.dart +++ b/app/lib/pages/conversations/widgets/conversation_list_item.dart @@ -10,6 +10,7 @@ import 'package:omi/providers/connectivity_provider.dart'; import 'package:omi/providers/conversation_provider.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/other/temp.dart'; +import 'package:omi/utils/other/time_utils.dart'; import 'package:omi/widgets/confirmation_dialog.dart'; import 'package:omi/widgets/dialog.dart'; import 'package:omi/widgets/extensions/string.dart'; @@ -83,8 +84,7 @@ class _ConversationListItemState extends State { } }, child: Padding( - padding: - EdgeInsets.only(top: 12, left: widget.isFromOnboarding ? 0 : 16, right: widget.isFromOnboarding ? 0 : 16), + padding: EdgeInsets.only(top: 12, left: widget.isFromOnboarding ? 0 : 16, right: widget.isFromOnboarding ? 0 : 16), child: Container( width: double.maxFinite, decoration: BoxDecoration( @@ -114,8 +114,7 @@ class _ConversationListItemState extends State { builder: (context, setState) { return ConfirmationDialog( title: "Delete Conversation?", - description: - "Are you sure you want to delete this conversation? This action cannot be undone.", + description: "Are you sure you want to delete this conversation? This action cannot be undone.", checkboxValue: !showDeleteConfirmation, checkboxText: "Don't ask me again", onCheckboxChanged: (value) { @@ -134,9 +133,7 @@ class _ConversationListItemState extends State { }); } else { return showDialog( - builder: (c) => getDialog(context, () => Navigator.pop(context), () => Navigator.pop(context), - 'Unable to Delete Conversation', 'Please check your internet connection and try again.', - singleButton: true, okButtonText: 'OK'), + builder: (c) => getDialog(context, () => Navigator.pop(context), () => Navigator.pop(context), 'Unable to Delete Conversation', 'Please check your internet connection and try again.', singleButton: true, okButtonText: 'OK'), context: context, ); } @@ -166,19 +163,13 @@ class _ConversationListItemState extends State { ? const SizedBox.shrink() : Text( structured.overview.decodeString, - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith(color: Colors.grey.shade300, height: 1.3), + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.grey.shade300, height: 1.3), maxLines: 2, ), widget.conversation.discarded ? Text( widget.conversation.getTranscript(maxCount: 100), - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith(color: Colors.grey.shade300, height: 1.3), + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.grey.shade300, height: 1.3), ) : const SizedBox(height: 8), ], @@ -196,50 +187,91 @@ class _ConversationListItemState extends State { return Padding( padding: const EdgeInsets.only(left: 4.0, right: 12), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - widget.conversation.discarded - ? const SizedBox.shrink() - : Text(widget.conversation.structured.getEmoji(), - style: const TextStyle(color: Colors.white, fontSize: 22, fontWeight: FontWeight.w500)), - widget.conversation.structured.category.isNotEmpty && !widget.conversation.discarded - ? const SizedBox(width: 12) - : const SizedBox.shrink(), - widget.conversation.structured.category.isNotEmpty - ? Container( - decoration: BoxDecoration( - color: widget.conversation.getTagColor(), - borderRadius: BorderRadius.circular(16), + // ๐Ÿง  Emoji + Tag + Flexible( + fit: FlexFit.tight, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (!widget.conversation.discarded) + Text( + widget.conversation.structured.getEmoji(), + style: const TextStyle(color: Colors.white, fontSize: 22, fontWeight: FontWeight.w500), ), - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), - child: Text( - widget.conversation.getTag(), - style: - Theme.of(context).textTheme.bodyMedium!.copyWith(color: widget.conversation.getTagTextColor()), - maxLines: 1, + if (widget.conversation.structured.category.isNotEmpty && !widget.conversation.discarded) const SizedBox(width: 8), + if (widget.conversation.structured.category.isNotEmpty) + Flexible( + child: Container( + decoration: BoxDecoration( + color: widget.conversation.getTagColor(), + borderRadius: BorderRadius.circular(16), + ), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + child: Text( + widget.conversation.getTag(), + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: widget.conversation.getTagTextColor()), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ), ), - ) - : const SizedBox.shrink(), - const SizedBox( - width: 16, + ], + ), ), - Expanded( + + const SizedBox(width: 12), + + // ๐Ÿ•’ Timestamp + Duration or New + FittedBox( + fit: BoxFit.scaleDown, child: isNew - ? const Align( - alignment: Alignment.centerRight, - child: ConversationNewStatusIndicator(text: "New ๐Ÿš€"), - ) - : Text( - dateTimeFormat('MMM d, h:mm a', widget.conversation.startedAt ?? widget.conversation.createdAt), - style: TextStyle(color: Colors.grey.shade400, fontSize: 14), - maxLines: 1, - textAlign: TextAlign.end, + ? const ConversationNewStatusIndicator(text: "New ๐Ÿš€") + : Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + dateTimeFormat( + 'MMM d, h:mm a', + widget.conversation.startedAt ?? widget.conversation.createdAt, + ), + style: TextStyle(color: Colors.grey.shade400, fontSize: 14), + maxLines: 1, + ), + if (widget.conversation.transcriptSegments.isNotEmpty && _getConversationDuration().isNotEmpty) + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey.shade800, + borderRadius: BorderRadius.circular(4), + ), + child: Text( + _getConversationDuration(), + style: TextStyle(color: Colors.grey.shade300, fontSize: 11), + maxLines: 1, + ), + ), + ), + ], ), - ) + ), ], ), ); } + + String _getConversationDuration() { + if (widget.conversation.transcriptSegments.isEmpty) return ''; + + // Get the total duration in seconds + int durationSeconds = widget.conversation.getDurationInSeconds(); + if (durationSeconds <= 0) return ''; + + return secondsToCompactDuration(durationSeconds); + } } class ConversationNewStatusIndicator extends StatefulWidget { @@ -251,8 +283,7 @@ class ConversationNewStatusIndicator extends StatefulWidget { State createState() => _ConversationNewStatusIndicatorState(); } -class _ConversationNewStatusIndicatorState extends State - with SingleTickerProviderStateMixin { +class _ConversationNewStatusIndicatorState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _opacityAnim; diff --git a/app/lib/pages/conversations/widgets/processing_capture.dart b/app/lib/pages/conversations/widgets/processing_capture.dart index 3e7b77c00..94c88e3be 100644 --- a/app/lib/pages/conversations/widgets/processing_capture.dart +++ b/app/lib/pages/conversations/widgets/processing_capture.dart @@ -1,3 +1,5 @@ +import 'dart:io'; // Added for Platform check + import 'package:flutter/material.dart'; import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/conversation.dart'; @@ -73,28 +75,41 @@ class _ConversationCaptureWidgetState extends State { _toggleRecording(BuildContext context, CaptureProvider provider) async { var recordingState = provider.recordingState; - if (recordingState == RecordingState.record) { - await provider.stopStreamRecording(); - MixpanelManager().phoneMicRecordingStopped(); - } else if (recordingState == RecordingState.initialising) { - debugPrint('initialising, have to wait'); + + if (Platform.isMacOS) { + if (recordingState == RecordingState.systemAudioRecord) { + await provider.stopSystemAudioRecording(); + // MixpanelManager().track("System Audio Recording Stopped"); + } else if (recordingState == RecordingState.initialising) { + debugPrint('initialising, have to wait'); + } else { + await provider.streamSystemAudioRecording(); + // MixpanelManager().track("System Audio Recording Started"); + } } else { - showDialog( - context: context, - builder: (c) => getDialog( - context, - () => Navigator.pop(context), - () async { - Navigator.pop(context); - provider.updateRecordingState(RecordingState.initialising); - await provider.streamRecording(); - MixpanelManager().phoneMicRecordingStarted(); - }, - 'Limited Capabilities', - 'Recording with your phone microphone has a few limitations, including but not limited to: speaker profiles, background reliability.', - okButtonText: 'Ok, I understand', - ), - ); + // Existing phone mic logic + if (recordingState == RecordingState.record) { + await provider.stopStreamRecording(); + MixpanelManager().phoneMicRecordingStopped(); + } else if (recordingState == RecordingState.initialising) { + debugPrint('initialising, have to wait'); + } else { + showDialog( + context: context, + builder: (c) => getDialog( + context, + () => Navigator.pop(context), + () async { + Navigator.pop(context); + await provider.streamRecording(); + MixpanelManager().phoneMicRecordingStarted(); + }, + 'Limited Capabilities', + 'Recording with your phone microphone has a few limitations, including but not limited to: speaker profiles, background reliability.', + okButtonText: 'Ok, I understand', + ), + ); + } } } @@ -256,32 +271,77 @@ class _RecordingStatusIndicatorState extends State wit } } -getPhoneMicRecordingButton(BuildContext context, toggleRecording, RecordingState state) { - if (SharedPreferencesUtil().btDevice.id.isNotEmpty) return const SizedBox.shrink(); +getPhoneMicRecordingButton(BuildContext context, VoidCallback toggleRecordingCb, RecordingState currentActualState) { + if (SharedPreferencesUtil().btDevice.id.isNotEmpty && !Platform.isMacOS) { + // If a BT device is configured and we are NOT on macOS, don't show this button. + // On macOS, this button might be repurposed for system audio. + return const SizedBox.shrink(); + } + // If on macOS, AND a BT device is connected, this button should still be hidden + // as the primary interaction should be via the BT device, not system audio as a fallback to phone mic. + // This button is primarily for when NO BT device is the target. + final deviceProvider = Provider.of(context, listen: false); + if (Platform.isMacOS && + deviceProvider.connectedDevice != null && + SharedPreferencesUtil().btDevice.id == deviceProvider.connectedDevice!.id) { + return const SizedBox.shrink(); + } + + final bool isMac = Platform.isMacOS; + String text; + Widget icon; + bool isLoading = currentActualState == RecordingState.initialising; + + if (isMac) { + if (isLoading) { + text = 'Initialising System Audio'; + icon = const SizedBox( + height: 8, + width: 8, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ); + } else if (currentActualState == RecordingState.systemAudioRecord) { + text = 'Stop Recording'; + icon = const Icon(Icons.stop, color: Colors.red, size: 12); + } else { + text = 'Start Recording'; + icon = const Icon(Icons.mic, size: 18); + } + } else { + // Phone Mic + if (isLoading) { + text = 'Initialising Recorder'; + icon = const SizedBox( + height: 8, + width: 8, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ); + } else if (currentActualState == RecordingState.record) { + text = 'Stop Recording'; + icon = const Icon(Icons.stop, color: Colors.red, size: 12); + } else { + text = 'Try With Phone Mic'; + icon = const Icon(Icons.mic, size: 18); + } + } + return MaterialButton( - onPressed: state == RecordingState.initialising ? null : toggleRecording, + onPressed: isLoading ? null : toggleRecordingCb, child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ - state == RecordingState.initialising - ? const SizedBox( - height: 8, - width: 8, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Colors.white, - ), - ) - : (state == RecordingState.record - ? const Icon(Icons.stop, color: Colors.red, size: 12) - : const Icon(Icons.mic, size: 18)), + icon, const SizedBox(width: 4), Text( - state == RecordingState.initialising - ? 'Initialising Recorder' - : (state == RecordingState.record ? 'Stop Recording' : 'Try With Phone Mic'), + text, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.white, fontWeight: FontWeight.w500), ), const SizedBox(width: 4), diff --git a/app/lib/pages/conversations/widgets/synced_conversation_list_item.dart b/app/lib/pages/conversations/widgets/synced_conversation_list_item.dart index 597133da0..a5419c7a0 100644 --- a/app/lib/pages/conversations/widgets/synced_conversation_list_item.dart +++ b/app/lib/pages/conversations/widgets/synced_conversation_list_item.dart @@ -5,6 +5,7 @@ import 'package:omi/pages/conversation_detail/conversation_detail_provider.dart' import 'package:omi/pages/conversation_detail/page.dart'; import 'package:omi/providers/conversation_provider.dart'; import 'package:omi/utils/other/temp.dart'; +import 'package:omi/utils/other/time_utils.dart'; import 'package:omi/widgets/extensions/string.dart'; import 'package:provider/provider.dart'; @@ -174,15 +175,47 @@ class _SyncedConversationListItemState extends State width: 16, ), Expanded( - child: Text( - dateTimeFormat('MMM d, h:mm a', conversation.startedAt ?? conversation.createdAt), - style: TextStyle(color: Colors.grey.shade400, fontSize: 14), - maxLines: 1, - textAlign: TextAlign.end, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + dateTimeFormat('MMM d, h:mm a', conversation.startedAt ?? conversation.createdAt), + style: TextStyle(color: Colors.grey.shade400, fontSize: 14), + maxLines: 1, + textAlign: TextAlign.end, + ), + if (conversation.transcriptSegments.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 2.0), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey.shade800, + borderRadius: BorderRadius.circular(4), + ), + child: Text( + _getConversationDuration(), + style: TextStyle(color: Colors.grey.shade300, fontSize: 11), + maxLines: 1, + textAlign: TextAlign.end, + ), + ), + ), + ], ), ) ], ), ); } + + String _getConversationDuration() { + if (conversation.transcriptSegments.isEmpty) return ''; + + // Get the total duration in seconds + int durationSeconds = conversation.getDurationInSeconds(); + if (durationSeconds <= 0) return ''; + + return secondsToCompactDuration(durationSeconds); + } } diff --git a/app/lib/pages/home/firmware_update.dart b/app/lib/pages/home/firmware_update.dart index 19807c5ac..2e311ab54 100644 --- a/app/lib/pages/home/firmware_update.dart +++ b/app/lib/pages/home/firmware_update.dart @@ -242,8 +242,8 @@ class _FirmwareUpdateState extends State with FirmwareMixin { } Widget _buildUpdateSection() { - bool hasChangelog = latestFirmwareDetails['changelog'] != null && - (List.from(latestFirmwareDetails['changelog'])).isNotEmpty; + dynamic changelogData = latestFirmwareDetails['changelog']; + bool hasChangelog = changelogData != null && changelogData is List && (List.from(changelogData)).isNotEmpty; return Card( color: Colors.black.withOpacity(0.2), @@ -340,7 +340,7 @@ class _FirmwareUpdateState extends State with FirmwareMixin { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ...(List.from(latestFirmwareDetails['changelog'])).map((change) => Padding( + ...(List.from(changelogData)).map((change) => Padding( padding: const EdgeInsets.only(bottom: 6.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/app/lib/pages/home/page.dart b/app/lib/pages/home/page.dart index 4ae6ab58d..71c807649 100644 --- a/app/lib/pages/home/page.dart +++ b/app/lib/pages/home/page.dart @@ -2,41 +2,41 @@ import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_foreground_task/flutter_foreground_task.dart'; -import 'package:omi/gen/assets.gen.dart'; -import 'package:omi/pages/persona/persona_provider.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:gradient_borders/gradient_borders.dart'; import 'package:omi/backend/http/api/users.dart'; import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/app.dart'; import 'package:omi/backend/schema/geolocation.dart'; +import 'package:omi/gen/assets.gen.dart'; import 'package:omi/main.dart'; +import 'package:omi/pages/action_items/action_items_page.dart'; import 'package:omi/pages/apps/page.dart'; import 'package:omi/pages/chat/page.dart'; import 'package:omi/pages/conversations/conversations_page.dart'; -import 'package:omi/pages/memories/page.dart'; import 'package:omi/pages/home/widgets/chat_apps_dropdown_widget.dart'; -import 'package:omi/pages/persona/persona_profile.dart'; -import 'package:omi/pages/home/widgets/speech_language_sheet.dart'; +import 'package:omi/pages/memories/page.dart'; import 'package:omi/pages/settings/page.dart'; import 'package:omi/providers/app_provider.dart'; import 'package:omi/providers/capture_provider.dart'; import 'package:omi/providers/connectivity_provider.dart'; +import 'package:omi/providers/conversation_provider.dart'; import 'package:omi/providers/device_provider.dart'; import 'package:omi/providers/home_provider.dart'; -import 'package:omi/providers/conversation_provider.dart'; import 'package:omi/providers/message_provider.dart'; import 'package:omi/services/notifications.dart'; import 'package:omi/utils/analytics/analytics_manager.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/audio/foreground.dart'; import 'package:omi/utils/other/temp.dart'; +import 'package:omi/utils/platform/platform_service.dart'; import 'package:omi/widgets/upgrade_alert.dart'; -import 'package:gradient_borders/gradient_borders.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:upgrader/upgrader.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; import '../conversations/sync_page.dart'; import 'widgets/battery_info_widget.dart'; @@ -72,9 +72,6 @@ class _HomePageWrapperState extends State { if (mounted) { await context.read().getInitialConversations(); } - if (mounted) { - context.read().setSelectedChatAppId(null); - } }); _navigateToRoute = widget.navigateToRoute; super.initState(); @@ -119,8 +116,8 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker // Reload convos if (mounted) { - debugPrint('Reload convos'); - Provider.of(context, listen: false).fetchNewConversations(); + Provider.of(context, listen: false).refreshConversations(); + Provider.of(context, listen: false).refreshInProgressConversations(); } } else if (state == AppLifecycleState.hidden) { event = 'App is hidden'; @@ -130,7 +127,7 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker return; } debugPrint(event); - InstabugLog.logInfo(event); + PlatformManager.instance.instabug.logInfo(event); } ///Screens with respect to subpage @@ -182,13 +179,16 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker break; case "chat": homePageIdx = 1; - case "apps": + case "memoriesPage": homePageIdx = 2; break; + case "apps": + homePageIdx = 3; + break; } } - // Home controler + // Home controller _controller = PageController(initialPage: homePageIdx); context.read().selectedIndex = homePageIdx; context.read().onSelectedIndexChanged = (index) { @@ -200,8 +200,10 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker _initiateApps(); // ForegroundUtil.requestPermissions(); - await ForegroundUtil.initializeForegroundService(); - ForegroundUtil.startForegroundTask(); + if (!Platform.isMacOS) { + await ForegroundUtil.initializeForegroundService(); + ForegroundUtil.startForegroundTask(); + } if (mounted) { await Provider.of(context, listen: false).setUserPeople(); } @@ -213,6 +215,7 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker // Navigate switch (pageAlias) { case "chat": + print('inside chat alias $detailPageId'); if (detailPageId != null && detailPageId.isNotEmpty) { var appId = detailPageId != "omi" ? detailPageId : ''; // omi ~ no select if (mounted) { @@ -355,9 +358,9 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker builder: (context, homeProvider, _) { return Scaffold( backgroundColor: Theme.of(context).colorScheme.primary, - appBar: homeProvider.selectedIndex == 3 ? null : _buildAppBar(context), + appBar: homeProvider.selectedIndex == 5 ? null : _buildAppBar(context), body: DefaultTabController( - length: 3, + length: 5, initialIndex: _controller?.initialPage ?? 0, child: GestureDetector( onTap: () { @@ -374,25 +377,28 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker children: const [ ConversationsPage(), ChatPage(isPivotBottom: false), + MemoriesPage(), + ActionItemsPage(), AppsPage(), - PersonaProfilePage(bottomMargin: 120), ], ), ), Consumer( builder: (context, home, child) { - if (home.chatFieldFocusNode.hasFocus || - home.convoSearchFieldFocusNode.hasFocus || - home.appsSearchFieldFocusNode.hasFocus) { + if (home.isChatFieldFocused || + home.isConvoSearchFieldFocused || + home.isAppsSearchFieldFocused || + home.isMemoriesSearchFieldFocused) { return const SizedBox.shrink(); } else { return Align( alignment: Alignment.bottomCenter, child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10), margin: const EdgeInsets.fromLTRB(20, 16, 20, 42), decoration: const BoxDecoration( color: Colors.black, - borderRadius: BorderRadius.all(Radius.circular(16)), + borderRadius: BorderRadius.all(Radius.circular(18)), border: GradientBoxBorder( gradient: LinearGradient(colors: [ Color.fromARGB(127, 208, 208, 208), @@ -405,11 +411,11 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker shape: BoxShape.rectangle, ), child: TabBar( - labelPadding: const EdgeInsets.only(top: 4, bottom: 4), + labelPadding: const EdgeInsets.symmetric(vertical: 10), indicatorPadding: EdgeInsets.zero, onTap: (index) { - MixpanelManager() - .bottomNavigationTabClicked(['Memories', 'Chat', 'Explore'][index]); + MixpanelManager().bottomNavigationTabClicked( + ['Memories', 'Chat', 'Facts', 'Action Items', 'Explore'][index]); primaryFocus?.unfocus(); if (home.selectedIndex == index) { return; @@ -421,30 +427,103 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker indicatorColor: Colors.transparent, tabs: [ Tab( - child: Text( - 'Home', - style: TextStyle( - color: home.selectedIndex == 0 ? Colors.white : Colors.grey, - fontSize: MediaQuery.sizeOf(context).width < 410 ? 13 : 15, - ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.house, + color: home.selectedIndex == 0 ? Colors.white : Colors.grey, + size: 18, + ), + const SizedBox(height: 6), + Text( + 'Home', + style: TextStyle( + color: home.selectedIndex == 0 ? Colors.white : Colors.grey, + fontSize: 12, + ), + ), + ], ), ), Tab( - child: Text( - 'Chat', - style: TextStyle( - color: home.selectedIndex == 1 ? Colors.white : Colors.grey, - fontSize: MediaQuery.sizeOf(context).width < 410 ? 13 : 15, - ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.solidMessage, + color: home.selectedIndex == 1 ? Colors.white : Colors.grey, + size: 18, + ), + const SizedBox(height: 6), + Text( + 'Chat', + style: TextStyle( + color: home.selectedIndex == 1 ? Colors.white : Colors.grey, + fontSize: 12, + ), + ), + ], ), ), Tab( - child: Text( - 'Explore', - style: TextStyle( - color: home.selectedIndex == 2 ? Colors.white : Colors.grey, - fontSize: MediaQuery.sizeOf(context).width < 410 ? 13 : 15, - ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.brain, + color: home.selectedIndex == 2 ? Colors.white : Colors.grey, + size: 18, + ), + const SizedBox(height: 6), + Text( + 'Memories', + style: TextStyle( + color: home.selectedIndex == 2 ? Colors.white : Colors.grey, + fontSize: 12, + ), + ), + ], + ), + ), + Tab( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.listCheck, + color: home.selectedIndex == 3 ? Colors.white : Colors.grey, + size: 18, + ), + const SizedBox(height: 6), + Text( + 'Actions', + style: TextStyle( + color: home.selectedIndex == 3 ? Colors.white : Colors.grey, + fontSize: 12, + ), + ), + ], + ), + ), + Tab( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + FontAwesomeIcons.search, + color: home.selectedIndex == 4 ? Colors.white : Colors.grey, + size: 18, + ), + const SizedBox(height: 6), + Text( + 'Explore', + style: TextStyle( + color: home.selectedIndex == 4 ? Colors.white : Colors.grey, + fontSize: 12, + ), + ), + ], ), ), ], @@ -469,6 +548,7 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker return AppBar( automaticallyImplyLeading: false, backgroundColor: Theme.of(context).colorScheme.surface, + toolbarHeight: Platform.isMacOS ? 80 : null, title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, @@ -484,7 +564,7 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker }, child: Container( padding: const EdgeInsets.only(left: 12), - child: const Icon(Icons.download, color: Colors.white, size: 24), + child: const Icon(Icons.download, color: Colors.white, size: 28), ), ); } else { @@ -502,16 +582,53 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker controller: _controller!, ); } else if (provider.selectedIndex == 2) { - return Padding( - padding: EdgeInsets.only(right: MediaQuery.sizeOf(context).width * 0.16), - child: const Text('Explore', style: TextStyle(color: Colors.white, fontSize: 18)), + return Center( + child: Padding( + padding: EdgeInsets.only(right: MediaQuery.sizeOf(context).width * 0.10), + child: const Text('Memories', + style: TextStyle( + color: Colors.white, + fontSize: 22, + fontWeight: FontWeight.w600, + )), + ), + ); + } else if (provider.selectedIndex == 3) { + return const Expanded( + child: Center( + child: Text( + 'Actions', + style: TextStyle( + color: Colors.white, + fontSize: 22, + fontWeight: FontWeight.w600, + ), + ), + ), + ); + } else if (provider.selectedIndex == 4) { + return Center( + child: Padding( + padding: EdgeInsets.only(right: MediaQuery.sizeOf(context).width * 0.10), + child: const Text('Explore', + style: TextStyle( + color: Colors.white, + fontSize: 22, + fontWeight: FontWeight.w600, + )), + ), ); } else { - return Expanded( - child: Row( - children: [ - const Spacer(), - ], + return const Expanded( + child: Center( + child: Text( + '', + style: TextStyle( + color: Colors.white, + fontSize: 22, + fontWeight: FontWeight.w600, + ), + ), ), ); } @@ -519,27 +636,34 @@ class _HomePageState extends State with WidgetsBindingObserver, Ticker ), Row( children: [ - IconButton( - padding: const EdgeInsets.all(8.0), + Container( + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Colors.transparent, + ), + child: IconButton( + padding: const EdgeInsets.fromLTRB(2.0, 2.0, 0, 2.0), icon: SvgPicture.asset( - Assets.images.icPersonaProfile.path, - width: 28, - height: 28, + Assets.images.icSettingPersona.path, + width: 36, + height: 36, ), onPressed: () { - MixpanelManager().pageOpened('Persona Profile'); - - // Set routing in provider - var personaProvider = Provider.of(context, listen: false); - personaProvider.setRouting(PersonaProfileRouting.home); - - // Navigate - var homeProvider = Provider.of(context, listen: false); - homeProvider.setIndex(3); - if (homeProvider.onSelectedIndexChanged != null) { - homeProvider.onSelectedIndexChanged!(3); + MixpanelManager().pageOpened('Settings'); + String language = SharedPreferencesUtil().userPrimaryLanguage; + bool hasSpeech = SharedPreferencesUtil().hasSpeakerProfile; + String transcriptModel = SharedPreferencesUtil().transcriptionModel; + routeToPage(context, const SettingsPage()); + if (language != SharedPreferencesUtil().userPrimaryLanguage || + hasSpeech != SharedPreferencesUtil().hasSpeakerProfile || + transcriptModel != SharedPreferencesUtil().transcriptionModel) { + if (context.mounted) { + context.read().onRecordProfileSettingChanged(); + } } - }), + }, + ), + ), ], ), ], diff --git a/app/lib/pages/home/widgets/chat_apps_dropdown_widget.dart b/app/lib/pages/home/widgets/chat_apps_dropdown_widget.dart index c15d4df3d..d17df3e69 100644 --- a/app/lib/pages/home/widgets/chat_apps_dropdown_widget.dart +++ b/app/lib/pages/home/widgets/chat_apps_dropdown_widget.dart @@ -96,8 +96,8 @@ class ChatAppsDropdownWidget extends StatelessWidget { // enable apps if (val == 'enable') { MixpanelManager().pageOpened('Chat Apps'); - context.read().setIndex(2); - controller?.animateToPage(2, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut); + context.read().setIndex(4); + controller?.animateToPage(4, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut); return; } diff --git a/app/lib/pages/memories/memories_review_page.dart b/app/lib/pages/memories/memories_review_page.dart index 5c1528b52..c9c5e246f 100644 --- a/app/lib/pages/memories/memories_review_page.dart +++ b/app/lib/pages/memories/memories_review_page.dart @@ -63,7 +63,7 @@ class _MemoriesReviewPageState extends State { // Process memories with a small delay to allow UI to update for (var memory in memoriesToProcess) { await Future.delayed(const Duration(milliseconds: 20)); - context.read().reviewMemory(memory, approve); + context.read().reviewMemory(memory, approve, 'review_page_batch'); } setState(() { @@ -98,6 +98,46 @@ class _MemoriesReviewPageState extends State { } } + void _processSingleMemory(Memory memory, bool approve) async { + if (_isProcessing) return; + + setState(() => _isProcessing = true); + + // Process the single memory + context.read().reviewMemory(memory, approve, 'review_page_single'); + + setState(() { + remainingMemories.remove(memory); + displayedMemories = selectedCategory == null + ? List.from(remainingMemories) + : remainingMemories.where((f) => f.category == selectedCategory).toList(); + _isProcessing = false; + }); + + // Show feedback + if (!mounted) return; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + approve ? 'Memory saved' : 'Memory discarded', + style: const TextStyle(color: Colors.white), + ), + backgroundColor: Colors.grey.shade800, + duration: const Duration(seconds: 2), + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + margin: const EdgeInsets.fromLTRB(16, 0, 16, 16), + ), + ); + + if (remainingMemories.isEmpty) { + Navigator.pop(context); + } + } + @override Widget build(BuildContext context) { return Consumer(builder: (context, provider, child) { @@ -110,9 +150,9 @@ class _MemoriesReviewPageState extends State { children: [ const Text('Review Memories'), Text( - '${displayedMemories.length} ${selectedCategory != null ? "in ${selectedCategory.toString().split('.').last}" : "total"}', + _getFilterSubtitle(), style: TextStyle( - fontSize: 14, + fontSize: 13, color: Colors.grey.shade400, fontWeight: FontWeight.normal, ), @@ -123,8 +163,8 @@ class _MemoriesReviewPageState extends State { body: Column( children: [ Container( - height: 50, - margin: const EdgeInsets.symmetric(vertical: 8), + height: 46, + margin: const EdgeInsets.only(top: 4, bottom: 8), child: ListView( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), @@ -137,6 +177,7 @@ class _MemoriesReviewPageState extends State { style: TextStyle( color: selectedCategory == null ? Colors.black : Colors.white70, fontWeight: selectedCategory == null ? FontWeight.w600 : FontWeight.normal, + fontSize: 13, ), ), selected: selectedCategory == null, @@ -145,20 +186,27 @@ class _MemoriesReviewPageState extends State { selectedColor: Colors.white, checkmarkColor: Colors.black, showCheckmark: false, - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), ), ), ...categoryCounts.entries.map((entry) { final category = entry.key; final count = entry.value; + + // Format category name to be more concise + String categoryName = category.toString().split('.').last; + // Capitalize first letter only + categoryName = categoryName[0].toUpperCase() + categoryName.substring(1); + return Padding( padding: const EdgeInsets.only(right: 8), child: FilterChip( label: Text( - '${category.toString().split('.').last} ($count)', + '$categoryName ($count)', style: TextStyle( color: selectedCategory == category ? Colors.black : Colors.white70, fontWeight: selectedCategory == category ? FontWeight.w600 : FontWeight.normal, + fontSize: 13, ), ), selected: selectedCategory == category, @@ -167,7 +215,7 @@ class _MemoriesReviewPageState extends State { selectedColor: Colors.white, checkmarkColor: Colors.black, showCheckmark: false, - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), ), ); }), @@ -185,10 +233,10 @@ class _MemoriesReviewPageState extends State { Text( selectedCategory == null ? 'All memories have been reviewed' - : 'No memories to review in this category', + : 'No memories in this category', style: TextStyle( color: Colors.grey.shade400, - fontSize: 18, + fontSize: 16, ), ), ], @@ -200,16 +248,16 @@ class _MemoriesReviewPageState extends State { itemBuilder: (context, index) { final memory = displayedMemories[index]; return Container( - margin: const EdgeInsets.only(bottom: 12), + margin: const EdgeInsets.only(bottom: 10), decoration: BoxDecoration( color: Colors.grey.shade900, - borderRadius: BorderRadius.circular(16), + borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -217,108 +265,85 @@ class _MemoriesReviewPageState extends State { category: memory.category, showIcon: true, ), - const SizedBox(height: 12), + const SizedBox(height: 10), Text( memory.content.decodeString, style: const TextStyle( color: Colors.white, - fontSize: 16, + fontSize: 15, height: 1.4, ), ), ], ), ), - Row( - children: [ - Expanded( - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.transparent, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(16), + Container( + decoration: BoxDecoration( + color: Colors.grey.shade800, + borderRadius: const BorderRadius.vertical( + bottom: Radius.circular(12), + ), + ), + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), + child: Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () => _processSingleMemory(memory, false), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 8), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), ), - ), - ), - onPressed: _isProcessing - ? null - : () { - provider.reviewMemory(memory, false); - setState(() { - remainingMemories.remove(memory); - displayedMemories.remove(memory); - }); - if (remainingMemories.isEmpty) { - Navigator.pop(context); - } - }, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.delete_outline, size: 18, color: Colors.red.shade400), - const SizedBox(width: 8), - Text( - 'Discard', - style: TextStyle( - color: Colors.red.shade400, - fontSize: 15, + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.delete_outline, size: 16, color: Colors.white70), + SizedBox(width: 6), + Text( + 'Discard', + style: TextStyle( + color: Colors.white70, + fontSize: 13, + fontWeight: FontWeight.w500, + ), ), - ), - ], + ], + ), ), ), ), - ), - Container( - width: 1, - height: 45, - color: Colors.white.withOpacity(0.1), - ), - Expanded( - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.transparent, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(16), + const SizedBox(width: 10), + Expanded( + child: GestureDetector( + onTap: () => _processSingleMemory(memory, true), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 8), + decoration: BoxDecoration( + color: Colors.purple.shade700, + borderRadius: BorderRadius.circular(8), ), - ), - ), - onPressed: _isProcessing - ? null - : () { - provider.reviewMemory(memory, true); - setState(() { - remainingMemories.remove(memory); - displayedMemories.remove(memory); - }); - if (remainingMemories.isEmpty) { - Navigator.pop(context); - } - }, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.check, size: 18, color: Colors.white), - const SizedBox(width: 8), - Text( - 'Save', - style: TextStyle( - color: Colors.grey.shade100, - fontSize: 15, + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.check, size: 16, color: Colors.white), + SizedBox(width: 6), + Text( + 'Save', + style: TextStyle( + color: Colors.white, + fontSize: 13, + fontWeight: FontWeight.w500, + ), ), - ), - ], + ], + ), ), ), ), - ), - ], + ], + ), ), ], ), @@ -351,56 +376,59 @@ class _MemoriesReviewPageState extends State { : Row( children: [ Expanded( - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.red.shade900.withOpacity(0.3), + child: GestureDetector( + onTap: () => _processBatchAction(false), + child: Container( padding: const EdgeInsets.symmetric(vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.1), + borderRadius: BorderRadius.circular(10), ), - ), - onPressed: () => _processBatchAction(false), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.delete_outline, size: 18, color: Colors.red.shade400), - const SizedBox(width: 8), - Text( - 'Discard all', - style: TextStyle( - color: Colors.red.shade400, - fontSize: 15, + alignment: Alignment.center, + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.delete_outline, size: 18, color: Colors.white70), + SizedBox(width: 8), + Text( + 'Discard All', + style: TextStyle( + color: Colors.white70, + fontSize: 14, + fontWeight: FontWeight.w500, + ), ), - ), - ], + ], + ), ), ), ), const SizedBox(width: 12), Expanded( - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.white, + child: GestureDetector( + onTap: () => _processBatchAction(true), + child: Container( padding: const EdgeInsets.symmetric(vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), + decoration: BoxDecoration( + color: Colors.purple.shade700, + borderRadius: BorderRadius.circular(10), ), - ), - onPressed: () => _processBatchAction(true), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.check, size: 18, color: Colors.black), - SizedBox(width: 8), - Text( - 'Save all', - style: TextStyle( - color: Colors.black, - fontSize: 15, - fontWeight: FontWeight.w600, + alignment: Alignment.center, + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.check, size: 18, color: Colors.white), + SizedBox(width: 8), + Text( + 'Save All', + style: TextStyle( + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.w500, + ), ), - ), - ], + ], + ), ), ), ), @@ -412,4 +440,15 @@ class _MemoriesReviewPageState extends State { ); }); } + + String _getFilterSubtitle() { + if (selectedCategory == null) { + return '${displayedMemories.length} memories to review'; + } + + String categoryName = selectedCategory.toString().split('.').last; + categoryName = categoryName[0].toUpperCase() + categoryName.substring(1); + + return '${displayedMemories.length} ${categoryName} memories'; + } } diff --git a/app/lib/pages/memories/page.dart b/app/lib/pages/memories/page.dart index 6fc0c207b..c20472300 100644 --- a/app/lib/pages/memories/page.dart +++ b/app/lib/pages/memories/page.dart @@ -1,14 +1,22 @@ import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:omi/backend/schema/memory.dart'; +import 'package:omi/providers/home_provider.dart'; import 'package:omi/providers/memories_provider.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; +import 'package:omi/utils/ui_guidelines.dart'; import 'package:omi/widgets/extensions/functions.dart'; import 'package:provider/provider.dart'; +import 'package:shimmer/shimmer.dart'; import 'widgets/memory_edit_sheet.dart'; import 'widgets/memory_item.dart'; import 'widgets/memory_dialog.dart'; import 'widgets/memory_review_sheet.dart'; +import 'widgets/memory_management_sheet.dart'; + +// Filter options for the dropdown +enum FilterOption { interesting, system, all } class MemoriesPage extends StatefulWidget { const MemoriesPage({super.key}); @@ -17,30 +25,120 @@ class MemoriesPage extends StatefulWidget { State createState() => MemoriesPageState(); } -class MemoriesPageState extends State { +class _ReviewPromptHeaderDelegate extends SliverPersistentHeaderDelegate { + final double height; + final Widget child; + + _ReviewPromptHeaderDelegate({ + required this.height, + required this.child, + }); + + @override + double get minExtent => height; + + @override + double get maxExtent => height; + + @override + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { + return SizedBox.expand(child: child); + } + + @override + bool shouldRebuild(_ReviewPromptHeaderDelegate oldDelegate) { + return height != oldDelegate.height || child != oldDelegate.child; + } +} + +class MemoriesPageState extends State with AutomaticKeepAliveClientMixin { + @override + bool get wantKeepAlive => true; + final TextEditingController _searchController = TextEditingController(); + MemoryCategory? _selectedCategory; + final ScrollController _scrollController = ScrollController(); + + // Filter options for the dropdown + // Default will be set in initState based on current date + late FilterOption _currentFilter; @override void dispose() { _searchController.dispose(); + _scrollController.dispose(); super.dispose(); } @override void initState() { - () async { - await context.read().init(); + super.initState(); + // Set default filter based on current date + final now = DateTime.now(); + final cutoffDate = DateTime(2025, 5, 31); + + if (now.isAfter(cutoffDate)) { + _currentFilter = FilterOption.interesting; + } else { + _currentFilter = FilterOption.all; + } - final unreviewedMemories = context.read().unreviewed; - if (unreviewedMemories.isNotEmpty) { - _showReviewSheet(unreviewedMemories); + (() async { + final provider = context.read(); + await provider.init(); + + // Apply the date-based default filter + _applyFilter(_currentFilter); + + if (!mounted) return; + final unreviewedMemories = provider.unreviewed; + final home = context.read(); + if (unreviewedMemories.isNotEmpty && home.selectedIndex == 2) { + _showReviewSheet(context, unreviewedMemories, provider); } - }.withPostFrameCallback(); - super.initState(); + }).withPostFrameCallback(); + } + + void _applyFilter(FilterOption option) { + final provider = context.read(); + setState(() { + _currentFilter = option; + + switch (option) { + case FilterOption.interesting: + _filterByCategory(MemoryCategory.interesting); + MixpanelManager().memoriesFiltered('interesting'); + break; + case FilterOption.system: + _filterByCategory(MemoryCategory.system); + MixpanelManager().memoriesFiltered('system'); + break; + case FilterOption.all: + _filterByCategory(null); // null means no category filter + MixpanelManager().memoriesFiltered('all'); + break; + } + }); + } + + void _filterByCategory(MemoryCategory? category) { + setState(() { + _selectedCategory = category; + }); + context.read().setCategoryFilter(category); + } + + Map _getCategoryCounts(List memories) { + var counts = {}; + for (var memory in memories) { + counts[memory.category] = (counts[memory.category] ?? 0) + 1; + } + return counts; } @override Widget build(BuildContext context) { + super.build(context); return Consumer( builder: (context, provider, _) { return PopScope( @@ -48,114 +146,346 @@ class MemoriesPageState extends State { child: Scaffold( backgroundColor: Theme.of(context).colorScheme.primary, body: provider.loading - ? const Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(Colors.white), - )) - : CustomScrollView( - slivers: [ - SliverAppBar( - backgroundColor: Theme.of(context).colorScheme.primary, - pinned: true, - snap: true, - floating: true, - title: const Text('My Memory'), - actions: [ - IconButton( - icon: const Icon(Icons.delete_sweep_outlined), - onPressed: () { - _showDeleteAllConfirmation(context, provider); - }, - ), - IconButton( - icon: const Icon(Icons.add), - onPressed: () { - showMemoryDialog(context, provider); - MixpanelManager().memoriesPageCreateMemoryBtn(); - }, - ), - ], - bottom: PreferredSize( - preferredSize: const Size.fromHeight(68), + ? NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) { + return [ + SliverToBoxAdapter( child: Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 10), - child: SearchBar( - hintText: 'Search Omi\'s memory about you', - leading: const Icon(Icons.search, color: Colors.white70), - backgroundColor: WidgetStateProperty.all(Colors.grey.shade900), - elevation: WidgetStateProperty.all(0), - padding: WidgetStateProperty.all( - const EdgeInsets.symmetric(horizontal: 10, vertical: 6), - ), - controller: _searchController, - trailing: provider.searchQuery.isNotEmpty - ? [ - IconButton( - icon: const Icon(Icons.close, color: Colors.white70), - onPressed: () { - _searchController.clear(); - setState(() {}); - provider.setSearchQuery(''); - }, - ) - ] - : null, - hintStyle: WidgetStateProperty.all( - TextStyle(color: Colors.grey.shade400, fontSize: 14), - ), - shape: WidgetStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), + padding: const EdgeInsets.fromLTRB(16, 12, 16, 10), + child: Row( + children: [ + Expanded( + child: SizedBox( + height: 44, + child: SearchBar( + hintText: 'Search memories', + leading: const Padding( + padding: EdgeInsets.only(left: 6.0), + child: Icon(FontAwesomeIcons.magnifyingGlass, color: Colors.white70, size: 14), + ), + backgroundColor: WidgetStateProperty.all(AppStyles.backgroundSecondary), + elevation: WidgetStateProperty.all(0), + padding: WidgetStateProperty.all( + const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + ), + hintStyle: WidgetStateProperty.all( + TextStyle(color: AppStyles.textTertiary, fontSize: 14), + ), + textStyle: WidgetStateProperty.all( + TextStyle(color: AppStyles.textPrimary, fontSize: 14), + ), + shape: WidgetStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyles.radiusLarge), + ), + ), + ), + ), ), - ), - onChanged: (value) => provider.setSearchQuery(value), + const SizedBox(width: 8), + SizedBox( + width: 44, + height: 44, + child: _buildShimmerButton(), + ), + const SizedBox(width: 8), + SizedBox( + width: 44, + height: 44, + child: _buildShimmerButton(), + ), + const SizedBox(width: 8), + SizedBox( + width: 44, + height: 44, + child: _buildShimmerButton(), + ), + ], ), ), ), - ), - SliverPadding( - padding: const EdgeInsets.all(16), - sliver: provider.filteredMemories.isEmpty - ? SliverFillRemaining( - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.note_add, size: 48, color: Colors.grey.shade600), - const SizedBox(height: 16), - Text( - provider.searchQuery.isEmpty ? 'No memories yet' : 'No memories found', - style: TextStyle( - color: Colors.grey.shade400, - fontSize: 18, + ]; + }, + body: _buildShimmerMemoryList(), + ) + : NestedScrollView( + controller: _scrollController, + headerSliverBuilder: (context, innerBoxIsScrolled) { + return [ + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 10), + child: Row( + children: [ + Consumer(builder: (context, home, child) { + return Expanded( + child: SizedBox( + height: 44, + child: SearchBar( + hintText: 'Search memories', + leading: const Padding( + padding: EdgeInsets.only(left: 6.0), + child: Icon(FontAwesomeIcons.magnifyingGlass, color: Colors.white70, size: 14), + ), + backgroundColor: WidgetStateProperty.all(AppStyles.backgroundSecondary), + elevation: WidgetStateProperty.all(0), + padding: WidgetStateProperty.all( + const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + ), + focusNode: home.memoriesSearchFieldFocusNode, + controller: _searchController, + trailing: provider.searchQuery.isNotEmpty + ? [ + IconButton( + icon: const Icon(Icons.close, color: Colors.white70, size: 16), + padding: EdgeInsets.zero, + constraints: const BoxConstraints( + minHeight: 36, + minWidth: 36, + ), + onPressed: () { + _searchController.clear(); + provider.setSearchQuery(''); + MixpanelManager().memorySearchCleared(provider.memories.length); + }, + ) + ] + : null, + hintStyle: WidgetStateProperty.all( + TextStyle(color: AppStyles.textTertiary, fontSize: 14), + ), + textStyle: WidgetStateProperty.all( + TextStyle(color: AppStyles.textPrimary, fontSize: 14), ), + shape: WidgetStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyles.radiusLarge), + ), + ), + onChanged: (value) => provider.setSearchQuery(value), + onSubmitted: (value) { + if (value.isNotEmpty) { + MixpanelManager().memorySearched(value, provider.filteredMemories.length); + } + }, ), - if (provider.searchQuery.isEmpty) ...[ - const SizedBox(height: 8), - TextButton( - onPressed: () => showMemoryDialog(context, provider), - child: const Text('Add your first memory'), + ), + ); + }), + const SizedBox(width: 8), + SizedBox( + width: 44, + height: 44, + child: PopupMenuButton( + onSelected: _applyFilter, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + color: AppStyles.backgroundSecondary, + offset: const Offset(0, 8), + elevation: 4, + tooltip: 'Filter memories by category', + position: PopupMenuPosition.under, + itemBuilder: (BuildContext context) => >[ + PopupMenuItem( + value: FilterOption.all, + child: Row( + children: [ + const Text( + 'All', + style: TextStyle(color: Colors.white), + ), + const Spacer(), + if (_currentFilter == FilterOption.all) const Icon(Icons.check, size: 16, color: Colors.white), + ], ), - ], + ), + PopupMenuItem( + value: FilterOption.interesting, + child: Row( + children: [ + const Text( + 'Interesting', + style: TextStyle(color: Colors.white), + ), + const Spacer(), + if (_currentFilter == FilterOption.interesting) const Icon(Icons.check, size: 16, color: Colors.white), + ], + ), + ), + PopupMenuItem( + value: FilterOption.system, + child: Row( + children: [ + const Text( + 'System', + style: TextStyle(color: Colors.white), + ), + const Spacer(), + if (_currentFilter == FilterOption.system) const Icon(Icons.check, size: 16, color: Colors.white), + ], + ), + ), ], + child: Container( + decoration: BoxDecoration( + color: AppStyles.backgroundSecondary, + borderRadius: BorderRadius.circular(12), + ), + child: const Center( + child: Icon( + FontAwesomeIcons.filter, + size: 16, + color: Colors.white, + ), + ), + ), ), ), - ) - : SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - final memory = provider.filteredMemories[index]; - return MemoryItem( - memory: memory, - provider: provider, - onTap: _showQuickEditSheet, - ); - }, - childCount: provider.filteredMemories.length, + const SizedBox(width: 8), + SizedBox( + width: 44, + height: 44, + child: ElevatedButton( + onPressed: () { + _showMemoryManagementSheet(context, provider); + }, + style: ElevatedButton.styleFrom( + backgroundColor: AppStyles.backgroundSecondary, + foregroundColor: Colors.white, + padding: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: const Icon(FontAwesomeIcons.sliders, size: 16), + ), + ), + const SizedBox(width: 8), + SizedBox( + width: 44, + height: 44, + child: ElevatedButton( + onPressed: () { + showMemoryDialog(context, provider); + MixpanelManager().memoriesPageCreateMemoryBtn(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: AppStyles.backgroundSecondary, + foregroundColor: Colors.white, + padding: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: const Icon(FontAwesomeIcons.plus, size: 18), + ), + ), + ], + ), + ), + ), + if (provider.unreviewed.isNotEmpty) + SliverPersistentHeader( + pinned: true, + floating: true, + delegate: _ReviewPromptHeaderDelegate( + height: 56.0, + child: Material( + color: Theme.of(context).colorScheme.surfaceVariant, + elevation: 1, + child: InkWell( + onTap: () => _showReviewSheet(context, provider.unreviewed, provider), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + children: [ + Icon(FontAwesomeIcons.listCheck, color: Theme.of(context).colorScheme.onSurfaceVariant, size: 18), + const SizedBox(width: 12), + Flexible( + child: Text( + '${provider.unreviewed.length} ${provider.unreviewed.length == 1 ? "memory" : "memories"} to review', + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant, fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Text('Review', style: TextStyle(color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.bold)), + ), + ], + ), + ), ), ), - ), - ], + ), + ), + SliverPersistentHeader( + pinned: true, + floating: true, + delegate: _SliverSearchBarDelegate( + minHeight: 0, + maxHeight: 0, + child: Container(), + ), + ), + ]; + }, + body: provider.filteredMemories.isEmpty + ? Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.note_add, size: 48, color: Colors.grey.shade600), + const SizedBox(height: 16), + Text( + provider.searchQuery.isEmpty && _selectedCategory == null + ? 'No memories yet' + : _selectedCategory != null + ? _selectedCategory == MemoryCategory.interesting + ? 'No interesting memories yet' + : _selectedCategory == MemoryCategory.system + ? 'No system memories yet' + : 'No memories in this category' + : 'No memories found', + style: TextStyle( + color: Colors.grey.shade400, + fontSize: 18, + ), + ), + if (provider.searchQuery.isEmpty && _selectedCategory == null) ...[ + const SizedBox(height: 8), + TextButton( + onPressed: () => showMemoryDialog(context, provider), + child: const Text('Add your first memory'), + ), + ], + ], + ), + ) + : ListView.builder( + // Add significant bottom padding to prevent content from being covered by floating action bar + padding: const EdgeInsets.only(top: 8, left: 16, right: 16, bottom: 120), + itemCount: provider.filteredMemories.length, + itemBuilder: (context, index) { + final memory = provider.filteredMemories[index]; + return MemoryItem( + memory: memory, + provider: provider, + onTap: (BuildContext context, Memory tappedMemory, MemoriesProvider tappedProvider) { + MixpanelManager().memoryListItemClicked(tappedMemory); + _showQuickEditSheet(context, tappedMemory, tappedProvider); + }, + ); + }, + ), ), ), ); @@ -163,6 +493,42 @@ class MemoriesPageState extends State { ); } + Widget _buildShimmerButton() { + return Shimmer.fromColors( + baseColor: AppStyles.backgroundSecondary, + highlightColor: AppStyles.backgroundTertiary, + child: Container( + decoration: BoxDecoration( + color: AppStyles.backgroundSecondary, + borderRadius: BorderRadius.circular(12), + ), + ), + ); + } + + Widget _buildShimmerMemoryList() { + return Padding( + padding: const EdgeInsets.only(top: 8, left: 16, right: 16, bottom: 120), + child: ListView.builder( + itemCount: 8, // Show 8 shimmer items + itemBuilder: (context, index) { + return Shimmer.fromColors( + baseColor: AppStyles.backgroundSecondary, + highlightColor: AppStyles.backgroundTertiary, + child: Container( + margin: const EdgeInsets.only(bottom: AppStyles.spacingM), + height: 88, // Approximate height of a memory item + decoration: BoxDecoration( + color: AppStyles.backgroundSecondary, + borderRadius: BorderRadius.circular(AppStyles.radiusLarge), + ), + ), + ); + }, + ), + ); + } + void _showQuickEditSheet(BuildContext context, Memory memory, MemoriesProvider provider) { showModalBottomSheet( context: context, @@ -176,21 +542,23 @@ class MemoriesPageState extends State { ); } - void _showReviewSheet(List memories) async { - if (memories.isEmpty) return; + void _showReviewSheet(BuildContext context, List memories, MemoriesProvider existingProvider) async { + if (memories.isEmpty || !mounted) return; await showModalBottomSheet( context: context, backgroundColor: Colors.transparent, isDismissible: true, enableDrag: false, - builder: (context) => ListenableProvider( - create: (_) => MemoriesProvider(), - builder: (context, _) { - return MemoriesReviewSheet( - memories: memories, - provider: context.read(), - ); - }), + isScrollControlled: true, + builder: (sheetContext) { + return ChangeNotifierProvider.value( + value: existingProvider, + child: MemoriesReviewSheet( + memories: memories, + provider: existingProvider, + ), + ); + }, ); } @@ -245,4 +613,42 @@ class MemoriesPageState extends State { ), ); } + + void _showMemoryManagementSheet(BuildContext context, MemoriesProvider provider) { + MixpanelManager().memoriesManagementSheetOpened(); + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + isScrollControlled: true, + builder: (context) => MemoryManagementSheet(provider: provider), + ); + } +} + +class _SliverSearchBarDelegate extends SliverPersistentHeaderDelegate { + final double minHeight; + final double maxHeight; + final Widget child; + + _SliverSearchBarDelegate({ + required this.minHeight, + required this.maxHeight, + required this.child, + }); + + @override + double get minExtent => minHeight; + + @override + double get maxExtent => maxHeight; + + @override + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { + return SizedBox.expand(child: child); + } + + @override + bool shouldRebuild(_SliverSearchBarDelegate oldDelegate) { + return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || child != oldDelegate.child; + } } diff --git a/app/lib/pages/memories/widgets/category_chip.dart b/app/lib/pages/memories/widgets/category_chip.dart index fff4bc54f..88c641f2c 100644 --- a/app/lib/pages/memories/widgets/category_chip.dart +++ b/app/lib/pages/memories/widgets/category_chip.dart @@ -19,34 +19,71 @@ class CategoryChip extends StatelessWidget { this.showCheckmark = false, }); + Color _getCategoryColor() { + switch (category) { + case MemoryCategory.interesting: + return Colors.blue; + case MemoryCategory.system: + return Colors.grey; + } + } + + IconData _getCategoryIcon() { + switch (category) { + case MemoryCategory.interesting: + return Icons.star_outline; + case MemoryCategory.system: + return Icons.settings_outlined; + } + } + @override Widget build(BuildContext context) { final categoryName = category.toString().split('.').last; - final displayName = count != null ? '$categoryName ($count)' : categoryName; + // Use shorter display names for categories + String displayName; + switch (category) { + case MemoryCategory.interesting: + displayName = "Interesting"; + break; + case MemoryCategory.system: + displayName = "System"; + break; + } + + final countText = count != null ? ' ($count)' : ''; + + final categoryColor = _getCategoryColor(); + final categoryIcon = _getCategoryIcon(); Widget chip = Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + height: 26, + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0), decoration: BoxDecoration( - color: isSelected ? (onTap != null ? Colors.white : Colors.white.withOpacity(0.1)) : Colors.grey.shade800, - borderRadius: BorderRadius.circular(16), - border: isSelected && onTap == null ? Border.all(color: Colors.white, width: 1) : null, + color: isSelected ? (onTap != null ? categoryColor : categoryColor.withOpacity(0.15)) : Colors.grey.shade800.withOpacity(0.6), + borderRadius: BorderRadius.circular(13), + border: isSelected && onTap == null ? Border.all(color: categoryColor, width: 1) : null, ), child: Row( mainAxisSize: MainAxisSize.min, children: [ if (showIcon) ...[ - const Icon(Icons.label_outline, size: 14, color: Colors.white), + Icon( + categoryIcon, + size: 14, + color: isSelected && onTap != null ? Colors.white : categoryColor, + ), const SizedBox(width: 4), ], if (showCheckmark && isSelected) ...[ - const Icon(Icons.check, size: 14, color: Colors.white), - const SizedBox(width: 4), + const Icon(Icons.check, size: 12, color: Colors.white), + const SizedBox(width: 2), ], Text( - displayName, + displayName + countText, style: TextStyle( - color: isSelected ? (onTap != null ? Colors.black : Colors.white) : Colors.white70, - fontSize: 13, + color: isSelected ? (onTap != null ? Colors.white : categoryColor) : Colors.white70, + fontSize: 12, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), ), @@ -61,6 +98,9 @@ class CategoryChip extends StatelessWidget { ); } - return chip; + return Align( + alignment: Alignment.centerLeft, + child: chip, + ); } } diff --git a/app/lib/pages/memories/widgets/memory_dialog.dart b/app/lib/pages/memories/widgets/memory_dialog.dart index be811f169..f43865152 100644 --- a/app/lib/pages/memories/widgets/memory_dialog.dart +++ b/app/lib/pages/memories/widgets/memory_dialog.dart @@ -222,8 +222,8 @@ class _MemoryDialogState extends State { } MixpanelManager().memoriesPageEditedMemory(); } else { - widget.provider.createMemory(value, selectedVisibility); - MixpanelManager().memoriesPageCreatedMemory(MemoryCategory.values.first); + widget.provider.createMemory(value, selectedVisibility, MemoryCategory.interesting); + MixpanelManager().memoriesPageCreatedMemory(MemoryCategory.interesting); } Navigator.pop(context); } diff --git a/app/lib/pages/memories/widgets/memory_item.dart b/app/lib/pages/memories/widgets/memory_item.dart index f5f19d61e..fe396aba6 100644 --- a/app/lib/pages/memories/widgets/memory_item.dart +++ b/app/lib/pages/memories/widgets/memory_item.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:omi/backend/schema/memory.dart'; import 'package:omi/providers/memories_provider.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; +import 'package:omi/utils/ui_guidelines.dart'; import 'package:omi/widgets/extensions/string.dart'; import 'delete_confirmation.dart'; @@ -25,25 +26,22 @@ class MemoryItem extends StatelessWidget { final Widget memoryWidget = GestureDetector( onTap: () => onTap(context, memory, provider), child: Container( - margin: const EdgeInsets.only(bottom: 8), - decoration: BoxDecoration( - color: Colors.grey.shade900, - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + margin: const EdgeInsets.only(bottom: AppStyles.spacingM), + padding: const EdgeInsets.symmetric(horizontal: AppStyles.spacingL, vertical: AppStyles.spacingL), + decoration: AppStyles.cardDecoration, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - ListTile( - contentPadding: const EdgeInsets.fromLTRB(16, 8, 16, 8), - title: Text( + Expanded( + child: Text( memory.content.decodeString, - style: const TextStyle( - color: Colors.white, - fontSize: 16, - ), + style: AppStyles.body, + maxLines: 3, + overflow: TextOverflow.ellipsis, ), - trailing: _buildVisibilityButton(context), ), + const SizedBox(width: AppStyles.spacingM), + _buildVisibilityButton(context), ], ), ), @@ -65,10 +63,10 @@ class MemoryItem extends StatelessWidget { MixpanelManager().memoriesPageDeletedMemory(memory); }, background: Container( - margin: const EdgeInsets.only(bottom: 8), + margin: const EdgeInsets.only(bottom: AppStyles.spacingM), decoration: BoxDecoration( - color: Colors.red.shade900, - borderRadius: BorderRadius.circular(12), + color: AppStyles.error, + borderRadius: BorderRadius.circular(AppStyles.radiusLarge), ), alignment: Alignment.centerRight, padding: const EdgeInsets.only(right: 20), @@ -83,29 +81,31 @@ class MemoryItem extends StatelessWidget { padding: EdgeInsets.zero, position: PopupMenuPosition.under, surfaceTintColor: Colors.transparent, - color: Colors.grey.shade800, + color: AppStyles.backgroundTertiary, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), + borderRadius: BorderRadius.circular(AppStyles.radiusLarge), ), offset: const Offset(0, 4), child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + height: 36, + width: 56, decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(AppStyles.radiusMedium), ), child: Row( mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( memory.visibility == MemoryVisibility.private ? Icons.lock_outline : Icons.public, size: 16, color: Colors.white70, ), - const SizedBox(width: 4), + const SizedBox(width: 6), const Icon( Icons.keyboard_arrow_down, - size: 16, + size: 18, color: Colors.white70, ), ], @@ -127,6 +127,7 @@ class MemoryItem extends StatelessWidget { ], onSelected: (visibility) { provider.updateMemoryVisibility(memory, visibility); + MixpanelManager().memoryVisibilityChanged(memory, visibility); }, ); } @@ -162,13 +163,14 @@ class MemoryItem extends StatelessWidget { fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), ), - const SizedBox(height: 2), Text( description, style: TextStyle( color: Colors.grey.shade400, fontSize: 12, ), + maxLines: 2, + overflow: TextOverflow.ellipsis, ), ], ), diff --git a/app/lib/pages/memories/widgets/memory_management_sheet.dart b/app/lib/pages/memories/widgets/memory_management_sheet.dart new file mode 100644 index 000000000..a90c8103e --- /dev/null +++ b/app/lib/pages/memories/widgets/memory_management_sheet.dart @@ -0,0 +1,280 @@ +import 'package:flutter/material.dart'; +import 'package:omi/providers/memories_provider.dart'; +import 'package:omi/utils/ui_guidelines.dart'; + +class MemoryManagementSheet extends StatelessWidget { + final MemoriesProvider provider; + + const MemoryManagementSheet({ + super.key, + required this.provider, + }); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: AppStyles.backgroundSecondary, + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), + ), + child: SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _buildHeader(context), + const Divider(height: 1, color: Colors.white10), + _buildMemoryCount(context), + _buildActionButtons(context), + ], + ), + ), + ); + } + + Widget _buildHeader(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 16, 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Memory Management', + style: AppStyles.subtitle, + ), + IconButton( + icon: const Icon(Icons.close, color: Colors.white70), + onPressed: () => Navigator.pop(context), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), + ), + ], + ), + ); + } + + Widget _buildMemoryCount(BuildContext context) { + final totalMemories = provider.memories.length; + final publicMemories = provider.memories.where((m) => !m.deleted && m.visibility.name == 'public').length; + final privateMemories = provider.memories.where((m) => !m.deleted && m.visibility.name == 'private').length; + + return Container( + width: double.infinity, + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'You have $totalMemories total memories', + style: AppStyles.body, + ), + const SizedBox(height: 8), + _buildMemoryCountRow(Icons.public, 'Public memories', publicMemories), + const SizedBox(height: 4), + _buildMemoryCountRow(Icons.lock_outline, 'Private memories', privateMemories), + ], + ), + ); + } + + Widget _buildMemoryCountRow(IconData icon, String label, int count) { + return Row( + children: [ + Icon(icon, size: 16, color: Colors.white60), + const SizedBox(width: 8), + Text( + label, + style: AppStyles.caption, + ), + const Spacer(), + Text( + count.toString(), + style: AppStyles.caption.copyWith( + fontWeight: FontWeight.w600, + ), + ), + ], + ); + } + + Widget _buildActionButtons(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _buildActionButton( + context, + 'Make All Memories Private', + Icons.lock_outline, + Colors.white.withOpacity(0.1), + () => _makeAllMemoriesPrivate(context), + ), + const SizedBox(height: 12), + _buildActionButton( + context, + 'Make All Memories Public', + Icons.public, + Colors.white.withOpacity(0.1), + () => _makeAllMemoriesPublic(context), + ), + const SizedBox(height: 24), + const Divider(height: 1, color: Colors.white10), + const SizedBox(height: 24), + _buildActionButton( + context, + 'Delete All Memories', + Icons.delete_outline, + Colors.red.withOpacity(0.1), + () => _confirmDeleteAllMemories(context), + textColor: Colors.red, + iconColor: Colors.red, + ), + const SizedBox(height: 12), + ], + ), + ); + } + + Widget _buildActionButton( + BuildContext context, + String text, + IconData icon, + Color backgroundColor, + VoidCallback onPressed, { + Color textColor = Colors.white, + Color iconColor = Colors.white, + }) { + return ElevatedButton( + onPressed: onPressed, + style: ElevatedButton.styleFrom( + backgroundColor: backgroundColor, + foregroundColor: textColor, + elevation: 0, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + child: Row( + children: [ + Icon(icon, size: 20, color: iconColor), + const SizedBox(width: 12), + Text( + text, + style: TextStyle( + color: textColor, + fontSize: 15, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ); + } + + void _makeAllMemoriesPrivate(BuildContext context) async { + Navigator.pop(context); + await provider.updateAllMemoriesVisibility(true); + + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('All memories are now private'), + backgroundColor: AppStyles.backgroundTertiary, + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + margin: const EdgeInsets.fromLTRB(16, 0, 16, 16), + duration: const Duration(seconds: 2), + ), + ); + } + } + + void _makeAllMemoriesPublic(BuildContext context) async { + Navigator.pop(context); + await provider.updateAllMemoriesVisibility(false); + + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('All memories are now public'), + backgroundColor: AppStyles.backgroundTertiary, + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + margin: const EdgeInsets.fromLTRB(16, 0, 16, 16), + duration: const Duration(seconds: 2), + ), + ); + } + } + + void _confirmDeleteAllMemories(BuildContext context) { + if (provider.memories.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('No memories to delete'), + backgroundColor: AppStyles.backgroundTertiary, + duration: const Duration(seconds: 2), + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + margin: const EdgeInsets.fromLTRB(16, 0, 16, 16), + ), + ); + Navigator.pop(context); + return; + } + + showDialog( + context: context, + builder: (context) => AlertDialog( + backgroundColor: AppStyles.backgroundSecondary, + title: const Text( + 'Clear Omi\'s Memory', + style: TextStyle(color: Colors.white), + ), + content: Text( + 'Are you sure you want to clear Omi\'s memory? This action cannot be undone.', + style: TextStyle(color: Colors.grey.shade300), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + 'Cancel', + style: TextStyle(color: Colors.grey.shade400), + ), + ), + TextButton( + onPressed: () { + provider.deleteAllMemories(); + Navigator.pop(context); // Close dialog + Navigator.pop(context); // Close sheet + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('Omi\'s memory about you has been cleared'), + backgroundColor: AppStyles.backgroundTertiary, + duration: const Duration(seconds: 2), + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + margin: const EdgeInsets.fromLTRB(16, 0, 16, 16), + ), + ); + }, + child: const Text( + 'Clear Memory', + style: TextStyle(color: Colors.red), + ), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/app/lib/pages/memories/widgets/memory_review_sheet.dart b/app/lib/pages/memories/widgets/memory_review_sheet.dart index f0a343464..b91c94645 100644 --- a/app/lib/pages/memories/widgets/memory_review_sheet.dart +++ b/app/lib/pages/memories/widgets/memory_review_sheet.dart @@ -25,10 +25,11 @@ class MemoriesReviewSheet extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Container( - padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14), - margin: const EdgeInsets.only(bottom: 16), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + margin: const EdgeInsets.only(bottom: 12), child: Column( children: [ + const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -38,11 +39,11 @@ class MemoriesReviewSheet extends StatelessWidget { SizedBox( width: MediaQuery.of(context).size.width * 0.74, child: Text( - 'Review and save ${memories.length} memories generated from today\'s conversation with Omi', + '${memories.length} new memories to review', style: const TextStyle( color: Colors.white, fontSize: 16, - fontWeight: FontWeight.w400, + fontWeight: FontWeight.w500, ), ), ), @@ -51,28 +52,38 @@ class MemoriesReviewSheet extends StatelessWidget { ), IconButton( icon: const Icon(Icons.close, color: Colors.white70), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), onPressed: () => Navigator.pop(context), ), ], ), - const SizedBox(height: 24), + const SizedBox(height: 20), Row( children: [ Expanded( child: TextButton( style: TextButton.styleFrom( backgroundColor: Colors.white.withOpacity(0.1), - padding: const EdgeInsets.symmetric(vertical: 12), + padding: const EdgeInsets.symmetric(vertical: 10), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), + borderRadius: BorderRadius.circular(10), ), ), - onPressed: () => Navigator.pop(context), + onPressed: () { + Navigator.pop(context); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => MemoriesReviewPage(memories: memories), + ), + ); + }, child: Text( - 'Review later', + 'Review Manually', style: TextStyle( color: Colors.grey.shade300, - fontSize: 15, + fontSize: 14, ), ), ), @@ -82,25 +93,22 @@ class MemoriesReviewSheet extends StatelessWidget { child: TextButton( style: TextButton.styleFrom( backgroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 12), + padding: const EdgeInsets.symmetric(vertical: 10), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), + borderRadius: BorderRadius.circular(10), ), ), onPressed: () { + for (var memory in memories) { + provider.reviewMemory(memory, true, 'review_sheet_accept_all'); + } Navigator.pop(context); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => MemoriesReviewPage(memories: memories), - ), - ); }, child: const Text( - 'Review now', + 'Accept All', style: TextStyle( color: Colors.black, - fontSize: 15, + fontSize: 14, fontWeight: FontWeight.w600, ), ), @@ -108,6 +116,7 @@ class MemoriesReviewSheet extends StatelessWidget { ), ], ), + const SizedBox(height: 10), ], ), ), diff --git a/app/lib/pages/onboarding/auth.dart b/app/lib/pages/onboarding/auth.dart index a62ef06b6..cc56666bb 100644 --- a/app/lib/pages/onboarding/auth.dart +++ b/app/lib/pages/onboarding/auth.dart @@ -38,7 +38,7 @@ class _AuthComponentState extends State { ), ), SizedBox(height: MediaQuery.of(context).textScaleFactor > 1.0 ? 18 : 32), - if (Platform.isIOS) ...[ + if (Platform.isIOS || Platform.isMacOS) ...[ SignInButton.withApple( title: 'Sign in with Apple', onTap: () async { diff --git a/app/lib/pages/onboarding/device_selection.dart b/app/lib/pages/onboarding/device_selection.dart index ce584a35e..d6645b3d4 100644 --- a/app/lib/pages/onboarding/device_selection.dart +++ b/app/lib/pages/onboarding/device_selection.dart @@ -109,22 +109,22 @@ class _DeviceSelectionPageState extends State with SingleTi const SizedBox( height: 24, ), - TextButton( - onPressed: () async { - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => const SocialHandleScreen()), - ); - }, - child: const Text( - 'I don\'t have omi', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 16, - ), - ), - ), + // TextButton( + // onPressed: () async { + // Navigator.pushReplacement( + // context, + // MaterialPageRoute(builder: (context) => const SocialHandleScreen()), + // ); + // }, + // child: const Text( + // 'I don\'t have omi', + // style: TextStyle( + // color: Colors.white, + // fontWeight: FontWeight.bold, + // fontSize: 16, + // ), + // ), + // ), ], ), const Spacer(flex: 3), diff --git a/app/lib/pages/onboarding/name/name_widget.dart b/app/lib/pages/onboarding/name/name_widget.dart index 9bbe705cf..29d02e527 100644 --- a/app/lib/pages/onboarding/name/name_widget.dart +++ b/app/lib/pages/onboarding/name/name_widget.dart @@ -3,8 +3,7 @@ import 'package:omi/backend/auth.dart'; import 'package:omi/backend/preferences.dart'; import 'package:gradient_borders/gradient_borders.dart'; import 'package:intercom_flutter/intercom_flutter.dart'; -import 'package:omi/providers/home_provider.dart'; -import 'package:provider/provider.dart'; +import 'package:omi/utils/platform/platform_service.dart'; class NameWidget extends StatefulWidget { final Function goNext; @@ -26,7 +25,6 @@ class _NameWidgetState extends State { super.initState(); } - @override Widget build(BuildContext context) { return Padding( @@ -108,18 +106,20 @@ class _NameWidgetState extends State { const SizedBox( height: 12, ), - InkWell( - child: Text( - 'Need Help?', - style: TextStyle( - color: Colors.grey.shade300, - decoration: TextDecoration.underline, - ), - ), - onTap: () { - Intercom.instance.displayMessenger(); - }, - ), + PlatformService.isIntercomSupported + ? InkWell( + child: Text( + 'Need Help?', + style: TextStyle( + color: Colors.grey.shade300, + decoration: TextDecoration.underline, + ), + ), + onTap: () { + Intercom.instance.displayMessenger(); + }, + ) + : const SizedBox.shrink(), ], ), ); diff --git a/app/lib/pages/onboarding/permissions/permissions_macos_widget.dart b/app/lib/pages/onboarding/permissions/permissions_macos_widget.dart new file mode 100644 index 000000000..fb00914d6 --- /dev/null +++ b/app/lib/pages/onboarding/permissions/permissions_macos_widget.dart @@ -0,0 +1,255 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:omi/providers/onboarding_provider.dart'; +import 'package:omi/utils/platform/platform_service.dart'; +import 'package:gradient_borders/box_borders/gradient_box_border.dart'; +import 'package:intercom_flutter/intercom_flutter.dart'; +import 'package:provider/provider.dart'; + +class PermissionsMacOSWidget extends StatefulWidget { + final VoidCallback goNext; + + const PermissionsMacOSWidget({super.key, required this.goNext}); + + @override + State createState() => _PermissionsMacOSWidgetState(); +} + +class _PermissionsMacOSWidgetState extends State { + void _showPermissionDialog({ + required String title, + required String description, + required VoidCallback onContinue, + }) { + showCupertinoDialog( + context: context, + builder: (ctx) { + return CupertinoAlertDialog( + title: Text( + title, + style: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + content: Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + description, + style: const TextStyle( + fontSize: 13, + color: Colors.white, + height: 1.4, + ), + ), + ), + actions: [ + CupertinoDialogAction( + child: Text( + 'Cancel', + style: TextStyle( + color: Colors.grey.shade500, + fontSize: 17, + ), + ), + onPressed: () => Navigator.of(context).pop(), + ), + CupertinoDialogAction( + isDefaultAction: true, + child: const Text( + 'Continue', + style: TextStyle( + color: Colors.white, + fontSize: 17, + ), + ), + onPressed: () { + Navigator.of(context).pop(); + onContinue(); + }, + ), + ], + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, provider, child) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + // Informational header section + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + margin: const EdgeInsets.only(bottom: 16), + decoration: BoxDecoration( + color: Colors.grey.shade800.withOpacity(0.3), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: const Color.fromARGB(255, 188, 99, 121).withOpacity(0.3), + width: 1, + ), + ), + child: Row( + children: [ + const Icon( + Icons.info_outline, + color: Color.fromARGB(255, 188, 99, 121), + size: 16, + ), + const SizedBox(width: 8), + Expanded( + child: Text( + 'Select permissions to grant - we\'ll guide you through each one', + style: TextStyle( + fontSize: 12, + color: Colors.grey.shade300, + height: 1.2, + ), + ), + ), + ], + ), + ), + CheckboxListTile( + value: provider.hasBluetoothPermission, + onChanged: (s) async { + if (s != null) { + if (s) { + _showPermissionDialog( + title: 'Bluetooth Access', + description: + 'This app uses Bluetooth to connect and communicate with your device. Your device data stays private and secure.', + onContinue: () async { + await provider.askForBluetoothPermissions(); + }, + ); + } else { + provider.updateBluetoothPermission(false); + } + } + }, + title: const Text( + 'Connect to your Omi device via Bluetooth', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + contentPadding: const EdgeInsets.only(left: 8), + checkboxShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + ), + CheckboxListTile( + value: provider.hasLocationPermission, + onChanged: (s) async { + if (s != null) { + if (s) { + _showPermissionDialog( + title: 'Location Services', + description: + 'This app may use your location to tag your conversations and improve your experience.', + onContinue: () async { + await provider.askForLocationPermissions(); + }, + ); + } else { + provider.updateLocationPermission(false); + } + } + }, + title: const Text( + 'Access location to improve your experience', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + contentPadding: const EdgeInsets.only(left: 8), + checkboxShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + ), + CheckboxListTile( + value: provider.hasNotificationPermission, + onChanged: (s) async { + if (s != null) { + if (s) { + _showPermissionDialog( + title: 'Notifications', + description: + 'This app would like to send you notifications to keep you informed about important updates and activities.', + onContinue: () async { + await provider.askForNotificationPermissions(); + }, + ); + } else { + provider.updateNotificationPermission(false); + } + } + }, + title: const Text( + 'Receive Important Notifications', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + contentPadding: const EdgeInsets.only(left: 8), + checkboxShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + ), + const SizedBox(height: 16), + provider.isLoading + ? const CircularProgressIndicator( + color: Colors.white, + ) + : Row( + children: [ + Expanded( + child: Container( + width: double.infinity, + decoration: BoxDecoration( + border: const GradientBoxBorder( + gradient: LinearGradient(colors: [ + Color.fromARGB(127, 208, 208, 208), + Color.fromARGB(127, 188, 99, 121), + Color.fromARGB(127, 86, 101, 182), + Color.fromARGB(127, 126, 190, 236) + ]), + width: 2, + ), + borderRadius: BorderRadius.circular(12), + ), + child: MaterialButton( + padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16), + onPressed: () async { + provider.setLoading(false); + widget.goNext(); + }, + child: const Text( + 'Skip', + style: TextStyle( + decoration: TextDecoration.none, + ), + ), + ), + ), + ) + ], + ), + const SizedBox( + height: 12, + ), + PlatformService.isIntercomSupported + ? InkWell( + child: Text( + 'Need Help?', + style: TextStyle( + color: Colors.grey.shade300, + decoration: TextDecoration.underline, + ), + ), + onTap: () { + Intercom.instance.displayMessenger(); + }, + ) + : const SizedBox.shrink(), + ], + ), + ); + }); + } +} diff --git a/app/lib/pages/onboarding/permissions/permissions_widget.dart b/app/lib/pages/onboarding/permissions/permissions_widget.dart index 03ef0d4d7..b3acd25a1 100644 --- a/app/lib/pages/onboarding/permissions/permissions_widget.dart +++ b/app/lib/pages/onboarding/permissions/permissions_widget.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:omi/providers/onboarding_provider.dart'; +import 'package:omi/utils/platform/platform_service.dart'; import 'package:omi/widgets/dialog.dart'; import 'package:gradient_borders/box_borders/gradient_box_border.dart'; import 'package:intercom_flutter/intercom_flutter.dart'; @@ -43,7 +44,6 @@ class _PermissionsWidgetState extends State { style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), ), contentPadding: const EdgeInsets.only(left: 8), - // controlAffinity: ListTileControlAffinity.leading, checkboxShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), ) : const SizedBox.shrink(), @@ -81,6 +81,7 @@ class _PermissionsWidgetState extends State { 'Background Location Access Denied', 'Please go to device settings and set location permission to "Always Allow"', singleButton: true, + okButtonText: 'Continue', ); }, ); @@ -99,6 +100,7 @@ class _PermissionsWidgetState extends State { 'Background Location Access Denied', 'Please go to device settings and set location permission to "Always Allow"', singleButton: true, + okButtonText: 'Continue', ); }, ); @@ -114,7 +116,6 @@ class _PermissionsWidgetState extends State { style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), ), contentPadding: const EdgeInsets.only(left: 8), - // controlAffinity: ListTileControlAffinity.leading, checkboxShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), ), CheckboxListTile( @@ -133,7 +134,6 @@ class _PermissionsWidgetState extends State { style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500), ), contentPadding: const EdgeInsets.only(left: 8), - // controlAffinity: ListTileControlAffinity.leading, checkboxShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), ), const SizedBox(height: 16), @@ -220,18 +220,20 @@ class _PermissionsWidgetState extends State { const SizedBox( height: 12, ), - InkWell( - child: Text( - 'Need Help?', - style: TextStyle( - color: Colors.grey.shade300, - decoration: TextDecoration.underline, - ), - ), - onTap: () { - Intercom.instance.displayMessenger(); - }, - ), + PlatformService.isIntercomSupported + ? InkWell( + child: Text( + 'Need Help?', + style: TextStyle( + color: Colors.grey.shade300, + decoration: TextDecoration.underline, + ), + ), + onTap: () { + Intercom.instance.displayMessenger(); + }, + ) + : const SizedBox.shrink(), ], ), ); diff --git a/app/lib/pages/onboarding/primary_language/primary_language_widget.dart b/app/lib/pages/onboarding/primary_language/primary_language_widget.dart index 5935aea8f..40cbca405 100644 --- a/app/lib/pages/onboarding/primary_language/primary_language_widget.dart +++ b/app/lib/pages/onboarding/primary_language/primary_language_widget.dart @@ -3,6 +3,7 @@ import 'package:gradient_borders/gradient_borders.dart'; import 'package:intercom_flutter/intercom_flutter.dart'; import 'package:omi/backend/preferences.dart'; import 'package:omi/providers/home_provider.dart'; +import 'package:omi/utils/platform/platform_service.dart'; import 'package:provider/provider.dart'; class PrimaryLanguageWidget extends StatefulWidget { @@ -58,8 +59,7 @@ class _LanguageSelectorWidgetState extends State { filteredLanguages = List.from(languages); } else { filteredLanguages = languages.where((lang) { - return lang.key.toLowerCase().contains(searchQuery) || - lang.value.toLowerCase().contains(searchQuery); + return lang.key.toLowerCase().contains(searchQuery) || lang.value.toLowerCase().contains(searchQuery); }).toList(); } @@ -81,17 +81,19 @@ class _LanguageSelectorWidgetState extends State { children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + textBaseline: TextBaseline.alphabetic, children: [ - IconButton( - icon: const Icon(Icons.close, color: Colors.white), - onPressed: () => Navigator.pop(context), - ), - const Text( - 'Select your primary language', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.white, + const Flexible( + child: Text( + 'Select your primary language', + maxLines: 2, + overflow: TextOverflow.ellipsis, + softWrap: true, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.white, + ), ), ), TextButton( @@ -346,18 +348,20 @@ class _PrimaryLanguageWidgetState extends State { const SizedBox( height: 12, ), - InkWell( - child: Text( - 'Need Help?', - style: TextStyle( - color: Colors.grey.shade300, - decoration: TextDecoration.underline, - ), - ), - onTap: () { - Intercom.instance.displayMessenger(); - }, - ), + PlatformService.isIntercomSupported + ? InkWell( + child: Text( + 'Need Help?', + style: TextStyle( + color: Colors.grey.shade300, + decoration: TextDecoration.underline, + ), + ), + onTap: () { + Intercom.instance.displayMessenger(); + }, + ) + : const SizedBox.shrink(), ], ), ); diff --git a/app/lib/pages/onboarding/welcome/page.dart b/app/lib/pages/onboarding/welcome/page.dart index 5747f97c9..2b8ac2b70 100644 --- a/app/lib/pages/onboarding/welcome/page.dart +++ b/app/lib/pages/onboarding/welcome/page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:omi/providers/onboarding_provider.dart'; import 'package:omi/utils/analytics/intercom.dart'; +import 'package:omi/utils/platform/platform_service.dart'; import 'package:omi/widgets/dialog.dart'; import 'package:gradient_borders/box_borders/gradient_box_border.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -107,18 +108,20 @@ class _WelcomePageState extends State with SingleTickerProviderStat const SizedBox( height: 12, ), - InkWell( - child: Text( - 'Need Help?', - style: TextStyle( - color: Colors.grey.shade300, - decoration: TextDecoration.underline, - ), - ), - onTap: () { - IntercomManager.instance.intercom.displayMessenger(); - }, - ), + PlatformService.isIntercomSupported + ? InkWell( + child: Text( + 'Need Help?', + style: TextStyle( + color: Colors.grey.shade300, + decoration: TextDecoration.underline, + ), + ), + onTap: () { + IntercomManager.instance.intercom.displayMessenger(); + }, + ) + : const SizedBox.shrink(), const SizedBox(height: 10) ], ); diff --git a/app/lib/pages/onboarding/wrapper.dart b/app/lib/pages/onboarding/wrapper.dart index 63fd5afe7..2165adbff 100644 --- a/app/lib/pages/onboarding/wrapper.dart +++ b/app/lib/pages/onboarding/wrapper.dart @@ -10,6 +10,7 @@ import 'package:omi/pages/onboarding/auth.dart'; import 'package:omi/pages/onboarding/find_device/page.dart'; import 'package:omi/pages/onboarding/name/name_widget.dart'; import 'package:omi/pages/onboarding/permissions/permissions_widget.dart'; +import 'package:omi/pages/onboarding/permissions/permissions_macos_widget.dart'; import 'package:omi/pages/onboarding/primary_language/primary_language_widget.dart'; import 'package:omi/pages/onboarding/speech_profile_widget.dart'; import 'package:omi/pages/onboarding/welcome/page.dart'; @@ -19,6 +20,7 @@ import 'package:omi/services/services.dart'; import 'package:omi/utils/analytics/intercom.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/other/temp.dart'; +import 'package:omi/utils/platform/platform_service.dart'; import 'package:omi/widgets/device_widget.dart'; import 'package:provider/provider.dart'; @@ -50,6 +52,11 @@ class _OnboardingWrapperState extends State with TickerProvid _controller = TabController(length: 7, vsync: this); _controller!.addListener(() => setState(() {})); WidgetsBinding.instance.addPostFrameCallback((_) async { + // Let's not update permissions here because of Apple's review process + // if (mounted) { + // context.read().updatePermissions(); + // } + if (isSignedIn()) { // && !SharedPreferencesUtil().onboardingCompleted if (mounted) { @@ -96,9 +103,7 @@ class _OnboardingWrapperState extends State with TickerProvid SharedPreferencesUtil().verifiedPersonaId = null; MixpanelManager().onboardingStepCompleted('Auth'); context.read().setupHasSpeakerProfile(); - IntercomManager.instance.intercom.loginIdentifiedUser( - userId: SharedPreferencesUtil().uid, - ); + IntercomManager.instance.loginIdentifiedUser(SharedPreferencesUtil().uid); if (SharedPreferencesUtil().onboardingCompleted) { routeToPage(context, const HomePageWrapper(), replace: true); } else { @@ -119,12 +124,19 @@ class _OnboardingWrapperState extends State with TickerProvid _goNext(); // Go to Permissions page MixpanelManager().onboardingStepCompleted('Primary Language'); }), - PermissionsWidget( - goNext: () { - _goNext(); // Go to Welcome page - MixpanelManager().onboardingStepCompleted('Permissions'); - }, - ), + PlatformService.isMacOS + ? PermissionsMacOSWidget( + goNext: () { + _goNext(); // Go to Welcome page + MixpanelManager().onboardingStepCompleted('Permissions'); + }, + ) + : PermissionsWidget( + goNext: () { + _goNext(); // Go to Welcome page + MixpanelManager().onboardingStepCompleted('Permissions'); + }, + ), WelcomePage( goNext: () { _goNext(); // Go to Find Devices page diff --git a/app/lib/pages/persona/persona_profile.dart b/app/lib/pages/persona/persona_profile.dart index 801b3a508..bcaddeb3c 100644 --- a/app/lib/pages/persona/persona_profile.dart +++ b/app/lib/pages/persona/persona_profile.dart @@ -6,16 +6,11 @@ import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/app.dart'; import 'package:omi/gen/assets.gen.dart'; import 'package:omi/main.dart'; -import 'package:omi/pages/chat/clone_chat_page.dart'; import 'package:omi/pages/onboarding/wrapper.dart'; import 'package:omi/pages/persona/persona_provider.dart'; -import 'package:omi/providers/app_provider.dart'; import 'package:omi/providers/auth_provider.dart'; import 'package:omi/providers/home_provider.dart'; import 'package:omi/pages/persona/twitter/social_profile.dart'; -import 'package:omi/pages/settings/page.dart'; -import 'package:omi/providers/capture_provider.dart'; -import 'package:omi/providers/message_provider.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/other/temp.dart'; import 'package:posthog_flutter/posthog_flutter.dart'; @@ -46,10 +41,20 @@ class _PersonaProfilePageState extends State { void initState() { WidgetsBinding.instance.addPostFrameCallback((_) async { final provider = Provider.of(context, listen: false); + String source = 'unknown'; // Default source + + // Check if we came from settings + final isFromSettings = ModalRoute.of(context)?.settings.arguments == 'from_settings'; + if (isFromSettings) { + provider.setRouting(PersonaProfileRouting.home); + } + if (provider.routing == PersonaProfileRouting.apps_updates && provider.userPersona != null) { provider.prepareUpdatePersona(provider.userPersona!); + MixpanelManager().personaProfileViewed(personaId: provider.userPersona!.id, source: source); } else { await provider.getVerifiedUserPersona(); + MixpanelManager().personaProfileViewed(personaId: provider.userPersona?.id, source: source); } }); super.initState(); @@ -71,95 +76,37 @@ class _PersonaProfilePageState extends State { backgroundColor: Colors.transparent, appBar: AppBar( backgroundColor: Colors.transparent, - leading: Consumer(builder: (context, personaProvider, _) { - return personaProvider.routing == PersonaProfileRouting.apps_updates - ? IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.white), - onPressed: () { - Navigator.pop(context); - }, - ) - : GestureDetector( - onTap: () async { - if (personaProvider.routing == PersonaProfileRouting.no_device) { - routeToPage(context, const CloneChatPage(), replace: false); - } else { - context.read().setIndex(1); - if (context.read().onSelectedIndexChanged != null) { - context.read().onSelectedIndexChanged!(1); - } - var appId = persona!.id; - var appProvider = Provider.of(context, listen: false); - var messageProvider = Provider.of(context, listen: false); - App? selectedApp; - if (appId.isNotEmpty) { - selectedApp = await appProvider.getAppFromId(appId); - } - appProvider.setSelectedChatAppId(appId); - await messageProvider.refreshMessages(); - if (messageProvider.messages.isEmpty) { - messageProvider.sendInitialAppMessage(selectedApp); - } - } - }, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: SvgPicture.asset( - Assets.images.icCloneChat.path, - width: 24, - height: 24, - ), - ), - ); - }), - actions: [ - // Only show settings icon for create_my_clone or home routing - Consumer(builder: (context, personaProvider, _) { - if (personaProvider.routing == PersonaProfileRouting.no_device) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: GestureDetector( - onTap: () async { - await routeToPage(context, const SettingsPage(mode: SettingsMode.no_device)); - }, - child: SvgPicture.asset( - Assets.images.icSettingPersona.path, - width: 44, - height: 44, - ), - ), - ); - } - if (personaProvider.routing == PersonaProfileRouting.create_my_clone || - personaProvider.routing == PersonaProfileRouting.home) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: GestureDetector( - onTap: () async { - MixpanelManager().pageOpened('Settings'); - String language = SharedPreferencesUtil().userPrimaryLanguage; - bool hasSpeech = SharedPreferencesUtil().hasSpeakerProfile; - String transcriptModel = SharedPreferencesUtil().transcriptionModel; - await routeToPage(context, const SettingsPage()); - if (language != SharedPreferencesUtil().userPrimaryLanguage || - hasSpeech != SharedPreferencesUtil().hasSpeakerProfile || - transcriptModel != SharedPreferencesUtil().transcriptionModel) { - if (context.mounted) { - context.read().onRecordProfileSettingChanged(); - } - } - }, - child: SvgPicture.asset( - Assets.images.icSettingPersona.path, - width: 44, - height: 44, - ), - ), - ); + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.white), + onPressed: () { + final isFromSettings = ModalRoute.of(context)?.settings.arguments == 'from_settings'; + + if (isFromSettings) { + // If we came from settings, just pop back to it + Navigator.pop(context); + } else if (provider.routing == PersonaProfileRouting.apps_updates) { + // Regular back for apps updates flow + Navigator.pop(context); + } else { + // For main app navigation + var homeProvider = Provider.of(context, listen: false); + homeProvider.setIndex(0); // Go back to home tab + if (homeProvider.onSelectedIndexChanged != null) { + homeProvider.onSelectedIndexChanged!(0); + } } - return const SizedBox.shrink(); - }), - ], + }, + ), + title: const Text( + 'Persona', + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + centerTitle: true, + actions: [], // Empty actions - no settings button needed ), body: persona == null ? const Center( @@ -320,6 +267,8 @@ class _PersonaProfilePageState extends State { await Posthog().capture(eventName: 'share_persona_clicked', properties: { 'persona_username': persona.username ?? '', }); + MixpanelManager() + .personaShared(personaId: persona.id, personaUsername: persona.username); Share.share( 'https://personas.omi.me/u/${persona.username}', subject: '${persona.getName()} Persona', @@ -738,6 +687,8 @@ class _PersonaProfilePageState extends State { bool isComingSoon = false, bool showConnect = false, }) { + final Color grayedOutColor = Colors.grey[600]!; + return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( @@ -759,7 +710,7 @@ class _PersonaProfilePageState extends State { Text( text, style: TextStyle( - color: isComingSoon ? Colors.grey[600] : Colors.white, + color: isComingSoon ? grayedOutColor : Colors.white, fontSize: 16, ), ), @@ -771,10 +722,10 @@ class _PersonaProfilePageState extends State { color: const Color(0xFF373737), borderRadius: BorderRadius.circular(16), ), - child: const Text( + child: Text( 'Coming soon', style: TextStyle( - color: Colors.white, + color: grayedOutColor, fontSize: 12, ), ), diff --git a/app/lib/pages/persona/persona_provider.dart b/app/lib/pages/persona/persona_provider.dart index b2d74b613..d03d1f00e 100644 --- a/app/lib/pages/persona/persona_provider.dart +++ b/app/lib/pages/persona/persona_provider.dart @@ -6,6 +6,7 @@ import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/app.dart'; import 'package:omi/utils/alerts/app_snackbar.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:omi/utils/analytics/mixpanel.dart'; typedef ShowSuccessDialogCallback = void Function(String url); @@ -77,12 +78,17 @@ class PersonaProvider extends ChangeNotifier { if (res['status'] == 'notfound') { AppSnackbar.showSnackbarError('Twitter handle not found'); _twitterProfile = {}; + MixpanelManager().personaTwitterProfileFetched(twitterHandle: handle, fetchSuccessful: false); } else if (res['status'] == 'suspended') { AppSnackbar.showSnackbarError('Twitter handle is suspended'); _twitterProfile = {}; + MixpanelManager().personaTwitterProfileFetched(twitterHandle: handle, fetchSuccessful: false); } else { _twitterProfile = res; + MixpanelManager().personaTwitterProfileFetched(twitterHandle: handle, fetchSuccessful: true); } + } else { + MixpanelManager().personaTwitterProfileFetched(twitterHandle: handle, fetchSuccessful: false); } setIsLoading(false); notifyListeners(); @@ -93,6 +99,10 @@ class PersonaProvider extends ChangeNotifier { if (!verified) { AppSnackbar.showSnackbarError('Failed to verify Twitter handle'); } + MixpanelManager().personaTwitterOwnershipVerified( + personaId: verifiedPersonaId ?? personaId, + twitterHandle: _twitterProfile['profile'], + verificationSuccessful: verified); SharedPreferencesUtil().hasPersonaCreated = true; SharedPreferencesUtil().verifiedPersonaId = verifiedPersonaId; toggleTwitterConnection(true); @@ -158,6 +168,9 @@ class PersonaProvider extends ChangeNotifier { // Update debugPrint("setPersonaPublic"); + if (_userPersona != null) { + MixpanelManager().personaPublicToggled(personaId: _userPersona!.id, isPublic: makePersonaPublic); + } updatePersona(); } @@ -180,6 +193,7 @@ class PersonaProvider extends ChangeNotifier { final XFile? image = await picker.pickImage(source: ImageSource.gallery); if (image != null) { selectedImage = File(image.path); + MixpanelManager().personaCreateImagePicked(); validateForm(); } notifyListeners(); @@ -190,6 +204,11 @@ class PersonaProvider extends ChangeNotifier { final XFile? image = await picker.pickImage(source: ImageSource.gallery); if (image != null) { selectedImage = File(image.path); + if (_userPersona != null) { + MixpanelManager().personaUpdateImagePicked(personaId: _userPersona!.id); + } else { + MixpanelManager().personaCreateImagePicked(); + } validateForm(); // Update @@ -224,6 +243,9 @@ class PersonaProvider extends ChangeNotifier { void toggleOmiConnection(bool value) { hasOmiConnection = value; + if (_userPersona != null) { + MixpanelManager().personaOmiConnectionToggled(personaId: _userPersona!.id, omiConnected: value); + } notifyListeners(); } @@ -232,6 +254,9 @@ class PersonaProvider extends ChangeNotifier { if (!value) { _twitterProfile = {}; } + if (_userPersona != null) { + MixpanelManager().personaTwitterConnectionToggled(personaId: _userPersona!.id, twitterConnected: value); + } notifyListeners(); } @@ -242,6 +267,9 @@ class PersonaProvider extends ChangeNotifier { debugPrint("disconnectTwitter"); if (_isEditablePersona()) { updatePersona(); + if (_userPersona != null) { + MixpanelManager().personaTwitterConnectionToggled(personaId: _userPersona!.id, twitterConnected: false); + } } notifyListeners(); } @@ -251,6 +279,9 @@ class PersonaProvider extends ChangeNotifier { debugPrint("disconnectOmi"); if (_isEditablePersona()) { updatePersona(); + if (_userPersona != null) { + MixpanelManager().personaOmiConnectionToggled(personaId: _userPersona!.id, omiConnected: false); + } } notifyListeners(); } @@ -265,6 +296,7 @@ class PersonaProvider extends ChangeNotifier { return; } + MixpanelManager().personaUpdateStarted(personaId: _userPersona!.id); setIsLoading(true); try { Map personaData = { @@ -297,23 +329,42 @@ class PersonaProvider extends ChangeNotifier { _userPersona!.connectedAccounts.where((element) => element != 'twitter').toList(); } + List updatedFields = []; + if (personaData['name'] != _userPersona!.name) updatedFields.add('name'); + if (personaData['username'] != _userPersona!.username) updatedFields.add('username'); + if (personaData['private'] == _userPersona!.private) { + updatedFields.add('privacy'); + } + if (selectedImage != null) updatedFields.add('image'); + bool success = await updatePersonaApp(selectedImage, personaData); if (success) { AppSnackbar.showSnackbarSuccess('Persona updated successfully'); + MixpanelManager().personaUpdated( + personaId: _userPersona!.id, + isPublic: !(personaData['private'] as bool? ?? true), + updatedFields: updatedFields, + connectedAccounts: personaData['connected_accounts'] as List?, + hasOmiConnection: (personaData['connected_accounts'] as List?)?.contains('omi'), + hasTwitterConnection: (personaData['connected_accounts'] as List?)?.contains('twitter')); await getVerifiedUserPersona(); notifyListeners(); } else { AppSnackbar.showSnackbarError('Failed to update persona'); + MixpanelManager() + .personaUpdateFailed(personaId: _userPersona!.id, errorMessage: 'Failed to update persona API call'); } } catch (e) { print('Error updating persona: $e'); AppSnackbar.showSnackbarError('Failed to update persona'); + MixpanelManager().personaUpdateFailed(personaId: _userPersona!.id, errorMessage: e.toString()); } finally { setIsLoading(false); } } Future createPersona() async { + MixpanelManager().personaCreateStarted(); if (!formKey.currentState!.validate() || selectedImage == null) { if (selectedImage == null) { AppSnackbar.showSnackbarError('Please select an image'); @@ -353,14 +404,23 @@ class PersonaProvider extends ChangeNotifier { if (res.isNotEmpty) { String personaUrl = 'personas.omi.me/u/${res['username']}'; debugPrint('Persona URL: $personaUrl'); + MixpanelManager().personaCreated( + personaId: res['id'], + isPublic: !(personaData['private'] as bool? ?? true), + connectedAccounts: personaData['connected_accounts'] as List?, + hasOmiConnection: (personaData['connected_accounts'] as List?)?.contains('omi'), + hasTwitterConnection: (personaData['connected_accounts'] as List?)?.contains('twitter')); if (onShowSuccessDialog != null) { onShowSuccessDialog!(personaUrl); } } else { AppSnackbar.showSnackbarError('Failed to create your persona. Please try again later.'); + MixpanelManager().personaCreateFailed(errorMessage: 'API response empty or no ID'); } } catch (e) { AppSnackbar.showSnackbarError('Failed to create persona: $e'); + MixpanelManager().personaCreateFailed(errorMessage: e.toString()); + setIsLoading(false); } finally { setIsLoading(false); } @@ -369,6 +429,7 @@ class PersonaProvider extends ChangeNotifier { Future checkIsUsernameTaken(String username) async { setIsCheckingUsername(true); isUsernameTaken = await checkPersonaUsername(username); + MixpanelManager().personaUsernameCheck(username: username, isTaken: isUsernameTaken); setIsCheckingUsername(false); } @@ -390,13 +451,18 @@ class PersonaProvider extends ChangeNotifier { try { var enabled = await enableAppServer(_userPersona!.id); if (enabled) { + MixpanelManager().personaEnabled(personaId: _userPersona!.id); return true; } else { AppSnackbar.showSnackbarError('Failed to enable persona'); + MixpanelManager().personaEnableFailed(personaId: _userPersona!.id, errorMessage: 'API returned false'); return false; } } catch (e) { AppSnackbar.showSnackbarError('Error enabling persona: $e'); + if (_userPersona != null) { + MixpanelManager().personaEnableFailed(personaId: _userPersona!.id, errorMessage: e.toString()); + } return false; } finally { setIsLoading(false); diff --git a/app/lib/pages/settings/about.dart b/app/lib/pages/settings/about.dart index a1bc7ba4b..53b6a4d16 100644 --- a/app/lib/pages/settings/about.dart +++ b/app/lib/pages/settings/about.dart @@ -60,7 +60,7 @@ class _AboutOmiPageState extends State { ListTile( contentPadding: const EdgeInsets.fromLTRB(4, 0, 24, 0), title: const Text('Join the community!', style: TextStyle(color: Colors.white)), - subtitle: const Text('4900+ members and counting.'), + subtitle: const Text('7000+ members and counting.'), trailing: const Icon(Icons.discord, color: Colors.purple, size: 20), onTap: () { MixpanelManager().pageOpened('About Join Discord'); diff --git a/app/lib/pages/settings/page.dart b/app/lib/pages/settings/page.dart index 8d50db0b5..ba0b968af 100644 --- a/app/lib/pages/settings/page.dart +++ b/app/lib/pages/settings/page.dart @@ -8,6 +8,7 @@ import 'package:omi/pages/settings/developer.dart'; import 'package:omi/pages/settings/profile.dart'; import 'package:omi/pages/settings/widgets.dart'; import 'package:omi/utils/other/temp.dart'; +import 'package:omi/utils/platform/platform_service.dart'; import 'package:omi/widgets/dialog.dart'; import 'package:intercom_flutter/intercom_flutter.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -56,23 +57,19 @@ class _SettingsPageState extends State { bool loadingExportMemories = false; Widget _buildOmiModeContent(BuildContext context) { + // Group settings by category: Account, Device, Support, Info, Actions return Column( children: [ - const SizedBox(height: 32.0), - getItemAddOn2( - 'Need Help? Chat with us', - () async { - await Intercom.instance.displayMessenger(); - }, - icon: Icons.chat, - ), - const SizedBox(height: 20), + const SizedBox(height: 24.0), + // Account Settings getItemAddOn2( 'Profile', () => routeToPage(context, const ProfilePage()), - icon: Icons.person, + icon: const Icon(Icons.person, color: Colors.white, size: 22), ), - const SizedBox(height: 20), + const SizedBox(height: 12), + + // Device Settings getItemAddOn2( 'Device Settings', () { @@ -82,56 +79,86 @@ class _SettingsPageState extends State { ), ); }, - icon: Icons.bluetooth_connected_sharp, + icon: const Icon(Icons.bluetooth_connected_sharp, color: Colors.white, size: 22), ), - const SizedBox(height: 8), + const SizedBox(height: 12), + + // Advanced Settings getItemAddOn2( - 'Guides & Tutorials', + 'Developer Mode', () async { - await Intercom.instance.displayHelpCenter(); + await routeToPage(context, const DeveloperSettingsPage()); + setState(() {}); }, - icon: Icons.help_outline_outlined, + icon: const Icon(Icons.code, color: Colors.white, size: 22), ), - const SizedBox(height: 20), + const SizedBox(height: 12), + + // Help & Support + !PlatformService.isIntercomSupported + ? const SizedBox() + : getItemAddOn2( + 'Guides & Tutorials', + () async { + await Intercom.instance.displayHelpCenter(); + }, + icon: const Icon(Icons.help_outline_outlined, color: Colors.white, size: 22), + ), + SizedBox(height: PlatformService.isIntercomSupported ? 12 : 0), + !PlatformService.isIntercomSupported + ? const SizedBox() + : getItemAddOn2( + 'Need Help? Chat with us', + () async { + await Intercom.instance.displayMessenger(); + }, + icon: const Icon(Icons.chat, color: Colors.white, size: 22), + ), + SizedBox(height: PlatformService.isIntercomSupported ? 12 : 0), + + // Information getItemAddOn2( 'About Omi', () => routeToPage(context, const AboutOmiPage()), - icon: Icons.workspace_premium_sharp, + icon: const Icon(Icons.info_outline, color: Colors.white, size: 22), ), - const SizedBox(height: 8), - getItemAddOn2('Developer Mode', () async { - await routeToPage(context, const DeveloperSettingsPage()); - setState(() {}); - }, icon: Icons.code), - const SizedBox(height: 32), - getItemAddOn2('Sign Out', () async { - await showDialog( - context: context, - builder: (ctx) { - return getDialog(context, () { - Navigator.of(context).pop(); - }, () async { - await SharedPreferencesUtil().clearUserPreferences(); - Provider.of(context, listen: false).setRouting(PersonaProfileRouting.no_device); - await signOut(); - Navigator.of(context).pop(); - routeToPage(context, const DeciderWidget(), replace: true); - }, "Sign Out?", "Are you sure you want to sign out?"); - }, - ); - }, icon: Icons.logout), const SizedBox(height: 24), + + // Actions + getItemAddOn2( + 'Sign Out', + () async { + await showDialog( + context: context, + builder: (ctx) { + return getDialog(context, () { + Navigator.of(context).pop(); + }, () async { + await SharedPreferencesUtil().clearUserPreferences(); + Provider.of(context, listen: false).setRouting(PersonaProfileRouting.no_device); + await signOut(); + Navigator.of(context).pop(); + routeToPage(context, const DeciderWidget(), replace: true); + }, "Sign Out?", "Are you sure you want to sign out?"); + }, + ); + }, + icon: const Icon(Icons.logout, color: Colors.white, size: 22), + ), + const SizedBox(height: 20), + + // Version Info Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Align( alignment: Alignment.center, child: Text( 'Version: $version+$buildVersion', - style: const TextStyle(color: Color.fromARGB(255, 150, 150, 150), fontSize: 16), + style: const TextStyle(color: Color.fromARGB(255, 150, 150, 150), fontSize: 14), ), ), ), - const SizedBox(height: 32), + const SizedBox(height: 24), ], ); } @@ -139,15 +166,19 @@ class _SettingsPageState extends State { Widget _buildNoDeviceModeContent(BuildContext context) { return Column( children: [ - const SizedBox(height: 32.0), + const SizedBox(height: 24.0), + + // Help & Support getItemAddOn2( 'Need Help? Chat with us', () async { await Intercom.instance.displayMessenger(); }, - icon: Icons.chat, + icon: const Icon(Icons.chat, color: Colors.white, size: 22), ), - const SizedBox(height: 32), + const SizedBox(height: 24), + + // Actions getItemAddOn2('Sign Out', () async { await showDialog( context: context, @@ -164,19 +195,21 @@ class _SettingsPageState extends State { }, "Sign Out?", "Are you sure you want to sign out?"); }, ); - }, icon: Icons.logout), - const SizedBox(height: 24), + }, icon: const Icon(Icons.logout, color: Colors.white, size: 22)), + const SizedBox(height: 20), + + // Version Info Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Align( alignment: Alignment.center, child: Text( 'Version: $version+$buildVersion', - style: const TextStyle(color: Color.fromARGB(255, 150, 150, 150), fontSize: 16), + style: const TextStyle(color: Color.fromARGB(255, 150, 150, 150), fontSize: 14), ), ), ), - const SizedBox(height: 32), + const SizedBox(height: 24), ], ); } @@ -190,8 +223,14 @@ class _SettingsPageState extends State { appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.primary, automaticallyImplyLeading: true, - title: const Text('Settings'), - centerTitle: false, + title: const Text( + 'Settings', + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w600, + ), + ), + centerTitle: true, leading: IconButton( icon: const Icon(Icons.arrow_back_ios_new), onPressed: () { diff --git a/app/lib/pages/settings/profile.dart b/app/lib/pages/settings/profile.dart index 1453b891c..e54af1013 100644 --- a/app/lib/pages/settings/profile.dart +++ b/app/lib/pages/settings/profile.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:omi/backend/preferences.dart'; -import 'package:omi/pages/memories/page.dart'; import 'package:omi/pages/payments/payments_page.dart'; import 'package:omi/pages/settings/change_name_widget.dart'; import 'package:omi/pages/settings/language_selection_dialog.dart'; @@ -12,6 +11,9 @@ import 'package:omi/providers/home_provider.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/other/temp.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:omi/gen/assets.gen.dart'; +import 'package:omi/pages/persona/persona_profile.dart'; import 'delete_account.dart'; @@ -23,78 +25,152 @@ class ProfilePage extends StatefulWidget { } class _ProfilePageState extends State { - // Future _checkRecordingPermission() async { - // final permission = await getStoreRecordingPermission(); - // if (mounted) { - // setState(() { - // if (permission != null) { - // SharedPreferencesUtil().permissionStoreRecordingsEnabled = permission; - // } else { - // SharedPreferencesUtil().permissionStoreRecordingsEnabled = false; - // } - // }); - // } - // } - @override void initState() { - // _checkRecordingPermission(); super.initState(); } + Widget _buildSectionHeader(String title) { + return Padding( + padding: const EdgeInsets.only(top: 18, bottom: 8), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + title, + style: const TextStyle( + color: Color(0xFFE0E0E0), + fontSize: 14, + fontWeight: FontWeight.w600, + letterSpacing: 1.2, + ), + ), + ), + ); + } + + Widget _buildProfileTile({ + required String title, + required String subtitle, + required Widget iconWidget, + required VoidCallback onTap, + Color iconColor = Colors.white, + }) { + return Container( + margin: const EdgeInsets.only(bottom: 8), + decoration: BoxDecoration( + color: const Color(0xFF1D1D1D), + borderRadius: BorderRadius.circular(10), + ), + child: ListTile( + dense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + title: Text( + title, + style: const TextStyle( + color: Colors.white, + fontSize: 15, + fontWeight: FontWeight.w500, + ), + ), + subtitle: Text( + subtitle, + style: const TextStyle( + color: Color(0xFFAAAAAA), + fontSize: 13, + ), + ), + trailing: iconWidget, + onTap: onTap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + ); + } + + Widget _buildPreferenceToggle({ + required String title, + required bool value, + required Function(bool) onChanged, + required VoidCallback onInfoTap, + }) { + return Container( + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + color: const Color(0xFF1D1D1D), + borderRadius: BorderRadius.circular(10), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: GestureDetector( + onTap: onInfoTap, + child: Text( + title, + style: const TextStyle( + color: Color(0xFFAAAAAA), + fontSize: 14, + decoration: TextDecoration.underline, + ), + ), + ), + ), + const SizedBox(width: 16), + GestureDetector( + onTap: () => onChanged(!value), + child: Container( + decoration: BoxDecoration( + color: value ? const Color(0xFF4A90E2) : Colors.transparent, + border: Border.all( + color: value ? const Color(0xFF4A90E2) : const Color(0xFFAAAAAA), + width: 2, + ), + borderRadius: BorderRadius.circular(12), + ), + width: 20, + height: 20, + child: value + ? const Icon( + Icons.check, + color: Colors.white, + size: 16, + ) + : null, + ), + ), + ], + ), + ); + } + @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Theme.of(context).colorScheme.primary, appBar: AppBar( - title: const Text('Profile'), + title: const Text( + 'Profile', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + centerTitle: true, backgroundColor: Theme.of(context).colorScheme.primary, + elevation: 0, ), body: Padding( - padding: const EdgeInsets.fromLTRB(16, 16, 4, 16), + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), child: ListView( children: [ - ListTile( - contentPadding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - title: const Text('Identifying Others', style: TextStyle(color: Colors.white)), - subtitle: const Text('Tell Omi who said it ๐Ÿ—ฃ๏ธ'), - trailing: const Icon(Icons.people, size: 20), - onTap: () { - routeToPage(context, const UserPeoplePage()); - }, - ), - ListTile( - contentPadding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - title: Text( - SharedPreferencesUtil().givenName.isEmpty - ? 'About YOU' - : 'About ${SharedPreferencesUtil().givenName.toUpperCase()}', - style: const TextStyle(color: Colors.white)), - subtitle: const Text('What Omi has learned about you ๐Ÿ‘€'), - trailing: const Icon(Icons.self_improvement, size: 20), - onTap: () { - routeToPage(context, const MemoriesPage()); - MixpanelManager().pageOpened('Profile Facts'); - }, - ), - ListTile( - contentPadding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - title: const Text('Speech Profile', style: TextStyle(color: Colors.white)), - subtitle: const Text('Teach Omi your voice'), - trailing: const Icon(Icons.multitrack_audio, size: 20), - onTap: () { - routeToPage(context, const SpeechProfilePage()); - MixpanelManager().pageOpened('Profile Speech Profile'); - }, - ), - ListTile( - contentPadding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - title: Text( - SharedPreferencesUtil().givenName.isEmpty ? 'Set Your Name' : 'Change Your Name', - style: const TextStyle(color: Colors.white), - ), - subtitle: Text(SharedPreferencesUtil().givenName.isEmpty ? 'Not set' : SharedPreferencesUtil().givenName), - trailing: const Icon(Icons.person, size: 20), + // YOUR INFORMATION SECTION + _buildSectionHeader('YOUR INFORMATION'), + _buildProfileTile( + title: SharedPreferencesUtil().givenName.isEmpty ? 'Set Your Name' : 'Change Your Name', + subtitle: SharedPreferencesUtil().givenName.isEmpty ? 'Not set' : SharedPreferencesUtil().givenName, + iconWidget: const Icon(Icons.person, size: 20, color: Colors.white), onTap: () async { MixpanelManager().pageOpened('Profile Change Name'); await showDialog( @@ -114,202 +190,111 @@ class _ProfilePageState extends State { ) .key : 'Not set'; - - return ListTile( - contentPadding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - title: const Text('Primary Language', style: TextStyle(color: Colors.white)), - subtitle: Text(languageName), - trailing: const Icon(Icons.language, size: 20), + + return _buildProfileTile( + title: 'Primary Language', + subtitle: languageName, + iconWidget: const Icon(Icons.language, size: 20, color: Colors.white), onTap: () async { MixpanelManager().pageOpened('Profile Change Language'); - // Force the dialog to show even if the user has already set a language await LanguageSelectionDialog.show(context, isRequired: false, forceShow: true); - // Refresh the UI after language is updated await homeProvider.setupUserPrimaryLanguage(); setState(() {}); }, ); }, ), - const SizedBox(height: 56), - const Align( - alignment: Alignment.centerLeft, - child: Text( - 'CREATORS', - style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500), - textAlign: TextAlign.start, + _buildProfileTile( + title: 'Persona', + subtitle: 'Manage your Omi persona', + iconWidget: SvgPicture.asset( + Assets.images.icPersonaProfile.path, + width: 20, + height: 20, + colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn), ), + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => const PersonaProfilePage(), + settings: const RouteSettings( + arguments: 'from_settings', + ), + ), + ); + MixpanelManager().pageOpened('Profile Persona Settings'); + }, ), - ListTile( - contentPadding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - title: const Text('Payments', style: TextStyle(color: Colors.white)), - subtitle: const Text('Add or change your payment method'), - trailing: const Icon(Icons.attach_money_outlined, size: 20), + + // VOICE & PEOPLE SECTION + _buildSectionHeader('VOICE & PEOPLE'), + _buildProfileTile( + title: 'Speech Profile', + subtitle: 'Teach Omi your voice', + iconWidget: const Icon(Icons.multitrack_audio, size: 20, color: Colors.white), onTap: () { - routeToPage(context, const PaymentsPage()); - // MixpanelManager().pageOpened('Profile Connect Stripe'); + routeToPage(context, const SpeechProfilePage()); + MixpanelManager().pageOpened('Profile Speech Profile'); }, ), - const SizedBox(height: 56), - const Align( - alignment: Alignment.centerLeft, - child: Text( - 'PREFERENCES', - style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500), - textAlign: TextAlign.start, - ), + _buildProfileTile( + title: 'Identifying Others', + subtitle: 'Tell Omi who said it ๐Ÿ—ฃ๏ธ', + iconWidget: const Icon(Icons.people, size: 20, color: Colors.white), + onTap: () { + routeToPage(context, const UserPeoplePage()); + }, ), - Padding( - padding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - child: InkWell( - onTap: () { - setState(() { - SharedPreferencesUtil().optInAnalytics = !SharedPreferencesUtil().optInAnalytics; - SharedPreferencesUtil().optInAnalytics - ? MixpanelManager().optInTracking() - : MixpanelManager().optOutTracking(); - }); - }, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 12.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: GestureDetector( - onTap: () { - routeToPage(context, const PrivacyInfoPage()); - MixpanelManager().pageOpened('Share Analytics Data Details'); - }, - child: const Text( - 'Help improve Omi by sharing anonymized analytics data', - style: TextStyle( - color: Colors.grey, - fontSize: 16, - decoration: TextDecoration.underline, - ), - ), - ), - ), - const SizedBox( - width: 16, - ), - Container( - decoration: BoxDecoration( - color: SharedPreferencesUtil().optInAnalytics - ? const Color.fromARGB(255, 150, 150, 150) - : Colors.transparent, // Fill color when checked - border: Border.all( - color: const Color.fromARGB(255, 150, 150, 150), - width: 2, - ), - borderRadius: BorderRadius.circular(12), - ), - width: 22, - height: 22, - child: SharedPreferencesUtil().optInAnalytics // Show the icon only when checked - ? const Icon( - Icons.check, - color: Colors.white, // Tick color - size: 18, - ) - : null, // No icon when unchecked - ), - ], - ), - ), - ), + + // PAYMENT SECTION + _buildSectionHeader('PAYMENT'), + _buildProfileTile( + title: 'Payment Methods', + subtitle: 'Add or change your payment method', + iconWidget: const Icon(Icons.attach_money_outlined, size: 20, color: Colors.white), + onTap: () { + routeToPage(context, const PaymentsPage()); + }, ), - // Padding( - // padding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - // child: InkWell( - // onTap: () { - // routeToPage(context, const RecordingsStoragePermission()); - // }, - // child: Padding( - // padding: const EdgeInsets.symmetric(vertical: 12.0), - // child: Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Expanded( - // child: GestureDetector( - // onTap: () { - // routeToPage(context, const RecordingsStoragePermission()); - // }, - // child: const Text( - // 'Allow Omi to store recordings of your conversations', - // style: TextStyle( - // color: Colors.grey, - // fontSize: 16, - // decoration: TextDecoration.underline, - // ), - // ), - // ), - // ), - // const SizedBox( - // width: 16, - // ), - // Container( - // decoration: BoxDecoration( - // color: SharedPreferencesUtil().permissionStoreRecordingsEnabled - // ? const Color.fromARGB(255, 150, 150, 150) - // : Colors.transparent, - // border: Border.all( - // color: const Color.fromARGB(255, 150, 150, 150), - // width: 2, - // ), - // borderRadius: BorderRadius.circular(12), - // ), - // width: 22, - // height: 22, - // child: SharedPreferencesUtil().permissionStoreRecordingsEnabled - // ? const Icon( - // Icons.check, - // color: Colors.white, - // size: 18, - // ) - // : null, - // ), - // ], - // ), - // ), - // ), - // ), - const SizedBox(height: 32), - // Divider(color: Colors.grey.shade300, height: 1), - const SizedBox(height: 24), - const Align( - alignment: Alignment.centerLeft, - child: Text( - 'OTHER', - style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500), - textAlign: TextAlign.start, - ), + + // PREFERENCES SECTION + _buildSectionHeader('PREFERENCES'), + _buildPreferenceToggle( + title: 'Help improve Omi by sharing anonymized analytics data', + value: SharedPreferencesUtil().optInAnalytics, + onChanged: (value) { + setState(() { + SharedPreferencesUtil().optInAnalytics = value; + value ? MixpanelManager().optInTracking() : MixpanelManager().optOutTracking(); + }); + }, + onInfoTap: () { + routeToPage(context, const PrivacyInfoPage()); + MixpanelManager().pageOpened('Share Analytics Data Details'); + }, ), - ListTile( - contentPadding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - title: const Text('Your User ID', style: TextStyle(color: Colors.white)), - subtitle: Text(SharedPreferencesUtil().uid), - trailing: const Icon(Icons.copy_rounded, size: 20, color: Colors.white), + + // ACCOUNT SECTION + _buildSectionHeader('ACCOUNT'), + _buildProfileTile( + title: 'User ID', + subtitle: SharedPreferencesUtil().uid, + iconWidget: const Icon(Icons.copy_rounded, size: 20, color: Colors.white), onTap: () { Clipboard.setData(ClipboardData(text: SharedPreferencesUtil().uid)); ScaffoldMessenger.of(context) .showSnackBar(const SnackBar(content: Text('User ID copied to clipboard'))); }, ), - ListTile( - contentPadding: const EdgeInsets.fromLTRB(0, 0, 24, 0), - title: const Text('Delete Account', style: TextStyle(color: Colors.white)), - subtitle: const Text('Delete your account and all data'), - trailing: const Icon( - Icons.warning, - size: 20, - ), + _buildProfileTile( + title: 'Delete Account', + subtitle: 'Delete your account and all data', + iconWidget: Icon(Icons.warning, size: 20, color: Colors.red.shade300), onTap: () { MixpanelManager().pageOpened('Profile Delete Account Dialog'); Navigator.push(context, MaterialPageRoute(builder: (context) => const DeleteAccount())); }, - ) + ), ], ), ), diff --git a/app/lib/pages/settings/widgets.dart b/app/lib/pages/settings/widgets.dart index 7be140a05..447fb7e52 100644 --- a/app/lib/pages/settings/widgets.dart +++ b/app/lib/pages/settings/widgets.dart @@ -47,37 +47,49 @@ getItemAddOn(String title, VoidCallback onTap, {required IconData icon, bool vis ); } -getItemAddOn2(String title, VoidCallback onTap, {required IconData icon}) { +getItemAddOn2(String title, VoidCallback onTap, {required Widget icon}) { return GestureDetector( onTap: () { MixpanelManager().pageOpened('Settings $title'); onTap(); }, - child: Padding( - padding: const EdgeInsets.fromLTRB(0, 0, 0, 0), - child: Container( - decoration: BoxDecoration( - color: const Color.fromARGB(255, 29, 29, 29), - borderRadius: BorderRadius.circular(10.0), - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( + child: Container( + decoration: BoxDecoration( + color: const Color.fromARGB(255, 29, 29, 29), + borderRadius: BorderRadius.circular(10.0), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( children: [ - Text( - title, - style: const TextStyle(color: Color.fromARGB(255, 150, 150, 150), fontSize: 16), - ), + icon, const SizedBox(width: 16), - Icon(icon, color: Colors.white, size: 18), + Expanded( + child: Text( + title, + style: const TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), ], ), - const Icon(Icons.arrow_forward_ios, color: Colors.white, size: 16), - ], - ), + ), + const Icon(Icons.arrow_forward_ios, color: Colors.white, size: 16), + ], ), ), ), diff --git a/app/lib/providers/app_provider.dart b/app/lib/providers/app_provider.dart index 523b41b3a..8b93fdd9e 100644 --- a/app/lib/providers/app_provider.dart +++ b/app/lib/providers/app_provider.dart @@ -55,7 +55,10 @@ class AppProvider extends BaseProvider { Future getAppDetails(String id) async { var app = await getAppDetailsServer(id); if (app != null) { - var oldApp = apps.where((element) => element.id == id).first; + var oldApp = apps.where((element) => element.id == id).firstOrNull; + if (oldApp == null) { + return null; + } var idx = apps.indexOf(oldApp); apps[idx] = App.fromJson(app); notifyListeners(); diff --git a/app/lib/providers/auth_provider.dart b/app/lib/providers/auth_provider.dart index e48e0bb3e..e6c210811 100644 --- a/app/lib/providers/auth_provider.dart +++ b/app/lib/providers/auth_provider.dart @@ -6,7 +6,7 @@ import 'package:omi/providers/base_provider.dart'; import 'package:omi/services/notifications.dart'; import 'package:omi/utils/alerts/app_snackbar.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:omi/backend/http/api/apps.dart' as apps_api; @@ -88,8 +88,7 @@ class AuthenticationProvider extends BaseProvider { return token; } catch (e, stackTrace) { AppSnackbar.showSnackbarError('Failed to retrieve firebase token, please try again.'); - - CrashReporting.reportHandledCrash(e, stackTrace, level: NonFatalExceptionLevel.error); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return null; } @@ -105,7 +104,7 @@ class AuthenticationProvider extends BaseProvider { } catch (e, stackTrace) { AppSnackbar.showSnackbarError('Unexpected error signing in, Firebase error, please try again.'); - CrashReporting.reportHandledCrash(e, stackTrace, level: NonFatalExceptionLevel.error); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); return; } String newUid = user.uid; @@ -118,7 +117,7 @@ class AuthenticationProvider extends BaseProvider { } void openTermsOfService() { - _launchUrl('https://basedhardware.com/terms'); + _launchUrl('https://www.omi.me/pages/terms-of-service'); } void openPrivacyPolicy() { diff --git a/app/lib/providers/capture_provider.dart b/app/lib/providers/capture_provider.dart index cdd318148..bcfc40924 100644 --- a/app/lib/providers/capture_provider.dart +++ b/app/lib/providers/capture_provider.dart @@ -1,8 +1,11 @@ import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; +import 'dart:ui'; +import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_foreground_task/flutter_foreground_task.dart'; import 'package:flutter_provider_utilities/flutter_provider_utilities.dart'; import 'package:omi/backend/http/api/conversations.dart'; @@ -22,6 +25,7 @@ import 'package:omi/services/sockets/pure_socket.dart'; import 'package:omi/services/sockets/sdcard_socket.dart'; import 'package:omi/services/sockets/transcription_connection.dart'; import 'package:omi/services/wals.dart'; +import 'package:omi/utils/alerts/app_snackbar.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/enums.dart'; import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart'; @@ -37,10 +41,8 @@ class CaptureProvider extends ChangeNotifier SdCardSocketService sdCardSocket = SdCardSocketService(); Timer? _keepAliveTimer; - // In progress memory - ServerConversation? _inProgressConversation; - - ServerConversation? get inProgressConversation => _inProgressConversation; + // Method channel for system audio permissions + static const MethodChannel _screenCaptureChannel = MethodChannel('screenCapturePlatform'); IWalService get _wal => ServiceManager.instance().wal; @@ -93,14 +95,13 @@ class CaptureProvider extends ChangeNotifier bool get transcriptServiceReady => _transcriptServiceReady && _internetStatus == InternetStatus.connected; // having a connected device or using the phone's mic for recording - bool get recordingDeviceServiceReady => _recordingDevice != null || recordingState == RecordingState.record; + bool get recordingDeviceServiceReady => + _recordingDevice != null || + recordingState == RecordingState.record || + recordingState == RecordingState.systemAudioRecord; bool get havingRecordingDevice => _recordingDevice != null; - // ----------------------- - // Conversation creation variables - String conversationId = const Uuid().v4(); - void setHasTranscripts(bool value) { hasTranscripts = value; notifyListeners(); @@ -124,7 +125,6 @@ class CaptureProvider extends ChangeNotifier Future _resetStateVariables() async { segments = []; - conversationId = const Uuid().v4(); hasTranscripts = false; notifyListeners(); } @@ -136,30 +136,37 @@ class CaptureProvider extends ChangeNotifier Future changeAudioRecordProfile({ required BleAudioCodec audioCodec, int? sampleRate, + int? channels, + bool? isPcm, }) async { - debugPrint("changeAudioRecordProfile"); + print("changeAudioRecordProfile"); await _resetState(); - await _initiateWebsocket(audioCodec: audioCodec, sampleRate: sampleRate); + await _initiateWebsocket(audioCodec: audioCodec, sampleRate: sampleRate, channels: channels, isPcm: isPcm); } Future _initiateWebsocket({ required BleAudioCodec audioCodec, int? sampleRate, + int? channels, + bool? isPcm, bool force = false, }) async { - debugPrint('initiateWebsocket in capture_provider'); + print('initiateWebsocket in capture_provider'); BleAudioCodec codec = audioCodec; - sampleRate ??= (codec.isOpusSupported() ? 16000 : 8000); + sampleRate ??= mapCodecToSampleRate(codec); + channels ??= (codec == BleAudioCodec.pcm16 || codec == BleAudioCodec.pcm8) ? 1 : 2; debugPrint('is ws null: ${_socket == null}'); + print('Initiating WebSocket with: codec=$codec, sampleRate=$sampleRate, channels=$channels, isPcm=$isPcm'); // Connect to the transcript socket String language = SharedPreferencesUtil().hasSetPrimaryLanguage ? SharedPreferencesUtil().userPrimaryLanguage : "multi"; + _socket = await ServiceManager.instance() .socket - .conversation(codec: codec, sampleRate: sampleRate, language: language, force: force); + .conversation(codec: codec, sampleRate: sampleRate!, language: language, force: force); if (_socket == null) { _startKeepAliveServices(); debugPrint("Can not create new conversation socket"); @@ -180,13 +187,15 @@ class CaptureProvider extends ChangeNotifier } BleAudioCodec codec = await _getAudioCodec(_recordingDevice!.id); - await messageProvider?.sendVoiceMessageStreamToServer( - data, - onFirstChunkRecived: () { - _playSpeakerHaptic(deviceId, 2); - }, - codec: codec, - ); + if (messageProvider != null) { + await messageProvider?.sendVoiceMessageStreamToServer( + data, + onFirstChunkRecived: () { + _playSpeakerHaptic(deviceId, 2); + }, + codec: codec, + ); + } } // Just incase the ble connection get loss @@ -423,6 +432,7 @@ class CaptureProvider extends ChangeNotifier stopStreamRecording() async { await _cleanupCurrentState(); ServiceManager.instance().mic.stop(); + updateRecordingState(RecordingState.stop); await _socket?.stop(reason: 'stop stream recording'); } @@ -438,10 +448,85 @@ class CaptureProvider extends ChangeNotifier _updateRecordingDevice(null); } await _cleanupCurrentState(); + updateRecordingState(RecordingState.stop); await _socket?.stop(reason: 'stop stream device recording'); } - // Socket handling + Future streamSystemAudioRecording() async { + if (!Platform.isMacOS) { + notifyError('System audio recording is only available on macOS.'); + return; + } + + updateRecordingState(RecordingState.initialising); + + try { + // Check microphone permission first + String micStatus = await _screenCaptureChannel.invokeMethod('checkMicrophonePermission'); + if (micStatus != 'granted') { + debugPrint('Microphone permission not granted: $micStatus'); + if (micStatus == 'undetermined') { + bool micGranted = await _screenCaptureChannel.invokeMethod('requestMicrophonePermission'); + if (!micGranted) { + AppSnackbar.showSnackbarError('Microphone permission is required for system audio recording.'); + updateRecordingState(RecordingState.stop); + return; + } + } else if (micStatus == 'denied') { + AppSnackbar.showSnackbarError('Microphone permission denied. Please grant permission in System Preferences.'); + updateRecordingState(RecordingState.stop); + return; + } + } + + // Check screen capture permission + String screenStatus = await _screenCaptureChannel.invokeMethod('checkScreenCapturePermission'); + if (screenStatus != 'granted') { + debugPrint('Screen capture permission not granted: $screenStatus'); + if (screenStatus == 'undetermined' || screenStatus == 'denied') { + bool screenGranted = await _screenCaptureChannel.invokeMethod('requestScreenCapturePermission'); + if (!screenGranted) { + AppSnackbar.showSnackbarError('Screen capture permission is required for system audio recording.'); + updateRecordingState(RecordingState.stop); + return; + } + } + } + + await changeAudioRecordProfile(audioCodec: BleAudioCodec.pcm16, sampleRate: 16000); + + await ServiceManager.instance().systemAudio.start(onFormatReceived: (Map format) async { + final int sampleRate = format['sampleRate'] as int? ?? 16000; + final int channels = format['channels'] as int? ?? 1; + BleAudioCodec determinedCodec = BleAudioCodec.pcm16; + }, onByteReceived: (bytes) { + if (_socket?.state == SocketServiceState.connected) { + _socket?.send(bytes); + } + }, onRecording: () { + updateRecordingState(RecordingState.systemAudioRecord); + }, onStop: () { + updateRecordingState(RecordingState.stop); + _socket?.stop(reason: 'system audio stream ended from native'); + }, onError: (error) { + notifyError('System Audio Error: $error'); + updateRecordingState(RecordingState.stop); + _socket?.stop(reason: 'system audio stream error: $error'); + }); + } catch (e) { + debugPrint('Error checking/requesting permissions: $e'); + notifyError('Failed to check permissions: $e'); + updateRecordingState(RecordingState.stop); + } + } + + Future stopSystemAudioRecording() async { + if (!Platform.isMacOS) return; + ServiceManager.instance().systemAudio.stop(); + updateRecordingState(RecordingState.stop); + await _socket?.stop(reason: 'stop system audio recording from Flutter'); + await _cleanupCurrentState(); + } @override void onClosed() { @@ -449,11 +534,6 @@ class CaptureProvider extends ChangeNotifier _transcriptServiceReady = false; debugPrint('[Provider] Socket is closed'); - // Wait for in process Conversation or reset - if (inProgressConversation == null) { - _resetStateVariables(); - } - notifyListeners(); _startKeepAliveServices(); } @@ -475,6 +555,9 @@ class CaptureProvider extends ChangeNotifier await _initiateWebsocket(audioCodec: BleAudioCodec.pcm16, sampleRate: 16000); return; } + if (recordingState == RecordingState.systemAudioRecord && Platform.isMacOS) { + debugPrint("[Provider] System audio was recording, but socket disconnected. Consider manual restart."); + } }); } @@ -493,13 +576,19 @@ class CaptureProvider extends ChangeNotifier notifyListeners(); } - void _loadInProgressConversation() async { - var memories = await getConversations(statuses: [ConversationStatus.in_progress], limit: 1); - _inProgressConversation = memories.isNotEmpty ? memories.first : null; - if (_inProgressConversation != null) { - segments = _inProgressConversation!.transcriptSegments; - setHasTranscripts(segments.isNotEmpty); + Future refreshInProgressConversations() async { + _loadInProgressConversation(); + } + + Future _loadInProgressConversation() async { + var convos = await getConversations(statuses: [ConversationStatus.in_progress], limit: 1); + var convo = convos.isNotEmpty ? convos.first : null; + if (convo != null) { + segments = convo.transcriptSegments; + } else { + segments = []; } + setHasTranscripts(segments.isNotEmpty); notifyListeners(); } @@ -616,12 +705,16 @@ class CaptureProvider extends ChangeNotifier @override void onSegmentReceived(List newSegments) { + _processNewSegmentReceived(newSegments); + } + + void _processNewSegmentReceived(List newSegments) async { if (newSegments.isEmpty) return; if (segments.isEmpty) { debugPrint('newSegments: ${newSegments.last}'); FlutterForegroundTask.sendDataToTask(jsonEncode({'location': true})); - _loadInProgressConversation(); + await _loadInProgressConversation(); } var remainSegments = TranscriptSegment.updateSegments(segments, newSegments); TranscriptSegment.combineSegments(segments, remainSegments); diff --git a/app/lib/providers/conversation_provider.dart b/app/lib/providers/conversation_provider.dart index e4133de95..f9701eaff 100644 --- a/app/lib/providers/conversation_provider.dart +++ b/app/lib/providers/conversation_provider.dart @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:omi/backend/http/api/conversations.dart'; import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/conversation.dart'; +import 'package:omi/backend/schema/structured.dart'; import 'package:omi/services/services.dart'; import 'package:omi/services/wals.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; @@ -161,14 +162,35 @@ class ConversationProvider extends ChangeNotifier implements IWalServiceListener notifyListeners(); } - Future fetchNewConversations() async { - List newConversations = await getConversationsFromServer(); - List upsertConvos = - newConversations.where((c) => conversations.indexWhere((cc) => cc.id == c.id) == -1).toList(); - if (upsertConvos.isEmpty) { - return; + Future refreshConversations() async { + _fetchNewConversations(); + } + + Future _fetchNewConversations() async { + setLoadingConversations(true); + List newConversations = await _getConversationsFromServer(); + setLoadingConversations(false); + + List upsertConvos = []; + + // processing convos + upsertConvos = newConversations + .where((c) => + c.status == ConversationStatus.processing && + processingConversations.indexWhere((cc) => cc.id == c.id) == -1) + .toList(); + if (upsertConvos.isNotEmpty) { + processingConversations.insertAll(0, upsertConvos); } - conversations.insertAll(0, upsertConvos); + + // completed convos + upsertConvos = newConversations + .where((c) => c.status == ConversationStatus.completed && conversations.indexWhere((cc) => cc.id == c.id) == -1) + .toList(); + if (upsertConvos.isNotEmpty) { + conversations.insertAll(0, upsertConvos); + } + _groupConversationsByDateWithoutNotify(); notifyListeners(); } @@ -179,10 +201,14 @@ class ConversationProvider extends ChangeNotifier implements IWalServiceListener totalSearchPages = 0; searchedConversations = []; - conversations = await getConversationsFromServer(); + setLoadingConversations(true); + conversations = await _getConversationsFromServer(); + setLoadingConversations(false); + // processing convos processingConversations = conversations.where((m) => m.status == ConversationStatus.processing).toList(); + // completed convos conversations = conversations.where((m) => m.status == ConversationStatus.completed).toList(); if (conversations.isEmpty) { conversations = SharedPreferencesUtil().cachedConversations; @@ -252,14 +278,8 @@ class ConversationProvider extends ChangeNotifier implements IWalServiceListener notifyListeners(); } - Future getConversationsFromServer() async { - setLoadingConversations(true); - var mem = await getConversations(includeDiscarded: showDiscardedConversations); - conversations = mem; - conversations.sort((a, b) => b.createdAt.compareTo(a.createdAt)); - setLoadingConversations(false); - notifyListeners(); - return conversations; + Future _getConversationsFromServer() async { + return await getConversations(includeDiscarded: showDiscardedConversations); } void updateActionItemState(String convoId, bool state, int i, DateTime date) { @@ -614,4 +634,94 @@ class ConversationProvider extends ChangeNotifier implements IWalServiceListener isFetchingConversations = value; notifyListeners(); } + + // New Getter for Action Items Page + Map> get conversationsWithActiveActionItems { + final Map> result = {}; + final List sourceList = conversations; + + for (final convo in sourceList) { + if (convo.discarded && !showDiscardedConversations) continue; + + final activeItems = convo.structured.actionItems.where((item) => !item.deleted).toList(); + if (activeItems.isNotEmpty) { + result[convo] = activeItems; + } + } + return result; + } + + Future updateGlobalActionItemState( + ServerConversation conversation, int itemIndexInConversation, bool newState) async { + final convoId = conversation.id; + bool conversationFoundAndUpdated = false; + + final originalConvoIndex = conversations.indexWhere((c) => c.id == convoId); + if (originalConvoIndex != -1) { + if (conversations[originalConvoIndex].structured.actionItems.length > itemIndexInConversation) { + conversations[originalConvoIndex].structured.actionItems[itemIndexInConversation].completed = newState; + conversationFoundAndUpdated = true; + } + } + + var dateKey = DateTime(conversation.createdAt.year, conversation.createdAt.month, conversation.createdAt.day); + if (groupedConversations.containsKey(dateKey)) { + final groupIndex = groupedConversations[dateKey]!.indexWhere((c) => c.id == convoId); + if (groupIndex != -1) { + if (groupedConversations[dateKey]![groupIndex].structured.actionItems.length > itemIndexInConversation) { + groupedConversations[dateKey]![groupIndex].structured.actionItems[itemIndexInConversation].completed = + newState; + } + } + } + + if (conversationFoundAndUpdated) { + await setConversationActionItemState(convoId, [itemIndexInConversation], [newState]); + notifyListeners(); + } else { + debugPrint("Error: Conversation or action item not found for updateGlobalActionItemState."); + } + } + + void updateActionItemDescriptionInConversation(String conversationId, int itemIndex, String newDescription) { + final convoIndex = conversations.indexWhere((c) => c.id == conversationId); + if (convoIndex != -1) { + if (conversations[convoIndex].structured.actionItems.length > itemIndex) { + conversations[convoIndex].structured.actionItems[itemIndex].description = newDescription; + } + } + + groupedConversations.forEach((date, convoList) { + final groupIndex = convoList.indexWhere((c) => c.id == conversationId); + if (groupIndex != -1) { + if (convoList[groupIndex].structured.actionItems.length > itemIndex) { + convoList[groupIndex].structured.actionItems[itemIndex].description = newDescription; + } + } + }); + + notifyListeners(); + } + + Future deleteActionItemAndUpdateLocally(String conversationId, int itemIndex, ActionItem actionItem) async { + deleteConversationActionItem(conversationId, actionItem); + + final convoIndex = conversations.indexWhere((c) => c.id == conversationId); + if (convoIndex != -1) { + if (conversations[convoIndex].structured.actionItems.length > itemIndex) { + conversations[convoIndex].structured.actionItems.removeAt(itemIndex); + } + } + + groupedConversations.forEach((date, convoList) { + final groupConvoIndex = convoList.indexWhere((c) => c.id == conversationId); + if (groupConvoIndex != -1) { + if (convoList[groupConvoIndex].structured.actionItems.length > itemIndex) { + convoList[groupConvoIndex].structured.actionItems.removeAt(itemIndex); + } + } + }); + + notifyListeners(); + } } diff --git a/app/lib/providers/device_provider.dart b/app/lib/providers/device_provider.dart index b43836895..0afda4967 100644 --- a/app/lib/providers/device_provider.dart +++ b/app/lib/providers/device_provider.dart @@ -13,7 +13,7 @@ import 'package:omi/services/services.dart'; import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:omi/utils/device.dart'; import 'package:omi/widgets/confirmation_dialog.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; class DeviceProvider extends ChangeNotifier implements IDeviceServiceSubsciption { CaptureProvider? captureProvider; @@ -249,7 +249,7 @@ class DeviceProvider extends ChangeNotifier implements IDeviceServiceSubsciption // Wals ServiceManager.instance().wal.getSyncs().sdcard.setDevice(null); - InstabugLog.logInfo('Omi Device Disconnected'); + PlatformManager.instance.instabug.logInfo('Omi Device Disconnected'); _disconnectNotificationTimer?.cancel(); _disconnectNotificationTimer = Timer(const Duration(seconds: 30), () { NotificationService.instance.createNotification( diff --git a/app/lib/providers/home_provider.dart b/app/lib/providers/home_provider.dart index 3051013e7..83c4d7427 100644 --- a/app/lib/providers/home_provider.dart +++ b/app/lib/providers/home_provider.dart @@ -12,9 +12,11 @@ class HomeProvider extends ChangeNotifier { final FocusNode chatFieldFocusNode = FocusNode(); final FocusNode appsSearchFieldFocusNode = FocusNode(); final FocusNode convoSearchFieldFocusNode = FocusNode(); + final FocusNode memoriesSearchFieldFocusNode = FocusNode(); bool isAppsSearchFieldFocused = false; bool isChatFieldFocused = false; bool isConvoSearchFieldFocused = false; + bool isMemoriesSearchFieldFocused = false; bool hasSpeakerProfile = true; bool isLoading = false; String userPrimaryLanguage = SharedPreferencesUtil().userPrimaryLanguage; @@ -67,12 +69,14 @@ class HomeProvider extends ChangeNotifier { chatFieldFocusNode.addListener(_onFocusChange); appsSearchFieldFocusNode.addListener(_onFocusChange); convoSearchFieldFocusNode.addListener(_onFocusChange); + memoriesSearchFieldFocusNode.addListener(_onFocusChange); } void _onFocusChange() { isChatFieldFocused = chatFieldFocusNode.hasFocus; isAppsSearchFieldFocused = appsSearchFieldFocusNode.hasFocus; isConvoSearchFieldFocused = convoSearchFieldFocusNode.hasFocus; + isMemoriesSearchFieldFocused = memoriesSearchFieldFocusNode.hasFocus; notifyListeners(); } @@ -177,6 +181,8 @@ class HomeProvider extends ChangeNotifier { chatFieldFocusNode.removeListener(_onFocusChange); appsSearchFieldFocusNode.removeListener(_onFocusChange); convoSearchFieldFocusNode.removeListener(_onFocusChange); + memoriesSearchFieldFocusNode.removeListener(_onFocusChange); + memoriesSearchFieldFocusNode.dispose(); chatFieldFocusNode.dispose(); appsSearchFieldFocusNode.dispose(); convoSearchFieldFocusNode.dispose(); diff --git a/app/lib/providers/memories_provider.dart b/app/lib/providers/memories_provider.dart index b8cbcab47..4099eea37 100644 --- a/app/lib/providers/memories_provider.dart +++ b/app/lib/providers/memories_provider.dart @@ -3,40 +3,71 @@ import 'package:omi/backend/http/api/memories.dart'; import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/memory.dart'; import 'package:omi/providers/base_provider.dart'; +import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:tuple/tuple.dart'; import 'package:uuid/uuid.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; -class MemoriesProvider extends BaseProvider { - List memories = []; - List filteredMemories = []; +class MemoriesProvider extends ChangeNotifier { + List _memories = []; + List _unreviewed = []; + bool _loading = true; + String _searchQuery = ''; + MemoryCategory? _categoryFilter; + bool _excludeInteresting = false; List> categories = []; MemoryCategory? selectedCategory; - String searchQuery = ''; - List get unreviewed => memories - .where((f) => !f.reviewed && f.createdAt.isAfter(DateTime.now().subtract(const Duration(days: 1)))) - .toList(); + List get memories => _memories; + List get unreviewed => _unreviewed; + bool get loading => _loading; + String get searchQuery => _searchQuery; + MemoryCategory? get categoryFilter => _categoryFilter; + bool get excludeInteresting => _excludeInteresting; + + List get filteredMemories { + return _memories.where((memory) { + // Apply search filter + final matchesSearch = _searchQuery.isEmpty || memory.content.decodeString.toLowerCase().contains(_searchQuery.toLowerCase()); + + // Apply category filter or exclusion logic + bool categoryMatch; + if (_excludeInteresting) { + // Show all categories except interesting + categoryMatch = memory.category != MemoryCategory.interesting; + } else if (_categoryFilter != null) { + // Show only selected category + categoryMatch = memory.category == _categoryFilter; + } else { + // Show all categories if no filter is applied + categoryMatch = true; + } + + return matchesSearch && categoryMatch; + }).toList() + ..sort((a, b) => b.createdAt.compareTo(a.createdAt)); + } + + void setExcludeInteresting(bool exclude) { + _excludeInteresting = exclude; + notifyListeners(); + } void setCategory(MemoryCategory? category) { selectedCategory = category; - _filterMemories(); notifyListeners(); } void setSearchQuery(String query) { - searchQuery = query.toLowerCase(); - _filterMemories(); + _searchQuery = query.toLowerCase(); notifyListeners(); } - void _filterMemories() { - if (searchQuery.isNotEmpty) { - filteredMemories = - memories.where((memory) => memory.content.decodeString.toLowerCase().contains(searchQuery)).toList(); - } else { - filteredMemories = memories; - } - filteredMemories.sort((a, b) => b.createdAt.compareTo(a.createdAt)); + void setCategoryFilter(MemoryCategory? category) { + _categoryFilter = category; + _excludeInteresting = false; // Reset exclude filter when setting a category filter + notifyListeners(); } void _setCategories() { @@ -44,7 +75,6 @@ class MemoriesProvider extends BaseProvider { final count = memories.where((memory) => memory.category == category).length; return Tuple2(category, count); }).toList(); - _filterMemories(); notifyListeners(); } @@ -52,85 +82,146 @@ class MemoriesProvider extends BaseProvider { await loadMemories(); } - Future loadMemories() async { - loading = true; + Future loadMemories() async { + _loading = true; notifyListeners(); - memories = await getMemories(); - loading = false; + + _memories = await getMemories(); + _unreviewed = _memories.where((memory) => !memory.reviewed && memory.createdAt.isAfter(DateTime.now().subtract(const Duration(days: 1)))).toList(); + + _loading = false; _setCategories(); } void deleteMemory(Memory memory) async { - deleteMemoryServer(memory.id); - memories.remove(memory); + await deleteMemoryServer(memory.id); + _memories.remove(memory); + _unreviewed.remove(memory); _setCategories(); - notifyListeners(); } void deleteAllMemories() async { - deleteAllMemoriesServer(); - memories.clear(); - filteredMemories.clear(); + final int countBeforeDeletion = _memories.length; + await deleteAllMemoriesServer(); + _memories.clear(); + _unreviewed.clear(); + if (countBeforeDeletion > 0) { + MixpanelManager().memoriesAllDeleted(countBeforeDeletion); + } _setCategories(); - notifyListeners(); } - void createMemory(String content, [MemoryVisibility visibility = MemoryVisibility.public]) async { - createMemoryServer(content, visibility.name); - memories.add(Memory( + void createMemory(String content, [MemoryVisibility visibility = MemoryVisibility.public, MemoryCategory category = MemoryCategory.interesting]) async { + final newMemory = Memory( id: const Uuid().v4(), uid: SharedPreferencesUtil().uid, content: content, - category: MemoryCategory.other, + category: category, createdAt: DateTime.now(), updatedAt: DateTime.now(), - manuallyAdded: true, - edited: false, - reviewed: false, - userReview: null, conversationId: null, - deleted: false, + reviewed: false, + manuallyAdded: true, visibility: visibility, - )); + ); + + await createMemoryServer(content, visibility.name); + _memories.add(newMemory); _setCategories(); } - void updateMemoryVisibility(Memory memory, MemoryVisibility visibility) async { - var idx = memories.indexWhere((f) => f.id == memory.id); - updateMemoryVisibilityServer(memory.id, visibility.name); - memory.visibility = visibility; - memories[idx] = memory; - _setCategories(); + Future updateMemoryVisibility(Memory memory, MemoryVisibility visibility) async { + await updateMemoryVisibilityServer(memory.id, visibility.name); + + final idx = _memories.indexWhere((m) => m.id == memory.id); + if (idx != -1) { + Memory memoryToUpdate = _memories[idx]; + memoryToUpdate.visibility = visibility; + _memories[idx] = memoryToUpdate; + _unreviewed.removeWhere((m) => m.id == memory.id); + + MixpanelManager().memoryVisibilityChanged(memoryToUpdate, visibility); + _setCategories(); + } } void editMemory(Memory memory, String value, [MemoryCategory? category]) async { - var idx = memories.indexWhere((f) => f.id == memory.id); - editMemoryServer(memory.id, value); - memory.content = value; - if (category != null) { - memory.category = category; + await editMemoryServer(memory.id, value); + + final idx = _memories.indexWhere((m) => m.id == memory.id); + if (idx != -1) { + memory.content = value; + if (category != null) { + memory.category = category; + } + memory.updatedAt = DateTime.now(); + memory.edited = true; + _memories[idx] = memory; + + // Remove from unreviewed if it was there + final unreviewedIdx = _unreviewed.indexWhere((m) => m.id == memory.id); + if (unreviewedIdx != -1) { + _unreviewed.removeAt(unreviewedIdx); + } + + _setCategories(); } - memory.updatedAt = DateTime.now(); - memory.edited = true; - memories[idx] = memory; - _setCategories(); } - void reviewMemory(Memory memory, bool approved) async { - var idx = memories.indexWhere((f) => f.id == memory.id); + void reviewMemory(Memory memory, bool approved, String source) async { + MixpanelManager().memoryReviewed(memory, approved, source); + + await reviewMemoryServer(memory.id, approved); + + final idx = _memories.indexWhere((m) => m.id == memory.id); if (idx != -1) { memory.reviewed = true; memory.userReview = approved; + if (!approved) { memory.deleted = true; - memories.removeAt(idx); - deleteMemory(memory); + _memories.removeAt(idx); + _unreviewed.remove(memory); + // Don't call deleteMemory again because it would be a duplicate deletion } else { - memories[idx] = memory; - reviewMemoryServer(memory.id, approved); + _memories[idx] = memory; + + // Remove from unreviewed list + final unreviewedIdx = _unreviewed.indexWhere((m) => m.id == memory.id); + if (unreviewedIdx != -1) { + _unreviewed.removeAt(unreviewedIdx); + } } + _setCategories(); - notifyListeners(); } } + + Future updateAllMemoriesVisibility(bool makePrivate) async { + final visibility = makePrivate ? MemoryVisibility.private : MemoryVisibility.public; + int updatedCount = 0; + List memoriesSuccessfullyUpdated = []; + + for (var memory in List.from(_memories)) { + if (memory.visibility != visibility) { + try { + await updateMemoryVisibilityServer(memory.id, visibility.name); + final idx = _memories.indexWhere((m) => m.id == memory.id); + if (idx != -1) { + _memories[idx].visibility = visibility; + memoriesSuccessfullyUpdated.add(_memories[idx]); + updatedCount++; + } + } catch (e) { + print('Failed to update visibility for memory ${memory.id}: $e'); + } + } + } + + if (updatedCount > 0) { + MixpanelManager().memoriesAllVisibilityChanged(visibility, updatedCount); + } + + _setCategories(); + } } diff --git a/app/lib/providers/message_provider.dart b/app/lib/providers/message_provider.dart index 4375175fe..d1a6f8e31 100644 --- a/app/lib/providers/message_provider.dart +++ b/app/lib/providers/message_provider.dart @@ -14,11 +14,13 @@ import 'package:omi/providers/app_provider.dart'; import 'package:omi/utils/alerts/app_snackbar.dart'; import 'package:image_picker/image_picker.dart'; import 'package:omi/utils/file.dart'; +import 'package:omi/utils/analytics/mixpanel.dart'; import 'package:uuid/uuid.dart'; class MessageProvider extends ChangeNotifier { AppProvider? appProvider; List messages = []; + bool _isNextMessageFromVoice = false; bool isLoadingMessages = false; bool hasCachedMessages = false; @@ -38,6 +40,10 @@ class MessageProvider extends ChangeNotifier { appProvider = p; } + void setNextMessageOriginIsVoice(bool isVoice) { + _isNextMessageFromVoice = isVoice; + } + void setIsUploadingFiles() { if (uploadingFiles.values.contains(true)) { isUploadingFiles = true; @@ -277,6 +283,19 @@ class MessageProvider extends ChangeNotifier { codec?.getFrameSize() ?? 160, ); + var currentAppId = appProvider?.selectedChatAppId; + if (currentAppId == 'no_selected') { + currentAppId = null; + } + String chatTargetId = currentAppId ?? 'omi'; + App? targetApp = currentAppId != null ? appProvider?.apps.firstWhereOrNull((app) => app.id == currentAppId) : null; + bool isPersonaChat = targetApp != null ? !targetApp.isNotPersona() : false; + + MixpanelManager().chatVoiceInputUsed( + chatTargetId: chatTargetId, + isPersonaChat: isPersonaChat, + ); + setShowTypingIndicator(true); var message = ServerMessage.empty(); messages.insert(0, message); @@ -333,18 +352,33 @@ class MessageProvider extends ChangeNotifier { Future sendMessageStreamToServer(String text) async { setShowTypingIndicator(true); - var appId = appProvider?.selectedChatAppId; - if (appId == 'no_selected') { - appId = null; + var currentAppId = appProvider?.selectedChatAppId; + if (currentAppId == 'no_selected') { + currentAppId = null; } - var message = ServerMessage.empty(appId: appId); + + String chatTargetId = currentAppId ?? 'omi'; + App? targetApp = currentAppId != null ? appProvider?.apps.firstWhereOrNull((app) => app.id == currentAppId) : null; + bool isPersonaChat = targetApp != null ? !targetApp.isNotPersona() : false; + + MixpanelManager().chatMessageSent( + message: text, + includesFiles: uploadedFiles.isNotEmpty, + numberOfFiles: uploadedFiles.length, + chatTargetId: chatTargetId, + isPersonaChat: isPersonaChat, + isVoiceInput: _isNextMessageFromVoice, + ); + _isNextMessageFromVoice = false; + + var message = ServerMessage.empty(appId: currentAppId); messages.insert(0, message); notifyListeners(); List fileIds = uploadedFiles.map((e) => e.id).toList(); clearSelectedFiles(); clearUploadedFiles(); try { - await for (var chunk in sendMessageStreamServer(text, appId: appProvider?.selectedChatAppId, filesId: fileIds)) { + await for (var chunk in sendMessageStreamServer(text, appId: currentAppId, filesId: fileIds)) { if (chunk.type == MessageChunkType.think) { message.thinkings.add(chunk.text); notifyListeners(); @@ -378,18 +412,6 @@ class MessageProvider extends ChangeNotifier { setShowTypingIndicator(false); } - Future sendMessageToServer(String message, String? appId) async { - setShowTypingIndicator(true); - messages.insert(0, ServerMessage.empty(appId: appId)); - List fileIds = uploadedFiles.map((e) => e.id).toList(); - var mes = await sendMessageServer(message, appId: appId, fileIds: fileIds); - if (messages[0].id == '0000') { - messages[0] = mes; - } - setShowTypingIndicator(false); - notifyListeners(); - } - Future sendInitialAppMessage(App? app) async { setSendingMessage(true); ServerMessage message = await getInitialAppMessage(app?.id); diff --git a/app/lib/providers/onboarding_provider.dart b/app/lib/providers/onboarding_provider.dart index 3797c84e5..a0abf52e7 100644 --- a/app/lib/providers/onboarding_provider.dart +++ b/app/lib/providers/onboarding_provider.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:flutter_foreground_task/flutter_foreground_task.dart'; @@ -40,10 +41,35 @@ class OnboardingProvider extends BaseProvider with MessageNotifierMixin implemen bool hasBackgroundPermission = false; // Android only bool isLoading = false; + // Method channel for macOS permissions + static const MethodChannel _screenCaptureChannel = MethodChannel('screenCapturePlatform'); + Future updatePermissions() async { - hasBluetoothPermission = await Permission.bluetooth.isGranted; - hasLocationPermission = await Permission.location.isGranted; - hasNotificationPermission = await Permission.notification.isGranted; + if (Platform.isMacOS) { + try { + // Use macOS-specific permission checking + String bluetoothStatus = await _screenCaptureChannel.invokeMethod('checkBluetoothPermission'); + hasBluetoothPermission = bluetoothStatus == 'granted'; + + String locationStatus = await _screenCaptureChannel.invokeMethod('checkLocationPermission'); + hasLocationPermission = locationStatus == 'granted'; + + // Use macOS-specific notification permission checking + String notificationStatus = await _screenCaptureChannel.invokeMethod('checkNotificationPermission'); + hasNotificationPermission = notificationStatus == 'granted' || notificationStatus == 'provisional'; + } catch (e) { + debugPrint('Error updating permissions on macOS: $e'); + // Fallback to standard permission checking + hasBluetoothPermission = await Permission.bluetooth.isGranted; + hasLocationPermission = await Permission.location.isGranted; + hasNotificationPermission = await Permission.notification.isGranted; + } + } else { + hasBluetoothPermission = await Permission.bluetooth.isGranted; + hasLocationPermission = await Permission.location.isGranted; + hasNotificationPermission = await Permission.notification.isGranted; + } + SharedPreferencesUtil().notificationsEnabled = hasNotificationPermission; SharedPreferencesUtil().locationEnabled = hasLocationPermission; notifyListeners(); @@ -81,7 +107,36 @@ class OnboardingProvider extends BaseProvider with MessageNotifierMixin implemen Future askForBluetoothPermissions() async { FlutterBluePlus.setLogLevel(LogLevel.info, color: true); - if (Platform.isIOS) { + + if (Platform.isMacOS) { + try { + // Use macOS-specific permission handling + String bluetoothStatus = await _screenCaptureChannel.invokeMethod('checkBluetoothPermission'); + if (bluetoothStatus == 'granted') { + updateBluetoothPermission(true); + return; + } + + if (bluetoothStatus == 'undetermined') { + bool granted = await _screenCaptureChannel.invokeMethod('requestBluetoothPermission'); + updateBluetoothPermission(granted); + if (!granted) { + AppSnackbar.showSnackbarError('Bluetooth permission is required to connect to your device.'); + } + } else if (bluetoothStatus == 'denied' || bluetoothStatus == 'restricted') { + updateBluetoothPermission(false); + AppSnackbar.showSnackbarError('Bluetooth permission denied. Please grant permission in System Preferences.'); + } else { + updateBluetoothPermission(false); + AppSnackbar.showSnackbarError( + 'Bluetooth permission status: $bluetoothStatus. Please check System Preferences.'); + } + } catch (e) { + debugPrint('Error checking/requesting Bluetooth permission on macOS: $e'); + AppSnackbar.showSnackbarError('Failed to check Bluetooth permission: $e'); + updateBluetoothPermission(false); + } + } else if (Platform.isIOS) { PermissionStatus bleStatus = await Permission.bluetooth.request(); debugPrint('bleStatus: $bleStatus'); updateBluetoothPermission(bleStatus.isGranted); @@ -108,8 +163,36 @@ class OnboardingProvider extends BaseProvider with MessageNotifierMixin implemen } Future askForNotificationPermissions() async { - var isAllowed = await NotificationService.instance.requestNotificationPermissions(); - updateNotificationPermission(isAllowed); + if (Platform.isMacOS) { + try { + // Use macOS-specific permission handling + String notificationStatus = await _screenCaptureChannel.invokeMethod('checkNotificationPermission'); + debugPrint('notificationStatus: $notificationStatus'); + if (notificationStatus == 'granted') { + updateNotificationPermission(true); + return; + } + + if (notificationStatus == 'undetermined') { + bool granted = await _screenCaptureChannel.invokeMethod('requestNotificationPermission'); + updateNotificationPermission(granted); + } else if (notificationStatus == 'denied') { + updateNotificationPermission(false); + } else if (notificationStatus == 'provisional') { + updateNotificationPermission(true); // Provisional permissions are still functional + debugPrint('Notification permission is provisional - notifications will be delivered quietly'); + } else { + updateNotificationPermission(false); + } + } catch (e) { + debugPrint('Error checking/requesting Notification permission on macOS: $e'); + updateNotificationPermission(false); + } + } else { + // Existing logic for iOS/Android + var isAllowed = await NotificationService.instance.requestNotificationPermissions(); + updateNotificationPermission(isAllowed); + } notifyListeners(); } @@ -121,20 +204,65 @@ class OnboardingProvider extends BaseProvider with MessageNotifierMixin implemen } Future<(bool, PermissionStatus)> askForLocationPermissions() async { - if (await Permission.location.serviceStatus.isDisabled) { - debugPrint('Location service is disabled'); - return (false, PermissionStatus.permanentlyDenied); + if (Platform.isMacOS) { + try { + // Use macOS-specific permission handling + String locationStatus = await _screenCaptureChannel.invokeMethod('checkLocationPermission'); + debugPrint('locationStatus: $locationStatus'); + if (locationStatus == 'granted') { + updateLocationPermission(true); + return (true, PermissionStatus.granted); + } + + if (locationStatus == 'undetermined') { + bool granted = await _screenCaptureChannel.invokeMethod('requestLocationPermission'); + updateLocationPermission(granted); + debugPrint('undetermined location permission granted: $granted'); + return (true, granted ? PermissionStatus.granted : PermissionStatus.denied); + } else if (locationStatus == 'denied' || locationStatus == 'restricted') { + updateLocationPermission(false); + return (true, PermissionStatus.permanentlyDenied); + } else { + updateLocationPermission(false); + return (true, PermissionStatus.denied); + } + } catch (e) { + debugPrint('Error checking/requesting Location permission on macOS: $e'); + updateLocationPermission(false); + return (false, PermissionStatus.denied); + } } else { - var res = await Permission.locationWhenInUse.request(); - return (true, res); + // Existing logic for iOS/Android + if (await Permission.location.serviceStatus.isDisabled) { + debugPrint('Location service is disabled'); + return (false, PermissionStatus.permanentlyDenied); + } else { + var res = await Permission.locationWhenInUse.request(); + return (true, res); + } } } Future alwaysAllowLocation() async { - PermissionStatus locationStatus = await Permission.locationAlways.request(); - debugPrint('alwaysAllowLocation permission status: $locationStatus'); - updateLocationPermission(locationStatus.isGranted); - return locationStatus.isGranted; + if (Platform.isMacOS) { + // On macOS, the location permission request already handles the full permission + // Just check the current status + try { + String locationStatus = await _screenCaptureChannel.invokeMethod('checkLocationPermission'); + bool granted = locationStatus == 'granted'; + updateLocationPermission(granted); + return granted; + } catch (e) { + debugPrint('Error checking location permission on macOS: $e'); + updateLocationPermission(false); + return false; + } + } else { + PermissionStatus locationStatus = await Permission.locationAlways.request(); + debugPrint('alwaysAllowLocation permission status: $locationStatus'); + updateLocationPermission(locationStatus.isGranted); + return locationStatus.isGranted; + } } //----------------- Onboarding Permissions ----------------- diff --git a/app/lib/services/devices/errors.dart b/app/lib/services/devices/errors.dart index c0b66f4af..b15ca4b81 100644 --- a/app/lib/services/devices/errors.dart +++ b/app/lib/services/devices/errors.dart @@ -1,32 +1,19 @@ import 'package:flutter/material.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; void logErrorMessage(String message, String deviceId) { debugPrint('($deviceId) $message'); - CrashReporting.reportHandledCrash( - Exception(message), - StackTrace.current, - level: NonFatalExceptionLevel.error, - ); + PlatformManager.instance.instabug.reportCrash(Exception(message), StackTrace.current); } void logCommonErrorMessage(String message) { - debugPrint('$message'); - CrashReporting.reportHandledCrash( - Exception(message), - StackTrace.current, - level: NonFatalExceptionLevel.error, - ); + debugPrint(message); + PlatformManager.instance.instabug.reportCrash(Exception(message), StackTrace.current); } void logCrashMessage(String message, String deviceId, Object e, StackTrace stackTrace) { logErrorMessage('$message error: $e', deviceId); - CrashReporting.reportHandledCrash( - e, - stackTrace, - level: NonFatalExceptionLevel.error, - userAttributes: {'deviceId': deviceId}, - ); + PlatformManager.instance.instabug.reportCrash(e, stackTrace); } void logServiceNotFoundError(String serviceName, String deviceId) { diff --git a/app/lib/services/notifications.dart b/app/lib/services/notifications.dart index 7dbd2f406..55be52f94 100644 --- a/app/lib/services/notifications.dart +++ b/app/lib/services/notifications.dart @@ -135,6 +135,7 @@ class NotificationService { if (Platform.isIOS) { await _firebaseMessaging.getAPNSToken(); } + if (Platform.isMacOS) return; String? token = await _firebaseMessaging.getToken(); await saveFcmToken(token); _firebaseMessaging.onTokenRefresh.listen(saveFcmToken); diff --git a/app/lib/services/services.dart b/app/lib/services/services.dart index c2afbf0fa..25f2a56e4 100644 --- a/app/lib/services/services.dart +++ b/app/lib/services/services.dart @@ -8,12 +8,14 @@ import 'package:flutter_sound/flutter_sound.dart'; import 'package:omi/services/devices.dart'; import 'package:omi/services/sockets.dart'; import 'package:omi/services/wals.dart'; +import 'package:flutter/services.dart'; class ServiceManager { late IMicRecorderService _mic; late IDeviceService _device; late ISocketService _socket; late IWalService _wal; + late ISystemAudioRecorderService _systemAudio; static ServiceManager? _instance; @@ -25,6 +27,9 @@ class ServiceManager { sm._device = DeviceService(); sm._socket = SocketServicePool(); sm._wal = WalService(); + if (Platform.isMacOS) { + sm._systemAudio = MacSystemAudioRecorderService(); + } return sm; } @@ -45,6 +50,13 @@ class ServiceManager { IWalService get wal => _wal; + ISystemAudioRecorderService get systemAudio { + if (!Platform.isMacOS) { + throw Exception("System audio recording is only available on macOS"); + } + return _systemAudio; + } + static void init() { if (_instance != null) { throw Exception("Service manager is initiated"); @@ -55,12 +67,19 @@ class ServiceManager { Future start() async { _device.start(); _wal.start(); + if (Platform.isMacOS) { + // TODO: Decide if system audio should start automatically or be user-initiated + // await _systemAudio.start(); + } } void deinit() async { await _wal.stop(); _mic.stop(); _device.stop(); + if (Platform.isMacOS) { + _systemAudio.stop(); + } } } @@ -352,3 +371,146 @@ class MicRecorderService implements IMicRecorderService { _onRecording = null; } } + +abstract class ISystemAudioRecorderService { + Future start({ + required Function(Uint8List bytes) onByteReceived, + required Function(Map format) onFormatReceived, + Function()? onRecording, + Function()? onStop, + Function(String error)? onError, + }); + void stop(); + // TODO: Add status property +} + +class MacSystemAudioRecorderService implements ISystemAudioRecorderService { + static const MethodChannel _channel = MethodChannel('screenCapturePlatform'); + Function(Uint8List bytes)? _onByteReceived; + Function(Map format)? _onFormatReceived; + Function()? _onRecording; + Function()? _onStop; + Function(String error)? _onError; + + // To keep track of recording state from Dart's perspective + bool _isRecording = false; + + MacSystemAudioRecorderService() { + _channel.setMethodCallHandler(_handleMethodCall); + } + + Future _handleMethodCall(MethodCall call) async { + switch (call.method) { + case 'audioFrame': + if (_onByteReceived != null && call.arguments is Uint8List) { + _onByteReceived!(call.arguments); + } + break; + case 'audioFormat': + debugPrint("audioFormat: ${call.arguments}"); + if (_onFormatReceived != null && call.arguments is Map) { + final Map format = Map.from(call.arguments as Map); + _onFormatReceived!(format); + } + break; + case 'audioStreamEnded': + debugPrint("audioStreamEnded"); + _isRecording = false; + if (_onStop != null) { + _onStop!(); + } + _clearCallbacks(); // Clear callbacks after stopping + break; + case 'captureError': + case 'converterError': + debugPrint("captureError: ${call.arguments}"); + _isRecording = false; + if (_onError != null && call.arguments is String) { + _onError!(call.arguments as String); + } + if (_onStop != null) { + _onStop!(); // Also call onStop if there's an error + } + _clearCallbacks(); // Clear callbacks after error + break; + default: + debugPrint('MacSystemAudioRecorderService: Unhandled method call: \${call.method}'); + } + } + + void _clearCallbacks() { + _onByteReceived = null; + _onFormatReceived = null; + _onRecording = null; + _onStop = null; + _onError = null; + } + + @override + Future start({ + required Function(Uint8List bytes) onByteReceived, + required Function(Map format) onFormatReceived, + Function()? onRecording, + Function()? onStop, + Function(String error)? onError, + }) async { + if (_isRecording) { + // Potentially call onError or throw if already recording + onError?.call("Already recording. Please stop the current recording first."); + return; + } + + // Store the callbacks + _onByteReceived = onByteReceived; + _onFormatReceived = onFormatReceived; + _onRecording = onRecording; + _onStop = onStop; + _onError = onError; + + try { + await _channel.invokeMethod('start'); + _isRecording = true; // Assume recording starts successfully + if (_onRecording != null) { + _onRecording!(); + } + } catch (e) { + debugPrint("Error starting system audio recording: \$e"); + _isRecording = false; + if (_onError != null) { + _onError!(e.toString()); + } + if (_onStop != null) { + // Ensure onStop is called if start fails immediately + _onStop!(); + } + _clearCallbacks(); // Clear callbacks if start fails + } + } + + @override + void stop() { + if (!_isRecording) { + // Optionally, log or call onError if trying to stop when not recording + // _onError?.call("Not recording."); + // return; + // Or silently do nothing if preferred + } + try { + _channel.invokeMethod('stop'); + // _isRecording will be set to false and _onStop called + // when 'audioStreamEnded' is received from native code. + // If the invokeMethod 'stop' itself fails, we might not get 'audioStreamEnded'. + } catch (e) { + debugPrint("Error stopping system audio recording: \$e"); + // If stopping failed, force cleanup on Dart side. + _isRecording = false; + if (_onError != null) { + _onError!(e.toString()); + } + if (_onStop != null) { + _onStop!(); + } + _clearCallbacks(); + } + } +} diff --git a/app/lib/services/sockets/pure_socket.dart b/app/lib/services/sockets/pure_socket.dart index b64a4e7d2..49614e8fb 100644 --- a/app/lib/services/sockets/pure_socket.dart +++ b/app/lib/services/sockets/pure_socket.dart @@ -3,12 +3,12 @@ import 'dart:io'; import 'dart:math'; import 'package:flutter/material.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart'; import 'package:web_socket_channel/io.dart'; import 'package:web_socket_channel/status.dart' as socket_channel_status; import 'package:web_socket_channel/web_socket_channel.dart'; import 'package:omi/backend/http/shared.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; enum PureSocketStatus { notConnected, connecting, connected, disconnected } @@ -122,7 +122,7 @@ class PureSocket implements IPureSocket { 'Authorization': await getAuthHeader(), }, pingInterval: const Duration(seconds: 20), - connectTimeout: const Duration(seconds: 10), + connectTimeout: const Duration(seconds: 15), ); if (_channel?.ready == null) { return false; @@ -208,8 +208,7 @@ class PureSocket implements IPureSocket { debugPrintStack(stackTrace: trace); _listener?.onError(err, trace); - - CrashReporting.reportHandledCrash(err, trace, level: NonFatalExceptionLevel.error); + PlatformManager.instance.instabug.reportCrash(err, trace); } @override diff --git a/app/lib/services/sockets/sdcard_socket.dart b/app/lib/services/sockets/sdcard_socket.dart index f53c76a8c..5dc006ddc 100644 --- a/app/lib/services/sockets/sdcard_socket.dart +++ b/app/lib/services/sockets/sdcard_socket.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/message_event.dart'; import 'package:omi/env/env.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; import 'package:web_socket_channel/io.dart'; enum WebsocketConnectionStatus { notConnected, connected, failed, closed, error } @@ -116,7 +116,7 @@ class SdCardSocketService { }, onError: (err, stackTrace) { onWebsocketConnectionError(err); // error during connection - CrashReporting.reportHandledCrash(err!, stackTrace, level: NonFatalExceptionLevel.warning); + PlatformManager.instance.instabug.reportCrash(err!, stackTrace); }, onDone: (() { debugPrint('Websocket connection onDone sd'); // FIXME @@ -128,7 +128,7 @@ class SdCardSocketService { // no closing reason or code print(err); debugPrint('Websocket connection failed sd: $err'); - CrashReporting.reportHandledCrash(err!, stackTrace, level: NonFatalExceptionLevel.warning); + PlatformManager.instance.instabug.reportCrash(err!, stackTrace); onWebsocketConnectionFailed(err); // initial connection failed }); diff --git a/app/lib/utils/analytics/analytics_manager.dart b/app/lib/utils/analytics/analytics_manager.dart index 098d6f47f..897e8aa2d 100644 --- a/app/lib/utils/analytics/analytics_manager.dart +++ b/app/lib/utils/analytics/analytics_manager.dart @@ -1,5 +1,6 @@ -import 'package:omi/utils/analytics/intercom.dart'; -import 'package:omi/utils/analytics/mixpanel.dart'; +import 'dart:io'; + +import 'package:omi/utils/platform/platform_manager.dart'; class AnalyticsManager { static final AnalyticsManager _instance = AnalyticsManager._internal(); @@ -11,12 +12,17 @@ class AnalyticsManager { AnalyticsManager._internal(); void setUserAttributes() { - MixpanelManager().setPeopleValues(); - IntercomManager.instance.setUserAttributes(); + PlatformManager.instance.mixpanel.setPeopleValues(); + PlatformManager.instance.intercom.setUserAttributes(); } void setUserAttribute(String key, dynamic value) { - MixpanelManager().setUserProperty(key, value); - IntercomManager.instance.updateCustomAttributes({key: value}); + PlatformManager.instance.mixpanel.setUserProperty(key, value); + PlatformManager.instance.intercom.updateCustomAttributes({key: value}); + } + + void trackEvent(String eventName, {Map? properties}) { + PlatformManager.instance.mixpanel.track(eventName, properties: properties); + PlatformManager.instance.intercom.logEvent(eventName, metaData: properties); } } diff --git a/app/lib/utils/analytics/intercom.dart b/app/lib/utils/analytics/intercom.dart index a4291515a..46cc4680d 100644 --- a/app/lib/utils/analytics/intercom.dart +++ b/app/lib/utils/analytics/intercom.dart @@ -1,7 +1,9 @@ import 'dart:async'; +import 'dart:io'; import 'package:omi/backend/preferences.dart'; import 'package:omi/env/env.dart'; +import 'package:omi/utils/platform/platform_service.dart'; import 'package:intercom_flutter/intercom_flutter.dart'; class IntercomManager { @@ -19,55 +21,88 @@ class IntercomManager { Future initIntercom() async { if (Env.intercomAppId == null) return; - await intercom.initialize( - Env.intercomAppId!, - iosApiKey: Env.intercomIOSApiKey, - androidApiKey: Env.intercomAndroidApiKey, + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () => intercom.initialize( + Env.intercomAppId!, + iosApiKey: Env.intercomIOSApiKey, + androidApiKey: Env.intercomAndroidApiKey, + ), ); } Future displayChargingArticle(String device) async { - if (device == 'Omi DevKit 2') { - return await intercom.displayArticle('10003257-how-to-charge-devkit2'); - } else { - return await intercom.displayArticle('9907475-how-to-charge-the-device'); - } + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () async { + if (device == 'Omi DevKit 2') { + return await intercom.displayArticle('10003257-how-to-charge-devkit2'); + } else { + return await intercom.displayArticle('9907475-how-to-charge-the-device'); + } + }, + ); + } + + Future loginIdentifiedUser(String uid) async { + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () => intercom.loginIdentifiedUser(userId: uid), + ); } Future displayEarnMoneyArticle() async { - return await intercom.displayArticle('10401566-build-publish-and-earn-with-omi-apps'); + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () => intercom.displayArticle('10401566-build-publish-and-earn-with-omi-apps'), + ); } Future displayFirmwareUpdateArticle() async { - return await intercom.displayArticle('9995941-updating-your-devkit2-firmware'); + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () => intercom.displayArticle('9995941-updating-your-devkit2-firmware'), + ); } Future logEvent(String eventName, {Map? metaData}) async { - return await intercom.logEvent(eventName, metaData); + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () => intercom.logEvent(eventName, metaData), + ); } Future updateCustomAttributes(Map attributes) async { - return await intercom.updateUser(customAttributes: attributes); + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () => intercom.updateUser(customAttributes: attributes), + ); } Future updateUser(String? email, String? name, String? uid) async { - return await intercom.updateUser( - email: email, - name: name, - userId: uid, + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () => intercom.updateUser( + email: email, + name: name, + userId: uid, + ), ); } Future setUserAttributes() async { - await updateCustomAttributes({ - 'Notifications Enabled': _preferences.notificationsEnabled, - 'Location Enabled': _preferences.locationEnabled, - 'Apps Enabled Count': _preferences.enabledAppsCount, - 'Apps Integrations Enabled Count': _preferences.enabledAppsIntegrationsCount, - 'Speaker Profile': _preferences.hasSpeakerProfile, - 'Calendar Enabled': _preferences.calendarEnabled, - 'Primary Language': _preferences.userPrimaryLanguage, - 'Authorized Storing Recordings': _preferences.permissionStoreRecordingsEnabled, - }); + return PlatformService.executeIfSupportedAsync( + PlatformService.isIntercomSupported, + () => updateCustomAttributes({ + 'Notifications Enabled': _preferences.notificationsEnabled, + 'Location Enabled': _preferences.locationEnabled, + 'Apps Enabled Count': _preferences.enabledAppsCount, + 'Apps Integrations Enabled Count': _preferences.enabledAppsIntegrationsCount, + 'Speaker Profile': _preferences.hasSpeakerProfile, + 'Calendar Enabled': _preferences.calendarEnabled, + 'Primary Language': _preferences.userPrimaryLanguage, + 'Authorized Storing Recordings': _preferences.permissionStoreRecordingsEnabled, + }), + ); } } diff --git a/app/lib/utils/analytics/mixpanel.dart b/app/lib/utils/analytics/mixpanel.dart index 86b71cf0d..733697a49 100644 --- a/app/lib/utils/analytics/mixpanel.dart +++ b/app/lib/utils/analytics/mixpanel.dart @@ -1,7 +1,10 @@ +import 'dart:io'; + import 'package:omi/backend/preferences.dart'; import 'package:omi/backend/schema/memory.dart'; import 'package:omi/backend/schema/conversation.dart'; import 'package:omi/env/env.dart'; +import 'package:omi/utils/platform/platform_service.dart'; import 'package:mixpanel_flutter/mixpanel_flutter.dart'; class MixpanelManager { @@ -11,14 +14,19 @@ class MixpanelManager { static Future init() async { if (Env.mixpanelProjectToken == null) return; - if (_mixpanel == null) { - _mixpanel = await Mixpanel.init( - Env.mixpanelProjectToken!, - optOutTrackingDefault: false, - trackAutomaticEvents: true, - ); - _mixpanel?.setLoggingEnabled(false); - } + return PlatformService.executeIfSupportedAsync( + PlatformService.isMixpanelSupported, + () async { + if (_mixpanel == null) { + _mixpanel = await Mixpanel.init( + Env.mixpanelProjectToken!, + optOutTrackingDefault: false, + trackAutomaticEvents: true, + ); + _mixpanel?.setLoggingEnabled(false); + } + }, + ); } factory MixpanelManager() { @@ -28,38 +36,66 @@ class MixpanelManager { MixpanelManager._internal(); setPeopleValues() { - setUserProperty('Notifications Enabled', _preferences.notificationsEnabled); - setUserProperty('Location Enabled', _preferences.locationEnabled); - setUserProperty('Apps Enabled Count', _preferences.enabledAppsCount); - setUserProperty('Apps Integrations Enabled Count', _preferences.enabledAppsIntegrationsCount); - setUserProperty('Speaker Profile', _preferences.hasSpeakerProfile); - setUserProperty('Calendar Enabled', _preferences.calendarEnabled); - setUserProperty('Primary Language', _preferences.userPrimaryLanguage); - setUserProperty('Authorized Storing Recordings', _preferences.permissionStoreRecordingsEnabled); + PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () { + setUserProperty('Notifications Enabled', _preferences.notificationsEnabled); + setUserProperty('Location Enabled', _preferences.locationEnabled); + setUserProperty('Apps Enabled Count', _preferences.enabledAppsCount); + setUserProperty('Apps Integrations Enabled Count', _preferences.enabledAppsIntegrationsCount); + setUserProperty('Speaker Profile', _preferences.hasSpeakerProfile); + setUserProperty('Calendar Enabled', _preferences.calendarEnabled); + setUserProperty('Primary Language', _preferences.userPrimaryLanguage); + setUserProperty('Authorized Storing Recordings', _preferences.permissionStoreRecordingsEnabled); + }, + ); } - setUserProperty(String key, dynamic value) => _mixpanel?.getPeople().set(key, value); + setUserProperty(String key, dynamic value) => PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () => _mixpanel?.getPeople().set(key, value), + ); void optInTracking() { - _mixpanel?.optInTracking(); - identify(); + PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () { + _mixpanel?.optInTracking(); + identify(); + }, + ); } void optOutTracking() { - _mixpanel?.optOutTracking(); - _mixpanel?.reset(); + PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () { + _mixpanel?.optOutTracking(); + _mixpanel?.reset(); + }, + ); } void identify() { - _mixpanel?.identify(_preferences.uid); - _instance.setPeopleValues(); - setNameAndEmail(); + PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () { + _mixpanel?.identify(_preferences.uid); + _instance.setPeopleValues(); + setNameAndEmail(); + }, + ); } void migrateUser(String newUid) { - _mixpanel?.alias(newUid, _preferences.uid); - _mixpanel?.identify(newUid); - setNameAndEmail(); + PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () { + _mixpanel?.alias(newUid, _preferences.uid); + _mixpanel?.identify(newUid); + setNameAndEmail(); + }, + ); } void setNameAndEmail() { @@ -67,10 +103,15 @@ class MixpanelManager { setUserProperty('\$email', SharedPreferencesUtil().email); } - void track(String eventName, {Map? properties}) => - _mixpanel?.track(eventName, properties: properties); + void track(String eventName, {Map? properties}) => PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () => _mixpanel?.track(eventName, properties: properties), + ); - void startTimingEvent(String eventName) => _mixpanel?.timeEvent(eventName); + void startTimingEvent(String eventName) => PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () => _mixpanel?.timeEvent(eventName), + ); void onboardingDeviceConnected() => track('Onboarding Device Connected'); @@ -162,9 +203,63 @@ class MixpanelManager { void memoriesPageCreateMemoryBtn() => track('Fact Page Create Fact Button Pressed'); + void memoriesPageReviewBtn() => track('Fact page Review Button Pressed'); + void memoriesPageCreatedMemory(MemoryCategory category) => track('Fact Page Created Fact', properties: {'fact_category': category.toString().split('.').last}); + void memorySearched(String query, int resultsCount) { + track('Fact Searched', properties: { + 'search_query_length': query.length, + 'results_count': resultsCount, + }); + } + + void memorySearchCleared(int totalFactsCount) { + track('Fact Search Cleared', properties: {'total_facts_count': totalFactsCount}); + } + + void memoryListItemClicked(Memory memory) { + track('Fact List Item Clicked', properties: { + 'fact_id': memory.id, + 'fact_category': memory.category.toString().split('.').last, + }); + } + + void memoryVisibilityChanged(Memory memory, MemoryVisibility newVisibility) { + track('Fact Visibility Changed', properties: { + 'fact_id': memory.id, + 'fact_category': memory.category.toString().split('.').last, + 'new_visibility': newVisibility.name, + }); + } + + void memoriesAllVisibilityChanged(MemoryVisibility newVisibility, int count) { + track('All Facts Visibility Changed', properties: { + 'new_visibility': newVisibility.name, + 'facts_count': count, + }); + } + + void memoryReviewed(Memory memory, bool approved, String source) { + track('Fact Reviewed', properties: { + 'fact_id': memory.id, + 'fact_category': memory.category.toString().split('.').last, + 'status': approved ? 'approved' : 'discarded', + 'source': source, + }); + } + + void memoriesAllDeleted(int countBeforeDeletion) { + track('All Facts Deleted', properties: { + 'facts_count_before_deletion': countBeforeDeletion, + }); + } + + void memoriesFiltered(String filter) => track('Facts Filtered', properties: {'filter': filter}); + + void memoriesManagementSheetOpened() => track('Facts Management Sheet Opened'); + Map _getTranscriptProperties(String transcript) { String transcriptCopy = transcript.substring(0, transcript.length); int speakersCount = 0; @@ -206,8 +301,30 @@ class MixpanelManager { void conversationDeleted(ServerConversation conversation) => track('Memory Deleted', properties: getConversationEventProperties(conversation)); - void chatMessageSent(String message) => track('Chat Message Sent', - properties: {'message_length': message.length, 'message_word_count': message.split(' ').length}); + void chatMessageSent({ + required String message, + required bool includesFiles, + required int numberOfFiles, + required String chatTargetId, + required bool isPersonaChat, + required bool isVoiceInput, + }) => + track('Chat Message Sent', properties: { + 'message_length': message.length, + 'message_word_count': message.split(' ').length, + 'includes_files': includesFiles, + 'number_of_files': numberOfFiles, + 'chat_target_id': chatTargetId, + 'is_persona_chat': isPersonaChat, + 'is_voice_input': isVoiceInput, + }); + + void chatVoiceInputUsed({required String chatTargetId, required bool isPersonaChat}) { + track('Chat Voice Input Used', properties: { + 'chat_target_id': chatTargetId, + 'is_persona_chat': isPersonaChat, + }); + } void speechProfileCapturePageClicked() => track('Speech Profile Capture Page Clicked'); @@ -297,5 +414,223 @@ class MixpanelManager { void deleteAccountCancelled() => track('Delete Account Cancelled'); - void deleteUser() => _mixpanel?.getPeople().deleteUser(); + void deleteUser() => PlatformService.executeIfSupported( + PlatformService.isMixpanelSupported, + () => _mixpanel?.getPeople().deleteUser(), + ); + + // Apps Filter + void appsFilterOpened() => track('Apps Filter Opened'); + void appsFilterApplied() => track('Apps Filter Applied'); + void appsCategoryFilter(String category, bool isSelected) { + track('Apps Category Filter', properties: {'category': category, 'selected': isSelected}); + } + + void appsTypeFilter(String type, bool isSelected) { + track('Apps Type Filter', properties: {'type': type, 'selected': isSelected}); + } + + void appsSortFilter(String sortBy, bool isSelected) { + track('Apps Sort Filter', properties: {'sort_by': sortBy, 'selected': isSelected}); + } + + void appsRatingFilter(String rating, bool isSelected) { + track('Apps Rating Filter', properties: {'rating': rating, 'selected': isSelected}); + } + + void appsCapabilityFilter(String capability, bool isSelected) { + track('Apps Capability Filter', properties: {'capability': capability, 'selected': isSelected}); + } + + void appsClearFilters() => track('Apps Clear Filters'); + + // Persona Events + void personaProfileViewed({String? personaId, required String source}) { + track('Persona Profile Viewed', properties: { + if (personaId != null) 'persona_id': personaId, + 'source': source, + }); + } + + void personaCreateStarted() => track('Persona Create Started'); + + void personaCreateImagePicked() => track('Persona Create Image Picked'); + + void personaCreated({ + required String personaId, + required bool isPublic, + List? connectedAccounts, + bool? hasOmiConnection, + bool? hasTwitterConnection, + }) { + track('Persona Created', properties: { + 'persona_id': personaId, + 'is_public': isPublic, + if (connectedAccounts != null) 'connected_accounts': connectedAccounts, + if (hasOmiConnection != null) 'has_omi_connection': hasOmiConnection, + if (hasTwitterConnection != null) 'has_twitter_connection': hasTwitterConnection, + }); + } + + void personaCreateFailed({String? errorMessage}) { + track('Persona Create Failed', properties: { + if (errorMessage != null) 'error_message': errorMessage, + }); + } + + void personaUpdateStarted({required String personaId}) { + track('Persona Update Started', properties: {'persona_id': personaId}); + } + + void personaUpdateImagePicked({required String personaId}) { + track('Persona Update Image Picked', properties: {'persona_id': personaId}); + } + + void personaUpdated({ + required String personaId, + List? updatedFields, + required bool isPublic, + List? connectedAccounts, + bool? hasOmiConnection, + bool? hasTwitterConnection, + }) { + track('Persona Updated', properties: { + 'persona_id': personaId, + if (updatedFields != null && updatedFields.isNotEmpty) 'updated_fields': updatedFields, + 'is_public': isPublic, + if (connectedAccounts != null) 'connected_accounts': connectedAccounts, + if (hasOmiConnection != null) 'has_omi_connection': hasOmiConnection, + if (hasTwitterConnection != null) 'has_twitter_connection': hasTwitterConnection, + }); + } + + void personaUpdateFailed({required String personaId, String? errorMessage}) { + track('Persona Update Failed', properties: { + 'persona_id': personaId, + if (errorMessage != null) 'error_message': errorMessage, + }); + } + + void personaPublicToggled({required String personaId, required bool isPublic}) { + track('Persona Public Toggled', properties: { + 'persona_id': personaId, + 'is_public': isPublic, + }); + } + + void personaOmiConnectionToggled({required String personaId, required bool omiConnected}) { + track('Persona OMI Connection Toggled', properties: { + 'persona_id': personaId, + 'omi_connected': omiConnected, + }); + } + + void personaTwitterConnectionToggled({required String personaId, required bool twitterConnected}) { + track('Persona Twitter Connection Toggled', properties: { + 'persona_id': personaId, + 'twitter_connected': twitterConnected, + }); + } + + void personaTwitterProfileFetched({required String twitterHandle, required bool fetchSuccessful}) { + track('Persona Twitter Profile Fetched', properties: { + 'twitter_handle': twitterHandle, + 'fetch_successful': fetchSuccessful, + }); + } + + void personaTwitterOwnershipVerified({ + String? personaId, + required String twitterHandle, + required bool verificationSuccessful, + }) { + track('Persona Twitter Ownership Verified', properties: { + if (personaId != null) 'persona_id': personaId, + 'twitter_handle': twitterHandle, + 'verification_successful': verificationSuccessful, + }); + } + + void personaShared({required String? personaId, required String? personaUsername}) { + track('Persona Shared', properties: { + if (personaId != null) 'persona_id': personaId, + if (personaUsername != null) 'persona_username': personaUsername, + }); + } + + void personaUsernameCheck({required String username, required bool isTaken}) { + track('Persona Username Check', properties: { + 'username': username, + 'is_taken': isTaken, + }); + } + + void personaEnabled({required String personaId}) { + track('Persona Enabled', properties: {'persona_id': personaId}); + } + + void personaEnableFailed({required String personaId, String? errorMessage}) { + track('Persona Enable Failed', properties: { + 'persona_id': personaId, + if (errorMessage != null) 'error_message': errorMessage, + }); + } + + // Summarized Apps Sheet Events + void summarizedAppSheetViewed({ + required String conversationId, + String? currentSummarizedAppId, + }) { + track('Summarized App Sheet Viewed', properties: { + 'conversation_id': conversationId, + 'current_summarized_app_id': currentSummarizedAppId ?? 'auto', + }); + } + + void summarizedAppSelected({ + required String conversationId, + required String selectedAppId, + String? previousAppId, + }) { + track('Summarized App Selected', properties: { + 'conversation_id': conversationId, + 'selected_app_id': selectedAppId, + 'previous_app_id': previousAppId ?? 'auto', + }); + } + + void summarizedAppEnableAppsClicked({required String conversationId}) { + track('Summarized App Enable Apps Clicked', properties: { + 'conversation_id': conversationId, + }); + } + + // Action Items Page Events + void actionItemsPageOpened() => track('Action Items Page Opened'); + + void actionItemsViewToggled(bool isGroupedView) { + track('Action Items View Toggled', properties: {'grouped_view': isGroupedView}); + } + + void actionItemToggledCompletionOnActionItemsPage({ + required String conversationId, + required String actionItemDescription, // Using description as a pseudo-ID if no stable ID exists + required bool isCompleted, + }) { + track('Action Item Completion Toggled on Action Items Page', properties: { + 'conversation_id': conversationId, + 'action_item_description': actionItemDescription, + 'is_completed': isCompleted, + }); + } + + void actionItemTappedForEditOnActionItemsPage({ + required String conversationId, + required String actionItemDescription, + }) { + track('Action Item Tapped for Edit on Action Items Page', properties: { + 'conversation_id': conversationId, + 'action_item_description': actionItemDescription, + }); + } } diff --git a/app/lib/utils/audio/wav_bytes.dart b/app/lib/utils/audio/wav_bytes.dart index e04d976fb..d735ef681 100644 --- a/app/lib/utils/audio/wav_bytes.dart +++ b/app/lib/utils/audio/wav_bytes.dart @@ -6,8 +6,8 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:omi/backend/schema/bt_device/bt_device.dart'; import 'package:omi/utils/logger.dart'; -import 'package:instabug_flutter/instabug_flutter.dart'; import 'package:intl/intl.dart'; +import 'package:omi/utils/platform/platform_manager.dart'; import 'package:opus_dart/opus_dart.dart'; import 'package:path_provider/path_provider.dart'; import 'package:tuple/tuple.dart'; @@ -294,8 +294,7 @@ class WavBytesUtil { wavBytes = getUInt8ListBytes(decodedSamples, 16000); } else { - CrashReporting.reportHandledCrash(UnimplementedError('unknown codec'), StackTrace.current, - level: NonFatalExceptionLevel.error); + PlatformManager.instance.instabug.reportCrash(UnimplementedError('unknown codec'), StackTrace.current); throw UnimplementedError('unknown codec'); } return createWav(wavBytes, filename: filename); diff --git a/app/lib/utils/debugging/instabug_manager.dart b/app/lib/utils/debugging/instabug_manager.dart new file mode 100644 index 000000000..3d73ebb95 --- /dev/null +++ b/app/lib/utils/debugging/instabug_manager.dart @@ -0,0 +1,140 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:omi/utils/platform/platform_service.dart'; +import 'package:instabug_flutter/instabug_flutter.dart'; + +/// Platform-aware manager for Instabug +/// Handles macOS compatibility internally without exposing platform checks +class InstabugManager { + static final InstabugManager _instance = InstabugManager._internal(); + static InstabugManager get instance => _instance; + + InstabugManager._internal(); + + factory InstabugManager() { + return _instance; + } + + /// Initialize Instabug with the provided token and settings + static Future init({ + required String token, + List invocationEvents = const [InvocationEvent.none], + }) async { + return PlatformService.executeIfSupportedAsync( + PlatformService.isInstabugSupported, + () => Instabug.init( + token: token, + invocationEvents: invocationEvents, + ), + ); + } + + /// Set welcome message mode + Future setWelcomeMessageMode(WelcomeMessageMode mode) async { + return PlatformService.executeIfSupportedAsync( + PlatformService.isInstabugSupported, + () => Instabug.setWelcomeMessageMode(mode), + ); + } + + /// Identify user with email, name, and user ID + void identifyUser(String email, String name, String userId) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => Instabug.identifyUser(email, name, userId), + ); + } + + /// Set color theme + void setColorTheme(ColorTheme theme) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => Instabug.setColorTheme(theme), + ); + } + + /// Log info message + void logInfo(String message) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => InstabugLog.logInfo(message), + ); + } + + /// Log error message + void logError(String message) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => InstabugLog.logError(message), + ); + } + + /// Log warning message + void logWarn(String message) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => InstabugLog.logWarn(message), + ); + } + + /// Log debug message + void logDebug(String message) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => InstabugLog.logDebug(message), + ); + } + + /// Log verbose message + void logVerbose(String message) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => InstabugLog.logVerbose(message), + ); + } + + /// Show bug reporting screen + void show() { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => Instabug.show(), + ); + } + + /// Set user attribute + void setUserAttribute(String key, String value) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => Instabug.setUserAttribute(key, value), + ); + } + + /// Set enabled state + void setEnabled(bool isEnabled) { + PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => Instabug.setEnabled(isEnabled), + ); + } + + Future reportCrash(Object exception, StackTrace stackTrace, {Map? userAttributes}) async { + await PlatformService.executeIfSupportedAsync( + PlatformService.isInstabugSupported, + () async => await CrashReporting.reportHandledCrash(exception, stackTrace, + level: NonFatalExceptionLevel.error, userAttributes: userAttributes), + ); + } + + /// Get navigator observer for navigation tracking + /// Returns null on unsupported platforms + NavigatorObserver? getNavigatorObserver() { + return PlatformService.executeIfSupported( + PlatformService.isInstabugSupported, + () => InstabugNavigatorObserver(), + ); + } + + /// Check if platform supports Instabug + bool get isSupported => PlatformService.isInstabugSupported; +} diff --git a/app/lib/utils/enums.dart b/app/lib/utils/enums.dart index 4d92a564c..c77a10d64 100644 --- a/app/lib/utils/enums.dart +++ b/app/lib/utils/enums.dart @@ -1 +1 @@ -enum RecordingState { pause, record, stop, initialising, error } +enum RecordingState { initialising, record, stop, deviceRecord, systemAudioRecord, pause, error } diff --git a/app/lib/utils/other/time_utils.dart b/app/lib/utils/other/time_utils.dart index f933ee54c..9b0eca41c 100644 --- a/app/lib/utils/other/time_utils.dart +++ b/app/lib/utils/other/time_utils.dart @@ -37,6 +37,31 @@ String secondsToHumanReadable(int seconds) { } } +/// Returns a compact representation of seconds (e.g., "10s", "5m", "2h 15m") +/// Designed for use in small UI elements like list items +String secondsToCompactDuration(int seconds) { + if (seconds < 60) { + return '${seconds}s'; + } else if (seconds < 3600) { + var minutes = (seconds / 60).floor(); + var remainingSeconds = seconds % 60; + if (remainingSeconds == 0 || minutes >= 10) { + return '${minutes}m'; + } else { + // Only show seconds for durations less than 10 minutes + return '${minutes}m ${remainingSeconds}s'; + } + } else { + var hours = (seconds / 3600).floor(); + var remainingMinutes = (seconds % 3600 / 60).floor(); + if (remainingMinutes == 0 || hours >= 10) { + return '${hours}h'; + } else { + return '${hours}h ${remainingMinutes}m'; + } + } +} + // convert seconds to hh:mm:ss format String secondsToHMS(int seconds) { var hours = (seconds / 3600).floor(); diff --git a/app/lib/utils/platform/platform_manager.dart b/app/lib/utils/platform/platform_manager.dart new file mode 100644 index 000000000..5c8945054 --- /dev/null +++ b/app/lib/utils/platform/platform_manager.dart @@ -0,0 +1,37 @@ +import 'package:omi/utils/analytics/intercom.dart'; +import 'package:omi/utils/analytics/mixpanel.dart'; +import 'package:omi/utils/debugging/instabug_manager.dart'; +import 'package:omi/utils/platform/platform_service.dart'; + +/// Centralized platform manager for all platform-specific services +/// This provides a single point of access for all platform services +class PlatformManager { + static final PlatformManager _instance = PlatformManager._internal(); + + factory PlatformManager() => _instance; + PlatformManager._internal(); + + static PlatformManager get instance => _instance; + + // Service instances + MixpanelManager get mixpanel => MixpanelManager(); + IntercomManager get intercom => IntercomManager.instance; + InstabugManager get instabug => InstabugManager.instance; + + /// Initialize all platform services + static Future initializeServices() async { + await MixpanelManager.init(); + await IntercomManager.instance.initIntercom(); + // Note: Instabug initialization is handled separately in main.dart + // due to its specific initialization requirements + } + + /// Check if analytics services are supported on current platform + bool get isAnalyticsSupported => PlatformService.isAnalyticsSupported; + + /// Check if debugging services are supported on current platform + bool get isDebuggingSupported => PlatformService.isInstabugSupported; + + /// Check if current platform is macOS + bool get isMacOS => PlatformService.isMacOS; +} diff --git a/app/lib/utils/platform/platform_service.dart b/app/lib/utils/platform/platform_service.dart new file mode 100644 index 000000000..30dff412c --- /dev/null +++ b/app/lib/utils/platform/platform_service.dart @@ -0,0 +1,27 @@ +import 'dart:io'; + +/// A utility class to handle platform-specific service availability +class PlatformService { + static bool get isMacOS => Platform.isMacOS; + static bool get isAnalyticsSupported => !Platform.isMacOS; + static bool get isNotificationSupported => !Platform.isMacOS; + static bool get isIntercomSupported => !Platform.isMacOS; + static bool get isMixpanelSupported => !Platform.isMacOS; + static bool get isInstabugSupported => !Platform.isMacOS; + + /// Execute a function only if the platform supports it + static T? executeIfSupported(bool isSupported, T Function() function, {T? fallback}) { + if (isSupported) { + return function(); + } + return fallback; + } + + /// Execute a future function only if the platform supports it + static Future executeIfSupportedAsync(bool isSupported, Future Function() function, {T? fallback}) async { + if (isSupported) { + return await function(); + } + return fallback; + } +} diff --git a/app/lib/utils/ui_guidelines.dart b/app/lib/utils/ui_guidelines.dart new file mode 100644 index 000000000..29091168f --- /dev/null +++ b/app/lib/utils/ui_guidelines.dart @@ -0,0 +1,164 @@ +import 'package:flutter/material.dart'; + +/// UI Guidelines to ensure consistent styling throughout the app +/// Use this class for reference when creating new UI components +class AppStyles { + // Text Styles + static const TextStyle title = TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.white, + ); + + static const TextStyle subtitle = TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white, + ); + + static const TextStyle body = TextStyle( + fontSize: 15, + height: 1.4, + color: Colors.white, + ); + + static const TextStyle caption = TextStyle( + fontSize: 14, + color: Colors.white70, + ); + + static const TextStyle small = TextStyle( + fontSize: 12, + color: Colors.white70, + ); + + static const TextStyle label = TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Colors.white70, + ); + + // Colors + static final Color backgroundPrimary = Colors.black; + static final Color backgroundSecondary = Colors.grey.shade900; + static final Color backgroundTertiary = Colors.grey.shade800; + + static const Color textPrimary = Colors.white; + static final Color textSecondary = Colors.white.withOpacity(0.8); + static final Color textTertiary = Colors.white.withOpacity(0.6); + + static const Color accent = Colors.blue; + static final Color error = Colors.red.shade800; + static final Color success = Colors.green.shade600; + + // Spacing + static const double spacingXS = 4.0; + static const double spacingS = 8.0; + static const double spacingM = 12.0; + static const double spacingL = 16.0; + static const double spacingXL = 24.0; + static const double spacingXXL = 32.0; + + // Radius + static const double radiusSmall = 6.0; + static const double radiusMedium = 8.0; + static const double radiusLarge = 12.0; + static const double radiusCircular = 100.0; + + // Widget specific + static final cardDecoration = BoxDecoration( + color: backgroundSecondary, + borderRadius: BorderRadius.circular(radiusLarge), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ); + + static final inputDecoration = InputDecoration( + filled: true, + fillColor: backgroundTertiary, + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(radiusMedium), + borderSide: BorderSide.none, + ), + ); + + static final chipDecoration = BoxDecoration( + color: backgroundTertiary.withOpacity(0.6), + borderRadius: BorderRadius.circular(radiusCircular), + ); +} + +/// Theme extension to provide app styles as part of the theme +class AppTheme extends ThemeExtension { + final TextStyle title; + final TextStyle subtitle; + final TextStyle body; + final TextStyle caption; + final TextStyle small; + final TextStyle label; + + AppTheme({ + required this.title, + required this.subtitle, + required this.body, + required this.caption, + required this.small, + required this.label, + }); + + @override + ThemeExtension copyWith({ + TextStyle? title, + TextStyle? subtitle, + TextStyle? body, + TextStyle? caption, + TextStyle? small, + TextStyle? label, + }) { + return AppTheme( + title: title ?? this.title, + subtitle: subtitle ?? this.subtitle, + body: body ?? this.body, + caption: caption ?? this.caption, + small: small ?? this.small, + label: label ?? this.label, + ); + } + + @override + ThemeExtension lerp(ThemeExtension? other, double t) { + if (other is! AppTheme) { + return this; + } + return AppTheme( + title: TextStyle.lerp(title, other.title, t)!, + subtitle: TextStyle.lerp(subtitle, other.subtitle, t)!, + body: TextStyle.lerp(body, other.body, t)!, + caption: TextStyle.lerp(caption, other.caption, t)!, + small: TextStyle.lerp(small, other.small, t)!, + label: TextStyle.lerp(label, other.label, t)!, + ); + } + + /// Apply AppTheme to ThemeData + static ThemeData applyToTheme(ThemeData theme) { + return theme.copyWith( + extensions: [ + AppTheme( + title: AppStyles.title, + subtitle: AppStyles.subtitle, + body: AppStyles.body, + caption: AppStyles.caption, + small: AppStyles.small, + label: AppStyles.label, + ), + ], + ); + } +} \ No newline at end of file diff --git a/app/lib/widgets/conversation_bottom_bar.dart b/app/lib/widgets/conversation_bottom_bar.dart index d5bab17bb..01b6f0a1d 100644 --- a/app/lib/widgets/conversation_bottom_bar.dart +++ b/app/lib/widgets/conversation_bottom_bar.dart @@ -13,7 +13,7 @@ enum ConversationBottomBarMode { detail // For viewing completed conversations } -enum ConversationTab { transcript, summary } +enum ConversationTab { transcript, summary, actionItems } class ConversationBottomBar extends StatelessWidget { final ConversationBottomBarMode mode; @@ -49,7 +49,7 @@ class ConversationBottomBar extends StatelessWidget { borderRadius: BorderRadius.circular(28), child: Container( height: 56, - width: mode == ConversationBottomBarMode.recording ? 180 : 290, + width: mode == ConversationBottomBarMode.recording ? 180 : 360, padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.grey.shade900, @@ -69,8 +69,15 @@ class ConversationBottomBar extends StatelessWidget { // Transcript tab _buildTranscriptTab(), - // Stop button or Summary tab - if (mode == ConversationBottomBarMode.recording) _buildStopButton() else _buildSummaryTab(context), + // Stop button or Summary/Action Items tabs + ...switch (mode) { + ConversationBottomBarMode.recording => [_buildStopButton()], + ConversationBottomBarMode.detail => [ + _buildSummaryTab(context), + _buildActionItemsTab(), + ], + _ => [_buildSummaryTab(context)], + }, ], ), ), @@ -164,4 +171,12 @@ class ConversationBottomBar extends StatelessWidget { }, ); } + + Widget _buildActionItemsTab() { + return TabButton( + icon: Icons.check_circle_outline, + isSelected: selectedTab == ConversationTab.actionItems, + onTap: () => onTabSelected(ConversationTab.actionItems), + ); + } } diff --git a/app/macos/Podfile b/app/macos/Podfile index fe733905d..a1cf8ff4c 100644 --- a/app/macos/Podfile +++ b/app/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.13' +platform :osx, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/app/macos/Runner.xcodeproj/project.pbxproj b/app/macos/Runner.xcodeproj/project.pbxproj index 0ef35460d..5c47f9cb0 100644 --- a/app/macos/Runner.xcodeproj/project.pbxproj +++ b/app/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -21,12 +21,13 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 332689E32D863DBF00CB35A1 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 332689E22D863DBF00CB35A1 /* GoogleService-Info.plist */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 8843F86C002116330968C1E7 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B35F3FB95FB2445F81FF93E0 /* GoogleService-Info.plist */; }; + 6CEA62AC1B6F48029F663C75 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 990C21DF2FB7195E1A0C66BB /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -53,9 +54,18 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1C2D026EB5A0346DDF59E311 /* Pods-Runner.release-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-dev.xcconfig"; sourceTree = ""; }; + 332689E22D863DBF00CB35A1 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 332689E42D870FC600CB35A1 /* RunnerRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerRelease.entitlements; sourceTree = ""; }; + 332689E52D8712BB00CB35A1 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; }; + 332689E62D8712C600CB35A1 /* RunnerProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerProfile.entitlements; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* Friend.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Friend.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33AE6BFE2D885D7400901B39 /* RunnerDebug-prod.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerDebug-prod.entitlements"; sourceTree = ""; }; + 33AE6BFF2D885D7700901B39 /* RunnerDebug-dev.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerDebug-dev.entitlements"; sourceTree = ""; }; + 33AE6C002D885D7E00901B39 /* RunnerRelease-prod.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerRelease-prod.entitlements"; sourceTree = ""; }; + 33AE6C012D885D8700901B39 /* RunnerProfile-prod.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerProfile-prod.entitlements"; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* Omi.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Omi.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -67,9 +77,17 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 499F292DC6760DF2E1C7EE6C /* Pods-Runner.profile-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-dev.xcconfig"; sourceTree = ""; }; + 727D30C5CE8BA20F9DDF5245 /* Pods-Runner.release-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-prod.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 8D3552C3B9FB89580AB02D4C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 96C47D61F21F055C4264E4ED /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - B35F3FB95FB2445F81FF93E0 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; + 990C21DF2FB7195E1A0C66BB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9E30D5C1306899D4214FF616 /* Pods-Runner.debug-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-dev.xcconfig"; sourceTree = ""; }; + ECA12410D4472837013672C6 /* Pods-Runner.debug-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-prod.xcconfig"; sourceTree = ""; }; + F8DCBD7DD8AB67EE93F0458C /* Pods-Runner.profile-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-prod.xcconfig"; sourceTree = ""; }; + FBFF4BAE9914B1C75B63AB20 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -77,6 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 6CEA62AC1B6F48029F663C75 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -97,18 +116,19 @@ 33CC10E42044A3C60003C045 = { isa = PBXGroup; children = ( + 332689E22D863DBF00CB35A1 /* GoogleService-Info.plist */, 33FAB671232836740065AC1E /* Runner */, 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - B35F3FB95FB2445F81FF93E0 /* GoogleService-Info.plist */, + 7E46E8344CECDAF8A1C52DC9 /* Pods */, + 8B6767900719AA147F326713 /* Frameworks */, ); sourceTree = ""; }; 33CC10EE2044A3C60003C045 /* Products */ = { isa = PBXGroup; children = ( - 33CC10ED2044A3C60003C045 /* Friend.app */, + 33CC10ED2044A3C60003C045 /* Omi.app */, ); name = Products; sourceTree = ""; @@ -138,6 +158,13 @@ 33FAB671232836740065AC1E /* Runner */ = { isa = PBXGroup; children = ( + 33AE6C012D885D8700901B39 /* RunnerProfile-prod.entitlements */, + 33AE6C002D885D7E00901B39 /* RunnerRelease-prod.entitlements */, + 33AE6BFF2D885D7700901B39 /* RunnerDebug-dev.entitlements */, + 33AE6BFE2D885D7400901B39 /* RunnerDebug-prod.entitlements */, + 332689E62D8712C600CB35A1 /* RunnerProfile.entitlements */, + 332689E52D8712BB00CB35A1 /* RunnerDebug.entitlements */, + 332689E42D870FC600CB35A1 /* RunnerRelease.entitlements */, 33CC10F02044A3C60003C045 /* AppDelegate.swift */, 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, 33E51913231747F40026EE4D /* DebugProfile.entitlements */, @@ -148,9 +175,26 @@ path = Runner; sourceTree = ""; }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { + 7E46E8344CECDAF8A1C52DC9 /* Pods */ = { isa = PBXGroup; children = ( + 8D3552C3B9FB89580AB02D4C /* Pods-Runner.debug.xcconfig */, + ECA12410D4472837013672C6 /* Pods-Runner.debug-prod.xcconfig */, + 9E30D5C1306899D4214FF616 /* Pods-Runner.debug-dev.xcconfig */, + 96C47D61F21F055C4264E4ED /* Pods-Runner.release.xcconfig */, + 727D30C5CE8BA20F9DDF5245 /* Pods-Runner.release-prod.xcconfig */, + 1C2D026EB5A0346DDF59E311 /* Pods-Runner.release-dev.xcconfig */, + FBFF4BAE9914B1C75B63AB20 /* Pods-Runner.profile.xcconfig */, + F8DCBD7DD8AB67EE93F0458C /* Pods-Runner.profile-prod.xcconfig */, + 499F292DC6760DF2E1C7EE6C /* Pods-Runner.profile-dev.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 8B6767900719AA147F326713 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 990C21DF2FB7195E1A0C66BB /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -162,11 +206,14 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 7A3C1E7136698D1467D05416 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + AF7BC7379FDDCB7A5029344E /* [CP] Embed Pods Frameworks */, + EE03BE128887DC44A9D12A0F /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -175,7 +222,7 @@ ); name = Runner; productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* Friend.app */; + productReference = 33CC10ED2044A3C60003C045 /* Omi.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -185,13 +232,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Sandbox = { enabled = 1; @@ -229,8 +275,8 @@ buildActionMask = 2147483647; files = ( 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 332689E32D863DBF00CB35A1 /* GoogleService-Info.plist in Resources */, 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - 8843F86C002116330968C1E7 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -239,6 +285,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -274,6 +321,62 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 7A3C1E7136698D1467D05416 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + AF7BC7379FDDCB7A5029344E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + EE03BE128887DC44A9D12A0F /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -310,6 +413,514 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 332689D02D863BCE00CB35A1 /* Debug-dev */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = "Debug-dev"; + }; + 332689D12D863BCE00CB35A1 /* Debug-dev */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = devAppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = "Runner/RunnerDebug-dev.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = "Debug-dev"; + }; + 332689D22D863BCE00CB35A1 /* Debug-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Debug-dev"; + }; + 332689D32D863BD900CB35A1 /* Debug-prod */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = "Debug-prod"; + }; + 332689D42D863BD900CB35A1 /* Debug-prod */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = prodAppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = "Runner/RunnerDebug-prod.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = "Debug-prod"; + }; + 332689D52D863BD900CB35A1 /* Debug-prod */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Debug-prod"; + }; + 332689D62D863BEA00CB35A1 /* Profile-dev */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = "Profile-dev"; + }; + 332689D72D863BEA00CB35A1 /* Profile-dev */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = devAppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = "Profile-dev"; + }; + 332689D82D863BEA00CB35A1 /* Profile-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Profile-dev"; + }; + 332689D92D863BF000CB35A1 /* Profile-prod */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = "Profile-prod"; + }; + 332689DA2D863BF000CB35A1 /* Profile-prod */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = prodAppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = "Runner/RunnerProfile-prod.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = "Profile-prod"; + }; + 332689DB2D863BF000CB35A1 /* Profile-prod */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Profile-prod"; + }; + 332689DC2D863BF900CB35A1 /* Release-dev */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = "Release-dev"; + }; + 332689DD2D863BF900CB35A1 /* Release-dev */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = devAppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = "Release-dev"; + }; + 332689DE2D863BF900CB35A1 /* Release-dev */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Release-dev"; + }; + 332689DF2D863BFF00CB35A1 /* Release-prod */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = "Release-prod"; + }; + 332689E02D863BFF00CB35A1 /* Release-prod */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = prodAppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-prod.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = "Release-prod"; + }; + 332689E12D863BFF00CB35A1 /* Release-prod */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = "Release-prod"; + }; 338D0CE9231458BD00FA5F75 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; @@ -336,7 +947,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -348,7 +959,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -362,15 +973,23 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; @@ -410,7 +1029,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -428,7 +1047,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -463,7 +1082,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_IDENTITY = "Apple Development: Mohammed Mohsin (F2FJK4TV67)"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -475,7 +1094,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -489,15 +1108,23 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -510,15 +1137,23 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 307; + DEVELOPMENT_TEAM = 9536L8KLMP; + ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = Omi; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0.64; + PRODUCT_BUNDLE_IDENTIFIER = "com.friend-app-with-wearable.ios12"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; }; @@ -547,8 +1182,14 @@ isa = XCConfigurationList; buildConfigurations = ( 33CC10F92044A3C60003C045 /* Debug */, + 332689D32D863BD900CB35A1 /* Debug-prod */, + 332689D02D863BCE00CB35A1 /* Debug-dev */, 33CC10FA2044A3C60003C045 /* Release */, + 332689DF2D863BFF00CB35A1 /* Release-prod */, + 332689DC2D863BF900CB35A1 /* Release-dev */, 338D0CE9231458BD00FA5F75 /* Profile */, + 332689D92D863BF000CB35A1 /* Profile-prod */, + 332689D62D863BEA00CB35A1 /* Profile-dev */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -557,8 +1198,14 @@ isa = XCConfigurationList; buildConfigurations = ( 33CC10FC2044A3C60003C045 /* Debug */, + 332689D42D863BD900CB35A1 /* Debug-prod */, + 332689D12D863BCE00CB35A1 /* Debug-dev */, 33CC10FD2044A3C60003C045 /* Release */, + 332689E02D863BFF00CB35A1 /* Release-prod */, + 332689DD2D863BF900CB35A1 /* Release-dev */, 338D0CEA231458BD00FA5F75 /* Profile */, + 332689DA2D863BF000CB35A1 /* Profile-prod */, + 332689D72D863BEA00CB35A1 /* Profile-dev */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -567,8 +1214,14 @@ isa = XCConfigurationList; buildConfigurations = ( 33CC111C2044C6BA0003C045 /* Debug */, + 332689D52D863BD900CB35A1 /* Debug-prod */, + 332689D22D863BCE00CB35A1 /* Debug-dev */, 33CC111D2044C6BA0003C045 /* Release */, + 332689E12D863BFF00CB35A1 /* Release-prod */, + 332689DE2D863BF900CB35A1 /* Release-dev */, 338D0CEB231458BD00FA5F75 /* Profile */, + 332689DB2D863BF000CB35A1 /* Profile-prod */, + 332689D82D863BEA00CB35A1 /* Profile-dev */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 21519e9cc..526e6fa88 100644 --- a/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ @@ -31,13 +31,24 @@ - - + + + + + + - - diff --git a/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/dev.xcscheme b/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/dev.xcscheme new file mode 100644 index 000000000..16928ff92 --- /dev/null +++ b/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/dev.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/prod.xcscheme b/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/prod.xcscheme new file mode 100644 index 000000000..86dd4b5b5 --- /dev/null +++ b/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/prod.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/macos/Runner/AppDelegate.swift b/app/macos/Runner/AppDelegate.swift index d53ef6437..b3c176141 100644 --- a/app/macos/Runner/AppDelegate.swift +++ b/app/macos/Runner/AppDelegate.swift @@ -1,9 +1,13 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/1024-mac.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/1024-mac.png new file mode 100644 index 000000000..28db11a99 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/1024-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/128-mac.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/128-mac.png new file mode 100644 index 000000000..46f71046a Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/128-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/16-mac.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/16-mac.png new file mode 100644 index 000000000..9fbba2c94 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/16-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/256-mac.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/256-mac.png new file mode 100644 index 000000000..fe95e4c5b Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/256-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/32-mac.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/32-mac.png new file mode 100644 index 000000000..7579458cf Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/32-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/512-mac.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/512-mac.png new file mode 100644 index 000000000..22f3495b5 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/512-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/64-mac.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/64-mac.png new file mode 100644 index 000000000..1bc475449 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/64-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f19..eba1335b9 100644 --- a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} +{"images":[{"size":"1024x1024","filename":"1024-mac.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"128x128","expected-size":"128","filename":"128-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]} \ No newline at end of file diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png deleted file mode 100644 index 3c4935a7c..000000000 Binary files a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png and /dev/null differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png deleted file mode 100644 index ed4cc1642..000000000 Binary files a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png and /dev/null differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png deleted file mode 100644 index 483be6138..000000000 Binary files a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png and /dev/null differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png deleted file mode 100644 index bcbf36df2..000000000 Binary files a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png and /dev/null differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png deleted file mode 100644 index 9c0a65286..000000000 Binary files a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png and /dev/null differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png deleted file mode 100644 index e71a72613..000000000 Binary files a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png and /dev/null differ diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png deleted file mode 100644 index 8a31fe2dd..000000000 Binary files a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png and /dev/null differ diff --git a/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/1024-mac.png b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/1024-mac.png new file mode 100644 index 000000000..28db11a99 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/1024-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/128-mac.png b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/128-mac.png new file mode 100644 index 000000000..46f71046a Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/128-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/16-mac.png b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/16-mac.png new file mode 100644 index 000000000..9fbba2c94 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/16-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/256-mac.png b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/256-mac.png new file mode 100644 index 000000000..fe95e4c5b Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/256-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/32-mac.png b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/32-mac.png new file mode 100644 index 000000000..7579458cf Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/32-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/512-mac.png b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/512-mac.png new file mode 100644 index 000000000..22f3495b5 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/512-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/64-mac.png b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/64-mac.png new file mode 100644 index 000000000..1bc475449 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/64-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/Contents.json b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/Contents.json new file mode 100644 index 000000000..eba1335b9 --- /dev/null +++ b/app/macos/Runner/Assets.xcassets/devAppIcon.appiconset/Contents.json @@ -0,0 +1 @@ +{"images":[{"size":"1024x1024","filename":"1024-mac.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"128x128","expected-size":"128","filename":"128-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]} \ No newline at end of file diff --git a/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/1024-mac.png b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/1024-mac.png new file mode 100644 index 000000000..28db11a99 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/1024-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/128-mac.png b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/128-mac.png new file mode 100644 index 000000000..46f71046a Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/128-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/16-mac.png b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/16-mac.png new file mode 100644 index 000000000..9fbba2c94 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/16-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/256-mac.png b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/256-mac.png new file mode 100644 index 000000000..fe95e4c5b Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/256-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/32-mac.png b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/32-mac.png new file mode 100644 index 000000000..7579458cf Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/32-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/512-mac.png b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/512-mac.png new file mode 100644 index 000000000..22f3495b5 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/512-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/64-mac.png b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/64-mac.png new file mode 100644 index 000000000..1bc475449 Binary files /dev/null and b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/64-mac.png differ diff --git a/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/Contents.json b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/Contents.json new file mode 100644 index 000000000..eba1335b9 --- /dev/null +++ b/app/macos/Runner/Assets.xcassets/prodAppIcon.appiconset/Contents.json @@ -0,0 +1 @@ +{"images":[{"size":"1024x1024","filename":"1024-mac.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"128x128","expected-size":"128","filename":"128-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024-mac.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]} \ No newline at end of file diff --git a/app/macos/Runner/Configs/AppInfo.xcconfig b/app/macos/Runner/Configs/AppInfo.xcconfig index baca66c70..d2642245c 100644 --- a/app/macos/Runner/Configs/AppInfo.xcconfig +++ b/app/macos/Runner/Configs/AppInfo.xcconfig @@ -5,10 +5,10 @@ // 'flutter create' template. // The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = Friend +PRODUCT_NAME = Omi // The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.friend.ios +PRODUCT_BUNDLE_IDENTIFIER = com.friend-app-with-wearable.ios12 // The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright ยฉ 2024 Friend. All rights reserved. +PRODUCT_COPYRIGHT = Copyright ยฉ 2024 Omi AI. All rights reserved. diff --git a/app/macos/Runner/DebugProfile.entitlements b/app/macos/Runner/DebugProfile.entitlements index 3ba6c1266..6ffa35f64 100644 --- a/app/macos/Runner/DebugProfile.entitlements +++ b/app/macos/Runner/DebugProfile.entitlements @@ -2,13 +2,26 @@ + com.apple.developer.applesignin + + Default + com.apple.security.app-sandbox com.apple.security.cs.allow-jit + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + com.apple.security.network.client - com.apple.security.network.server + com.apple.security.personal-information.location + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + diff --git a/app/macos/Runner/Info.plist b/app/macos/Runner/Info.plist index 4789daa6a..905ad7c36 100644 --- a/app/macos/Runner/Info.plist +++ b/app/macos/Runner/Info.plist @@ -18,15 +18,71 @@ APPL CFBundleShortVersionString $(FLUTTER_BUILD_NAME) + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + h.omi.me + CFBundleURLSchemes + + https + + + + CFBundleTypeRole + Editor + CFBundleURLName + h.omi.me + CFBundleURLSchemes + + com.googleusercontent.apps.208440318997-ukinsq3sijhcetkhr26ssqp1terbq7as + + + CFBundleVersion $(FLUTTER_BUILD_NUMBER) + LSApplicationCategoryType + public.app-category.productivity LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) + NSBluetoothAlwaysUsageDescription + Bluetooth permission is required to connect with your Omi. + NSBluetoothPeripheralUsageDescription + Bluetooth permission is required to connect with your Omi. + NSCalendarsFullAccessUsageDescription + Access most functions for calendar viewing and editing. + NSCalendarsUsageDescription + Access most functions for calendar viewing and editing. + NSCameraUsageDescription + Camera access is required to report issues + NSContactsUsageDescription + Access contacts for event attendee editing. NSHumanReadableCopyright $(PRODUCT_COPYRIGHT) + NSLocationAlwaysAndWhenInUseUsageDescription + Your location is used to tag where conversations take place, helping provide context in omi memory. This is optional, and your exact location is never stored or shared. + NSLocationUsageDescription + Your location is used to tag where conversations take place, helping provide context in omi memory. This is optional, and your exact location is never stored or shared.. + NSLocationWhenInUseUsageDescription + Your location is used to tag where conversations take place, helping provide context in omi memory. This is optional, and your exact location is never stored or shared. NSMainNibFile MainMenu + NSMicrophoneUsageDescription + Omi records your microphone audio as part of conversation recording feature and transcribes in real-time + NSPhotoLibraryUsageDescription + We need access to your photo library to allow you to upload and share photos through Instabug. NSPrincipalClass NSApplication + PermissionGroupNotification + You need to enable notifications to receive your pro-active feedback. + com.apple.security.app-sandbox + + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + diff --git a/app/macos/Runner/MainFlutterWindow.swift b/app/macos/Runner/MainFlutterWindow.swift index 2722837ec..c34dad5ea 100644 --- a/app/macos/Runner/MainFlutterWindow.swift +++ b/app/macos/Runner/MainFlutterWindow.swift @@ -1,15 +1,919 @@ import Cocoa import FlutterMacOS +import ScreenCaptureKit +import AVFoundation +import CoreBluetooth +import CoreLocation +import UserNotifications -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController.init() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) +class MainFlutterWindow: NSWindow, SCStreamDelegate, SCStreamOutput, CBCentralManagerDelegate, CLLocationManagerDelegate { - RegisterGeneratedPlugins(registry: flutterViewController) + enum AudioQuality: Int { + case normal = 128, good = 192, high = 256, extreme = 320 + } - super.awakeFromNib() - } + var availableContent: SCShareableContent? + var filter: SCContentFilter? + var audioSettings: [String: Any]! + var stream: SCStream! + + private let audioEngine = AVAudioEngine() + private let systemAudioPlayerNode = AVAudioPlayerNode() + private let mixerNode = AVAudioMixerNode() + + private var engineProcessingFormat: AVAudioFormat! + private var micNode: AVAudioInputNode! + private var micNodeFormat: AVAudioFormat! + var outputAudioFormat: AVAudioFormat? + var audioConverter: AVAudioConverter? + + private var screenCaptureChannel: FlutterMethodChannel! + private var audioFormatSentToFlutter: Bool = false + + private var scStreamSourceFormat: AVAudioFormat? + + // Two-step conversion: intermediate format and second converter + private var scStreamIntermediateFormat: AVAudioFormat? + private var scStreamSecondConverter: AVAudioConverter? + + // Bluetooth and Location managers + private var bluetoothManager: CBCentralManager? + private var locationManager: CLLocationManager? + private var bluetoothPermissionCompletion: ((Bool) -> Void)? + private var locationPermissionCompletion: ((Bool) -> Void)? + private var notificationPermissionCompletion: ((Bool) -> Void)? + + // Manual resampling function to avoid AVAudioConverter OSStatus errors + private func resampleAudio(input: [Float], fromRate: Double, toRate: Double) -> [Float] { + if fromRate == toRate { + return input + } + + let ratio = fromRate / toRate + let outputCount = Int(Double(input.count) / ratio) + var output = [Float](repeating: 0, count: outputCount) + + for i in 0.. [Float] { + let count = min(leftChannel.count, rightChannel.count) + var mono = [Float](repeating: 0, count: count) + for i in 0.. String { + switch AVAudioApplication.shared.recordPermission { + case .granted: + return "granted" + case .denied: + return "denied" + case .undetermined: + return "undetermined" + @unknown default: + return "unknown" + } + } + + @available(macOS 14.0, *) + func requestMicrophonePermission() async -> Bool { + guard AVAudioApplication.shared.recordPermission != .granted else { + return true // Already granted + } + + let granted = await AVAudioApplication.requestRecordPermission() + print("Microphone permission request result: \(granted)") + return granted + } + + func checkScreenCapturePermission() async -> String { + do { + // Try to get shareable content to check if we have permission + let content = try await SCShareableContent.excludingDesktopWindows(true, onScreenWindowsOnly: true) + return content.displays.isEmpty ? "denied" : "granted" + } catch { + if case SCStreamError.userDeclined = error { + return "denied" + } + return "undetermined" + } + } + + func requestScreenCapturePermission() async -> Bool { + do { + let content = try await SCShareableContent.excludingDesktopWindows(true, onScreenWindowsOnly: true) + return !content.displays.isEmpty + } catch { + if case SCStreamError.userDeclined = error { + // Open system preferences for user to grant permission + await MainActor.run { + NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture")!) + } + return false + } + print("Error checking screen capture permission: \(error)") + return false + } + } + + // MARK: - Bluetooth Permission Management + + func checkBluetoothPermission() -> String { + if #available(macOS 10.15, *) { + switch CBCentralManager.authorization { + case .allowedAlways: + return "granted" + case .denied: + return "denied" + case .restricted: + return "restricted" + case .notDetermined: + return "undetermined" + @unknown default: + return "unknown" + } + } else { + // For older macOS versions, assume granted if Bluetooth is available + return "granted" + } + } + + func requestBluetoothPermission() async -> Bool { + if #available(macOS 10.15, *) { + guard CBCentralManager.authorization != .allowedAlways else { + return true + } + + // If explicitly denied or restricted, can't request again + if CBCentralManager.authorization == .denied || CBCentralManager.authorization == .restricted { + print("Bluetooth permission is \(CBCentralManager.authorization.rawValue), cannot request again") + return false + } + + // Check if Bluetooth service is available first + let tempManager = CBCentralManager() + if tempManager.state == .poweredOff { + print("Bluetooth is powered off. User needs to enable Bluetooth in System Settings.") + await MainActor.run { + NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.bluetooth")!) + } + return false + } else if tempManager.state == .unsupported { + print("Bluetooth is not supported on this device.") + return false + } + + return await withCheckedContinuation { continuation in + // Set up timeout to prevent continuation leak + Task { + try? await Task.sleep(nanoseconds: 15_000_000_000) // 15 seconds timeout for Bluetooth + if bluetoothPermissionCompletion != nil { + print("Bluetooth permission request timed out") + bluetoothPermissionCompletion?(false) + } + } + + bluetoothPermissionCompletion = { granted in + continuation.resume(returning: granted) + self.bluetoothPermissionCompletion = nil // Clear to prevent multiple calls + } + + // Initialize CBCentralManager to trigger permission request + if bluetoothManager == nil { + print("Initializing Bluetooth central manager...") + bluetoothManager = CBCentralManager(delegate: self, queue: nil) + } else { + // If manager already exists, check current state + print("Bluetooth manager exists, checking current state...") + centralManagerDidUpdateState(bluetoothManager!) + } + } + } else { + print("Bluetooth permission handling not available on macOS < 10.15, assuming granted") + return true + } + } + + // MARK: - Location Permission Management + + func checkLocationPermission() -> String { + switch CLLocationManager.authorizationStatus() { + case .authorizedAlways, .authorized: + return "granted" + case .denied: + return "denied" + case .restricted: + return "restricted" + case .notDetermined: + return "undetermined" + @unknown default: + return "unknown" + } + } + + func requestLocationPermission() async -> Bool { + let currentStatus = CLLocationManager.authorizationStatus() + guard currentStatus != .authorizedAlways && currentStatus != .authorized else { + return true // Already granted + } + + guard currentStatus == .notDetermined else { + // If denied or restricted, open system preferences + print("Location permission is \(currentStatus.rawValue), opening System Preferences") + await MainActor.run { + NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_LocationServices")!) + } + return false + } + + // Check if location services are enabled before requesting + guard CLLocationManager.locationServicesEnabled() else { + print("Location services are disabled system-wide, opening System Preferences") + await MainActor.run { + NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_LocationServices")!) + } + return false + } + + return await withCheckedContinuation { continuation in + // Set up timeout to prevent continuation leak + Task { + try? await Task.sleep(nanoseconds: 10_000_000_000) // 10 seconds timeout + if locationPermissionCompletion != nil { + print("Location permission request timed out") + locationPermissionCompletion?(false) + } + } + + locationPermissionCompletion = { granted in + continuation.resume(returning: granted) + self.locationPermissionCompletion = nil // Clear to prevent multiple calls + } + + if locationManager == nil { + locationManager = CLLocationManager() + locationManager?.delegate = self + } + + locationManager?.requestWhenInUseAuthorization() + } + } + + // MARK: - Notification Permission Management + + func checkNotificationPermission() async -> String { + let center = UNUserNotificationCenter.current() + let settings = await center.notificationSettings() + + switch settings.authorizationStatus { + case .authorized: + return "granted" + case .denied: + return "denied" + case .notDetermined: + return "undetermined" + case .provisional: + return "provisional" + case .ephemeral: + return "ephemeral" + @unknown default: + return "unknown" + } + } + + func requestNotificationPermission() async -> Bool { + let center = UNUserNotificationCenter.current() + let currentSettings = await center.notificationSettings() + + guard currentSettings.authorizationStatus != .authorized else { + return true + } + + guard currentSettings.authorizationStatus == .notDetermined else { + // If denied, open system preferences + print("Notification permission is \(currentSettings.authorizationStatus.rawValue), opening System Preferences") + await MainActor.run { + NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.notifications")!) + } + return false + } + + do { + let granted = try await center.requestAuthorization(options: [.alert, .sound, .badge]) + print("Notification permission request result: \(granted)") + return granted + } catch { + print("Error requesting notification permission: \(error.localizedDescription)") + return false + } + } + + // MARK: - CBCentralManagerDelegate + + func centralManagerDidUpdateState(_ central: CBCentralManager) { + print("Bluetooth central manager state updated to: \(central.state.rawValue)") + + // Handle different Bluetooth states + switch central.state { + case .poweredOff: + print("Bluetooth is powered off. Permission cannot be granted until Bluetooth is enabled.") + bluetoothPermissionCompletion?(false) + bluetoothPermissionCompletion = nil + return + case .unsupported: + print("Bluetooth is not supported on this device.") + bluetoothPermissionCompletion?(false) + bluetoothPermissionCompletion = nil + return + case .unauthorized: + print("Bluetooth access is not authorized for this app.") + bluetoothPermissionCompletion?(false) + bluetoothPermissionCompletion = nil + return + case .poweredOn: + break + case .unknown, .resetting: + print("Bluetooth state is \(central.state). Waiting for definitive state...") + return + @unknown default: + print("Unknown Bluetooth state: \(central.state)") + return + } + + if #available(macOS 10.15, *) { + let granted: Bool + switch CBCentralManager.authorization { + case .allowedAlways: + granted = true + case .denied, .restricted: + granted = false + case .notDetermined: + granted = (central.state == .poweredOn) + @unknown default: + granted = false + } + + print("Bluetooth permission resolved: granted=\(granted)") + bluetoothPermissionCompletion?(granted) + bluetoothPermissionCompletion = nil + } else { + let granted = (central.state == .poweredOn) + bluetoothPermissionCompletion?(granted) + bluetoothPermissionCompletion = nil + } + } + + // MARK: - CLLocationManagerDelegate + + func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { + print("Location authorization changed to: \(status.rawValue)") + + guard let completion = locationPermissionCompletion else { + print("Location permission completion is nil, ignoring delegate call") + return + } + + let granted = (status == .authorizedAlways || status == .authorized) + print("Location permission resolved: granted=\(granted)") + completion(granted) + } + + func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { + print("Location manager failed with error: \(error.localizedDescription)") + locationPermissionCompletion?(false) + } + + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + screenCaptureChannel = FlutterMethodChannel( + name: "screenCapturePlatform", + binaryMessenger: flutterViewController.engine.binaryMessenger) + + self.micNode = audioEngine.inputNode + self.micNodeFormat = self.micNode.outputFormat(forBus: 0) + + // Attempt to enable voice processing for AEC + // This should be done before the engine is started or the graph is fully configured. + if #available(macOS 10.15, *) { + do { + try self.micNode.setVoiceProcessingEnabled(true) + // Configure ducking to minimum level to keep system audio audible + if #available(macOS 14.0, *) { + var duckingConfig = AVAudioVoiceProcessingOtherAudioDuckingConfiguration() + duckingConfig.enableAdvancedDucking = false + duckingConfig.duckingLevel = .min + self.micNode.voiceProcessingOtherAudioDuckingConfiguration = duckingConfig + print("DEBUG: Configured voice processing ducking to minimum level to preserve system audio volume.") + } else { + print("INFO: Voice processing ducking configuration requires macOS 14.0+. System audio may be ducked on older OS versions.") + } + print("DEBUG: Successfully enabled voice processing on microphone input node. This may help reduce echo.") + } catch { + print("ERROR: Could not enable voice processing on microphone input node: \(error.localizedDescription). Echo might persist.") + } + } else { + print("INFO: Voice processing on AVAudioInputNode requires macOS 10.15+. Echo might persist on older OS versions.") + } + + engineProcessingFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, + sampleRate: self.micNodeFormat.sampleRate, // Use mic's native rate + channels: 1, // MONO for mixing + interleaved: false) + + print("DEBUG: Engine processing format (mic native SR: \(self.micNodeFormat.sampleRate)) SR: \(engineProcessingFormat.sampleRate), CH: \(engineProcessingFormat.channelCount)") + + setupAudioEngine() // Uses engineProcessingFormat for mixer tap and systemAudioPlayerNode connection + + screenCaptureChannel.setMethodCallHandler { [weak self] (call, result) in + guard let self = self else { return } + switch call.method { + case "checkMicrophonePermission": + if #available(macOS 14.0, *) { + let status = self.checkMicrophonePermission() + result(status) + } else { + result("unavailable") + } + + case "requestMicrophonePermission": + if #available(macOS 14.0, *) { + Task { + let granted = await self.requestMicrophonePermission() + result(granted) + } + } else { + result(false) + } + + case "checkScreenCapturePermission": + Task { + let status = await self.checkScreenCapturePermission() + result(status) + } + + case "requestScreenCapturePermission": + Task { + let granted = await self.requestScreenCapturePermission() + result(granted) + } + + case "checkBluetoothPermission": + let status = self.checkBluetoothPermission() + result(status) + + case "requestBluetoothPermission": + Task { + let granted = await self.requestBluetoothPermission() + result(granted) + } + + case "checkLocationPermission": + let status = self.checkLocationPermission() + result(status) + + case "requestLocationPermission": + Task { + let granted = await self.requestLocationPermission() + result(granted) + } + + case "checkNotificationPermission": + Task { + let status = await self.checkNotificationPermission() + result(status) + } + + case "requestNotificationPermission": + Task { + let granted = await self.requestNotificationPermission() + result(granted) + } + + case "start": + Task { + // Check permissions before starting + if #available(macOS 14.0, *) { + let micStatus = self.checkMicrophonePermission() + if micStatus != "granted" { + result(FlutterError(code: "MIC_PERMISSION_REQUIRED", + message: "Microphone permission is required. Current status: \(micStatus)", + details: nil)) + return + } + } + + let screenStatus = await self.checkScreenCapturePermission() + if screenStatus != "granted" { + result(FlutterError(code: "SCREEN_PERMISSION_REQUIRED", + message: "Screen capture permission is required. Current status: \(screenStatus)", + details: nil)) + return + } + + self.audioFormatSentToFlutter = false + self.scStreamSourceFormat = nil // Reset for new stream + + SCShareableContent.getExcludingDesktopWindows(true, onScreenWindowsOnly: true) { content, error in + if let error = error { + self.handleError(error, result: result) + return + } + self.availableContent = content + + // outputAudioFormat for Flutter (e.g., 16kHz or 44.1kHz Mono Int16) + // Let's target 16kHz for Flutter as a common speech rate. + let flutterOutputSampleRate = 16000.0 + let flutterOutputChannels: AVAudioChannelCount = 1 + self.updateAudioSettings(sampleRate: flutterOutputSampleRate, channels: flutterOutputChannels) + + print("DEBUG: Flutter output format will be SR: \(flutterOutputSampleRate), CH: \(flutterOutputChannels)") + self.outputAudioFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, + sampleRate: flutterOutputSampleRate, + channels: flutterOutputChannels, + interleaved: true) + + guard let strongOutputAudioFormat = self.outputAudioFormat else { + result(FlutterError(code: "AUDIO_FORMAT_ERROR", message: "Could not create final output audio format for Flutter", details: nil)) + return + } + + // Final converter: engineProcessingFormat -> outputAudioFormat (for Flutter) + self.audioConverter = AVAudioConverter(from: self.engineProcessingFormat, to: strongOutputAudioFormat) + guard self.audioConverter != nil else { + result(FlutterError(code: "CONVERTER_SETUP_ERROR", message: "Could not create main audio converter to Flutter format", details: nil)) + return + } + self.audioConverter?.sampleRateConverterAlgorithm = AVSampleRateConverterAlgorithm_Mastering + self.audioConverter?.sampleRateConverterQuality = .max + + // Enable dithering for better quality when converting to Int16 + self.audioConverter?.dither = true + print("DEBUG: Final audioConverter configured with mastering algorithm and dithering") + + // Send format details to Flutter + let isBigEndian = (strongOutputAudioFormat.streamDescription.pointee.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 + let formatDetails: [String: Any] = [ + "sampleRate": strongOutputAudioFormat.sampleRate, + "channels": strongOutputAudioFormat.channelCount, + "bitsPerChannel": strongOutputAudioFormat.streamDescription.pointee.mBitsPerChannel, + "isFloat": (strongOutputAudioFormat.commonFormat == .pcmFormatFloat32 || strongOutputAudioFormat.commonFormat == .pcmFormatFloat64), + "isBigEndian": isBigEndian, + "isInterleaved": strongOutputAudioFormat.isInterleaved + ] + self.screenCaptureChannel.invokeMethod("audioFormat", arguments: formatDetails) + self.audioFormatSentToFlutter = true + + self.prepSCStreamFilter() + + do { + try self.startAudioEngineAndCapture() + Task { await self.recordSCStream(filter: self.filter!) } + result(nil) + } catch { + print("Error starting audio engine or capture: \(error.localizedDescription)") + result(FlutterError(code: "ENGINE_START_ERROR", message: error.localizedDescription, details: nil)) + } + } + } + case "stop": + self.stopAudioEngineAndCapture() + result(nil) + default: + result(FlutterMethodNotImplemented) + } + } + super.awakeFromNib() + } + + func handleError(_ error: Error, result: FlutterResult) { + switch error { + case SCStreamError.userDeclined: + NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture")!) + result(FlutterError(code: "PERMISSION_ERROR", message: "User declined screen capture permission.", details: nil)) + default: + print("[err] failed to fetch available content: \(error.localizedDescription)") + result(FlutterError(code: "SHAREABLE_CONTENT_ERROR", message: error.localizedDescription, details: nil)) + } + } + + func setupAudioEngine() { + audioEngine.attach(systemAudioPlayerNode) + audioEngine.attach(mixerNode) + + // Set systemAudioPlayerNode to full volume to ensure system audio is captured properly + systemAudioPlayerNode.volume = 4.0 + + print("DEBUG: Mic native format: \(self.micNodeFormat!))") + print("DEBUG: Engine processing format: \(self.engineProcessingFormat!))") + + audioEngine.connect(self.micNode, to: mixerNode, format: self.micNodeFormat) // Mic uses its native format + + // systemAudioPlayerNode connected to mixer using engineProcessingFormat + audioEngine.connect(systemAudioPlayerNode, to: mixerNode, format: self.engineProcessingFormat) + + // Set mixer output volume to ensure proper levels + mixerNode.outputVolume = 4.0 + + // Mixer tap is at engineProcessingFormat + mixerNode.installTap(onBus: 0, bufferSize: 1024, format: self.engineProcessingFormat) { [weak self] (buffer, time) in + guard let self = self, let finalConverter = self.audioConverter, let finalOutputFormat = self.outputAudioFormat else { + // print("Mixer tap: finalConverter or finalOutputFormat is nil") + return + } + + let outputBufferFrameCapacity = AVAudioFrameCount(Double(buffer.frameLength) * (finalOutputFormat.sampleRate / buffer.format.sampleRate)) + guard let outputPCMBuffer = AVAudioPCMBuffer(pcmFormat: finalOutputFormat, frameCapacity: outputBufferFrameCapacity) else { + print("Failed to create output PCM buffer for final converter.") + return + } + // outputPCMBuffer.frameLength = outputPCMBuffer.frameCapacity // Set frameLength after conversion + + var error: NSError? + let status = finalConverter.convert(to: outputPCMBuffer, error: &error) { inNumPackets, outStatus in + outStatus.pointee = .haveData + return buffer + } + + if status == .error || error != nil { + print("Final audio conversion error from mixer tap: \(error?.localizedDescription ?? "Unknown error")") + return + } + + if status == .haveData && outputPCMBuffer.frameLength > 0 { + outputPCMBuffer.frameLength = outputPCMBuffer.frameCapacity // THIS WAS IN THE WRONG PLACE - set it before checking data size if using frameCapacity + // Actually, the converter sets the frameLength of outputPCMBuffer. + + if finalOutputFormat.commonFormat == .pcmFormatInt16 && finalOutputFormat.isInterleaved { + let dataSize = Int(outputPCMBuffer.frameLength) * Int(finalOutputFormat.streamDescription.pointee.mBytesPerFrame) + if dataSize > 0, let int16Data = outputPCMBuffer.int16ChannelData?[0] { + let audioData = Data(bytes: int16Data, count: dataSize) + if self.audioFormatSentToFlutter { + self.screenCaptureChannel.invokeMethod("audioFrame", arguments: audioData) + } + } else if dataSize == 0 && outputPCMBuffer.frameLength > 0 { + print("DEBUG: Final converter output dataSize is 0 but frameLength > 0. Format: \(finalOutputFormat)") + } + } + } + } + + // REMOVED: The connection from mixerNode to outputNode was causing echo feedback. + // Keeping it in comment so that everyone can see it and understand why it was removed. + // The mixerNode was routing the combined audio (including microphone) back to system output, + // which SCStream would then capture, creating a circular feedback loop. + // We only need the mixer for combining sources and tapping for recording, not for playback. + // audioEngine.disconnectNodeOutput(mixerNode) // make sure we have a clean slot + // audioEngine.connect(mixerNode, to: audioEngine.outputNode, format: self.engineProcessingFormat) + // mixerNode.volume = 0 // mute โ€“ we only need the connection for clocking, not playback + print("DEBUG: Mixer NOT connected to outputNode to prevent echo feedback loop.") + + audioEngine.prepare() + } + + func prepSCStreamFilter() { + let excluded = availableContent?.applications.filter { app in + Bundle.main.bundleIdentifier == app.bundleIdentifier + } + filter = SCContentFilter(display: availableContent!.displays.first!, excludingApplications: excluded ?? [], exceptingWindows: []) + + // Reset SCStream source format for a new session + scStreamSourceFormat = nil + } + + func startAudioEngineAndCapture() throws { + // REMOVED AVAudioSession configuration lines that are unavailable/problematic on macOS + + if !audioEngine.isRunning { + try audioEngine.start() + print("DEBUG: AVAudioEngine started.") + } + + // Ensure systemAudioPlayerNode is playing AFTER the engine has started. + if systemAudioPlayerNode.engine != nil && !systemAudioPlayerNode.isPlaying { + systemAudioPlayerNode.play() + print("DEBUG: systemAudioPlayerNode explicitly started in startAudioEngineAndCapture.") + } else if systemAudioPlayerNode.engine == nil { + print("ERROR: systemAudioPlayerNode.engine is nil in startAudioEngineAndCapture. Cannot play.") + } else if systemAudioPlayerNode.isPlaying { + print("DEBUG: systemAudioPlayerNode was already playing in startAudioEngineAndCapture.") + } + } + + func recordSCStream(filter: SCContentFilter) async { + let conf = SCStreamConfiguration() + conf.width = 2 + conf.height = 2 + conf.minimumFrameInterval = CMTime(value: 1, timescale: CMTimeScale(600)) + conf.showsCursor = false + conf.capturesAudio = true + + // DO NOT explicitly set conf.sampleRate or conf.channelCount here. + // Let SCStream use its default/preferred audio format. + // We will convert it if necessary. + // conf.sampleRate = Int(self.engineProcessingFormat.sampleRate) + // conf.channelCount = Int(self.engineProcessingFormat.channelCount) + + stream = SCStream(filter: filter, configuration: conf, delegate: self) + do { + try stream.addStreamOutput(self, type: .audio, sampleHandlerQueue: .global(qos: .userInitiated)) + try await stream.startCapture() + print("DEBUG: SCStream capture started.") + } catch { + print("Error starting SCStream capture: \(error.localizedDescription)") + self.screenCaptureChannel.invokeMethod("captureError", arguments: "SCStream: \(error.localizedDescription)") + DispatchQueue.main.async { self.stopAudioEngineAndCapture() } + } } + + func stopAudioEngineAndCapture() { + // Stop SCStream first + if stream != nil { + Task { + try? await stream.stopCapture() // Errors handled in delegate or ignored for stop + self.stream = nil + } + } + + // Stop AVAudioEngine + if audioEngine.isRunning { + audioEngine.stop() + // audioEngine.inputNode.removeTap(onBus: 0) // If mic tap was used directly + // mixerNode.removeTap(onBus: 0) // Tap is auto-removed when engine stops or node is reset + } + systemAudioPlayerNode.stop() + + + // Reset converters and formats + self.audioConverter = nil + self.scStreamSourceFormat = nil + + // Notify Flutter + if audioFormatSentToFlutter { // Only send if start was successful enough to send format + self.screenCaptureChannel.invokeMethod("audioStreamEnded", arguments: nil) + print("Recording stopped (engine & SCStream), Flutter notified.") + } else { + print("Recording stopped (engine & SCStream), but Flutter was not fully initialized for audio.") + } + audioFormatSentToFlutter = false // Reset for next session + } + + // Modified to accept parameters + func updateAudioSettings(sampleRate: Double, channels: AVAudioChannelCount) { + audioSettings = [AVSampleRateKey: sampleRate, AVNumberOfChannelsKey: channels] + } + + // SCStream Delegate methods + func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { + guard sampleBuffer.isValid, type == .audio else { return } + + guard let pcmBufferFromSCStream = sampleBuffer.asPCMBuffer else { + print("SCStream: Failed to get PCM buffer from CMSampleBuffer") + return + } + + if scStreamSourceFormat == nil { + scStreamSourceFormat = pcmBufferFromSCStream.format + print("DEBUG: SCStream actual source format: \(scStreamSourceFormat!)") + + // Detailed format logging + let sourceDesc = scStreamSourceFormat!.streamDescription.pointee + print("DEBUG: SCStream format details - SR: \(sourceDesc.mSampleRate), CH: \(sourceDesc.mChannelsPerFrame), BitsPerCh: \(sourceDesc.mBitsPerChannel), BytesPerFrame: \(sourceDesc.mBytesPerFrame), BytesPerPacket: \(sourceDesc.mBytesPerPacket)") + + let engineDesc = self.engineProcessingFormat.streamDescription.pointee + print("DEBUG: Engine format details - SR: \(engineDesc.mSampleRate), CH: \(engineDesc.mChannelsPerFrame), BitsPerCh: \(engineDesc.mBitsPerChannel), BytesPerFrame: \(engineDesc.mBytesPerFrame), BytesPerPacket: \(engineDesc.mBytesPerPacket)") + + // Check if formats differ and note for manual processing + if scStreamSourceFormat != self.engineProcessingFormat { + print("DEBUG: SCStream format (\(scStreamSourceFormat!)) differs from Engine format (\(self.engineProcessingFormat!)). Will use manual conversion.") + } else { + print("DEBUG: SCStream format matches Engine format. No conversion needed.") + } + } + + var bufferToSchedule: AVAudioPCMBuffer = pcmBufferFromSCStream + + // Manual conversion if formats differ (avoiding AVAudioConverter OSStatus errors) + guard let currentSCStreamFormat = self.scStreamSourceFormat else { + print("ERROR: scStreamSourceFormat is nil. Cannot process SCStream audio buffer. Buffer skipped.") + return + } + + if currentSCStreamFormat != self.engineProcessingFormat { + // This block is for when SCStream's format differs from our desired engineProcessingFormat (mono, float, specific SR). + // We need to ensure the input is deinterleaved float to use floatChannelData directly. + + guard currentSCStreamFormat.commonFormat == .pcmFormatFloat32, + !currentSCStreamFormat.isInterleaved, // Must be deinterleaved for this specific access pattern + let floatDataPointers = pcmBufferFromSCStream.floatChannelData else { + print("ERROR: SCStream buffer (format: \(currentSCStreamFormat.description)) is not in deinterleaved float format or floatChannelData is nil. Cannot perform current manual conversion. Buffer skipped.") + // TODO: Consider a fallback to AVAudioConverter if other formats from SCStream need robust handling here. + return + } + + let inputFrameCount = Int(pcmBufferFromSCStream.frameLength) + let inputSampleRate = currentSCStreamFormat.sampleRate + let outputSampleRate = self.engineProcessingFormat.sampleRate + var monoResampled: [Float] // This will hold the audio data after resampling and mono conversion + + if currentSCStreamFormat.channelCount == 1 { + // Input is already mono (but deinterleaved float as per guard) + let sourceChannelPtr = floatDataPointers[0] + let sourceArray = Array(UnsafeBufferPointer(start: sourceChannelPtr, count: inputFrameCount)) + if inputSampleRate != outputSampleRate { + monoResampled = resampleAudio(input: sourceArray, fromRate: inputSampleRate, toRate: outputSampleRate) + } else { + monoResampled = sourceArray + } + } else if currentSCStreamFormat.channelCount >= 2 { + // Input is stereo (or more channels, take first two) deinterleaved float + let leftChannelPtr = floatDataPointers[0] + let rightChannelPtr = floatDataPointers[1] // Safe due to channelCount >= 2 + + let leftArray = Array(UnsafeBufferPointer(start: leftChannelPtr, count: inputFrameCount)) + let rightArray = Array(UnsafeBufferPointer(start: rightChannelPtr, count: inputFrameCount)) + + let leftResampled: [Float] + let rightResampled: [Float] + + if inputSampleRate != outputSampleRate { + leftResampled = resampleAudio(input: leftArray, fromRate: inputSampleRate, toRate: outputSampleRate) + rightResampled = resampleAudio(input: rightArray, fromRate: inputSampleRate, toRate: outputSampleRate) + } else { + leftResampled = leftArray + rightResampled = rightArray + } + monoResampled = stereoToMono(leftChannel: leftResampled, rightChannel: rightResampled) + } else { + print("ERROR: SCStream buffer has \(currentSCStreamFormat.channelCount) channels (e.g., 0), which is not supported for manual conversion. Buffer skipped.") + return + } + + // Create output buffer for the processed monoResampled data + let outputFrameCount = monoResampled.count + guard let manuallyConvertedBuffer = AVAudioPCMBuffer(pcmFormat: self.engineProcessingFormat, frameCapacity: AVAudioFrameCount(outputFrameCount)) else { + print("ERROR: Failed to create output buffer for manually converted audio.") + return + } + manuallyConvertedBuffer.frameLength = AVAudioFrameCount(outputFrameCount) + + // engineProcessingFormat is known to be non-interleaved Float32, so floatChannelData![0] is correct for it. + let monoOutputDataPtr = manuallyConvertedBuffer.floatChannelData![0] + for i in 0.. AVAudioPCMBuffer? in + guard var absd = self.formatDescription?.audioStreamBasicDescription else { return nil } + guard let format = AVAudioFormat(streamDescription: &absd) else { return nil} + return AVAudioPCMBuffer(pcmFormat: format, bufferListNoCopy: audioBufferList.unsafePointer) + } + } +} \ No newline at end of file diff --git a/app/macos/Runner/Release.entitlements b/app/macos/Runner/Release.entitlements index 7a2230dc3..e0df0dbef 100644 --- a/app/macos/Runner/Release.entitlements +++ b/app/macos/Runner/Release.entitlements @@ -2,11 +2,24 @@ + com.apple.developer.applesignin + + Default + com.apple.security.app-sandbox + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + com.apple.security.network.client - com.apple.security.network.server + com.apple.security.personal-information.location + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + diff --git a/app/macos/Runner/RunnerDebug-dev.entitlements b/app/macos/Runner/RunnerDebug-dev.entitlements new file mode 100644 index 000000000..6ffa35f64 --- /dev/null +++ b/app/macos/Runner/RunnerDebug-dev.entitlements @@ -0,0 +1,27 @@ + + + + + com.apple.developer.applesignin + + Default + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.network.client + + com.apple.security.personal-information.location + + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + + + diff --git a/app/macos/Runner/RunnerDebug-prod.entitlements b/app/macos/Runner/RunnerDebug-prod.entitlements new file mode 100644 index 000000000..6ffa35f64 --- /dev/null +++ b/app/macos/Runner/RunnerDebug-prod.entitlements @@ -0,0 +1,27 @@ + + + + + com.apple.developer.applesignin + + Default + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.network.client + + com.apple.security.personal-information.location + + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + + + diff --git a/app/macos/Runner/RunnerDebug.entitlements b/app/macos/Runner/RunnerDebug.entitlements new file mode 100644 index 000000000..0dc95ad16 --- /dev/null +++ b/app/macos/Runner/RunnerDebug.entitlements @@ -0,0 +1,29 @@ + + + + + com.apple.developer.applesignin + + Default + + com.apple.developer.aps-environment + development + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.network.client + + com.apple.security.personal-information.location + + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + + + diff --git a/app/macos/Runner/RunnerProfile-prod.entitlements b/app/macos/Runner/RunnerProfile-prod.entitlements new file mode 100644 index 000000000..6ffa35f64 --- /dev/null +++ b/app/macos/Runner/RunnerProfile-prod.entitlements @@ -0,0 +1,27 @@ + + + + + com.apple.developer.applesignin + + Default + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.network.client + + com.apple.security.personal-information.location + + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + + + diff --git a/app/macos/Runner/RunnerProfile.entitlements b/app/macos/Runner/RunnerProfile.entitlements new file mode 100644 index 000000000..6ffa35f64 --- /dev/null +++ b/app/macos/Runner/RunnerProfile.entitlements @@ -0,0 +1,27 @@ + + + + + com.apple.developer.applesignin + + Default + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.network.client + + com.apple.security.personal-information.location + + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + + + diff --git a/app/macos/Runner/RunnerRelease-prod.entitlements b/app/macos/Runner/RunnerRelease-prod.entitlements new file mode 100644 index 000000000..e0df0dbef --- /dev/null +++ b/app/macos/Runner/RunnerRelease-prod.entitlements @@ -0,0 +1,25 @@ + + + + + com.apple.developer.applesignin + + Default + + com.apple.security.app-sandbox + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.network.client + + com.apple.security.personal-information.location + + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + + + diff --git a/app/macos/Runner/RunnerRelease.entitlements b/app/macos/Runner/RunnerRelease.entitlements new file mode 100644 index 000000000..e0df0dbef --- /dev/null +++ b/app/macos/Runner/RunnerRelease.entitlements @@ -0,0 +1,25 @@ + + + + + com.apple.developer.applesignin + + Default + + com.apple.security.app-sandbox + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.network.client + + com.apple.security.personal-information.location + + keychain-access-groups + + $(AppIdentifierPrefix)com.google.GIDSignIn + $(AppIdentifierPrefix)com.friend-app-with-wearable.ios12 + + + diff --git a/app/macos/RunnerTests/RunnerTests.swift b/app/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000..61f3bd1fc --- /dev/null +++ b/app/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/pubspec.lock b/app/pubspec.lock new file mode 100644 index 000000000..bd0c48398 --- /dev/null +++ b/app/pubspec.lock @@ -0,0 +1,2359 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 + url: "https://pub.dev" + source: hosted + version: "72.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: de9ecbb3ddafd446095f7e833c853aff2fa1682b017921fe63a833f9d6f0e422 + url: "https://pub.dev" + source: hosted + version: "1.3.54" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.2" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 + url: "https://pub.dev" + source: hosted + version: "6.7.0" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" + url: "https://pub.dev" + source: hosted + version: "2.0.3" + app_links: + dependency: "direct main" + description: + name: app_links + sha256: "85ed8fc1d25a76475914fff28cc994653bd900bc2c26e4b57a49e097febb54ba" + url: "https://pub.dev" + source: hosted + version: "6.4.0" + app_links_linux: + dependency: transitive + description: + name: app_links_linux + sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + app_links_platform_interface: + dependency: transitive + description: + name: app_links_platform_interface + sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + app_links_web: + dependency: transitive + description: + name: app_links_web + sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + archive: + dependency: transitive + description: + name: archive + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + url: "https://pub.dev" + source: hosted + version: "3.6.1" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + audio_session: + dependency: transitive + description: + name: audio_session + sha256: "2b7fff16a552486d078bfc09a8cde19f426dc6d6329262b684182597bec5b1ac" + url: "https://pub.dev" + source: hosted + version: "0.1.25" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + awesome_notifications: + dependency: "direct main" + description: + name: awesome_notifications + sha256: d051ffb694a53da216ff13d02c8ec645d75320048262f7e6b3c1d95a4f54c902 + url: "https://pub.dev" + source: hosted + version: "0.10.0" + awesome_notifications_core: + dependency: "direct main" + description: + name: awesome_notifications_core + sha256: "38c9f9d2618c0c2abe0cea267dc161aa8c4a0a239ca2263400900b9610f33e6f" + url: "https://pub.dev" + source: hosted + version: "0.9.3" + barcode: + dependency: transitive + description: + name: barcode + sha256: "7b6729c37e3b7f34233e2318d866e8c48ddb46c1f7ad01ff7bb2a8de1da2b9f4" + url: "https://pub.dev" + source: hosted + version: "2.2.9" + bidi: + dependency: transitive + description: + name: bidi + sha256: "77f475165e94b261745cf1032c751e2032b8ed92ccb2bf5716036db79320637d" + url: "https://pub.dev" + source: hosted + version: "2.0.13" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: ea90e81dc4a25a043d9bee692d20ed6d1c4a1662a28c03a96417446c093ed6b4 + url: "https://pub.dev" + source: hosted + version: "8.9.5" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" + url: "https://pub.dev" + source: hosted + version: "3.4.1" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" + url: "https://pub.dev" + source: hosted + version: "4.1.1" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" + collection: + dependency: "direct main" + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + color: + dependency: transitive + description: + name: color + sha256: ddcdf1b3badd7008233f5acffaf20ca9f5dc2cd0172b75f68f24526a5f5725cb + url: "https://pub.dev" + source: hosted + version: "3.0.0" + connectivity_plus: + dependency: transitive + description: + name: connectivity_plus + sha256: "051849e2bd7c7b3bc5844ea0d096609ddc3a859890ec3a9ac4a65a2620cc1f99" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" + crypto: + dependency: "direct main" + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.7" + dartx: + dependency: transitive + description: + name: dartx + sha256: "8b25435617027257d43e6508b5fe061012880ddfdaa75a71d607c3de2a13d244" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + dbus: + dependency: transitive + description: + name: dbus + sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + url: "https://pub.dev" + source: hosted + version: "0.7.11" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 + url: "https://pub.dev" + source: hosted + version: "10.1.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2" + url: "https://pub.dev" + source: hosted + version: "7.0.2" + dio: + dependency: transitive + description: + name: dio + sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" + url: "https://pub.dev" + source: hosted + version: "5.8.0+1" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + dotted_border: + dependency: "direct main" + description: + name: dotted_border + sha256: "108837e11848ca776c53b30bc870086f84b62ed6e01c503ed976e8f8c7df9c04" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + envied: + dependency: "direct main" + description: + name: envied + sha256: bbff9c76120e4dc5e2e36a46690cf0a26feb65e7765633f4e8d916bcd173a450 + url: "https://pub.dev" + source: hosted + version: "0.5.4+1" + envied_generator: + dependency: "direct dev" + description: + name: envied_generator + sha256: "517b70de08d13dcd40e97b4e5347e216a0b1c75c99e704f3c85c0474a392d14a" + url: "https://pub.dev" + source: hosted + version: "0.5.4+1" + equatable: + dependency: "direct main" + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + expandable_text: + dependency: "direct main" + description: + name: expandable_text + sha256: "7d03ea48af6987b20ece232678b744862aa3250d4a71e2aaf1e4af90015d76b1" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: cacfdc5abe93e64d418caa9256eef663499ad791bb688d9fd12c85a311968fba + url: "https://pub.dev" + source: hosted + version: "8.3.2" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" + url: "https://pub.dev" + source: hosted + version: "0.9.4+2" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + url: "https://pub.dev" + source: hosted + version: "0.9.3+4" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + sha256: "06787c45d773af3db3ae693ff648ef488e6048a00b654620b3b8849988f63793" + url: "https://pub.dev" + source: hosted + version: "5.5.3" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + sha256: "5402d13f4bb7f29f2fb819f3b6b5a5a56c9f714aef2276546d397e25ac1b6b8e" + url: "https://pub.dev" + source: hosted + version: "7.6.2" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + sha256: "2be496911f0807895d5fe8067b70b7d758142dd7fb26485cbe23e525e2547764" + url: "https://pub.dev" + source: hosted + version: "5.14.2" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "017d17d9915670e6117497e640b2859e0b868026ea36bf3a57feb28c3b97debe" + url: "https://pub.dev" + source: hosted + version: "3.13.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf + url: "https://pub.dev" + source: hosted + version: "5.4.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: ddd72baa6f727e5b23f32d9af23d7d453d67946f380bd9c21daf474ee0f7326e + url: "https://pub.dev" + source: hosted + version: "2.23.0" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: "5f8918848ee0c8eb172fc7698619b2bcd7dda9ade8b93522c6297dd8f9178356" + url: "https://pub.dev" + source: hosted + version: "15.2.5" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: "0bbea00680249595fc896e7313a2bd90bd55be6e0abbe8b9a39d81b6b306acb6" + url: "https://pub.dev" + source: hosted + version: "4.6.5" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: ffb392ce2a7e8439cd0a9a80e3c702194e73c927e5c7b4f0adf6faa00b245b17 + url: "https://pub.dev" + source: hosted + version: "3.10.5" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_archive: + dependency: "direct main" + description: + name: flutter_archive + sha256: "5ca235f304c12bf468979235f400f79846d204169d715939e39197106f5fc970" + url: "https://pub.dev" + source: hosted + version: "6.0.3" + flutter_background_service: + dependency: "direct main" + description: + name: flutter_background_service + sha256: "8807ed792227be05329478870b92f2df62c7af96f49763f6d62ad39d2eac6ee6" + url: "https://pub.dev" + source: hosted + version: "5.0.7" + flutter_background_service_android: + dependency: "direct main" + description: + name: flutter_background_service_android + sha256: fe06c4bd719b8ce8512d5724a229526155c1f54f734524b8e43f8212e98384a8 + url: "https://pub.dev" + source: hosted + version: "6.2.4" + flutter_background_service_ios: + dependency: transitive + description: + name: flutter_background_service_ios + sha256: "45c8aca1e8850e5c45822152b06d5806aba9470517dcd2c291fce8ef99a44d60" + url: "https://pub.dev" + source: hosted + version: "5.0.2" + flutter_background_service_platform_interface: + dependency: "direct main" + description: + name: flutter_background_service_platform_interface + sha256: "91dd3391c213e37094fbc3fb7f34319b99ea9df76036a5c054d6371be843b0ae" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + flutter_blue_plus: + dependency: "direct main" + description: + name: flutter_blue_plus + sha256: "45ccee4a838f321c301b6130fbf3de28f07a2d6334a69eb5e13b6f83683080e0" + url: "https://pub.dev" + source: hosted + version: "1.33.6" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" + url: "https://pub.dev" + source: hosted + version: "3.4.1" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_flavorizr: + dependency: "direct dev" + description: + name: flutter_flavorizr + sha256: e9550f67a890b9111ac5a555954f3808cb8c0132ce6dea08e3381964de39b906 + url: "https://pub.dev" + source: hosted + version: "2.2.3" + flutter_foreground_task: + dependency: "direct main" + description: + name: flutter_foreground_task + sha256: "07a1719309be8c1d6ee09d2b2bb9c1136b877f94ddc272d43a7edcf11788ab57" + url: "https://pub.dev" + source: hosted + version: "8.13.0" + flutter_gen_core: + dependency: transitive + description: + name: flutter_gen_core + sha256: "46ecf0e317413dd065547887c43f93f55e9653e83eb98dc13dd07d40dd225325" + url: "https://pub.dev" + source: hosted + version: "5.8.0" + flutter_gen_runner: + dependency: "direct dev" + description: + name: flutter_gen_runner + sha256: "77f0a02fc30d9fcf2549fe874eb3fde091435724904bcbb1af60aa40cbfab1f4" + url: "https://pub.dev" + source: hosted + version: "5.8.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_markdown: + dependency: "direct main" + description: + name: flutter_markdown + sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27" + url: "https://pub.dev" + source: hosted + version: "0.7.7+1" + flutter_native_splash: + dependency: "direct main" + description: + name: flutter_native_splash + sha256: "7062602e0dbd29141fb8eb19220b5871ca650be5197ab9c1f193a28b17537bc7" + url: "https://pub.dev" + source: hosted + version: "2.4.4" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "1c2b787f99bdca1f3718543f81d38aa1b124817dfeb9fb196201bea85b6134bf" + url: "https://pub.dev" + source: hosted + version: "2.0.26" + flutter_provider_utilities: + dependency: "direct main" + description: + name: flutter_provider_utilities + sha256: a532fad19357ca79f8eaf0f162a9fdda80eda165c61f0f9fb7f46129a30dacfa + url: "https://pub.dev" + source: hosted + version: "1.0.6" + flutter_rating_bar: + dependency: "direct main" + description: + name: flutter_rating_bar + sha256: d2af03469eac832c591a1eba47c91ecc871fe5708e69967073c043b2d775ed93 + url: "https://pub.dev" + source: hosted + version: "4.0.1" + flutter_silero_vad: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: d4fcc2a287933c0d29f8bec568b3f6fffbf117ee + url: "https://github.com/char5742/flutter_silero_vad.git" + source: git + version: "0.0.1" + flutter_sound: + dependency: "direct main" + description: + name: flutter_sound + sha256: ef89477f6e8ce2fa395158ebc4a8b11982e3ada440b4021c06fd97a4e771554b + url: "https://pub.dev" + source: hosted + version: "9.28.0" + flutter_sound_platform_interface: + dependency: transitive + description: + name: flutter_sound_platform_interface + sha256: "3394d7e664a09796818014ff85a81db0dec397f4c286cbe52f8783886fa5a497" + url: "https://pub.dev" + source: hosted + version: "9.28.0" + flutter_sound_web: + dependency: transitive + description: + name: flutter_sound_web + sha256: "4e10c94a8574bd93bb8668af59bf76f5312a890bccd3778d73168a7133217dc5" + url: "https://pub.dev" + source: hosted + version: "9.28.0" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: d44bf546b13025ec7353091516f6881f1d4c633993cb109c3916c3a0159dadf1 + url: "https://pub.dev" + source: hosted + version: "2.1.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_timezone: + dependency: "direct main" + description: + name: flutter_timezone + sha256: "0cb5498dedfaac615c779138194052f04524c31d958fab33d378f22b6cc14686" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + font_awesome_flutter: + dependency: "direct main" + description: + name: font_awesome_flutter + sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a + url: "https://pub.dev" + source: hosted + version: "10.8.0" + frame_sdk: + dependency: "direct main" + description: + name: frame_sdk + sha256: afab5eede530d4f215d88bc8eb84d6b0944907bcbde58eee662253029392463b + url: "https://pub.dev" + source: hosted + version: "0.0.7" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + geolocator: + dependency: "direct main" + description: + name: geolocator + sha256: e7ebfa04ce451daf39b5499108c973189a71a919aa53c1204effda1c5b93b822 + url: "https://pub.dev" + source: hosted + version: "14.0.0" + geolocator_android: + dependency: "direct overridden" + description: + name: geolocator_android + sha256: "7aefc530db47d90d0580b552df3242440a10fe60814496a979aa67aa98b1fd47" + url: "https://pub.dev" + source: hosted + version: "4.6.1" + geolocator_apple: + dependency: transitive + description: + name: geolocator_apple + sha256: dbdd8789d5aaf14cf69f74d4925ad1336b4433a6efdf2fce91e8955dc921bf22 + url: "https://pub.dev" + source: hosted + version: "2.3.13" + geolocator_platform_interface: + dependency: transitive + description: + name: geolocator_platform_interface + sha256: "30cb64f0b9adcc0fb36f628b4ebf4f731a2961a0ebd849f4b56200205056fe67" + url: "https://pub.dev" + source: hosted + version: "4.2.6" + geolocator_web: + dependency: transitive + description: + name: geolocator_web + sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172 + url: "https://pub.dev" + source: hosted + version: "4.1.3" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6" + url: "https://pub.dev" + source: hosted + version: "0.2.5" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + google_identity_services_web: + dependency: transitive + description: + name: google_identity_services_web + sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454" + url: "https://pub.dev" + source: hosted + version: "0.3.3+1" + google_sign_in: + dependency: "direct main" + description: + name: google_sign_in + sha256: fad6ddc80c427b0bba705f2116204ce1173e09cf299f85e053d57a55e5b2dd56 + url: "https://pub.dev" + source: hosted + version: "6.2.2" + google_sign_in_android: + dependency: transitive + description: + name: google_sign_in_android + sha256: "7af72e5502c313865c729223b60e8ae7bce0a1011b250c24edcf30d3d7032748" + url: "https://pub.dev" + source: hosted + version: "6.1.35" + google_sign_in_ios: + dependency: "direct overridden" + description: + name: google_sign_in_ios + sha256: "1e0d4fde6cc07a8ff423f6bc931e83a74163d6af702004bacaee752649fdd2e7" + url: "https://pub.dev" + source: hosted + version: "5.7.5" + google_sign_in_platform_interface: + dependency: transitive + description: + name: google_sign_in_platform_interface + sha256: "5f6f79cf139c197261adb6ac024577518ae48fdff8e53205c5373b5f6430a8aa" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + google_sign_in_web: + dependency: transitive + description: + name: google_sign_in_web + sha256: "460547beb4962b7623ac0fb8122d6b8268c951cf0b646dd150d60498430e4ded" + url: "https://pub.dev" + source: hosted + version: "0.12.4+4" + googleapis_auth: + dependency: "direct main" + description: + name: googleapis_auth + sha256: befd71383a955535060acde8792e7efc11d2fccd03dd1d3ec434e85b68775938 + url: "https://pub.dev" + source: hosted + version: "1.6.0" + gradient_borders: + dependency: "direct main" + description: + name: gradient_borders + sha256: b1cd969552c83f458ff755aa68e13a0327d09f06c3f42f471b423b01427f21f8 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + group_button: + dependency: transitive + description: + name: group_button + sha256: "0610fcf28ed122bfb4b410fce161a390f7f2531d55d1d65c5375982001415940" + url: "https://pub.dev" + source: hosted + version: "5.3.4" + growthbook_sdk_flutter: + dependency: "direct main" + description: + name: growthbook_sdk_flutter + sha256: dceb65ae19be1dd8d026af578cbd52f71fc7dffd93758608dc13df837144985a + url: "https://pub.dev" + source: hosted + version: "3.9.2" + gtk: + dependency: transitive + description: + name: gtk + sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c + url: "https://pub.dev" + source: hosted + version: "2.1.0" + hashcodes: + dependency: transitive + description: + name: hashcodes + sha256: "80f9410a5b3c8e110c4b7604546034749259f5d6dcca63e0d3c17c9258f1a651" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" + http: + dependency: "direct main" + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image: + dependency: "direct dev" + description: + name: image + sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d + url: "https://pub.dev" + source: hosted + version: "4.3.0" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "82652a75e3dd667a91187769a6a2cc81bd8c111bbead698d8e938d2b63e5e89a" + url: "https://pub.dev" + source: hosted + version: "0.8.12+21" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + url: "https://pub.dev" + source: hosted + version: "0.8.12+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + url: "https://pub.dev" + source: hosted + version: "2.10.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_size_getter: + dependency: transitive + description: + name: image_size_getter + sha256: "9a299e3af2ebbcfd1baf21456c3c884037ff524316c97d8e56035ea8fdf35653" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + inject_js: + dependency: transitive + description: + name: inject_js + sha256: "849eacfd4b7e9182a7e743843a820d74bf1abcb692bdbe09e34ef0f753ad7227" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + instabug_flutter: + dependency: "direct main" + description: + name: instabug_flutter + sha256: "5f28080581dc5b07932d0e5e2fc3b6fc599ba492ce29ed10ae29d901657158d2" + url: "https://pub.dev" + source: hosted + version: "14.3.1" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + intercom_flutter: + dependency: "direct main" + description: + name: intercom_flutter + sha256: cf03612bbc9a66b0241d71ac70e874fd95fb74889d04fce262cfbac02ff8fbcc + url: "https://pub.dev" + source: hosted + version: "9.2.10" + intercom_flutter_platform_interface: + dependency: transitive + description: + name: intercom_flutter_platform_interface + sha256: "42cd30ff7fb987567d5e58092c3625e01ddb3d1831ec269df7567f333236aa51" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + intercom_flutter_web: + dependency: transitive + description: + name: intercom_flutter_web + sha256: "410f624093a30972c13df8775eaf84a8dd958629aadb90e5d367518cbea79f70" + url: "https://pub.dev" + source: hosted + version: "1.1.5" + internet_connection_checker_plus: + dependency: "direct main" + description: + name: internet_connection_checker_plus + sha256: "5aea4a1ee0fcca736980a7d04d96fe8c0b53dea330690053305a5c5392230112" + url: "https://pub.dev" + source: hosted + version: "2.7.2" + intl: + dependency: "direct main" + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + js: + dependency: "direct overridden" + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + json_serializable: + dependency: "direct main" + description: + name: json_serializable + sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b + url: "https://pub.dev" + source: hosted + version: "6.8.0" + just_audio: + dependency: "direct main" + description: + name: just_audio + sha256: f978d5b4ccea08f267dae0232ec5405c1b05d3f3cd63f82097ea46c015d5c09e + url: "https://pub.dev" + source: hosted + version: "0.9.46" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + sha256: "4cd94536af0219fa306205a58e78d67e02b0555283c1c094ee41e402a14a5c4a" + url: "https://pub.dev" + source: hosted + version: "4.5.0" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663" + url: "https://pub.dev" + source: hosted + version: "0.4.16" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: "direct dev" + description: + name: lints + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + location: + dependency: "direct main" + description: + name: location + sha256: ee57923720163324416ce0306b701db6d845d2c1a3bf44d25b607cbddbaa3973 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + location_platform_interface: + dependency: transitive + description: + name: location_platform_interface + sha256: "1e535ccc8b4a9612de4e4319871136b45d2b5d1fb0c2a8bf99687242bf7ca5f7" + url: "https://pub.dev" + source: hosted + version: "5.0.0" + location_web: + dependency: transitive + description: + name: location_web + sha256: e6435cfd175b0f6e94d6fdc43c104d13cec7e27b21a8cee00bd9516a3d6a4c81 + url: "https://pub.dev" + source: hosted + version: "5.0.4" + logger: + dependency: transitive + description: + name: logger + sha256: be4b23575aac7ebf01f225a241eb7f6b5641eeaf43c6a8613510fc2f8cf187d1 + url: "https://pub.dev" + source: hosted + version: "2.5.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + lottie: + dependency: "direct main" + description: + name: lottie + sha256: fa39707f36786707b01eca7626d2c16c32aa603b3f3a146518518458847dc127 + url: "https://pub.dev" + source: hosted + version: "3.2.0" + macros: + dependency: transitive + description: + name: macros + sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" + url: "https://pub.dev" + source: hosted + version: "0.1.2-main.4" + manage_calendar_events: + dependency: "direct main" + description: + path: "." + ref: master + resolved-ref: cdf5a528d6cd460d56bce3bd1a8ada84fe2106e3 + url: "https://github.com/beastoin/manage_calendar_events" + source: git + version: "2.0.3" + map_launcher: + dependency: "direct main" + description: + name: map_launcher + sha256: "7436d6ef9ae57ff15beafcedafe0a8f0604006cbecd2d26024c4cfb0158c2b9a" + url: "https://pub.dev" + source: hosted + version: "3.5.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" + url: "https://pub.dev" + source: hosted + version: "7.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + mcumgr_flutter: + dependency: "direct main" + description: + name: mcumgr_flutter + sha256: e19a5c420bdc20c831ffc4673a01b8fb1825fb3f42524cfc454a9862b20453f2 + url: "https://pub.dev" + source: hosted + version: "0.4.2" + meta: + dependency: transitive + description: + name: meta + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + url: "https://pub.dev" + source: hosted + version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" + url: "https://pub.dev" + source: hosted + version: "1.0.6" + mixpanel_flutter: + dependency: "direct main" + description: + name: mixpanel_flutter + sha256: "949732cdb4c115c0c33f6ad51ad217e642960ba9cf823c722b29a00c22ec47db" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + nm: + dependency: transitive + description: + name: nm + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + nordic_dfu: + dependency: "direct main" + description: + name: nordic_dfu + sha256: "498c18e7587f8aabb478fccfb93c2687ee2338595e3f81c26f82c8c8782c49ca" + url: "https://pub.dev" + source: hosted + version: "6.2.0" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + opus_dart: + dependency: "direct main" + description: + name: opus_dart + sha256: e8ab4774409997af33cbfdfe91a186854ed6458b2fec66b0e52f4434b1af2f7c + url: "https://pub.dev" + source: hosted + version: "3.0.1" + opus_flutter: + dependency: "direct main" + description: + name: opus_flutter + sha256: "86edfdab1220d64bd7daa3e9bda1785cc0c8c793629e89f34a2a87bdfce57e25" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + opus_flutter_android: + dependency: "direct overridden" + description: + path: opus_flutter_android + ref: HEAD + resolved-ref: "67ba9d8704a93c8a30b9266f4df6663e0b08e3c8" + url: "https://github.com/mdmohsin7/opus_flutter.git" + source: git + version: "3.0.1" + opus_flutter_ios: + dependency: "direct overridden" + description: + path: opus_flutter_ios + ref: dev + resolved-ref: "04696ff930a464bd47677026d45c3c3004f6daab" + url: "https://github.com/mdmohsin7/opus_flutter.git" + source: git + version: "3.0.0" + opus_flutter_platform_interface: + dependency: transitive + description: + name: opus_flutter_platform_interface + sha256: "41180b74f1dacc131270d49815fd4eb46bd7cc5ad57aac84eab748d08de59138" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + opus_flutter_web: + dependency: transitive + description: + name: opus_flutter_web + sha256: "037a4cdb27c3a1c05c85aed3dbe0a4b8c2f49ccce33cef259ef34f1815af6785" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + opus_flutter_windows: + dependency: transitive + description: + name: opus_flutter_windows + sha256: "6a26862dd331c9c4b5e4c805efe3dd4e4a049e4a18bee230d994c25d72928a3b" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + os_detect: + dependency: transitive + description: + name: os_detect + sha256: "7d87c0dd98c6faf110d5aa498e9a6df02ffce4bb78cc9cfc8ad02929be9bb71f" + url: "https://pub.dev" + source: hosted + version: "2.0.3" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + package_info_plus: + dependency: "direct main" + description: + name: package_info_plus + sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" + url: "https://pub.dev" + source: hosted + version: "8.3.0" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + path: + dependency: "direct main" + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + path_drawing: + dependency: transitive + description: + name: path_drawing + sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2" + url: "https://pub.dev" + source: hosted + version: "2.2.15" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + pdf: + dependency: "direct main" + description: + name: pdf + sha256: "28eacad99bffcce2e05bba24e50153890ad0255294f4dd78a17075a2ba5c8416" + url: "https://pub.dev" + source: hosted + version: "3.11.3" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" + url: "https://pub.dev" + source: hosted + version: "11.4.0" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc + url: "https://pub.dev" + source: hosted + version: "12.1.0" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 + url: "https://pub.dev" + source: hosted + version: "9.4.7" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" + url: "https://pub.dev" + source: hosted + version: "0.1.3+5" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 + url: "https://pub.dev" + source: hosted + version: "4.3.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" + photo_view: + dependency: "direct main" + description: + name: photo_view + sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e" + url: "https://pub.dev" + source: hosted + version: "0.15.0" + platform: + dependency: transitive + description: + name: platform + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + url: "https://pub.dev" + source: hosted + version: "3.9.1" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + posthog_flutter: + dependency: "direct main" + description: + name: posthog_flutter + sha256: "2a74b86306b3e1b27ad227aeeb5d63374afb03aa50e87af5062fec1341824b3b" + url: "https://pub.dev" + source: hosted + version: "4.11.0" + process: + dependency: transitive + description: + name: process + sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + url: "https://pub.dev" + source: hosted + version: "5.0.2" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + provider: + dependency: "direct main" + description: + name: provider + sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + url: "https://pub.dev" + source: hosted + version: "6.1.5" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + qr: + dependency: transitive + description: + name: qr + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + recase: + dependency: transitive + description: + name: recase + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "38658034f9f3c29f3b37ab0068db15caea9df2dd70d83e99300991a0d756c2a6" + url: "https://pub.dev" + source: hosted + version: "10.0.1" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b + url: "https://pub.dev" + source: hosted + version: "5.0.2" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "9f9f3d372d4304723e6136663bb291c0b93f5e4c8a4a6314347f481a33bda2b1" + url: "https://pub.dev" + source: hosted + version: "2.4.7" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + shimmer: + dependency: "direct main" + description: + name: shimmer + sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + sign_in_with_apple: + dependency: "direct main" + description: + name: sign_in_with_apple + sha256: e84a62e17b7e463abf0a64ce826c2cd1f0b72dff07b7b275e32d5302d76fb4c5 + url: "https://pub.dev" + source: hosted + version: "6.1.4" + sign_in_with_apple_platform_interface: + dependency: transitive + description: + name: sign_in_with_apple_platform_interface + sha256: c2ef2ce6273fce0c61acd7e9ff5be7181e33d7aa2b66508b39418b786cca2119 + url: "https://pub.dev" + source: hosted + version: "1.1.0" + sign_in_with_apple_web: + dependency: transitive + description: + name: sign_in_with_apple_web + sha256: "2f7c38368f49e3f2043bca4b46a4a61aaae568c140a79aa0675dc59ad0ca49bc" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + skeletonizer: + dependency: "direct main" + description: + name: skeletonizer + sha256: "0dcacc51c144af4edaf37672072156f49e47036becbc394d7c51850c5c1e884b" + url: "https://pub.dev" + source: hosted + version: "1.4.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" + url: "https://pub.dev" + source: hosted + version: "1.3.5" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709" + url: "https://pub.dev" + source: hosted + version: "2.5.4+6" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "22adfd9a2c7d634041e96d6241e6e1c8138ca6817018afc5d443fef91dcefa9c" + url: "https://pub.dev" + source: hosted + version: "2.4.1+1" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" + url: "https://pub.dev" + source: hosted + version: "3.3.0+3" + talker: + dependency: transitive + description: + name: talker + sha256: "13e4c7c77b2ebd24ca0394b42858e7d42f28b5758255129369842eb71ceac80d" + url: "https://pub.dev" + source: hosted + version: "4.7.9" + talker_flutter: + dependency: "direct main" + description: + name: talker_flutter + sha256: "3b7be2fe32750adef19a3642bb9a0256cc03750e2072f9ebad3d28150443a3f6" + url: "https://pub.dev" + source: hosted + version: "4.5.0" + talker_logger: + dependency: transitive + description: + name: talker_logger + sha256: d8d2afd912c4a185bc125d8ae84d5960c3505f7ec52856e732a4b8a0db510b5d + url: "https://pub.dev" + source: hosted + version: "4.7.9" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + time: + dependency: transitive + description: + name: time + sha256: "370572cf5d1e58adcb3e354c47515da3f7469dac3a95b447117e728e7be6f461" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + timeago: + dependency: "direct main" + description: + name: timeago + sha256: b05159406a97e1cbb2b9ee4faa9fb096fe0e2dfcd8b08fcd2a00553450d3422e + url: "https://pub.dev" + source: hosted + version: "3.7.1" + timing: + dependency: transitive + description: + name: timing + sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + tuple: + dependency: "direct main" + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + upgrader: + dependency: "direct main" + description: + name: upgrader + sha256: d45483694620883107c2f5ca1dff7cdd4237b16810337a9c9c234203eb79eb5f + url: "https://pub.dev" + source: hosted + version: "10.3.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" + url: "https://pub.dev" + source: hosted + version: "6.3.14" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" + url: "https://pub.dev" + source: hosted + version: "6.3.3" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + url: "https://pub.dev" + source: hosted + version: "3.1.4" + uuid: + dependency: "direct main" + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de" + url: "https://pub.dev" + source: hosted + version: "1.1.18" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" + url: "https://pub.dev" + source: hosted + version: "1.1.16" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + version: + dependency: "direct main" + description: + name: version + sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + visibility_detector: + dependency: "direct main" + description: + name: visibility_detector + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://pub.dev" + source: hosted + version: "0.4.0+2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + url: "https://pub.dev" + source: hosted + version: "14.2.5" + watcher: + dependency: transitive + description: + name: watcher + sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + wav: + dependency: "direct main" + description: + name: wav + sha256: e8f26c493017b64165098c13e6f27be22db6c3ed275544c048d97b667f5455bf + url: "https://pub.dev" + source: hosted + version: "1.4.0" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_ffi: + dependency: transitive + description: + name: web_ffi + sha256: "48ef8037f7bc051d11b88d0f2903e02bec21092c51833d37c3361c36e3edc4f7" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: "direct main" + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + sha256: "889a0a678e7c793c308c68739996227c9661590605e70b1f6cf6b9a6634f7aec" + url: "https://pub.dev" + source: hosted + version: "4.10.0" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "512c26ccc5b8a571fd5d13ec994b7509f142ff6faf85835e243dde3538fdc713" + url: "https://pub.dev" + source: hosted + version: "4.3.2" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: "7cb32b21825bd65569665c32bb00a34ded5779786d6201f5350979d2d529940d" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: a3d461fe3467014e05f3ac4962e5fdde2a4bf44c561cb53e9ae5c586600fdbc3 + url: "https://pub.dev" + source: hosted + version: "3.22.0" + win32: + dependency: transitive + description: + name: win32 + sha256: daf97c9d80197ed7b619040e86c8ab9a9dad285e7671ee7390f9180cc828a51e + url: "https://pub.dev" + source: hosted + version: "5.10.1" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" + url: "https://pub.dev" + source: hosted + version: "1.1.5" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 2306f9842..6ea3353a9 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. publish_to: "none" # Remove this line if you wish to publish to pub.dev -version: 1.0.61+283 +version: 1.0.64+316 environment: sdk: ">=3.0.0 <4.0.0" @@ -29,16 +29,16 @@ dependencies: visibility_detector: ^0.4.0+2 flutter_rating_bar: ^4.0.1 dotted_border: ^2.1.0 - skeletonizer: ^1.4.2 + skeletonizer: ^2.0.1 shimmer: ^3.0.0 # Firebase - firebase_core: 3.3.0 - firebase_auth: 5.1.4 - firebase_messaging: 15.0.4 + firebase_core: 3.13.0 + firebase_auth: 5.5.3 + firebase_messaging: 15.2.5 # Analytics and Support - intercom_flutter: + intercom_flutter: 9.2.10 mixpanel_flutter: ^2.2.0 posthog_flutter: ^4.10.2 @@ -48,9 +48,9 @@ dependencies: flutter_blue_plus: 1.33.6 http: ^1.2.1 pdf: ^3.11.0 - intl: ^0.19.0 + intl: ^0.20.2 permission_handler: ^11.3.1 - share_plus: ^9.0.0 + share_plus: 10.0.1 shared_preferences: ^2.2.3 url_launcher: ^6.3.0 wav: ^1.3.0 @@ -61,7 +61,7 @@ dependencies: envied: ^0.5.4+1 awesome_notifications_core: ^0.9.3 awesome_notifications: any - instabug_flutter: ^13.3.0 + instabug_flutter: ^14.3.1 nordic_dfu: ^6.1.4+hotfix mcumgr_flutter: ^0.4.2 flutter_archive: ^6.0.3 @@ -82,9 +82,9 @@ dependencies: manage_calendar_events: ^2.0.3 flutter_timezone: ^2.0.0 sign_in_with_apple: ^6.1.1 - google_sign_in: 6.2.1 + google_sign_in: 6.2.2 location: ^7.0.0 - cached_network_image: ^3.3.1 + cached_network_image: 3.4.1 map_launcher: ^3.3.1 internet_connection_checker_plus: ^2.5.0 geolocator: @@ -94,7 +94,7 @@ dependencies: just_audio: ^0.9.39 frame_sdk: ^0.0.7 web_socket_channel: ^3.0.1 - talker_flutter: + talker_flutter: 4.5.0 flutter_silero_vad: git: url: https://github.com/char5742/flutter_silero_vad.git @@ -102,14 +102,15 @@ dependencies: timeago: ^3.7.0 app_links: ^6.3.2 flutter_svg: ^2.0.16 - file_picker: 8.0.7 + file_picker: 8.3.2 photo_view: ^0.15.0 + font_awesome_flutter: ^10.8.0 dependency_overrides: http: ^1.2.1 uuid: ^4.4.0 js: ^0.7.1 - google_sign_in_ios: 5.8.1 + google_sign_in_ios: 5.7.5 opus_flutter_ios: git: url: https://github.com/mdmohsin7/opus_flutter.git @@ -119,11 +120,12 @@ dependency_overrides: git: url: https://github.com/mdmohsin7/opus_flutter.git path: opus_flutter_android - # flutter_blue_plus: - # git: - # url: https://github.com/chipweinberger/flutter_blue_plus - # ref: 1.32.13 - # version: ^1.32.13 + geolocator_android: 4.6.1 + # flutter_blue_plus: + # git: + # url: https://github.com/chipweinberger/flutter_blue_plus + # ref: 1.32.13 + # version: ^1.32.13 manage_calendar_events: git: url: https://github.com/beastoin/manage_calendar_events diff --git a/app/setup.sh b/app/setup.sh index 97ffa4739..060eae68d 100644 --- a/app/setup.sh +++ b/app/setup.sh @@ -1,14 +1,23 @@ #!/bin/bash # # Set up the Omi Mobile Project(iOS/Android). -# Prerequisites: -# - Flutter SDK -# - Dart SDK -# - Xcode (for iOS) -# - CocoaPods (for iOS dependencies) -# - Android Studio (for Android) -# - NDK 26.3.11579264 or above (to build Opus for ARM Devices) +# +# Prerequisites (stable versions, use these or higher): +# +# Common for all developers: +# - Flutter SDK (v3.24.1) # - Opus Codec: https://opus-codec.org +# +# For iOS Developers: +# - Xcode (v15.2) +# - CocoaPods (v1.14.3) +# +# For Android Developers: +# - Android Studio (Iguana | 2023.2.1 Patch 2) +# - Android SDK Platform (API 34) +# - JDK (v17) +# - Gradle (v8.10) +# - NDK (27.0.12077973) # Usages: # - $bash setup.sh ios # - $bash setup.sh android @@ -16,14 +25,22 @@ set -euo pipefail echo "๐Ÿ‘‹ Yo folks! Welcome to the OMI Mobile Project - We're hiring! Join us on Discord: http://discord.omi.me" -echo "Prerequisites:" -echo "- Flutter SDK" -echo "- Dart SDK" -echo "- Xcode (for iOS)" -echo "- CocoaPods (for iOS dependencies)" -echo "- Android Studio (for Android)" -echo "- NDK 26.3.11579264 or above (to build Opus for ARM Devices)" +echo "Prerequisites (stable versions, use these or higher):" +echo "" +echo "Common for all developers:" +echo "- Flutter SDK (v3.24.1)" echo "- Opus Codec: https://opus-codec.org" +echo "" +echo "For iOS Developers:" +echo "- Xcode (v15.2)" +echo "- CocoaPods (v1.14.3)" +echo "" +echo "For Android Developers:" +echo "- Android Studio (Iguana | 2023.2.1 Patch 2)" +echo "- Android SDK Platform (API 34)" +echo "- JDK (v17)" +echo "- Gradle (v8.10)" +echo "- NDK (27.0.12077973)" echo "Usages:" echo "- bash setup.sh ios" echo "- bash setup.sh android" diff --git a/app/setup/scripts/setup.ps1 b/app/setup/scripts/setup.ps1 index 192ca0d26..5ff761c19 100644 --- a/app/setup/scripts/setup.ps1 +++ b/app/setup/scripts/setup.ps1 @@ -1,20 +1,44 @@ # Set up the Omi Mobile Project(iOS/Android). -# Prerequisites same as original script +# +# Prerequisites (stable versions, use these or higher): +# +# Common for all developers: +# - Flutter SDK (v3.24.1) +# - Opus Codec: https://opus-codec.org +# +# For iOS Developers: +# - Xcode (v15.2) +# - CocoaPods (v1.14.3) +# +# For Android Developers: +# - Android Studio (Iguana | 2023.2.1 Patch 2) +# - Android SDK Platform (API 34) +# - JDK (v17) +# - Gradle (v8.10) +# - NDK (27.0.12077973) # Enable strict mode Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" Write-Host "๐Ÿ‘‹ Yo folks! Welcome to the OMI Mobile Project - We're hiring! Join us on Discord: http://discord.omi.me" -Write-Host "Prerequisites:" -Write-Host "- Flutter SDK" -Write-Host "- Dart SDK" -Write-Host "- Xcode (for iOS)" -Write-Host "- CocoaPods (for iOS dependencies)" -Write-Host "- Android Studio (for Android)" -Write-Host "- NDK 26.3.11579264 or above (to build Opus for ARM Devices)" +Write-Host "Prerequisites (stable versions, use these or higher):" +Write-Host "" +Write-Host "Common for all developers:" +Write-Host "- Flutter SDK (v3.24.1)" Write-Host "- Opus Codec: https://opus-codec.org" Write-Host "" +Write-Host "For iOS Developers:" +Write-Host "- Xcode (v15.2)" +Write-Host "- CocoaPods (v1.14.3)" +Write-Host "" +Write-Host "For Android Developers:" +Write-Host "- Android Studio (Iguana | 2023.2.1 Patch 2)" +Write-Host "- Android SDK Platform (API 34)" +Write-Host "- JDK (v17)" +Write-Host "- Gradle (v8.10)" +Write-Host "- NDK (27.0.12077973)" +Write-Host "" function SetupFirebase { @@ -154,4 +178,4 @@ switch ($platform.ToLower()) { Write-Host "Unexpected platform '$platform'. Please use 'ios' or 'android'" exit 1 } -} \ No newline at end of file +} diff --git a/backend/.env.template b/backend/.env.template index 6538ca77f..b75b49737 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -37,4 +37,9 @@ STRIPE_CONNECT_WEBHOOK_SECRET= BASE_API_URL= RAPID_API_HOST= -RAPID_API_KEY= \ No newline at end of file +RAPID_API_KEY= + +# Firebase OAuth +FIREBASE_API_KEY= +FIREBASE_AUTH_DOMAIN= +FIREBASE_PROJECT_ID= diff --git a/backend/charts/deepgram-self-hosted/.helmignore b/backend/charts/backend-listen/.helmignore similarity index 100% rename from backend/charts/deepgram-self-hosted/.helmignore rename to backend/charts/backend-listen/.helmignore diff --git a/backend/charts/backend-listen/Chart.yaml b/backend/charts/backend-listen/Chart.yaml new file mode 100644 index 000000000..3ad962e75 --- /dev/null +++ b/backend/charts/backend-listen/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: backend-listen +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. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/backend/charts/backend-listen/dev_omi_backend_listen_values.yaml b/backend/charts/backend-listen/dev_omi_backend_listen_values.yaml new file mode 100644 index 000000000..35fbafa61 --- /dev/null +++ b/backend/charts/backend-listen/dev_omi_backend_listen_values.yaml @@ -0,0 +1,289 @@ +# Default values for backend-listen. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ +replicaCount: 1 + +# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ +image: + repository: gcr.io/based-hardware-dev/backend + # This sets the pull policy for images. + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "latest" + +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# This is to override the chart name. +nameOverride: "" +fullnameOverride: "" + +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: 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: "" + +# This is for setting Kubernetes Annotations to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +podAnnotations: {} +# This is for setting Kubernetes Labels to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ +service: + # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ClusterIP + # This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports + port: 8080 + annotations: + cloud.google.com/neg: '{"exposed_ports": {"8080":{"name": "dev-backend-listen-neg"}}}' + +# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +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 + +env: + - name: DEEPGRAM_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: DEEPGRAM_API_KEY + - name: FAL_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: FAL_KEY + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: OPENAI_API_KEY + - name: GOOGLE_MAPS_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: GOOGLE_MAPS_API_KEY + - name: GITHUB_TOKEN + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: GITHUB_TOKEN + - name: SONIOX_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: SONIOX_API_KEY + - name: BUCKET_SPEECH_PROFILES + value: "speech-profiles-dev" + - name: BUCKET_TEMPORAL_SYNC_LOCAL + value: "syncing-local-development" + - name: HOSTED_VAD_API_URL + value: "http://34.172.155.20:80/v1/vad" + - name: HOSTED_SPEECH_PROFILE_API_URL + value: "http://34.172.155.20:80/v1/speaker-identification" + - name: PINECONE_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: PINECONE_API_KEY + - name: PINECONE_INDEX_NAME + value: "memories-backend-dev" + - name: REDIS_DB_HOST + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: REDIS_DB_HOST + - name: REDIS_DB_PORT + value: "10797" + - name: REDIS_DB_PASSWORD + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: REDIS_DB_PASSWORD + - name: ADMIN_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: ADMIN_KEY + - name: WORKFLOW_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: WORKFLOW_API_KEY + - name: NO_SOCKET_TIMEOUT + value: "true" + - name: HOSTED_PUSHER_API_URL + value: "http://internal-alb.pusher-ep-dev.il7.us-central1.lb.based-hardware-dev.internal" + - name: BUCKET_PLUGINS_LOGOS + value: "plugin_resources" + - name: GOOGLE_APPLICATION_CREDENTIALS + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: GOOGLE_APPLICATION_CREDENTIALS + - name: DD_SERVICE + value: "backend-listen" + - name: DD_ENV + value: "dev" + - name: DD_TRACE_SAMPLE_RATE + value: "1" + - name: DD_SITE + value: "us5.datadoghq.com" + - name: DD_TRACE_PROPAGATION_STYLE + value: "datadog" + - name: DD_TRACE_ENABLED + value: "false" + - name: DD_VERSION + value: "1" + - name: DD_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: DD_API_KEY + - name: LANGCHAIN_TRACING_V2 + value: "false" + - name: LANGCHAIN_ENDPOINT + value: "https://api.smith.langchain.com" + - name: LANGCHAIN_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: LANGCHAIN_API_KEY + - name: LANGCHAIN_PROJECT + value: "development" + - name: DD_LOGS_ENABLED + value: "false" + - name: STRIPE_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: STRIPE_API_KEY + - name: STRIPE_WEBHOOK_SECRET + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: STRIPE_WEBHOOK_SECRET + - name: MARKETPLACE_APP_REVIEWERS + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: MARKETPLACE_APP_REVIEWERS + - name: TYPESENSE_HOST + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: TYPESENSE_HOST + - name: TYPESENSE_HOST_PORT + value: "443" + - name: TYPESENSE_API_KEY + valueFrom: + secretKeyRef: + name: dev-omi-backend-secrets + key: TYPESENSE_API_KEY + - name: DEEPGRAM_SELF_HOSTED_ENABLED + value: "true" + - name: DEEPGRAM_SELF_HOSTED_URL + value: "https://dg.omiapi.com" + +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:'. + requests: + cpu: 1 + memory: 4Gi + limits: + cpu: 2 + memory: 6Gi + +# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +livenessProbe: + tcpSocket: + port: 8080 + failureThreshold: 30 + periodSeconds: 10 + +readinessProbe: + tcpSocket: + port: 8080 + failureThreshold: 30 + periodSeconds: 10 + +startupProbe: + tcpSocket: + port: 8080 + failureThreshold: 30 + periodSeconds: 10 + +# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ +autoscaling: + enabled: true + minReplicas: 1 + maxReplicas: 10 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 70 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: service + operator: In + values: + - backend-listen + - key: env + operator: In + values: + - dev diff --git a/backend/charts/backend-listen/node_pool_system_config.yaml b/backend/charts/backend-listen/node_pool_system_config.yaml new file mode 100644 index 000000000..fd3f4fab1 --- /dev/null +++ b/backend/charts/backend-listen/node_pool_system_config.yaml @@ -0,0 +1,4 @@ +kubeletConfig: {} +linuxConfig: + sysctl: + net.core.somaxconn: '1048576' diff --git a/backend/charts/backend-listen/prod_omi_backend_listen_values.yaml b/backend/charts/backend-listen/prod_omi_backend_listen_values.yaml new file mode 100644 index 000000000..da4492c82 --- /dev/null +++ b/backend/charts/backend-listen/prod_omi_backend_listen_values.yaml @@ -0,0 +1,316 @@ +# Default values for backend-listen. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ +replicaCount: 1 + +# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ +image: + repository: gcr.io/based-hardware/backend + # This sets the pull policy for images. + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "latest" + +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# This is to override the chart name. +nameOverride: "" +fullnameOverride: "" + +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: 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: "" + +# This is for setting Kubernetes Annotations to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +podAnnotations: {} +# This is for setting Kubernetes Labels to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ +service: + # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ClusterIP + # This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports + port: 8080 + annotations: + cloud.google.com/neg: '{"exposed_ports": {"8080":{"name": "prod-backend-listen-neg"}}}' + +# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +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 + +env: + - name: BUCKET_SPEECH_PROFILES + value: "speech-profiles" + - name: GITHUB_TOKEN + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: GITHUB_TOKEN + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: OPENAI_API_KEY + - name: FAL_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: FAL_KEY + - name: GROQ_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: GROQ_API_KEY + - name: SONIOX_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: SONIOX_API_KEY + - name: HOSTED_VAD_API_URL + value: "http://172.16.128.101:8080/v1/vad" + - name: HOSTED_SPEECH_PROFILE_API_URL + value: "http://172.16.128.101:8080/v1/speaker-identification" + - name: PINECONE_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: PINECONE_API_KEY + - name: PINECONE_INDEX_NAME + value: "memories-backend" + - name: REDIS_DB_HOST + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: REDIS_DB_HOST + - name: REDIS_DB_PORT + value: "13151" + - name: REDIS_DB_PASSWORD + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: REDIS_DB_PASSWORD + - name: ADMIN_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: ADMIN_KEY + - name: DEEPGRAM_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: DEEPGRAM_API_KEY + - name: GOOGLE_MAPS_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: GOOGLE_MAPS_API_KEY + - name: WORKFLOW_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: WORKFLOW_API_KEY + - name: NO_SOCKET_TIMEOUT + value: "true" + - name: BUCKET_TEMPORAL_SYNC_LOCAL + value: "syncing-local" + - name: GOOGLE_APPLICATION_CREDENTIALS + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: GOOGLE_APPLICATION_CREDENTIALS + - name: HOSTED_PUSHER_API_URL + value: "http://internal-alb.pusher-ep-prod.il7.us-central1.lb.based-hardware.internal" + - name: BUCKET_PLUGINS_LOGOS + value: "omi_plugins" + - name: LANGCHAIN_TRACING_V2 + value: "false" + - name: LANGCHAIN_ENDPOINT + value: "https://api.smith.langchain.com" + - name: LANGCHAIN_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: LANGCHAIN_API_KEY + - name: LANGCHAIN_PROJECT + value: "production" + - name: DD_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: DD_API_KEY + - name: DD_SITE + value: "us5.datadoghq.com" + - name: DD_TRACE_ENABLED + value: "true" + - name: DD_TRACE_PROPAGATION_STYLE + value: "datadog" + - name: DD_TRACE_SAMPLE_RATE + value: "1" + - name: DD_LOGS_ENABLED + value: "true" + - name: DD_SERVICE + value: "backend-listen" + - name: DD_ENV + value: "prod" + - name: DD_VERSION + value: "1" + - name: STRIPE_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: STRIPE_API_KEY + - name: STRIPE_WEBHOOK_SECRET + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: STRIPE_WEBHOOK_SECRET + - name: MARKETPLACE_APP_REVIEWERS + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: MARKETPLACE_APP_REVIEWERS + - name: TYPESENSE_HOST + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: TYPESENSE_HOST + - name: TYPESENSE_HOST_PORT + value: "443" + - name: TYPESENSE_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: TYPESENSE_API_KEY + - name: DEEPGRAM_SELF_HOSTED_ENABLED + value: "true" + - name: DEEPGRAM_SELF_HOSTED_URL + value: "https://dg.omi.me" + - name: RAPID_API_HOST + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: RAPID_API_HOST + - name: RAPID_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: RAPID_API_KEY + - name: OPENROUTER_API_KEY + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: OPENROUTER_API_KEY + - name: GOOGLE_CLOUD_PROJECT + value: "based-hardware" + - name: CONVERSATION_SUMMARIZED_APP_IDS + valueFrom: + secretKeyRef: + name: prod-omi-backend-secrets + key: CONVERSATION_SUMMARIZED_APP_IDS + +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:'. + requests: + cpu: 1 + memory: 4Gi + limits: + cpu: 2 + memory: 6Gi + +# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +livenessProbe: + tcpSocket: + port: 8080 + failureThreshold: 30 + periodSeconds: 10 + +readinessProbe: + tcpSocket: + port: 8080 + failureThreshold: 30 + periodSeconds: 10 + +startupProbe: + tcpSocket: + port: 8080 + failureThreshold: 30 + periodSeconds: 10 + +# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ +autoscaling: + enabled: true + minReplicas: 10 + maxReplicas: 50 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 70 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: service + operator: In + values: + - backend-listen + - key: env + operator: In + values: + - prod diff --git a/backend/charts/backend-listen/templates/NOTES.txt b/backend/charts/backend-listen/templates/NOTES.txt new file mode 100644 index 000000000..225d314f1 --- /dev/null +++ b/backend/charts/backend-listen/templates/NOTES.txt @@ -0,0 +1,22 @@ +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 }}{{ .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 "backend-listen.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 its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "backend-listen.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "backend-listen.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 "backend-listen.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/backend/charts/backend-listen/templates/_helpers.tpl b/backend/charts/backend-listen/templates/_helpers.tpl new file mode 100644 index 000000000..a40910f05 --- /dev/null +++ b/backend/charts/backend-listen/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "backend-listen.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 "backend-listen.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 "backend-listen.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "backend-listen.labels" -}} +helm.sh/chart: {{ include "backend-listen.chart" . }} +{{ include "backend-listen.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "backend-listen.selectorLabels" -}} +app.kubernetes.io/name: {{ include "backend-listen.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "backend-listen.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "backend-listen.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/backend/charts/backend-listen/templates/deployment.yaml b/backend/charts/backend-listen/templates/deployment.yaml new file mode 100644 index 000000000..10394f080 --- /dev/null +++ b/backend/charts/backend-listen/templates/deployment.yaml @@ -0,0 +1,86 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "backend-listen.fullname" . }} + labels: + {{- include "backend-listen.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "backend-listen.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "backend-listen.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "backend-listen.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.env }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.startupProbe }} + startupProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- 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 }} diff --git a/backend/charts/backend-listen/templates/hpa.yaml b/backend/charts/backend-listen/templates/hpa.yaml new file mode 100644 index 000000000..438a2ae86 --- /dev/null +++ b/backend/charts/backend-listen/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "backend-listen.fullname" . }} + labels: + {{- include "backend-listen.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "backend-listen.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/backend/charts/backend-listen/templates/ingress.yaml b/backend/charts/backend-listen/templates/ingress.yaml new file mode 100644 index 000000000..2c15dc45e --- /dev/null +++ b/backend/charts/backend-listen/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "backend-listen.fullname" . }} + labels: + {{- include "backend-listen.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- 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: {{ .path }} + {{- with .pathType }} + pathType: {{ . }} + {{- end }} + backend: + service: + name: {{ include "backend-listen.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backend/charts/backend-listen/templates/service.yaml b/backend/charts/backend-listen/templates/service.yaml new file mode 100644 index 000000000..e60b4dc37 --- /dev/null +++ b/backend/charts/backend-listen/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "backend-listen.fullname" . }} + labels: + {{- include "backend-listen.labels" . | nindent 4 }} +{{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "backend-listen.selectorLabels" . | nindent 4 }} diff --git a/backend/charts/backend-listen/templates/serviceaccount.yaml b/backend/charts/backend-listen/templates/serviceaccount.yaml new file mode 100644 index 000000000..7504df4c6 --- /dev/null +++ b/backend/charts/backend-listen/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "backend-listen.serviceAccountName" . }} + labels: + {{- include "backend-listen.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/backend/charts/backend-listen/templates/tests/test-connection.yaml b/backend/charts/backend-listen/templates/tests/test-connection.yaml new file mode 100644 index 000000000..a39247514 --- /dev/null +++ b/backend/charts/backend-listen/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "backend-listen.fullname" . }}-test-connection" + labels: + {{- include "backend-listen.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "backend-listen.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/backend/charts/backend-listen/values.yaml b/backend/charts/backend-listen/values.yaml new file mode 100644 index 000000000..9e0aafb59 --- /dev/null +++ b/backend/charts/backend-listen/values.yaml @@ -0,0 +1,123 @@ +# Default values for backend-listen. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ +replicaCount: 1 + +# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ +image: + repository: nginx + # This sets the pull policy for images. + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# This is to override the chart name. +nameOverride: "" +fullnameOverride: "" + +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: 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: "" + +# This is for setting Kubernetes Annotations to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +podAnnotations: {} +# This is for setting Kubernetes Labels to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ +service: + # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ClusterIP + # This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports + port: 80 + +# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +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 + # 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 + +# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +# livenessProbe: +# httpGet: +# path: / +# port: http +# readinessProbe: +# httpGet: +# path: / +# port: http + +# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/backend/charts/backend-secrets/dev_omi_backend_secrets_values.yaml b/backend/charts/backend-secrets/dev_omi_backend_secrets_values.yaml index ef72aef14..03e6e8ac6 100644 --- a/backend/charts/backend-secrets/dev_omi_backend_secrets_values.yaml +++ b/backend/charts/backend-secrets/dev_omi_backend_secrets_values.yaml @@ -16,3 +16,41 @@ externalSecret: secretKeys: # secretKey is the key in the Kubernetes secret, remoteKey is the key in the Secrets Manager - secretKey: HUGGINGFACE_TOKEN remoteKey: HUGGINGFACE_TOKEN + - secretKey: DEEPGRAM_API_KEY + remoteKey: DEEPGRAM_API_KEY + - secretKey: FAL_KEY + remoteKey: FAL_KEY + - secretKey: OPENAI_API_KEY + remoteKey: OPENAI_API_KEY + - secretKey: GOOGLE_MAPS_API_KEY + remoteKey: GOOGLE_MAPS_API_KEY + - secretKey: GITHUB_TOKEN + remoteKey: GITHUB_TOKEN + - secretKey: SONIOX_API_KEY + remoteKey: SONIOX_API_KEY + - secretKey: PINECONE_API_KEY + remoteKey: PINECONE_API_KEY + - secretKey: REDIS_DB_HOST + remoteKey: REDIS_DB_HOST + - secretKey: REDIS_DB_PASSWORD + remoteKey: REDIS_DB_PASSWORD + - secretKey: ADMIN_KEY + remoteKey: ADMIN_KEY + - secretKey: WORKFLOW_API_KEY + remoteKey: WORKFLOW_API_KEY + - secretKey: GOOGLE_APPLICATION_CREDENTIALS + remoteKey: GOOGLE_APPLICATION_CREDENTIALS + - secretKey: DD_API_KEY + remoteKey: DD_API_KEY + - secretKey: LANGCHAIN_API_KEY + remoteKey: LANGCHAIN_API_KEY + - secretKey: STRIPE_API_KEY + remoteKey: STRIPE_API_KEY + - secretKey: STRIPE_WEBHOOK_SECRET + remoteKey: STRIPE_WEBHOOK_SECRET + - secretKey: MARKETPLACE_APP_REVIEWERS + remoteKey: MARKETPLACE_APP_REVIEWERS + - secretKey: TYPESENSE_HOST + remoteKey: TYPESENSE_HOST + - secretKey: TYPESENSE_API_KEY + remoteKey: TYPESENSE_API_KEY diff --git a/backend/charts/backend-secrets/prod_omi_backend_secrets_values.yaml b/backend/charts/backend-secrets/prod_omi_backend_secrets_values.yaml index ef72aef14..26a97be17 100644 --- a/backend/charts/backend-secrets/prod_omi_backend_secrets_values.yaml +++ b/backend/charts/backend-secrets/prod_omi_backend_secrets_values.yaml @@ -16,3 +16,51 @@ externalSecret: secretKeys: # secretKey is the key in the Kubernetes secret, remoteKey is the key in the Secrets Manager - secretKey: HUGGINGFACE_TOKEN remoteKey: HUGGINGFACE_TOKEN + - secretKey: GITHUB_TOKEN + remoteKey: GITHUB_TOKEN + - secretKey: OPENAI_API_KEY + remoteKey: OPENAI_API_KEY + - secretKey: FAL_KEY + remoteKey: FAL_KEY + - secretKey: GROQ_API_KEY + remoteKey: GROQ_API_KEY + - secretKey: SONIOX_API_KEY + remoteKey: SONIOX_API_KEY + - secretKey: PINECONE_API_KEY + remoteKey: PINECONE_API_KEY + - secretKey: REDIS_DB_HOST + remoteKey: REDIS_DB_HOST + - secretKey: REDIS_DB_PASSWORD + remoteKey: REDIS_DB_PASSWORD + - secretKey: ADMIN_KEY + remoteKey: ADMIN_KEY + - secretKey: DEEPGRAM_API_KEY + remoteKey: DEEPGRAM_API_KEY + - secretKey: GOOGLE_MAPS_API_KEY + remoteKey: GOOGLE_MAPS_API_KEY + - secretKey: WORKFLOW_API_KEY + remoteKey: WORKFLOW_API_KEY + - secretKey: GOOGLE_APPLICATION_CREDENTIALS + remoteKey: GOOGLE_APPLICATION_CREDENTIALS + - secretKey: LANGCHAIN_API_KEY + remoteKey: LANGCHAIN_API_KEY + - secretKey: DD_API_KEY + remoteKey: DD_API_KEY + - secretKey: STRIPE_API_KEY + remoteKey: STRIPE_API_KEY + - secretKey: STRIPE_WEBHOOK_SECRET + remoteKey: STRIPE_WEBHOOK_SECRET + - secretKey: MARKETPLACE_APP_REVIEWERS + remoteKey: MARKETPLACE_APP_REVIEWERS + - secretKey: TYPESENSE_HOST + remoteKey: TYPESENSE_HOST + - secretKey: TYPESENSE_API_KEY + remoteKey: TYPESENSE_API_KEY + - secretKey: RAPID_API_HOST + remoteKey: RAPID_API_HOST + - secretKey: RAPID_API_KEY + remoteKey: RAPID_API_KEY + - secretKey: OPENROUTER_API_KEY + remoteKey: OPENROUTER_API_KEY + - secretKey: CONVERSATION_SUMMARIZED_APP_IDS + remoteKey: CONVERSATION_SUMMARIZED_APP_IDS diff --git a/backend/charts/deepgram-self-hosted/nova-2/.helmignore b/backend/charts/deepgram-self-hosted/nova-2/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-2/.helmignore @@ -0,0 +1,23 @@ +# 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/backend/charts/deepgram-self-hosted/CHANGELOG.md b/backend/charts/deepgram-self-hosted/nova-2/CHANGELOG.md similarity index 100% rename from backend/charts/deepgram-self-hosted/CHANGELOG.md rename to backend/charts/deepgram-self-hosted/nova-2/CHANGELOG.md diff --git a/backend/charts/deepgram-self-hosted/Chart.yaml b/backend/charts/deepgram-self-hosted/nova-2/Chart.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/Chart.yaml rename to backend/charts/deepgram-self-hosted/nova-2/Chart.yaml diff --git a/backend/charts/deepgram-self-hosted/README.md b/backend/charts/deepgram-self-hosted/nova-2/README.md similarity index 100% rename from backend/charts/deepgram-self-hosted/README.md rename to backend/charts/deepgram-self-hosted/nova-2/README.md diff --git a/backend/charts/deepgram-self-hosted/README.md.gotmpl b/backend/charts/deepgram-self-hosted/nova-2/README.md.gotmpl similarity index 100% rename from backend/charts/deepgram-self-hosted/README.md.gotmpl rename to backend/charts/deepgram-self-hosted/nova-2/README.md.gotmpl diff --git a/backend/charts/deepgram-self-hosted/charts/cluster-autoscaler-9.46.0.tgz b/backend/charts/deepgram-self-hosted/nova-2/charts/cluster-autoscaler-9.46.0.tgz similarity index 100% rename from backend/charts/deepgram-self-hosted/charts/cluster-autoscaler-9.46.0.tgz rename to backend/charts/deepgram-self-hosted/nova-2/charts/cluster-autoscaler-9.46.0.tgz diff --git a/backend/charts/deepgram-self-hosted/charts/gpu-operator-v24.9.2.tgz b/backend/charts/deepgram-self-hosted/nova-2/charts/gpu-operator-v24.9.2.tgz similarity index 100% rename from backend/charts/deepgram-self-hosted/charts/gpu-operator-v24.9.2.tgz rename to backend/charts/deepgram-self-hosted/nova-2/charts/gpu-operator-v24.9.2.tgz diff --git a/backend/charts/deepgram-self-hosted/charts/kube-prometheus-stack-69.3.2.tgz b/backend/charts/deepgram-self-hosted/nova-2/charts/kube-prometheus-stack-69.3.2.tgz similarity index 100% rename from backend/charts/deepgram-self-hosted/charts/kube-prometheus-stack-69.3.2.tgz rename to backend/charts/deepgram-self-hosted/nova-2/charts/kube-prometheus-stack-69.3.2.tgz diff --git a/backend/charts/deepgram-self-hosted/charts/prometheus-adapter-4.11.0.tgz b/backend/charts/deepgram-self-hosted/nova-2/charts/prometheus-adapter-4.11.0.tgz similarity index 100% rename from backend/charts/deepgram-self-hosted/charts/prometheus-adapter-4.11.0.tgz rename to backend/charts/deepgram-self-hosted/nova-2/charts/prometheus-adapter-4.11.0.tgz diff --git a/backend/charts/deepgram-self-hosted/dev_omi_deepgram_grafana_alb_cert.yaml b/backend/charts/deepgram-self-hosted/nova-2/dev_omi_deepgram_grafana_alb_cert.yaml similarity index 78% rename from backend/charts/deepgram-self-hosted/dev_omi_deepgram_grafana_alb_cert.yaml rename to backend/charts/deepgram-self-hosted/nova-2/dev_omi_deepgram_grafana_alb_cert.yaml index 95a16202c..4af795c0b 100644 --- a/backend/charts/deepgram-self-hosted/dev_omi_deepgram_grafana_alb_cert.yaml +++ b/backend/charts/deepgram-self-hosted/nova-2/dev_omi_deepgram_grafana_alb_cert.yaml @@ -4,4 +4,4 @@ metadata: name: dev-omi-deepgram-grafana-alb-cert spec: domains: - - dg-monitor.omiapi.com \ No newline at end of file + - dg-monitor.omiapi.com diff --git a/backend/charts/deepgram-self-hosted/dev_omi_values.yaml b/backend/charts/deepgram-self-hosted/nova-2/dev_omi_values.yaml similarity index 98% rename from backend/charts/deepgram-self-hosted/dev_omi_values.yaml rename to backend/charts/deepgram-self-hosted/nova-2/dev_omi_values.yaml index 027a04285..8553b46be 100644 --- a/backend/charts/deepgram-self-hosted/dev_omi_values.yaml +++ b/backend/charts/deepgram-self-hosted/nova-2/dev_omi_values.yaml @@ -67,7 +67,7 @@ scaling: api: image: path: us-central1-docker.pkg.dev/based-hardware-dev/deepgram/self-hosted-api - tag: release-250331 + tag: release-250130 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -100,7 +100,7 @@ api: engine: image: path: us-central1-docker.pkg.dev/based-hardware-dev/deepgram/self-hosted-engine - tag: release-250331 + tag: release-250130 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -136,7 +136,7 @@ licenseProxy: enabled: true image: path: us-central1-docker.pkg.dev/based-hardware-dev/deepgram/self-hosted-license-proxy - tag: release-250331 + tag: release-250130 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: diff --git a/backend/charts/deepgram-self-hosted/prod_omi_deepgram_grafana_alb_cert.yaml b/backend/charts/deepgram-self-hosted/nova-2/prod_omi_deepgram_grafana_alb_cert.yaml similarity index 80% rename from backend/charts/deepgram-self-hosted/prod_omi_deepgram_grafana_alb_cert.yaml rename to backend/charts/deepgram-self-hosted/nova-2/prod_omi_deepgram_grafana_alb_cert.yaml index e8ea9641a..6fb46f2ee 100644 --- a/backend/charts/deepgram-self-hosted/prod_omi_deepgram_grafana_alb_cert.yaml +++ b/backend/charts/deepgram-self-hosted/nova-2/prod_omi_deepgram_grafana_alb_cert.yaml @@ -4,4 +4,4 @@ metadata: name: prod-omi-deepgram-grafana-alb-cert spec: domains: - - dg-monitor.omi.me \ No newline at end of file + - dg-monitor.omi.me diff --git a/backend/charts/deepgram-self-hosted/prod_omi_values.yaml b/backend/charts/deepgram-self-hosted/nova-2/prod_omi_values.yaml similarity index 98% rename from backend/charts/deepgram-self-hosted/prod_omi_values.yaml rename to backend/charts/deepgram-self-hosted/nova-2/prod_omi_values.yaml index d5a18350f..f4fcfd36b 100644 --- a/backend/charts/deepgram-self-hosted/prod_omi_values.yaml +++ b/backend/charts/deepgram-self-hosted/nova-2/prod_omi_values.yaml @@ -45,7 +45,7 @@ scaling: engine: # -- Minimum number of Engine replicas. - minReplicas: 2 + minReplicas: 3 # -- Maximum number of Engine replicas. maxReplicas: 10 metrics: @@ -67,7 +67,7 @@ scaling: api: image: path: us-central1-docker.pkg.dev/based-hardware/deepgram/self-hosted-api - tag: release-250331 + tag: release-250130 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -100,7 +100,7 @@ api: engine: image: path: us-central1-docker.pkg.dev/based-hardware/deepgram/self-hosted-engine - tag: release-250331 + tag: release-250130 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -136,7 +136,7 @@ licenseProxy: enabled: true image: path: us-central1-docker.pkg.dev/based-hardware/deepgram/self-hosted-license-proxy - tag: release-250331 + tag: release-250130 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: diff --git a/backend/charts/deepgram-self-hosted/samples/01-basic-setup-aws.cluster-config.yaml b/backend/charts/deepgram-self-hosted/nova-2/samples/01-basic-setup-aws.cluster-config.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/samples/01-basic-setup-aws.cluster-config.yaml rename to backend/charts/deepgram-self-hosted/nova-2/samples/01-basic-setup-aws.cluster-config.yaml diff --git a/backend/charts/deepgram-self-hosted/samples/01-basic-setup-aws.values.yaml b/backend/charts/deepgram-self-hosted/nova-2/samples/01-basic-setup-aws.values.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/samples/01-basic-setup-aws.values.yaml rename to backend/charts/deepgram-self-hosted/nova-2/samples/01-basic-setup-aws.values.yaml diff --git a/backend/charts/deepgram-self-hosted/samples/02-basic-setup-gcp.yaml b/backend/charts/deepgram-self-hosted/nova-2/samples/02-basic-setup-gcp.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/samples/02-basic-setup-gcp.yaml rename to backend/charts/deepgram-self-hosted/nova-2/samples/02-basic-setup-gcp.yaml diff --git a/backend/charts/deepgram-self-hosted/samples/03-basic-setup-onprem.yaml b/backend/charts/deepgram-self-hosted/nova-2/samples/03-basic-setup-onprem.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/samples/03-basic-setup-onprem.yaml rename to backend/charts/deepgram-self-hosted/nova-2/samples/03-basic-setup-onprem.yaml diff --git a/backend/charts/deepgram-self-hosted/samples/README.md b/backend/charts/deepgram-self-hosted/nova-2/samples/README.md similarity index 100% rename from backend/charts/deepgram-self-hosted/samples/README.md rename to backend/charts/deepgram-self-hosted/nova-2/samples/README.md diff --git a/backend/charts/deepgram-self-hosted/templates/NOTES.txt b/backend/charts/deepgram-self-hosted/nova-2/templates/NOTES.txt similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/NOTES.txt rename to backend/charts/deepgram-self-hosted/nova-2/templates/NOTES.txt diff --git a/backend/charts/deepgram-self-hosted/templates/_helpers.tpl b/backend/charts/deepgram-self-hosted/nova-2/templates/_helpers.tpl similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/_helpers.tpl rename to backend/charts/deepgram-self-hosted/nova-2/templates/_helpers.tpl diff --git a/backend/charts/deepgram-self-hosted/templates/api/api.config.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/api/api.config.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/api/api.config.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/api/api.config.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/api/api.deployment.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/api/api.deployment.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/api/api.deployment.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/api/api.deployment.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/api/api.hpa.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/api/api.hpa.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/api/api.hpa.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/api/api.hpa.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/api/api.ingress.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/api/api.ingress.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/api/api.ingress.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/api/api.ingress.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/api/api.rbac.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/api/api.rbac.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/api/api.rbac.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/api/api.rbac.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/api/api.service.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/api/api.service.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/api/api.service.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/api/api.service.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/engine/engine.config.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.config.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/engine/engine.config.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.config.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/engine/engine.deployment.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.deployment.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/engine/engine.deployment.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.deployment.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/engine/engine.hpa.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.hpa.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/engine/engine.hpa.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.hpa.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/engine/engine.rbac.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.rbac.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/engine/engine.rbac.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.rbac.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/engine/engine.service.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.service.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/engine/engine.service.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/engine/engine.service.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/license-proxy/license-proxy.config.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/license-proxy/license-proxy.config.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/license-proxy/license-proxy.config.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/license-proxy/license-proxy.config.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/license-proxy/license-proxy.deployment.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/license-proxy/license-proxy.deployment.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/license-proxy/license-proxy.deployment.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/license-proxy/license-proxy.deployment.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/license-proxy/license-proxy.rbac.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/license-proxy/license-proxy.rbac.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/license-proxy/license-proxy.rbac.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/license-proxy/license-proxy.rbac.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/license-proxy/license-proxy.service.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/license-proxy/license-proxy.service.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/license-proxy/license-proxy.service.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/license-proxy/license-proxy.service.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/volumes/aws/efs-model-download.job.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/volumes/aws/efs-model-download.job.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/volumes/aws/efs-model-download.job.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/volumes/aws/efs-model-download.job.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/volumes/aws/efs.pv.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/volumes/aws/efs.pv.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/volumes/aws/efs.pv.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/volumes/aws/efs.pv.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/volumes/aws/efs.pvc.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/volumes/aws/efs.pvc.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/volumes/aws/efs.pvc.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/volumes/aws/efs.pvc.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/volumes/aws/efs.storageClass.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/volumes/aws/efs.storageClass.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/volumes/aws/efs.storageClass.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/volumes/aws/efs.storageClass.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/volumes/gcp/gpd.pv.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/volumes/gcp/gpd.pv.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/volumes/gcp/gpd.pv.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/volumes/gcp/gpd.pv.yaml diff --git a/backend/charts/deepgram-self-hosted/templates/volumes/gcp/gpd.pvc.yaml b/backend/charts/deepgram-self-hosted/nova-2/templates/volumes/gcp/gpd.pvc.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/templates/volumes/gcp/gpd.pvc.yaml rename to backend/charts/deepgram-self-hosted/nova-2/templates/volumes/gcp/gpd.pvc.yaml diff --git a/backend/charts/deepgram-self-hosted/values.yaml b/backend/charts/deepgram-self-hosted/nova-2/values.yaml similarity index 100% rename from backend/charts/deepgram-self-hosted/values.yaml rename to backend/charts/deepgram-self-hosted/nova-2/values.yaml diff --git a/backend/charts/deepgram-self-hosted/nova-3/.helmignore b/backend/charts/deepgram-self-hosted/nova-3/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/.helmignore @@ -0,0 +1,23 @@ +# 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/backend/charts/deepgram-self-hosted/nova-3/CHANGELOG.md b/backend/charts/deepgram-self-hosted/nova-3/CHANGELOG.md new file mode 100644 index 000000000..9cf676c1e --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/CHANGELOG.md @@ -0,0 +1,201 @@ +# Changelog + +All notable changes to this Helm chart will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## [0.12.0] - 2025-03-31 + +### Added + +- Updated default container tags to March 2025 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-march-2025-release-250331) for additional details. + + +## [0.11.1] - 2025-03-28 + +### Added + +- Exposed configuration values to enable named-entity recognition models. See the [March 2025 Deepgram Self-Hosted Changelog](https://deepgram.com/changelog/deepgram-self-hosted-march-2025-release-250307) for more details on features powered by these models. + +## [0.11.0] - 2025-03-07 + +### Added + +- Updated default container tags to March 2025 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-march-2025-release-250307) for additional details. + +## [0.10.0] - 2025-01-30 + +### Added + +- Updated default container tags to January 2025 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-january-2025-release-250130) for additional details. + +## [0.9.0] - 2024-12-26 + +### Added + +- Updated default container tags to December 2024 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-december-2024-release-241226) for additional details. + +## [0.8.1] - 2024-12-17 + +### Changed + +- Fixed default ratio metrics in Prometheus Adapter chart values to use 0.0 to 1.0 scale to match autoscaling documentation + +## [0.8.0] - 2024-11-21 + +### Added + +- Updated default container tags to November 2024 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-november-2024-release-241121) for additional details. + +### Fixed + +- Add the Engine Deployment tolerations to the Engine's model download Job. + +## [0.7.0] - 2024-10-24 + +### Added + +- Updated default container tags to October 2024 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-october-2024-release-241024) for additional details. Highlights include: + - Adds new [streaming websocket TTS](https://deepgram.com/changelog/websocket-text-to-speech-api)! This is a software feature, so no new TTS models are required. + +### Changed + +- AWS samples updated to take advantage of new [EKS accelerated AMIs](https://aws.amazon.com/about-aws/whats-new/2024/10/amazon-eks-nvidia-aws-neuron-instance-types-al2023/), which bundle the required NVIDIA driver and toolkit instead of being installed by the NVIDIA GPU operator + +## [0.6.0] - 2024-09-27 + +### Added + +- Updated default container tags to September 2024 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-september-2024-release-240927) for additional details. Highlights include: + - Adds broader support in Engine container for model auto-loading during runtime. + - Filesystems that don't support `inotify`, such as `nfs`/`csi` PersistentVolumes in Kubernetes, can now load and unload models during runtime without requiring a Pod restart. +- Automatic model management on AWS now supports model removal. See the `engine.modelManager.models.remove` section in the `values.yaml` file for details. +- Container orchestrator environment variable added to improve support. + +### Changed + +- Automatic model downloads on AWS are moved from `engine.modelManager.models.links` to `engine.modelManager.models.add`. The old `links` field is still supported, but migration is recommended. + +### Fixed + +- Update sample files to fix an issue with sample command for Kubernetes Secret creation storing Quay credential + - Previous command used `--from-file` with the user's Docker configuration file. Some local secret managers, like + Apple Keychain, scrub this file for sensitive information, which would result in an empty secret being created. + +## [0.5.0] - 2024-08-27 + +### Added + +- Updated default container tags to August 2024 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-august-2024-release-240827) for additional details. Highlights include: + - GA support for entity detection for pre-recorded English audio + - GA support for improved redaction for pre-recorded English audio + +### Fixed + +- Fixed a misleading comment in the `03-basic-setup-onprem.yaml` sample file that wrongly suggested `engine.modelManager.volumes.customVolumeClaim.name` should be a `PersistentVolume` instead of a `PersistentVolumeClaim` + +### Changed + +- Deepgram's core products are available to host both on-premises and in the cloud. Official resources have been updated to refer to a ["self-hosted" product offering](https://deepgram.com/self-hosted), instead of an "onprem" product offering, to align the product name with industry naming standards. The Deepgram Quay image repository names have been updated to reflect this. + +## [0.4.0] - 2024-07-25 + +### Added + +- Introduced entity detection feature flag for API containers (`false` by default). +- Updated default container tags to July 2024 release. Refer to the [main Deepgram changelog](https://deepgram.com/changelog/deepgram-self-hosted-july-2024-release-240725) for additional details. Highlights include: + - Support for Deepgram's new English/Spanish multilingual code-switching model + - Beta support for entity detection for pre-recorded English audio + - Beta support for improved redaction for pre-recorded English audio + - Beta support for improved entity formatting for streaming English audio + +### Removed + +- Removed some items nested under `api.features` and `engine.features` sections in favor of opinionated defaults. + +## [0.3.0] - 2024-07-18 + +### Added + +- Allow specifying custom annotations for deployments. + +## [0.2.3] - 2024-07-15 + +### Added + +- Sample `values.yaml` file for on-premises/self-managed Kubernetes clusters. + +### Fixed + +- Resolves a mismatch between PVC and SC prefix naming convention. +- Resolves error when specifying custom service account names. + +### Changed + +- Make `imagePullSecrets` optional. + +## [0.2.2-beta] - 2024-06-27 + +### Added + +- Adds more verbose logging for audio content length. +- Keeps our software up-to-date. +- See the [changelog](https://deepgram.com/changelog/deepgram-on-premises-june-2024-release-240627) associated with this routine monthly release. + +## [0.2.1-beta] - 2024-06-24 + +### Added + +- Restart Deepgram containers automatically when underlying ConfigMaps have been modified. + +## [0.2.0-beta] - 2024-06-20 + +### Added +- Support for managing node autoscaling with [cluster-autoscaler](https://github.com/kubernetes/autoscaler). +- Support for pod autoscaling of Deepgram components. +- Support for keeping the upstream Deepgram License server as a backup even when the License Proxy is deployed. See `licenseProxy.keepUpstreamServerAsBackup` for details. + +### Changed + +- Initial installation replica count values moved from `scaling.static.{api,engine}.replicas` to `scaling.replicas.{api,engine}`. +- License Proxy is no longer manually scaled. Instead, scaling can be indirectly controlled via `licenseProxy.{enabled,deploySecondReplica}`. +- Labels for Deepgram dedicated nodes in the sample `cluster-config.yaml` for AWS, and the `nodeAffinity` sections of the sample `values.yaml` files. The key has been renamed from `deepgram/nodeType` to `k8s.deepgram.com/node-type`, and the values are no longer prepended with `deepgram`. +- AWS EFS model download job hook delete policy changed to `before-hook-creation`. +- Concurrency limit moved from API (`api.concurrencyLimit.activeRequests`) to Engine level (`engine.concurrencyLimit.activeRequests`). + +## [0.1.1-alpha] - 2024-06-03 + +### Added + +- Various documentation improvements + +## [0.1.0-alpha] - 2024-05-31 + +### Added + +- Initial implementation of the Helm chart. + + +[unreleased]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.12.0...HEAD +[0.12.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.11.1...0.12.0 +[0.11.1]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.11.0...0.11.1 +[0.11.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.10.0...deepgram-self-hosted-0.11.0 +[0.10.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.9.0...deepgram-self-hosted-0.10.0 +[0.9.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.8.1...deepgram-self-hosted-0.9.0 +[0.8.1]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.8.0...deepgram-self-hosted-0.8.1 +[0.8.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.7.0...deepgram-self-hosted-0.8.0 +[0.7.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.6.0...deepgram-self-hosted-0.7.0 +[0.6.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.5.0...deepgram-self-hosted-0.6.0 +[0.5.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.4.0...deepgram-self-hosted-0.5.0 +[0.4.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.3.0...deepgram-self-hosted-0.4.0 +[0.3.0]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.2.3...deepgram-self-hosted-0.3.0 +[0.2.3]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.2.2-beta...deepgram-self-hosted-0.2.3 +[0.2.2-beta]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.2.1-beta...deepgram-self-hosted-0.2.2-beta +[0.2.1-beta]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.2.0-beta...deepgram-self-hosted-0.2.1-beta +[0.2.0-beta]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.1.1-alpha...deepgram-self-hosted-0.2.0-beta +[0.1.1-alpha]: https://github.com/deepgram/self-hosted-resources/compare/deepgram-self-hosted-0.1.0-alpha...deepgram-self-hosted-0.1.1-alpha +[0.1.0-alpha]: https://github.com/deepgram/self-hosted-resources/releases/tag/deepgram-self-hosted-0.1.0-alpha + + diff --git a/backend/charts/deepgram-self-hosted/nova-3/Chart.yaml b/backend/charts/deepgram-self-hosted/nova-3/Chart.yaml new file mode 100644 index 000000000..4cc013fe9 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/Chart.yaml @@ -0,0 +1,42 @@ +apiVersion: v2 +appVersion: release-250331 +dependencies: +- condition: gpu-operator.enabled + name: gpu-operator + repository: https://helm.ngc.nvidia.com/nvidia + version: ^24.3.0 +- condition: cluster-autoscaler.enabled + name: cluster-autoscaler + repository: https://kubernetes.github.io/autoscaler + version: ^9.37.0 +- condition: kube-prometheus-stack.includeDependency,scaling.auto.enabled + name: kube-prometheus-stack + repository: https://prometheus-community.github.io/helm-charts + version: ^60.2.0 +- condition: prometheus-adapter.includeDependency,scaling.auto.enabled + name: prometheus-adapter + repository: https://prometheus-community.github.io/helm-charts + version: ^4.10.0 +description: A Helm chart for running Deepgram services in a self-hosted environment +home: https://developers.deepgram.com/docs/self-hosted-introduction +icon: https://www.dropbox.com/scl/fi/v4jtfbsrx881pbevcga3j/D-icon-black-square-250x250.png?rlkey=barv5jeuhd7t2lczz0m3nane7&dl=1 +keywords: +- voice ai +- text-to-speech +- tts +- aura +- speech-to-text +- stt +- asr +- nova +- voice agent +- self-hosted +kubeVersion: '>=1.28.0-0' +maintainers: +- email: self.hosted@deepgram.com + name: Deepgram Self-Hosted +name: deepgram-self-hosted +sources: +- https://github.com/deepgram/self-hosted-resources +type: application +version: 0.12.0 diff --git a/backend/charts/deepgram-self-hosted/nova-3/README.md b/backend/charts/deepgram-self-hosted/nova-3/README.md new file mode 100644 index 000000000..82abcd6f4 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/README.md @@ -0,0 +1,331 @@ +# deepgram-self-hosted + +![Version: 0.12.0](https://img.shields.io/badge/Version-0.12.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: release-250331](https://img.shields.io/badge/AppVersion-release--250331-informational?style=flat-square) [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/deepgram-self-hosted)](https://artifacthub.io/packages/search?repo=deepgram-self-hosted) + +A Helm chart for running Deepgram services in a self-hosted environment + +**Homepage:** + +**Deepgram Self-Hosted Kubernetes Guides:** + +## Source Code + +* + +## Requirements + +Kubernetes: `>=1.28.0-0` + +| Repository | Name | Version | +|------------|------|---------| +| https://helm.ngc.nvidia.com/nvidia | gpu-operator | ^24.3.0 | +| https://kubernetes.github.io/autoscaler | cluster-autoscaler | ^9.37.0 | +| https://prometheus-community.github.io/helm-charts | kube-prometheus-stack | ^60.2.0 | +| https://prometheus-community.github.io/helm-charts | prometheus-adapter | ^4.10.0 | + +## Using the Chart + +### Get Repository Info + +```bash +helm repo add deepgram https://deepgram.github.io/self-hosted-resources +helm repo update +``` + +### Installing the Chart + +The Deepgram self-hosted chart requires Helm 3.7+ in order to install successfully. Please check your helm release before installation. + +You will need to provide your [self-service Deepgram licensing and credentials](https://developers.deepgram.com/docs/self-hosted-self-service-tutorial) information. See `global.deepgramSecretRef` and `global.pullSecretRef` in the [Values section](#values) for more details, and the [Deepgram Self-Hosted Kubernetes Guides](https://developers.deepgram.com/docs/kubernetes) for instructions on how to create these secrets. + +You may also override any default configuration values. See [the Values section](#values) for a list of available options, and the [samples directory](./samples) for examples of a standard installation. + +``` +helm install -f my-values.yaml [RELEASE_NAME] deepgram/deepgram-self-hosted --atomic --timeout 45m +``` + +### Upgrade and Rollback Strategies + +To upgrade the Deepgram components to a new version, follow these steps: + +1. Update the various `image.tag` values in the `values.yaml` file to the desired version. + +2. Run the Helm upgrade command: + + ```bash + helm upgrade -f my-values.yaml [RELEASE_NAME] deepgram/deepgram-self-hosted --atomic --timeout 60m + ``` + +If you encounter any issues during the upgrade process, you can perform a rollback to the previous version: + +```bash +helm rollback deepgram +``` + +Before upgrading, ensure that you have reviewed the release notes and any migration guides provided by Deepgram for the specific version you are upgrading to. + +### Uninstalling the Chart + +```bash +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +## Changelog + +See the [chart CHANGELOG](./CHANGELOG.md) for a list of relevant changes for each version of the Helm chart. + +For more details on changes to the underlying Deepgram resources, such as the container images or available models, see the [official Deepgram changelog](https://deepgram.com/changelog) ([RSS feed](https://deepgram.com/changelog.xml)). + +## Chart Configuration + +### Persistent Storage Options + +The Deepgram Helm chart supports different persistent storage options for storing Deepgram models and data. The available options include: + +- AWS Elastic File System (EFS) +- Google Cloud Persistent Disk (GPD) +- Custom PersistentVolumeClaim (PVC) + +To configure a specific storage option, see the `engine.modelManager.volumes` [configuration values](#values). Make sure to provide the necessary configuration values for the selected storage option, such as the EFS file system ID or the GPD disk type and size. + +For detailed instructions on setting up and configuring each storage option, refer to the [Deepgram self-hosted guides](https://developers.deepgram.com/docs/kubernetes) and the respective cloud provider's documentation. + +### Autoscaling + +Autoscaling your cluster's capacity to meet incoming traffic demands involves both node autoscaling and pod autoscaling. Node autoscaling for supported cloud providers is setup by default when using this Helm chart and creating your cluster with the [Deepgram self-hosted guides](https://developers.deepgram.com/docs/kubernetes). Pod autoscaling can be enabled via the `scaling.auto.enabled` configuration option in this chart. + +#### Engine + +The Engine component is the core of the Deepgram self-hosted platform, responsible for performing inference using your deployed models. Autoscaling increases the number of Engine replicas to maintain consistent performance for incoming traffic. + +There are currently two primary ways to scale the Engine component: scaling with a hard request limit per Engine Pod, or scaling with a soft request limit per Engine pod. + +To set a hard limit on which to scale, configure `engine.concurrencyLimit.activeRequests` and `scaling.auto.engine.metrics.requestCapacityRatio`. The `activeRequests` parameter will set a hard limit of how many requests any given Engine pod will accept, and the `requestCapacityRatio` will govern scaling the Engine deployment when a certain percentage of "available request slots" is filled. For example, a requestCapacityRatio of `0.8` will scale the Engine deployment when the current number of active requests is >=80% of the active request concurrency limit. If the cluster is not able to scale in time and current active requests hits 100% of the preset limit, additional client requests to the API will return a `429 Too Many Requests` HTTP response to clients. This hard limit means that if a request is accepted for inference, it will have consistent performance, as the cluster will refuse surplus requests that could overload the cluster and degrade performance, at the expense of possibly rejecting some incoming requests if capacity does not scale in time. + +To set a soft limit on which to scale, configure `scaling.auto.engine.metrics.{speechToText,textToSpeech}.{batch,streaming}.requestsPerPod`, depending on the primary traffic source for your environment. The cluster will attempt to scale to meet this target for number of requests per Engine pod, but will not reject extra requests with a `429 Too Many Request` HTTP response like the hard limit will. If the number of extra requests increases faster than the cluster can scale additional capacity, all incoming requests will still be accepted, but the performance of individual requests may degrade. + +> [!NOTE] +> Deepgram recommends provisioning separate environments for batch speech-to-text, streaming speech-to-text, and text-to-speech workloads because typical latency and throughput tradeoffs are different for each of those use cases. + +There is also a `scaling.auto.engine.metrics.custom` configuration value available to define your own custom scaling metric, if needed. + +#### API + +The API component is responsible for accepting incoming requests and forming responses, delegating inference work to the Deepgram Engine as needed. A single API pod can typically handle delegating requests to multiple Engine pods, so it is more compute efficient to deploy fewer API pods relative to the number of Engine pods. The `scaling.auto.api.metrics.engineToApiRatio` configuration value defines the ratio between Engine to API pods. The default value is appropriate for most deployments. + +There is also a `scaling.auto.api.metrics.custom` configuration value available to define your own custom scaling metric, if needed. + +#### License Proxy + +The [License Proxy](https://developers.deepgram.com/docs/license-proxy) is intended to be deployed as a fixed-scale deployment the proxies all licensing requests from your environment. It should not be upscaled with the traffic demands of your environment. + +This chart deploys one License Proxy Pod per environment by default. If you wish to deploy a second License Proxy Pod for redundancy, set `licenseProxy.deploySecondReplica` to `true`. + +### RBAC Configuration + +Role-Based Access Control (RBAC) is used to control access to Kubernetes resources based on the roles and permissions assigned to users or service accounts. The Deepgram Helm chart includes default RBAC roles and bindings for the API, Engine, and License Proxy components. + +To use custom RBAC roles and bindings based on your specific security requirements, you can individually specify pre-existing ServiceAccounts to bind to each deployment by specifying the following options in `values.yaml`: + +``` +{api|engine|licenseProxy}.serviceAccount.create=false +{api|engine|licenseProxy}.serviceAccount.name= +``` + +Make sure to review and adjust the RBAC configuration according to the principle of least privilege, granting only the necessary permissions for each component. + +### Secret Management + +The Deepgram Helm chart takes references to two existing secrets - one containing your distribution credentials to pull container images from Deepgram's image repository, and one containing your Deepgram self-hosted API key. + +Consult the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/secret/) for best practices on configuring Secrets for use in your cluster. + +## Getting Help + +See the [Getting Help](../../README.md#getting-help) section in the root of this repository for a list of resources to help you troubleshoot and resolve issues. + +### Troubleshooting + +If you encounter issues while deploying or using Deepgram, consider the following troubleshooting steps: + +1. Check the pod status and logs: + - Use `kubectl get pods` to check the status of the Deepgram pods. + - Use `kubectl logs ` to view the logs of a specific pod. + +2. Verify resource availability: + - Ensure that the cluster has sufficient CPU, memory, and storage resources to accommodate the Deepgram components. + - Check for any resource constraints or limits imposed by the namespace or the cluster. + +3. Review the Kubernetes events: + - Use `kubectl get events` to view any events or errors related to the Deepgram deployment. + +4. Check the network connectivity: + - Verify that the Deepgram components can communicate with each other and with the Deepgram license server (license.deepgram.com). + - Check the network policies and firewall rules to ensure that the necessary ports and protocols are allowed. + +5. Collect diagnostic information: + - Gather relevant logs and metrics. + - Export your existing Helm chart values: + ```bash + helm get values [RELEASE_NAME] > my-deployed-values.yaml + ``` + - Provide the collected diagnostic information to Deepgram for assistance. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| api.additionalAnnotations | object | `nil` | Additional annotations to add to the API deployment | +| api.additionalLabels | object | `{}` | Additional labels to add to API resources | +| api.affinity | object | `{}` | [Affinity and anti-affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to apply for API pods. | +| api.driverPool | object | `` | driverPool configures the backend pool of speech engines (generically referred to as "drivers" here). The API will load-balance among drivers in the standard pool; if one standard driver fails, the next one will be tried. | +| api.driverPool.standard | object | `` | standard is the main driver pool to use. | +| api.driverPool.standard.maxResponseSize | string | `"1073741824"` | Maximum response to deserialize from Driver (in bytes). Default is 1GB, expressed in bytes. | +| api.driverPool.standard.retryBackoff | float | `1.6` | retryBackoff is the factor to increase the retrySleep by for each additional retry (for exponential backoff). | +| api.driverPool.standard.retrySleep | string | `"2s"` | retrySleep defines the initial sleep period (in humantime duration) before attempting a retry. | +| api.driverPool.standard.timeoutBackoff | float | `1.2` | timeoutBackoff is the factor to increase the timeout by for each additional retry (for exponential backoff). | +| api.features | object | `` | Enable ancillary features | +| api.features.diskBufferPath | string | `nil` | If API is receiving requests faster than Engine can process them, a request queue will form. By default, this queue is stored in memory. Under high load, the queue may grow too large and cause Out-Of-Memory errors. To avoid this, set a diskBufferPath to buffer the overflow on the request queue to disk. WARN: This is only to temporarily buffer requests during high load. If there is not enough Engine capacity to process the queued requests over time, the queue (and response time) will grow indefinitely. | +| api.features.entityDetection | bool | `false` | Enables entity detection on pre-recorded audio *if* a valid entity detection model is available. | +| api.features.entityRedaction | bool | `false` | Enables entity-based redaction on pre-recorded audio *if* a valid entity detection model is available. | +| api.features.formatEntityTags | bool | `false` | Enables format entity tags on pre-recorded audio *if* a valid NER model is available. | +| api.image.path | string | `"quay.io/deepgram/self-hosted-api"` | path configures the image path to use for creating API containers. You may change this from the public Quay image path if you have imported Deepgram images into a private container registry. | +| api.image.pullPolicy | string | `"IfNotPresent"` | pullPolicy configures how the Kubelet attempts to pull the Deepgram API image | +| api.image.tag | string | `"release-250331"` | tag defines which Deepgram release to use for API containers | +| api.livenessProbe | object | `` | Liveness probe customization for API pods. | +| api.namePrefix | string | `"deepgram-api"` | namePrefix is the prefix to apply to the name of all K8s objects associated with the Deepgram API containers. | +| api.readinessProbe | object | `` | Readiness probe customization for API pods. | +| api.resolver | object | `` | Specify custom DNS resolution options. | +| api.resolver.maxTTL | int | `nil` | maxTTL sets the DNS TTL value if specifying a custom DNS nameserver. | +| api.resolver.nameservers | list | `[]` | nameservers allows for specifying custom domain name server(s). A valid list item's format is "{IP} {PORT} {PROTOCOL (tcp or udp)}", e.g. `"127.0.0.1 53 udp"`. | +| api.resources | object | `` | Configure resource limits per API container. See [Deepgram's documentation](https://developers.deepgram.com/docs/self-hosted-deployment-environments#api) for more details. | +| api.securityContext | object | `{}` | [Security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for API pods. | +| api.server | object | `` | Configure how the API will listen for your requests | +| api.server.callbackConnTimeout | string | `"1s"` | callbackConnTimeout configures how long to wait for a connection to a callback URL. See [Deepgram's callback documentation](https://developers.deepgram.com/docs/callback) for more details. The value should be a humantime duration. | +| api.server.callbackTimeout | string | `"10s"` | callbackTimeout configures how long to wait for a response from a callback URL. See [Deepgram's callback documentation](https://developers.deepgram.com/docs/callback) for more details. The value should be a humantime duration. | +| api.server.fetchConnTimeout | string | `"1s"` | fetchConnTimeout configures how long to wait for a connection to a fetch URL. The value should be a humantime duration. A fetch URL is a URL passed in an inference request from which a payload should be downloaded. | +| api.server.fetchTimeout | string | `"60s"` | fetchTimeout configures how long to wait for a response from a fetch URL. The value should be a humantime duration. A fetch URL is a URL passed in an inference request from which a payload should be downloaded. | +| api.server.host | string | `"0.0.0.0"` | host is the IP address to listen on. You will want to listen on all interfaces to interact with other pods in the cluster. | +| api.server.port | int | `8080` | port to listen on. | +| api.serviceAccount.create | bool | `true` | Specifies whether to create a default service account for the Deepgram API Deployment. | +| api.serviceAccount.name | string | `nil` | Allows providing a custom service account name for the API component. If left empty, the default service account name will be used. If specified, and `api.serviceAccount.create = true`, this defines the name of the default service account. If specified, and `api.serviceAccount.create = false`, this provides the name of a preconfigured service account you wish to attach to the API deployment. | +| api.tolerations | list | `[]` | [Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to apply to API pods. | +| api.updateStrategy.rollingUpdate.maxSurge | int | `1` | The maximum number of extra API pods that can be created during a rollingUpdate, relative to the number of replicas. See the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-surge) for more details. | +| api.updateStrategy.rollingUpdate.maxUnavailable | int | `0` | The maximum number of API pods, relative to the number of replicas, that can go offline during a rolling update. See the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-unavailable) for more details. | +| cluster-autoscaler.autoDiscovery.clusterName | string | `nil` | Name of your AWS EKS cluster. Using the [Cluster Autoscaler](https://github.com/kubernetes/autoscaler) on AWS requires knowledge of certain cluster metadata. | +| cluster-autoscaler.awsRegion | string | `nil` | Region of your AWS EKS cluster. Using the [Cluster Autoscaler](https://github.com/kubernetes/autoscaler) on AWS requires knowledge of certain cluster metadata. | +| cluster-autoscaler.enabled | bool | `false` | Set to `true` to enable node autoscaling with AWS EKS. Note needed for GKE, as autoscaling is enabled by a [cli option on cluster creation](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-autoscaler#creating_a_cluster_with_autoscaling). | +| cluster-autoscaler.rbac.serviceAccount.annotations."eks.amazonaws.com/role-arn" | string | `nil` | Replace with the AWS Role ARN configured for the Cluster Autoscaler. See the [Deepgram AWS EKS guide](https://developers.deepgram.com/docs/aws-k8s#creating-a-cluster) or [Cluster Autoscaler AWS documentation](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#permissions) for details. | +| cluster-autoscaler.rbac.serviceAccount.name | string | `"cluster-autoscaler-sa"` | Name of the IAM Service Account with the [necessary permissions](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#permissions) | +| engine.additionalAnnotations | object | `nil` | Additional annotations to add to the Engine deployment | +| engine.additionalLabels | object | `{}` | Additional labels to add to Engine resources | +| engine.affinity | object | `{}` | [Affinity and anti-affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to apply for Engine pods. | +| engine.chunking | object | `` | chunking defines the size of audio chunks to process in seconds. Adjusting these values will affect both inference performance and accuracy of results. Please contact your Deepgram Account Representative if you want to adjust any of these values. | +| engine.chunking.speechToText.batch.maxDuration | float | `nil` | minDuration is the maximum audio duration for a STT chunk size for a batch request | +| engine.chunking.speechToText.batch.minDuration | float | `nil` | minDuration is the minimum audio duration for a STT chunk size for a batch request | +| engine.chunking.speechToText.streaming.maxDuration | float | `nil` | minDuration is the maximum audio duration for a STT chunk size for a streaming request | +| engine.chunking.speechToText.streaming.minDuration | float | `nil` | minDuration is the minimum audio duration for a STT chunk size for a streaming request | +| engine.chunking.speechToText.streaming.step | float | `1` | step defines how often to return interim results, in seconds. This value may be lowered to increase the frequency of interim results. However, this also causes a significant decrease in the number of concurrent streams supported by a single GPU. Please contact your Deepgram Account representative for more details. | +| engine.concurrencyLimit.activeRequests | int | `nil` | activeRequests limits the number of active requests handled by a single Engine container. If additional requests beyond the limit are sent, the API container forming the request will try a different Engine pod. If no Engine pods are able to accept the request, the API will return a 429 HTTP response to the client. The `nil` default means no limit will be set. | +| engine.features.streamingNer | bool | `false` | Enables format entity tags on streaming audio *if* a valid NER model is available. | +| engine.halfPrecision.state | string | `"auto"` | Engine will automatically enable half precision operations if your GPU supports them. You can explicitly enable or disable this behavior with the state parameter which supports `"enable"`, `"disabled"`, and `"auto"`. | +| engine.image.path | string | `"quay.io/deepgram/self-hosted-engine"` | path configures the image path to use for creating Engine containers. You may change this from the public Quay image path if you have imported Deepgram images into a private container registry. | +| engine.image.pullPolicy | string | `"IfNotPresent"` | pullPolicy configures how the Kubelet attempts to pull the Deepgram Engine image | +| engine.image.tag | string | `"release-250331"` | tag defines which Deepgram release to use for Engine containers | +| engine.livenessProbe | object | `` | Liveness probe customization for Engine pods. | +| engine.metricsServer | object | `` | metricsServer exposes an endpoint on each Engine container for reporting inference-specific system metrics. See https://developers.deepgram.com/docs/metrics-guide#deepgram-engine for more details. | +| engine.metricsServer.host | string | `"0.0.0.0"` | host is the IP address to listen on for metrics requests. You will want to listen on all interfaces to interact with other pods in the cluster. | +| engine.metricsServer.port | int | `9991` | port to listen on for metrics requests | +| engine.modelManager.models.add | list | `[]` | Links to your Deepgram models to automatically download into storage backing a persistent volume. **Automatic model management is currently supported for AWS EFS volumes only.** Insert each model link provided to you by your Deepgram Account Representative. | +| engine.modelManager.models.links | list | `[]` | Deprecated field to automatically download models. Functionality still supported, but migration to use `engine.modelManager.models.add` is strongly recommended. | +| engine.modelManager.models.remove | list | `[]` | If desiring to remove a model from storage (to reduce number of models loaded by Engine on startup), move a link from the `engine.modelManager.models.add` section to this section. You can also use a model name instead of the full link to designate for removal. **Automatic model management is currently supported for AWS EFS volumes only.** | +| engine.modelManager.volumes.aws.efs.enabled | bool | `false` | Whether to use an [AWS Elastic File Sytem](https://aws.amazon.com/efs/) to store Deepgram models for use by Engine containers. This option requires your cluster to be running in [AWS EKS](https://aws.amazon.com/eks/). | +| engine.modelManager.volumes.aws.efs.fileSystemId | string | `nil` | FileSystemId of existing AWS Elastic File System where Deepgram model files will be persisted. You can find it using the AWS CLI: ``` $ aws efs describe-file-systems --query "FileSystems[*].FileSystemId" ``` | +| engine.modelManager.volumes.aws.efs.forceDownload | bool | `false` | Whether to force a fresh download of all model links provided, even if models are already present in EFS. | +| engine.modelManager.volumes.aws.efs.namePrefix | string | `"dg-models"` | Name prefix for the resources associated with the model storage in AWS EFS. | +| engine.modelManager.volumes.customVolumeClaim.enabled | bool | `false` | You may manually create your own PersistentVolume and PersistentVolumeClaim to store and expose model files to the Deepgram Engine. Configure your storage beforehand, and enable here. Note: Make sure the PV and PVC accessMode are set to `readWriteMany` or `readOnlyMany` | +| engine.modelManager.volumes.customVolumeClaim.modelsDirectory | string | `"/"` | Name of the directory within your pre-configured PersistentVolume where the models are stored | +| engine.modelManager.volumes.customVolumeClaim.name | string | `nil` | Name of your pre-configured PersistentVolumeClaim | +| engine.modelManager.volumes.gcp.gpd.enabled | bool | `false` | Whether to use an [GKE Persistent Disks](https://cloud.google.com/kubernetes-engine/docs/concepts/persistent-volumes) to store Deepgram models for use by Engine containers. This option requires your cluster to be running in [GCP GKE](https://cloud.google.com/kubernetes-engine). See the GKE documentation on [using pre-existing persistent disks](https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/preexisting-pd). | +| engine.modelManager.volumes.gcp.gpd.fsType | string | `"ext4"` | | +| engine.modelManager.volumes.gcp.gpd.namePrefix | string | `"dg-models"` | Name prefix for the resources associated with the model storage in GCP GPD. | +| engine.modelManager.volumes.gcp.gpd.storageCapacity | string | `"40G"` | The size of your pre-existing persistent disk. | +| engine.modelManager.volumes.gcp.gpd.storageClassName | string | `"standard-rwo"` | The storageClassName of the existing persistent disk. | +| engine.modelManager.volumes.gcp.gpd.volumeHandle | string | `""` | The identifier of your pre-existing persistent disk. The format is projects/{project_id}/zones/{zone_name}/disks/{disk_name} for Zonal persistent disks, or projects/{project_id}/regions/{region_name}/disks/{disk_name} for Regional persistent disks. | +| engine.namePrefix | string | `"deepgram-engine"` | namePrefix is the prefix to apply to the name of all K8s objects associated with the Deepgram Engine containers. | +| engine.readinessProbe | object | `` | Readiness probe customization for Engine pods. | +| engine.resources | object | `` | Configure resource limits per Engine container. See [Deepgram's documentation](https://developers.deepgram.com/docs/self-hosted-deployment-environments#engine) for more details. | +| engine.resources.limits.gpu | int | `1` | gpu maps to the nvidia.com/gpu resource parameter | +| engine.resources.requests.gpu | int | `1` | gpu maps to the nvidia.com/gpu resource parameter | +| engine.securityContext | object | `{}` | [Security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for API pods. | +| engine.server | object | `` | Configure Engine containers to listen for requests from API containers. | +| engine.server.host | string | `"0.0.0.0"` | host is the IP address to listen on for inference requests. You will want to listen on all interfaces to interact with other pods in the cluster. | +| engine.server.port | int | `8080` | port to listen on for inference requests | +| engine.serviceAccount.create | bool | `true` | Specifies whether to create a default service account for the Deepgram Engine Deployment. | +| engine.serviceAccount.name | string | `nil` | Allows providing a custom service account name for the Engine component. If left empty, the default service account name will be used. If specified, and `engine.serviceAccount.create = true`, this defines the name of the default service account. If specified, and `engine.serviceAccount.create = false`, this provides the name of a preconfigured service account you wish to attach to the Engine deployment. | +| engine.startupProbe | object | `` | The startupProbe combination of `periodSeconds` and `failureThreshold` allows time for the container to load all models and start listening for incoming requests. Model load time can be affected by hardware I/O speeds, as well as network speeds if you are using a network volume mount for the models. If you are hitting the failure threshold before models are finished loading, you may want to extend the startup probe. However, this will also extend the time it takes to detect a pod that can't establish a network connection to validate its license. | +| engine.startupProbe.failureThreshold | int | `60` | failureThreshold defines how many unsuccessful startup probe attempts are allowed before the container will be marked as Failed | +| engine.startupProbe.periodSeconds | int | `10` | periodSeconds defines how often to execute the probe. | +| engine.tolerations | list | `[]` | [Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to apply to Engine pods. | +| engine.updateStrategy.rollingUpdate.maxSurge | int | `1` | The maximum number of extra Engine pods that can be created during a rollingUpdate, relative to the number of replicas. See the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-surge) for more details. | +| engine.updateStrategy.rollingUpdate.maxUnavailable | int | `0` | The maximum number of Engine pods, relative to the number of replicas, that can go offline during a rolling update. See the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-unavailable) for more details. | +| global.additionalLabels | object | `{}` | Additional labels to add to all Deepgram resources | +| global.deepgramSecretRef | string | `nil` | Name of the pre-configured K8s Secret containing your Deepgram self-hosted API key. See chart docs for more details. | +| global.outstandingRequestGracePeriod | int | `1800` | When an API or Engine container is signaled to shutdown via Kubernetes sending a SIGTERM signal, the container will stop listening on its port, and no new requests will be routed to that container. However, the container will continue to run until all existing batch or streaming requests have completed, after which it will gracefully shut down. Batch requests should be finished within 10-15 minutes, but streaming requests can proceed indefinitely. outstandingRequestGracePeriod defines the period (in sec) after which Kubernetes will forcefully shutdown the container, terminating any outstanding connections. 1800 / 60 sec/min = 30 mins | +| global.pullSecretRef | string | `nil` | If using images from the Deepgram Quay image repositories, or another private registry to which your cluster doesn't have default access, you will need to provide a pre-configured K8s Secret with image repository credentials. See chart docs for more details. | +| gpu-operator | object | `` | Passthrough values for [NVIDIA GPU Operator Helm chart](https://github.com/NVIDIA/gpu-operator/blob/master/deployments/gpu-operator/values.yaml) You may use the NVIDIA GPU Operator to manage installation of NVIDIA drivers and the container toolkit on nodes with attached GPUs. | +| gpu-operator.driver.enabled | bool | `true` | Whether to install NVIDIA drivers on nodes where a NVIDIA GPU is detected. If your Kubernetes nodes run a base image that comes with NVIDIA drivers pre-configured, disable this option, but keep the parent `gpu-operator` and sibling `toolkit` options enabled. | +| gpu-operator.driver.version | string | `"550.54.15"` | NVIDIA driver version to install. | +| gpu-operator.enabled | bool | `true` | Whether to install the NVIDIA GPU Operator to manage driver and/or container toolkit installation. See the list of [supported Operating Systems](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/platform-support.html#supported-operating-systems-and-kubernetes-platforms) to verify compatibility with your cluster/nodes. Disable this option if your cluster/nodes are not compatible. If disabled, you will need to self-manage NVIDIA software installation on all nodes where you want to schedule Deepgram Engine pods. | +| gpu-operator.toolkit.enabled | bool | `true` | Whether to install NVIDIA drivers on nodes where a NVIDIA GPU is detected. | +| gpu-operator.toolkit.version | string | `"v1.15.0-ubi8"` | NVIDIA container toolkit to install. The default `ubuntu` image tag for the toolkit requires a dynamic runtime link to a version of GLIBC that may not be present on nodes running older Linux distribution releases, such as Ubuntu 22.04. Therefore, we specify the `ubi8` image, which statically links the GLIBC library and avoids this issue. | +| kube-prometheus-stack | object | `` | Passthrough values for [Prometheus k8s stack Helm chart](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack). Prometheus (and its adapter) should be configured when scaling.auto is enabled. You may choose to use the installation/configuration bundled in this Helm chart, or you may configure an existing Prometheus installation in your cluster to expose the needed values. See source Helm chart for explanation of available values. Default values provided in this chart are used to provide pod autoscaling for Deepgram pods. | +| kube-prometheus-stack.includeDependency | bool | `nil` | Normally, this chart will be installed if `scaling.auto.enabled` is true. However, if you wish to manage the Prometheus adapter in your cluster on your own and not as part of the Deepgram Helm chart, you can force it to not be installed by setting this to `false`. | +| licenseProxy | object | `` | Configuration options for the optional [Deepgram License Proxy](https://developers.deepgram.com/docs/license-proxy). | +| licenseProxy.additionalAnnotations | object | `nil` | Additional annotations to add to the LicenseProxy deployment | +| licenseProxy.additionalLabels | object | `{}` | Additional labels to add to License Proxy resources | +| licenseProxy.affinity | object | `{}` | [Affinity and anti-affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to apply for License Proxy pods. | +| licenseProxy.deploySecondReplica | bool | `false` | If the License Proxy is deployed, one replica should be sufficient to support many API/Engine pods. Highly available environments may wish to deploy a second replica to ensure uptime, which can be toggled with this option. | +| licenseProxy.enabled | bool | `false` | The License Proxy is optional, but highly recommended to be deployed in production to enable highly available environments. | +| licenseProxy.image.path | string | `"quay.io/deepgram/self-hosted-license-proxy"` | path configures the image path to use for creating License Proxy containers. You may change this from the public Quay image path if you have imported Deepgram images into a private container registry. | +| licenseProxy.image.pullPolicy | string | `"IfNotPresent"` | pullPolicy configures how the Kubelet attempts to pull the Deepgram License Proxy image | +| licenseProxy.image.tag | string | `"release-250331"` | tag defines which Deepgram release to use for License Proxy containers | +| licenseProxy.keepUpstreamServerAsBackup | bool | `true` | Even with a License Proxy deployed, API and Engine pods can be configured to keep the upstream `license.deepgram.com` license server as a fallback licensing option if the License Proxy is unavailable. Disable this option if you are restricting API/Engine Pod network access for security reasons, and only the License Proxy should send egress traffic to the upstream license server. | +| licenseProxy.livenessProbe | object | `` | Liveness probe customization for Proxy pods. | +| licenseProxy.namePrefix | string | `"deepgram-license-proxy"` | namePrefix is the prefix to apply to the name of all K8s objects associated with the Deepgram License Proxy containers. | +| licenseProxy.readinessProbe | object | `` | Readiness probe customization for License Proxy pods. | +| licenseProxy.resources | object | `` | Configure resource limits per License Proxy container. See [Deepgram's documentation](https://developers.deepgram.com/docs/license-proxy#system-requirements) for more details. | +| licenseProxy.securityContext | object | `{}` | [Security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for API pods. | +| licenseProxy.server | object | `` | Configure how the license proxy will listen for licensing requests. | +| licenseProxy.server.baseUrl | string | `"/"` | baseUrl is the prefix for incoming license verification requests. | +| licenseProxy.server.host | string | `"0.0.0.0"` | host is the IP address to listen on. You will want to listen on all interfaces to interact with other pods in the cluster. | +| licenseProxy.server.port | int | `8443` | port to listen on. | +| licenseProxy.server.statusPort | int | `8080` | statusPort is the port to listen on for the status/health endpoint. | +| licenseProxy.serviceAccount.create | bool | `true` | Specifies whether to create a default service account for the Deepgram License Proxy Deployment. | +| licenseProxy.serviceAccount.name | string | `nil` | Allows providing a custom service account name for the LicenseProxy component. If left empty, the default service account name will be used. If specified, and `licenseProxy.serviceAccount.create = true`, this defines the name of the default service account. If specified, and `licenseProxy.serviceAccount.create = false`, this provides the name of a preconfigured service account you wish to attach to the License Proxy deployment. | +| licenseProxy.tolerations | list | `[]` | [Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to apply to License Proxy pods. | +| licenseProxy.updateStrategy.rollingUpdate | object | `` | For the LicenseProxy, we only expose maxSurge and not maxUnavailable. This is to avoid accidentally having all LicenseProxy nodes go offline during upgrades, which could impact the entire cluster's connection to the Deepgram License Server. | +| licenseProxy.updateStrategy.rollingUpdate.maxSurge | int | `1` | The maximum number of extra License Proxy pods that can be created during a rollingUpdate, relative to the number of replicas. See the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-surge) for more details. | +| prometheus-adapter | object | `` | Passthrough values for [Prometheus Adapter Helm chart](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus-adapter). Prometheus, and its adapter here, should be configured when scaling.auto is enabled. You may choose to use the installation/configuration bundled in this Helm chart, or you may configure an existing Prometheus installation in your cluster to expose the needed values. See source Helm chart for explanation of available values. Default values provided in this chart are used to provide pod autoscaling for Deepgram pods. | +| prometheus-adapter.includeDependency | string | `nil` | Normally, this chart will be installed if `scaling.auto.enabled` is true. However, if you wish to manage the Prometheus adapter in your cluster on your own and not as part of the Deepgram Helm chart, you can force it to not be installed by setting this to `false`. | +| scaling | object | `` | Configuration options for horizontal scaling of Deepgram services. Only one of `static` and `auto` options can be enabled. | +| scaling.auto | object | `` | Enable pod autoscaling based on system load/traffic. | +| scaling.auto.api.metrics.custom | list | `nil` | If you have custom metrics you would like to scale with, you may add them here. See the [k8s docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) for how to structure a list of metrics | +| scaling.auto.api.metrics.engineToApiRatio | int | `4` | Scale the API deployment to this Engine-to-Api pod ratio | +| scaling.auto.engine.behavior | object | "*See values.yaml file for default*" | [Configurable scaling behavior](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior) | +| scaling.auto.engine.maxReplicas | int | `10` | Maximum number of Engine replicas. | +| scaling.auto.engine.metrics.custom | list | `[]` | If you have custom metrics you would like to scale with, you may add them here. See the [k8s docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) for how to structure a list of metrics | +| scaling.auto.engine.metrics.requestCapacityRatio | string | `nil` | If `engine.concurrencyLimit.activeRequests` is set, this variable will define the ratio of current active requests to maximum active requests at which the Engine pods will scale. Setting this value too close to 1.0 may lead to a situation where the cluster is at max capacity and rejects incoming requests. Setting the ratio too close to 0.0 will over-optimistically scale your cluster and increase compute costs unnecessarily. | +| scaling.auto.engine.metrics.speechToText.batch.requestsPerPod | int | `nil` | Scale the Engine pods based on a static desired number of speech-to-text batch requests per pod | +| scaling.auto.engine.metrics.speechToText.streaming.requestsPerPod | int | `nil` | Scale the Engine pods based on a static desired number of speech-to-text streaming requests per pod | +| scaling.auto.engine.metrics.textToSpeech.batch.requestsPerPod | int | `nil` | Scale the Engine pods based on a static desired number of text-to-speech batch requests per pod | +| scaling.auto.engine.minReplicas | int | `1` | Minimum number of Engine replicas. | +| scaling.replicas | object | `` | Number of replicas to set during initial installation. | + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Deepgram Self-Hosted | | | diff --git a/backend/charts/deepgram-self-hosted/nova-3/README.md.gotmpl b/backend/charts/deepgram-self-hosted/nova-3/README.md.gotmpl new file mode 100644 index 000000000..afc6dfedd --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/README.md.gotmpl @@ -0,0 +1,168 @@ +{{ template "chart.header" . }} +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }}[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/deepgram-self-hosted)](https://artifacthub.io/packages/search?repo=deepgram-self-hosted) + +{{ template "chart.description" . }} + +{{ template "chart.homepageLine" . }} + +**Deepgram Self-Hosted Kubernetes Guides:** + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +## Using the Chart + +### Get Repository Info + +```bash +helm repo add deepgram https://deepgram.github.io/self-hosted-resources +helm repo update +``` + +### Installing the Chart + +The Deepgram self-hosted chart requires Helm 3.7+ in order to install successfully. Please check your helm release before installation. + +You will need to provide your [self-service Deepgram licensing and credentials](https://developers.deepgram.com/docs/self-hosted-self-service-tutorial) information. See `global.deepgramSecretRef` and `global.pullSecretRef` in the [Values section](#values) for more details, and the [Deepgram Self-Hosted Kubernetes Guides](https://developers.deepgram.com/docs/kubernetes) for instructions on how to create these secrets. + +You may also override any default configuration values. See [the Values section](#values) for a list of available options, and the [samples directory](./samples) for examples of a standard installation. + +``` +helm install -f my-values.yaml [RELEASE_NAME] deepgram/deepgram-self-hosted --atomic --timeout 45m +``` + +### Upgrade and Rollback Strategies + +To upgrade the Deepgram components to a new version, follow these steps: + +1. Update the various `image.tag` values in the `values.yaml` file to the desired version. + +2. Run the Helm upgrade command: + + ```bash + helm upgrade -f my-values.yaml [RELEASE_NAME] deepgram/deepgram-self-hosted --atomic --timeout 60m + ``` + +If you encounter any issues during the upgrade process, you can perform a rollback to the previous version: + +```bash +helm rollback deepgram +``` + +Before upgrading, ensure that you have reviewed the release notes and any migration guides provided by Deepgram for the specific version you are upgrading to. + +### Uninstalling the Chart + +```bash +helm uninstall [RELEASE_NAME] +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +## Changelog + +See the [chart CHANGELOG](./CHANGELOG.md) for a list of relevant changes for each version of the Helm chart. + +For more details on changes to the underlying Deepgram resources, such as the container images or available models, see the [official Deepgram changelog](https://deepgram.com/changelog) ([RSS feed](https://deepgram.com/changelog.xml)). + +## Chart Configuration + +### Persistent Storage Options + +The Deepgram Helm chart supports different persistent storage options for storing Deepgram models and data. The available options include: + +- AWS Elastic File System (EFS) +- Google Cloud Persistent Disk (GPD) +- Custom PersistentVolumeClaim (PVC) + +To configure a specific storage option, see the `engine.modelManager.volumes` [configuration values](#values). Make sure to provide the necessary configuration values for the selected storage option, such as the EFS file system ID or the GPD disk type and size. + +For detailed instructions on setting up and configuring each storage option, refer to the [Deepgram self-hosted guides](https://developers.deepgram.com/docs/kubernetes) and the respective cloud provider's documentation. + +### Autoscaling + +Autoscaling your cluster's capacity to meet incoming traffic demands involves both node autoscaling and pod autoscaling. Node autoscaling for supported cloud providers is setup by default when using this Helm chart and creating your cluster with the [Deepgram self-hosted guides](https://developers.deepgram.com/docs/kubernetes). Pod autoscaling can be enabled via the `scaling.auto.enabled` configuration option in this chart. + +#### Engine + +The Engine component is the core of the Deepgram self-hosted platform, responsible for performing inference using your deployed models. Autoscaling increases the number of Engine replicas to maintain consistent performance for incoming traffic. + +There are currently two primary ways to scale the Engine component: scaling with a hard request limit per Engine Pod, or scaling with a soft request limit per Engine pod. + +To set a hard limit on which to scale, configure `engine.concurrencyLimit.activeRequests` and `scaling.auto.engine.metrics.requestCapacityRatio`. The `activeRequests` parameter will set a hard limit of how many requests any given Engine pod will accept, and the `requestCapacityRatio` will govern scaling the Engine deployment when a certain percentage of "available request slots" is filled. For example, a requestCapacityRatio of `0.8` will scale the Engine deployment when the current number of active requests is >=80% of the active request concurrency limit. If the cluster is not able to scale in time and current active requests hits 100% of the preset limit, additional client requests to the API will return a `429 Too Many Requests` HTTP response to clients. This hard limit means that if a request is accepted for inference, it will have consistent performance, as the cluster will refuse surplus requests that could overload the cluster and degrade performance, at the expense of possibly rejecting some incoming requests if capacity does not scale in time. + +To set a soft limit on which to scale, configure `scaling.auto.engine.metrics.{speechToText,textToSpeech}.{batch,streaming}.requestsPerPod`, depending on the primary traffic source for your environment. The cluster will attempt to scale to meet this target for number of requests per Engine pod, but will not reject extra requests with a `429 Too Many Request` HTTP response like the hard limit will. If the number of extra requests increases faster than the cluster can scale additional capacity, all incoming requests will still be accepted, but the performance of individual requests may degrade. + +> [!NOTE] +> Deepgram recommends provisioning separate environments for batch speech-to-text, streaming speech-to-text, and text-to-speech workloads because typical latency and throughput tradeoffs are different for each of those use cases. + +There is also a `scaling.auto.engine.metrics.custom` configuration value available to define your own custom scaling metric, if needed. + +#### API + +The API component is responsible for accepting incoming requests and forming responses, delegating inference work to the Deepgram Engine as needed. A single API pod can typically handle delegating requests to multiple Engine pods, so it is more compute efficient to deploy fewer API pods relative to the number of Engine pods. The `scaling.auto.api.metrics.engineToApiRatio` configuration value defines the ratio between Engine to API pods. The default value is appropriate for most deployments. + +There is also a `scaling.auto.api.metrics.custom` configuration value available to define your own custom scaling metric, if needed. + +#### License Proxy + +The [License Proxy](https://developers.deepgram.com/docs/license-proxy) is intended to be deployed as a fixed-scale deployment the proxies all licensing requests from your environment. It should not be upscaled with the traffic demands of your environment. + +This chart deploys one License Proxy Pod per environment by default. If you wish to deploy a second License Proxy Pod for redundancy, set `licenseProxy.deploySecondReplica` to `true`. + +### RBAC Configuration + +Role-Based Access Control (RBAC) is used to control access to Kubernetes resources based on the roles and permissions assigned to users or service accounts. The Deepgram Helm chart includes default RBAC roles and bindings for the API, Engine, and License Proxy components. + +To use custom RBAC roles and bindings based on your specific security requirements, you can individually specify pre-existing ServiceAccounts to bind to each deployment by specifying the following options in `values.yaml`: + +``` +{api|engine|licenseProxy}.serviceAccount.create=false +{api|engine|licenseProxy}.serviceAccount.name= +``` + +Make sure to review and adjust the RBAC configuration according to the principle of least privilege, granting only the necessary permissions for each component. + +### Secret Management + +The Deepgram Helm chart takes references to two existing secrets - one containing your distribution credentials to pull container images from Deepgram's image repository, and one containing your Deepgram self-hosted API key. + +Consult the [official Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/secret/) for best practices on configuring Secrets for use in your cluster. + +## Getting Help + +See the [Getting Help](../../README.md#getting-help) section in the root of this repository for a list of resources to help you troubleshoot and resolve issues. + +### Troubleshooting + +If you encounter issues while deploying or using Deepgram, consider the following troubleshooting steps: + +1. Check the pod status and logs: + - Use `kubectl get pods` to check the status of the Deepgram pods. + - Use `kubectl logs ` to view the logs of a specific pod. + +2. Verify resource availability: + - Ensure that the cluster has sufficient CPU, memory, and storage resources to accommodate the Deepgram components. + - Check for any resource constraints or limits imposed by the namespace or the cluster. + +3. Review the Kubernetes events: + - Use `kubectl get events` to view any events or errors related to the Deepgram deployment. + +4. Check the network connectivity: + - Verify that the Deepgram components can communicate with each other and with the Deepgram license server (license.deepgram.com). + - Check the network policies and firewall rules to ensure that the necessary ports and protocols are allowed. + +5. Collect diagnostic information: + - Gather relevant logs and metrics. + - Export your existing Helm chart values: + ```bash + helm get values [RELEASE_NAME] > my-deployed-values.yaml + ``` + - Provide the collected diagnostic information to Deepgram for assistance. + +{{ template "chart.valuesSection" . }} + +{{ template "chart.maintainersSection" . }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/.helmignore b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/.helmignore @@ -0,0 +1,23 @@ +# 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/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/Chart.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/Chart.yaml new file mode 100644 index 000000000..a8cfb9c52 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +appVersion: 1.32.0 +description: Scales Kubernetes worker nodes within autoscaling groups. +home: https://github.com/kubernetes/autoscaler +icon: https://github.com/kubernetes/kubernetes/raw/master/logo/logo.png +maintainers: +- email: guyjtempleton@googlemail.com + name: gjtempleton +name: cluster-autoscaler +sources: +- https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler +type: application +version: 9.46.3 diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/README.md b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/README.md new file mode 100644 index 000000000..5ccbdd3ff --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/README.md @@ -0,0 +1,528 @@ +# cluster-autoscaler + +Scales Kubernetes worker nodes within autoscaling groups. + +## TL;DR + +```console +$ helm repo add autoscaler https://kubernetes.github.io/autoscaler + +# Method 1 - Using Autodiscovery +$ helm install my-release autoscaler/cluster-autoscaler \ + --set 'autoDiscovery.clusterName'= + +# Method 2 - Specifying groups manually +$ helm install my-release autoscaler/cluster-autoscaler \ + --set "autoscalingGroups[0].name=your-asg-name" \ + --set "autoscalingGroups[0].maxSize=10" \ + --set "autoscalingGroups[0].minSize=1" +``` + +## Introduction + +This chart bootstraps a cluster-autoscaler deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Helm 3+ +- Kubernetes 1.8+ + - [Older versions](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#releases) may work by overriding the `image`. Cluster autoscaler internally simulates the scheduler and bugs between mismatched versions may be subtle. +- Azure AKS specific Prerequisites: + - Kubernetes 1.10+ with RBAC-enabled. + +## Previous Helm Chart + +The previous `cluster-autoscaler` Helm chart hosted at [helm/charts](https://github.com/helm/charts) has been moved to this repository in accordance with the [Deprecation timeline](https://github.com/helm/charts#deprecation-timeline). Note that a few things have changed between this version and the old version: + +- This repository **only** supports Helm chart installations using Helm 3+ since the `apiVersion` on the charts has been marked as `v2`. +- Previous versions of the Helm chart have not been migrated + +## Migration from 1.X to 9.X+ versions of this Chart + +**TL;DR:** +You should choose to use versions >=9.0.0 of the `cluster-autoscaler` chart published from this repository; previous versions, and the `cluster-autoscaler-chart` with versioning 1.X.X published from this repository are deprecated. + +
+ Previous versions of this chart - further details +On initial migration of this chart from the `helm/charts` repository this chart was renamed from `cluster-autoscaler` to `cluster-autoscaler-chart` due to technical limitations. This affected all `1.X` releases of the chart, version 2.0.0 of this chart exists only to mark the [`cluster-autoscaler-chart` chart](https://artifacthub.io/packages/helm/cluster-autoscaler/cluster-autoscaler-chart) as deprecated. + +Releases of the chart from `9.0.0` onwards return the naming of the chart to `cluster-autoscaler` and return to following the versioning established by the chart's previous location at . + +To migrate from a 1.X release of the chart to a `9.0.0` or later release, you should first uninstall your `1.X` install of the `cluster-autoscaler-chart` chart, before performing the installation of the new `cluster-autoscaler` chart. +
+ +## Migration from 9.0 to 9.1 + +Starting from `9.1.0` the `envFromConfigMap` value is expected to contain the name of a ConfigMap that is used as ref for `envFrom`, similar to `envFromSecret`. If you want to keep the previous behaviour of `envFromConfigMap` you must rename it to `extraEnvConfigMaps`. + +## Installing the Chart + +**By default, no deployment is created and nothing will autoscale**. + +You must provide some minimal configuration, either to specify instance groups or enable auto-discovery. It is not recommended to do both. + +Either: + +- Set `autoDiscovery.clusterName` and provide additional autodiscovery options if necessary **or** +- Set static node group configurations for one or more node groups (using `autoscalingGroups` or `autoscalingGroupsnamePrefix`). + +To create a valid configuration, follow instructions for your cloud provider: + +- [AWS](#aws---using-auto-discovery-of-tagged-instance-groups) +- [GCE](#gce) +- [Azure](#azure) +- [OpenStack Magnum](#openstack-magnum) +- [Cluster API](#cluster-api) +- [Exoscale](#exoscale) +- [Hetzner Cloud](#hetzner-cloud) +- [Civo](#civo) + +### Templating the autoDiscovery.clusterName + +The cluster name can be templated in the `autoDiscovery.clusterName` variable. This is useful when the cluster name is dynamically generated based on other values coming from external systems like Argo CD or Flux. This also allows you to use global Helm values to set the cluster name, e.g., `autoDiscovery.clusterName=\{\{ .Values.global.clusterName }}`, so that you don't need to set it in more than 1 location in the values file. + +### AWS - Using auto-discovery of tagged instance groups + +Auto-discovery finds ASGs tags as below and automatically manages them based on the min and max size specified in the ASG. `cloudProvider=aws` only. + +- Tag the ASGs with keys to match `.Values.autoDiscovery.tags`, by default: `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/` +- Verify the [IAM Permissions](#aws---iam) +- Set `autoDiscovery.clusterName=` +- Set `awsRegion=` +- Set (option) `awsAccessKeyID=` and `awsSecretAccessKey=` if you want to [use AWS credentials directly instead of an instance role](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials) + +```console +$ helm install my-release autoscaler/cluster-autoscaler \ + --set autoDiscovery.clusterName= \ + --set awsRegion= +``` + +Alternatively with your own AWS credentials + +```console +$ helm install my-release autoscaler/cluster-autoscaler \ + --set autoDiscovery.clusterName= \ + --set awsRegion= \ + --set awsAccessKeyID= \ + --set awsSecretAccessKey= +``` + +#### Specifying groups manually + +Without autodiscovery, specify an array of elements each containing ASG name, min size, max size. The sizes specified here will be applied to the ASG, assuming IAM permissions are correctly configured. + +- Verify the [IAM Permissions](#aws---iam) +- Either provide a yaml file setting `autoscalingGroups` (see values.yaml) or use `--set` e.g.: + +```console +$ helm install my-release autoscaler/cluster-autoscaler \ + --set "autoscalingGroups[0].name=your-asg-name" \ + --set "autoscalingGroups[0].maxSize=10" \ + --set "autoscalingGroups[0].minSize=1" +``` + +#### Auto-discovery + +For auto-discovery of instances to work, they must be tagged with the keys in `.Values.autoDiscovery.tags`, which by default are `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/`. + +The value of the tag does not matter, only the key. + +An example kops spec excerpt: + +```yaml +apiVersion: kops/v1alpha2 +kind: Cluster +metadata: + name: my.cluster.internal +spec: + additionalPolicies: + node: | + [ + {"Effect":"Allow","Action":["autoscaling:DescribeAutoScalingGroups","autoscaling:DescribeAutoScalingInstances","autoscaling:DescribeLaunchConfigurations","autoscaling:DescribeTags","autoscaling:SetDesiredCapacity","autoscaling:TerminateInstanceInAutoScalingGroup"],"Resource":"*"} + ] + ... +--- +apiVersion: kops/v1alpha2 +kind: InstanceGroup +metadata: + labels: + kops.k8s.io/cluster: my.cluster.internal + name: my-instances +spec: + cloudLabels: + k8s.io/cluster-autoscaler/enabled: "" + k8s.io/cluster-autoscaler/my.cluster.internal: "" + image: kops.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-01-14 + machineType: r4.large + maxSize: 4 + minSize: 0 +``` + +In this example you would need to `--set autoDiscovery.clusterName=my.cluster.internal` when installing. + +It is not recommended to try to mix this with setting `autoscalingGroups`. + +See [autoscaler AWS documentation](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup) for a more discussion of the setup. + +### GCE + +The following parameters are required: + +- `autoDiscovery.clusterName=any-name` +- `cloud-provider=gce` +- `autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefix[0].minSize=1` + +To use Managed Instance Group (MIG) auto-discovery, provide a YAML file setting `autoscalingGroupsnamePrefix` (see values.yaml) or use `--set` when installing the Chart - e.g. + +```console +$ helm install my-release autoscaler/cluster-autoscaler \ + --set "autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefi[0].minSize=1" \ + --set autoDiscovery.clusterName= \ + --set cloudProvider=gce +``` + +Note that `your-ig-prefix` should be a _prefix_ matching one or more MIGs, and _not_ the full name of the MIG. For example, to match multiple instance groups - `k8s-node-group-a-standard`, `k8s-node-group-b-gpu`, you would use a prefix of `k8s-node-group-`. + +In the event you want to explicitly specify MIGs instead of using auto-discovery, set members of the `autoscalingGroups` array directly - e.g. + +``` +# where 'n' is the index, starting at 0 +--set autoscalingGroups[n].name=https://content.googleapis.com/compute/v1/projects/$PROJECTID/zones/$ZONENAME/instanceGroups/$FULL-MIG-NAME,autoscalingGroups[n].maxSize=$MAXSIZE,autoscalingGroups[n].minSize=$MINSIZE +``` + +### Azure + +The following parameters are required: + +- `cloudProvider=azure` +- `autoscalingGroups[0].name=your-vmss,autoscalingGroups[0].maxSize=10,autoscalingGroups[0].minSize=1` +- `azureClientID: "your-service-principal-app-id"` +- `azureClientSecret: "your-service-principal-client-secret"` +- `azureSubscriptionID: "your-azure-subscription-id"` +- `azureTenantID: "your-azure-tenant-id"` +- `azureResourceGroup: "your-aks-cluster-resource-group-name"` +- `azureVMType: "vmss"` + +### OpenStack Magnum + +`cloudProvider: magnum` must be set, and then one of + +- `magnumClusterName=` and `autoscalingGroups` with the names of node groups and min/max node counts +- or `autoDiscovery.clusterName=` with one or more `autoDiscovery.roles`. + +Additionally, `cloudConfigPath: "/etc/kubernetes/cloud-config"` must be set as this should be the location of the cloud-config file on the host. + +Example values files can be found [here](../../cluster-autoscaler/cloudprovider/magnum/examples). + +Install the chart with + +```console +$ helm install my-release autoscaler/cluster-autoscaler -f myvalues.yaml +``` + +### Cluster-API + +`cloudProvider: clusterapi` must be set, and then one or more of + +- `autoDiscovery.clusterName` +- or `autoDiscovery.namespace` +- or `autoDiscovery.labels` + +See [here](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#configuring-node-group-auto-discovery) for more details. + +Additional config parameters available, see the `values.yaml` for more details + +- `clusterAPIMode` +- `clusterAPIKubeconfigSecret` +- `clusterAPIWorkloadKubeconfigPath` +- `clusterAPICloudConfigPath` + +### Exoscale + +Create a `values.yaml` file with the following content: +```yaml +cloudProvider: exoscale +autoDiscovery: + clusterName: cluster.local # this value is not used, but must be set +``` + +Optionally, you may specify the minimum and maximum size of a particular nodepool by adding the following to the `values.yaml` file: +```yaml +autoscalingGroups: + - name: your-nodepool-name + maxSize: 10 + minSize: 1 +``` + +Create an Exoscale API key with appropriate permissions as described in [cluster-autoscaler/cloudprovider/exoscale/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md). +A secret of name `-exoscale-cluster-autoscaler` needs to be created, containing the api key and secret, as well as the zone. + +```console +$ kubectl create secret generic my-release-exoscale-cluster-autoscaler \ + --from-literal=api-key="EXOxxxxxxxxxxxxxxxxxxxxxxxx" \ + --from-literal=api-secret="xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --from-literal=api-zone="ch-gva-2" +``` + +After creating the secret, the chart may be installed: + +```console +$ helm install my-release autoscaler/cluster-autoscaler -f values.yaml +``` + +Read [cluster-autoscaler/cloudprovider/exoscale/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md) for further information on the setup without helm. + +### Hetzner Cloud + +The following parameters are required: + +- `cloudProvider=hetzner` +- `extraEnv.HCLOUD_TOKEN=...` +- `autoscalingGroups=...` + +Each autoscaling group requires an additional `instanceType` and `region` key to be set. + +Read [cluster-autoscaler/cloudprovider/hetzner/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/hetzner/README.md) for further information on the setup without helm. + +### Civo + +The following parameters are required: + +- `cloudProvider=civo` +- `autoscalingGroups=...` + +When installing the helm chart to the namespace `kube-system`, you can set `secretKeyRefNameOverride` to `civo-api-access`. +Otherwise specify the following parameters: + +- `civoApiUrl=https://api.civo.com` +- `civoApiKey=...` +- `civoClusterID=...` +- `civoRegion=...` + +Read [cluster-autoscaler/cloudprovider/civo/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/civo/README.md) for further information on the setup without helm. + +## Uninstalling the Chart + +To uninstall `my-release`: + +```console +$ helm uninstall my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +> **Tip**: List all releases using `helm list` or start clean with `helm uninstall my-release` + +## Additional Configuration + +### AWS - IAM + +The worker running the cluster autoscaler will need access to certain resources and actions depending on the version you run and your configuration of it. + +For the up-to-date IAM permissions required, please see the [cluster autoscaler's AWS Cloudprovider Readme](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#iam-policy) and switch to the tag of the cluster autoscaler image you are using. + +### AWS - IAM Roles for Service Accounts (IRSA) + +For Kubernetes clusters that use Amazon EKS, the service account can be configured with an IAM role using [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) to avoid needing to grant access to the worker nodes for AWS resources. + +In order to accomplish this, you will first need to create a new IAM role with the above mentions policies. Take care in [configuring the trust relationship](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html#iam-role-configuration) to restrict access just to the service account used by cluster autoscaler. + +Once you have the IAM role configured, you would then need to `--set rbac.serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::123456789012:role/MyRoleName` when installing. + +### Azure - Using azure workload identity + +You can use the project [Azure workload identity](https://github.com/Azure/azure-workload-identity), to automatically configure the correct setup for your pods to used federated identity with Azure. + +You can also set the correct settings yourself instead of relying on this project. + +For example the following configuration will configure the Autoscaler to use your federated identity: + +```yaml +azureUseWorkloadIdentityExtension: true +extraEnv: + AZURE_CLIENT_ID: USER ASSIGNED IDENTITY CLIENT ID + AZURE_TENANT_ID: USER ASSIGNED IDENTITY TENANT ID + AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/tokens/azure-identity-token + AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ +extraVolumes: +- name: azure-identity-token + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + audience: api://AzureADTokenExchange + expirationSeconds: 3600 + path: azure-identity-token +extraVolumeMounts: +- mountPath: /var/run/secrets/tokens + name: azure-identity-token + readOnly: true +``` + +### Custom arguments + +You can use the `customArgs` value to give any argument to cluster autoscaler command. + +Typical use case is to give an environment variable as an argument which will be interpolated at execution time. + +This is helpful when you need to inject values from configmap or secret. + +## Troubleshooting + +The chart will succeed even if the container arguments are incorrect. A few minutes after starting `kubectl logs -l "app=aws-cluster-autoscaler" --tail=50` should loop through something like + +``` +polling_autoscaler.go:111] Poll finished +static_autoscaler.go:97] Starting main loop +utils.go:435] No pod using affinity / antiaffinity found in cluster, disabling affinity predicate for this loop +static_autoscaler.go:230] Filtering out schedulables +``` + +If not, find a pod that the deployment created and `describe` it, paying close attention to the arguments under `Command`. e.g.: + +``` +Containers: + cluster-autoscaler: + Command: + ./cluster-autoscaler + --cloud-provider=aws +# if specifying ASGs manually + --nodes=1:10:your-scaling-group-name +# if using autodiscovery + --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/ + --v=4 +``` + +### PodSecurityPolicy + +Though enough for the majority of installations, the default PodSecurityPolicy _could_ be too restrictive depending on the specifics of your release. Please make sure to check that the template fits with any customizations made or disable it by setting `rbac.pspEnabled` to `false`. + +### VerticalPodAutoscaler + +The CA Helm Chart can install a [`VerticalPodAutoscaler`](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/README.md) object from Chart version `9.27.0` +onwards for the Cluster Autoscaler Deployment to scale the CA as appropriate, but for that, we +need to install the VPA to the cluster separately. A VPA can help minimize wasted resources +when usage spikes periodically or remediate containers that are being OOMKilled. + +The following example snippet can be used to install VPA that allows scaling down from the default recommendations of the deployment template: + +```yaml +vpa: + enabled: true + containerPolicy: + minAllowed: + cpu: 20m + memory: 50Mi +``` + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| additionalLabels | object | `{}` | Labels to add to each object of the chart. | +| affinity | object | `{}` | Affinity for pod assignment | +| autoDiscovery.clusterName | string | `nil` | Enable autodiscovery for `cloudProvider=aws`, for groups matching `autoDiscovery.tags`. autoDiscovery.clusterName -- Enable autodiscovery for `cloudProvider=azure`, using tags defined in https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/azure/README.md#auto-discovery-setup. Enable autodiscovery for `cloudProvider=clusterapi`, for groups matching `autoDiscovery.labels`. Enable autodiscovery for `cloudProvider=gce`, but no MIG tagging required. Enable autodiscovery for `cloudProvider=magnum`, for groups matching `autoDiscovery.roles`. | +| autoDiscovery.labels | list | `[]` | Cluster-API labels to match https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#configuring-node-group-auto-discovery | +| autoDiscovery.namespace | string | `nil` | Enable autodiscovery via cluster namespace for for `cloudProvider=clusterapi` | +| autoDiscovery.roles | list | `["worker"]` | Magnum node group roles to match. | +| autoDiscovery.tags | list | `["k8s.io/cluster-autoscaler/enabled","k8s.io/cluster-autoscaler/{{ .Values.autoDiscovery.clusterName }}"]` | ASG tags to match, run through `tpl`. | +| autoscalingGroups | list | `[]` | For AWS, Azure AKS, Exoscale or Magnum. At least one element is required if not using `autoDiscovery`. For example:
 - name: asg1
maxSize: 2
minSize: 1
For Hetzner Cloud, the `instanceType` and `region` keys are also required.
 - name: mypool
maxSize: 2
minSize: 1
instanceType: CPX21
region: FSN1
| +| autoscalingGroupsnamePrefix | list | `[]` | For GCE. At least one element is required if not using `autoDiscovery`. For example:
 - name: ig01
maxSize: 10
minSize: 0
| +| awsAccessKeyID | string | `""` | AWS access key ID ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials)) | +| awsRegion | string | `"us-east-1"` | AWS region (required if `cloudProvider=aws`) | +| awsSecretAccessKey | string | `""` | AWS access secret key ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials)) | +| azureClientID | string | `""` | Service Principal ClientID with contributor permission to Cluster and Node ResourceGroup. Required if `cloudProvider=azure` | +| azureClientSecret | string | `""` | Service Principal ClientSecret with contributor permission to Cluster and Node ResourceGroup. Required if `cloudProvider=azure` | +| azureEnableForceDelete | bool | `false` | Whether to force delete VMs or VMSS instances when scaling down. | +| azureResourceGroup | string | `""` | Azure resource group that the cluster is located. Required if `cloudProvider=azure` | +| azureSubscriptionID | string | `""` | Azure subscription where the resources are located. Required if `cloudProvider=azure` | +| azureTenantID | string | `""` | Azure tenant where the resources are located. Required if `cloudProvider=azure` | +| azureUseManagedIdentityExtension | bool | `false` | Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID, resource group, and azure AKS cluster name are set. You can only use one authentication method at a time, either azureUseWorkloadIdentityExtension or azureUseManagedIdentityExtension should be set. | +| azureUseWorkloadIdentityExtension | bool | `false` | Whether to use Azure's workload identity extension for credentials. See the project here: https://github.com/Azure/azure-workload-identity for more details. You can only use one authentication method at a time, either azureUseWorkloadIdentityExtension or azureUseManagedIdentityExtension should be set. | +| azureUserAssignedIdentityID | string | `""` | When vmss has multiple user assigned identity assigned, azureUserAssignedIdentityID specifies which identity to be used | +| azureVMType | string | `"vmss"` | Azure VM type. | +| civoApiKey | string | `""` | API key for the Civo API. Required if `cloudProvider=civo` | +| civoApiUrl | string | `"https://api.civo.com"` | URL for the Civo API. Required if `cloudProvider=civo` | +| civoClusterID | string | `""` | Cluster ID for the Civo cluster. Required if `cloudProvider=civo` | +| civoRegion | string | `""` | Region for the Civo cluster. Required if `cloudProvider=civo` | +| cloudConfigPath | string | `""` | Configuration file for cloud provider. | +| cloudProvider | string | `"aws"` | The cloud provider where the autoscaler runs. Currently only `gce`, `aws`, `azure`, `magnum`, `clusterapi` and `civo` are supported. `aws` supported for AWS. `gce` for GCE. `azure` for Azure AKS. `magnum` for OpenStack Magnum, `clusterapi` for Cluster API. `civo` for Civo Cloud. | +| clusterAPICloudConfigPath | string | `"/etc/kubernetes/mgmt-kubeconfig"` | Path to kubeconfig for connecting to Cluster API Management Cluster, only used if `clusterAPIMode=kubeconfig-kubeconfig or incluster-kubeconfig` | +| clusterAPIConfigMapsNamespace | string | `""` | Namespace on the workload cluster to store Leader election and status configmaps | +| clusterAPIKubeconfigSecret | string | `""` | Secret containing kubeconfig for connecting to Cluster API managed workloadcluster Required if `cloudProvider=clusterapi` and `clusterAPIMode=kubeconfig-kubeconfig,kubeconfig-incluster or incluster-kubeconfig` | +| clusterAPIMode | string | `"incluster-incluster"` | Cluster API mode, see https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#connecting-cluster-autoscaler-to-cluster-api-management-and-workload-clusters Syntax: workloadClusterMode-ManagementClusterMode for `kubeconfig-kubeconfig`, `incluster-kubeconfig` and `single-kubeconfig` you always must mount the external kubeconfig using either `extraVolumeSecrets` or `extraMounts` and `extraVolumes` if you dont set `clusterAPIKubeconfigSecret`and thus use an in-cluster config or want to use a non capi generated kubeconfig you must do so for the workload kubeconfig as well | +| clusterAPIWorkloadKubeconfigPath | string | `"/etc/kubernetes/value"` | Path to kubeconfig for connecting to Cluster API managed workloadcluster, only used if `clusterAPIMode=kubeconfig-kubeconfig or kubeconfig-incluster` | +| containerSecurityContext | object | `{}` | [Security context for container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) | +| customArgs | list | `[]` | Additional custom container arguments. Refer to https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca for the full list of cluster autoscaler parameters and their default values. List of arguments as strings. | +| deployment.annotations | object | `{}` | Annotations to add to the Deployment object. | +| dnsPolicy | string | `"ClusterFirst"` | Defaults to `ClusterFirst`. Valid values are: `ClusterFirstWithHostNet`, `ClusterFirst`, `Default` or `None`. If autoscaler does not depend on cluster DNS, recommended to set this to `Default`. | +| envFromConfigMap | string | `""` | ConfigMap name to use as envFrom. | +| envFromSecret | string | `""` | Secret name to use as envFrom. | +| expanderPriorities | object | `{}` | The expanderPriorities is used if `extraArgs.expander` contains `priority` and expanderPriorities is also set with the priorities. If `extraArgs.expander` contains `priority`, then expanderPriorities is used to define cluster-autoscaler-priority-expander priorities. See: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/expander/priority/readme.md | +| extraArgs | object | `{"logtostderr":true,"stderrthreshold":"info","v":4}` | Additional container arguments. Refer to https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca for the full list of cluster autoscaler parameters and their default values. Everything after the first _ will be ignored allowing the use of multi-string arguments. | +| extraEnv | object | `{}` | Additional container environment variables. | +| extraEnvConfigMaps | object | `{}` | Additional container environment variables from ConfigMaps. | +| extraEnvSecrets | object | `{}` | Additional container environment variables from Secrets. | +| extraObjects | list | `[]` | Extra K8s manifests to deploy | +| extraVolumeMounts | list | `[]` | Additional volumes to mount. | +| extraVolumeSecrets | object | `{}` | Additional volumes to mount from Secrets. | +| extraVolumes | list | `[]` | Additional volumes. | +| fullnameOverride | string | `""` | String to fully override `cluster-autoscaler.fullname` template. | +| hostNetwork | bool | `false` | Whether to expose network interfaces of the host machine to pods. | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | +| image.pullSecrets | list | `[]` | Image pull secrets | +| image.repository | string | `"registry.k8s.io/autoscaling/cluster-autoscaler"` | Image repository | +| image.tag | string | `"v1.32.0"` | Image tag | +| initContainers | list | `[]` | Any additional init containers. | +| kubeTargetVersionOverride | string | `""` | Allow overriding the `.Capabilities.KubeVersion.GitVersion` check. Useful for `helm template` commands. | +| kwokConfigMapName | string | `"kwok-provider-config"` | configmap for configuring kwok provider | +| magnumCABundlePath | string | `"/etc/kubernetes/ca-bundle.crt"` | Path to the host's CA bundle, from `ca-file` in the cloud-config file. | +| magnumClusterName | string | `""` | Cluster name or ID in Magnum. Required if `cloudProvider=magnum` and not setting `autoDiscovery.clusterName`. | +| nameOverride | string | `""` | String to partially override `cluster-autoscaler.fullname` template (will maintain the release name) | +| nodeSelector | object | `{}` | Node labels for pod assignment. Ref: https://kubernetes.io/docs/user-guide/node-selection/. | +| podAnnotations | object | `{}` | Annotations to add to each pod. | +| podDisruptionBudget | object | `{"maxUnavailable":1}` | Pod disruption budget. | +| podLabels | object | `{}` | Labels to add to each pod. | +| priorityClassName | string | `"system-cluster-critical"` | priorityClassName | +| priorityConfigMapAnnotations | object | `{}` | Annotations to add to `cluster-autoscaler-priority-expander` ConfigMap. | +| prometheusRule.additionalLabels | object | `{}` | Additional labels to be set in metadata. | +| prometheusRule.enabled | bool | `false` | If true, creates a Prometheus Operator PrometheusRule. | +| prometheusRule.interval | string | `nil` | How often rules in the group are evaluated (falls back to `global.evaluation_interval` if not set). | +| prometheusRule.namespace | string | `"monitoring"` | Namespace which Prometheus is running in. | +| prometheusRule.rules | list | `[]` | Rules spec template (see https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#rule). | +| rbac.clusterScoped | bool | `true` | if set to false will only provision RBAC to alter resources in the current namespace. Most useful for Cluster-API | +| rbac.create | bool | `true` | If `true`, create and use RBAC resources. | +| rbac.pspEnabled | bool | `false` | If `true`, creates and uses RBAC resources required in the cluster with [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) enabled. Must be used with `rbac.create` set to `true`. | +| rbac.serviceAccount.annotations | object | `{}` | Additional Service Account annotations. | +| rbac.serviceAccount.automountServiceAccountToken | bool | `true` | Automount API credentials for a Service Account. | +| rbac.serviceAccount.create | bool | `true` | If `true` and `rbac.create` is also true, a Service Account will be created. | +| rbac.serviceAccount.name | string | `""` | The name of the ServiceAccount to use. If not set and create is `true`, a name is generated using the fullname template. | +| replicaCount | int | `1` | Desired number of pods | +| resources | object | `{}` | Pod resource requests and limits. | +| revisionHistoryLimit | int | `10` | The number of revisions to keep. | +| secretKeyRefNameOverride | string | `""` | Overrides the name of the Secret to use when loading the secretKeyRef for AWS, Azure and Civo env variables | +| securityContext | object | `{}` | [Security context for pod](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) | +| service.annotations | object | `{}` | Annotations to add to service | +| service.clusterIP | string | `""` | IP address to assign to service | +| service.create | bool | `true` | If `true`, a Service will be created. | +| service.externalIPs | list | `[]` | List of IP addresses at which the service is available. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips. | +| service.labels | object | `{}` | Labels to add to service | +| service.loadBalancerIP | string | `""` | IP address to assign to load balancer (if supported). | +| service.loadBalancerSourceRanges | list | `[]` | List of IP CIDRs allowed access to load balancer (if supported). | +| service.portName | string | `"http"` | Name for service port. | +| service.servicePort | int | `8085` | Service port to expose. | +| service.type | string | `"ClusterIP"` | Type of service to create. | +| serviceMonitor.annotations | object | `{}` | Annotations to add to service monitor | +| serviceMonitor.enabled | bool | `false` | If true, creates a Prometheus Operator ServiceMonitor. | +| serviceMonitor.interval | string | `"10s"` | Interval that Prometheus scrapes Cluster Autoscaler metrics. | +| serviceMonitor.metricRelabelings | object | `{}` | MetricRelabelConfigs to apply to samples before ingestion. | +| serviceMonitor.namespace | string | `"monitoring"` | Namespace which Prometheus is running in. | +| serviceMonitor.path | string | `"/metrics"` | The path to scrape for metrics; autoscaler exposes `/metrics` (this is standard) | +| serviceMonitor.relabelings | object | `{}` | RelabelConfigs to apply to metrics before scraping. | +| serviceMonitor.selector | object | `{"release":"prometheus-operator"}` | Default to kube-prometheus install (CoreOS recommended), but should be set according to Prometheus install. | +| tolerations | list | `[]` | List of node taints to tolerate (requires Kubernetes >= 1.6). | +| topologySpreadConstraints | list | `[]` | You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains such as regions, zones, nodes, and other user-defined topology domains. (requires Kubernetes >= 1.19). | +| updateStrategy | object | `{}` | [Deployment update strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) | +| vpa | object | `{"containerPolicy":{},"enabled":false,"updateMode":"Auto"}` | Configure a VerticalPodAutoscaler for the cluster-autoscaler Deployment. | +| vpa.containerPolicy | object | `{}` | [ContainerResourcePolicy](https://github.com/kubernetes/autoscaler/blob/vertical-pod-autoscaler/v0.13.0/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L159). The containerName is always et to the deployment's container name. This value is required if VPA is enabled. | +| vpa.enabled | bool | `false` | If true, creates a VerticalPodAutoscaler. | +| vpa.updateMode | string | `"Auto"` | [UpdateMode](https://github.com/kubernetes/autoscaler/blob/vertical-pod-autoscaler/v0.13.0/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L124) | diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/README.md.gotmpl b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/README.md.gotmpl new file mode 100644 index 000000000..786dbec1d --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/README.md.gotmpl @@ -0,0 +1,417 @@ +{{ template "chart.header" . }} + +{{ template "chart.description" . }} + +## TL;DR + +```console +$ helm repo add autoscaler https://kubernetes.github.io/autoscaler + +# Method 1 - Using Autodiscovery +$ helm install my-release autoscaler/cluster-autoscaler \ + --set 'autoDiscovery.clusterName'= + +# Method 2 - Specifying groups manually +$ helm install my-release autoscaler/cluster-autoscaler \ + --set "autoscalingGroups[0].name=your-asg-name" \ + --set "autoscalingGroups[0].maxSize=10" \ + --set "autoscalingGroups[0].minSize=1" +``` + +## Introduction + +This chart bootstraps a cluster-autoscaler deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Helm 3+ +- Kubernetes 1.8+ + - [Older versions](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#releases) may work by overriding the `image`. Cluster autoscaler internally simulates the scheduler and bugs between mismatched versions may be subtle. +- Azure AKS specific Prerequisites: + - Kubernetes 1.10+ with RBAC-enabled. + +## Previous Helm Chart + +The previous `cluster-autoscaler` Helm chart hosted at [helm/charts](https://github.com/helm/charts) has been moved to this repository in accordance with the [Deprecation timeline](https://github.com/helm/charts#deprecation-timeline). Note that a few things have changed between this version and the old version: + +- This repository **only** supports Helm chart installations using Helm 3+ since the `apiVersion` on the charts has been marked as `v2`. +- Previous versions of the Helm chart have not been migrated + +## Migration from 1.X to 9.X+ versions of this Chart + +**TL;DR:** +You should choose to use versions >=9.0.0 of the `cluster-autoscaler` chart published from this repository; previous versions, and the `cluster-autoscaler-chart` with versioning 1.X.X published from this repository are deprecated. + +
+ Previous versions of this chart - further details +On initial migration of this chart from the `helm/charts` repository this chart was renamed from `cluster-autoscaler` to `cluster-autoscaler-chart` due to technical limitations. This affected all `1.X` releases of the chart, version 2.0.0 of this chart exists only to mark the [`cluster-autoscaler-chart` chart](https://artifacthub.io/packages/helm/cluster-autoscaler/cluster-autoscaler-chart) as deprecated. + +Releases of the chart from `9.0.0` onwards return the naming of the chart to `cluster-autoscaler` and return to following the versioning established by the chart's previous location at . + +To migrate from a 1.X release of the chart to a `9.0.0` or later release, you should first uninstall your `1.X` install of the `cluster-autoscaler-chart` chart, before performing the installation of the new `cluster-autoscaler` chart. +
+ +## Migration from 9.0 to 9.1 + +Starting from `9.1.0` the `envFromConfigMap` value is expected to contain the name of a ConfigMap that is used as ref for `envFrom`, similar to `envFromSecret`. If you want to keep the previous behaviour of `envFromConfigMap` you must rename it to `extraEnvConfigMaps`. + +## Installing the Chart + +**By default, no deployment is created and nothing will autoscale**. + +You must provide some minimal configuration, either to specify instance groups or enable auto-discovery. It is not recommended to do both. + +Either: + +- Set `autoDiscovery.clusterName` and provide additional autodiscovery options if necessary **or** +- Set static node group configurations for one or more node groups (using `autoscalingGroups` or `autoscalingGroupsnamePrefix`). + +To create a valid configuration, follow instructions for your cloud provider: + +- [AWS](#aws---using-auto-discovery-of-tagged-instance-groups) +- [GCE](#gce) +- [Azure](#azure) +- [OpenStack Magnum](#openstack-magnum) +- [Cluster API](#cluster-api) +- [Exoscale](#exoscale) +- [Hetzner Cloud](#hetzner-cloud) +- [Civo](#civo) + +### Templating the autoDiscovery.clusterName + +The cluster name can be templated in the `autoDiscovery.clusterName` variable. This is useful when the cluster name is dynamically generated based on other values coming from external systems like Argo CD or Flux. This also allows you to use global Helm values to set the cluster name, e.g., `autoDiscovery.clusterName=\{\{ .Values.global.clusterName }}`, so that you don't need to set it in more than 1 location in the values file. + +### AWS - Using auto-discovery of tagged instance groups + +Auto-discovery finds ASGs tags as below and automatically manages them based on the min and max size specified in the ASG. `cloudProvider=aws` only. + +- Tag the ASGs with keys to match `.Values.autoDiscovery.tags`, by default: `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/` +- Verify the [IAM Permissions](#aws---iam) +- Set `autoDiscovery.clusterName=` +- Set `awsRegion=` +- Set (option) `awsAccessKeyID=` and `awsSecretAccessKey=` if you want to [use AWS credentials directly instead of an instance role](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials) + +```console +$ helm install my-release autoscaler/cluster-autoscaler \ + --set autoDiscovery.clusterName= \ + --set awsRegion= +``` + +Alternatively with your own AWS credentials + +```console +$ helm install my-release autoscaler/cluster-autoscaler \ + --set autoDiscovery.clusterName= \ + --set awsRegion= \ + --set awsAccessKeyID= \ + --set awsSecretAccessKey= +``` + +#### Specifying groups manually + +Without autodiscovery, specify an array of elements each containing ASG name, min size, max size. The sizes specified here will be applied to the ASG, assuming IAM permissions are correctly configured. + +- Verify the [IAM Permissions](#aws---iam) +- Either provide a yaml file setting `autoscalingGroups` (see values.yaml) or use `--set` e.g.: + +```console +$ helm install my-release autoscaler/cluster-autoscaler \ + --set "autoscalingGroups[0].name=your-asg-name" \ + --set "autoscalingGroups[0].maxSize=10" \ + --set "autoscalingGroups[0].minSize=1" +``` + +#### Auto-discovery + +For auto-discovery of instances to work, they must be tagged with the keys in `.Values.autoDiscovery.tags`, which by default are `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/`. + +The value of the tag does not matter, only the key. + +An example kops spec excerpt: + +```yaml +apiVersion: kops/v1alpha2 +kind: Cluster +metadata: + name: my.cluster.internal +spec: + additionalPolicies: + node: | + [ + {"Effect":"Allow","Action":["autoscaling:DescribeAutoScalingGroups","autoscaling:DescribeAutoScalingInstances","autoscaling:DescribeLaunchConfigurations","autoscaling:DescribeTags","autoscaling:SetDesiredCapacity","autoscaling:TerminateInstanceInAutoScalingGroup"],"Resource":"*"} + ] + ... +--- +apiVersion: kops/v1alpha2 +kind: InstanceGroup +metadata: + labels: + kops.k8s.io/cluster: my.cluster.internal + name: my-instances +spec: + cloudLabels: + k8s.io/cluster-autoscaler/enabled: "" + k8s.io/cluster-autoscaler/my.cluster.internal: "" + image: kops.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-01-14 + machineType: r4.large + maxSize: 4 + minSize: 0 +``` + +In this example you would need to `--set autoDiscovery.clusterName=my.cluster.internal` when installing. + +It is not recommended to try to mix this with setting `autoscalingGroups`. + +See [autoscaler AWS documentation](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup) for a more discussion of the setup. + +### GCE + +The following parameters are required: + +- `autoDiscovery.clusterName=any-name` +- `cloud-provider=gce` +- `autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefix[0].minSize=1` + +To use Managed Instance Group (MIG) auto-discovery, provide a YAML file setting `autoscalingGroupsnamePrefix` (see values.yaml) or use `--set` when installing the Chart - e.g. + +```console +$ helm install my-release autoscaler/cluster-autoscaler \ + --set "autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefi[0].minSize=1" \ + --set autoDiscovery.clusterName= \ + --set cloudProvider=gce +``` + +Note that `your-ig-prefix` should be a _prefix_ matching one or more MIGs, and _not_ the full name of the MIG. For example, to match multiple instance groups - `k8s-node-group-a-standard`, `k8s-node-group-b-gpu`, you would use a prefix of `k8s-node-group-`. + +In the event you want to explicitly specify MIGs instead of using auto-discovery, set members of the `autoscalingGroups` array directly - e.g. + +``` +# where 'n' is the index, starting at 0 +--set autoscalingGroups[n].name=https://content.googleapis.com/compute/v1/projects/$PROJECTID/zones/$ZONENAME/instanceGroups/$FULL-MIG-NAME,autoscalingGroups[n].maxSize=$MAXSIZE,autoscalingGroups[n].minSize=$MINSIZE +``` + +### Azure + +The following parameters are required: + +- `cloudProvider=azure` +- `autoscalingGroups[0].name=your-vmss,autoscalingGroups[0].maxSize=10,autoscalingGroups[0].minSize=1` +- `azureClientID: "your-service-principal-app-id"` +- `azureClientSecret: "your-service-principal-client-secret"` +- `azureSubscriptionID: "your-azure-subscription-id"` +- `azureTenantID: "your-azure-tenant-id"` +- `azureResourceGroup: "your-aks-cluster-resource-group-name"` +- `azureVMType: "vmss"` + +### OpenStack Magnum + +`cloudProvider: magnum` must be set, and then one of + +- `magnumClusterName=` and `autoscalingGroups` with the names of node groups and min/max node counts +- or `autoDiscovery.clusterName=` with one or more `autoDiscovery.roles`. + +Additionally, `cloudConfigPath: "/etc/kubernetes/cloud-config"` must be set as this should be the location of the cloud-config file on the host. + +Example values files can be found [here](../../cluster-autoscaler/cloudprovider/magnum/examples). + +Install the chart with + +```console +$ helm install my-release autoscaler/cluster-autoscaler -f myvalues.yaml +``` + +### Cluster-API + +`cloudProvider: clusterapi` must be set, and then one or more of + +- `autoDiscovery.clusterName` +- or `autoDiscovery.namespace` +- or `autoDiscovery.labels` + +See [here](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#configuring-node-group-auto-discovery) for more details. + +Additional config parameters available, see the `values.yaml` for more details + +- `clusterAPIMode` +- `clusterAPIKubeconfigSecret` +- `clusterAPIWorkloadKubeconfigPath` +- `clusterAPICloudConfigPath` + +### Exoscale + +Create a `values.yaml` file with the following content: +```yaml +cloudProvider: exoscale +autoDiscovery: + clusterName: cluster.local # this value is not used, but must be set +``` + +Optionally, you may specify the minimum and maximum size of a particular nodepool by adding the following to the `values.yaml` file: +```yaml +autoscalingGroups: + - name: your-nodepool-name + maxSize: 10 + minSize: 1 +``` + +Create an Exoscale API key with appropriate permissions as described in [cluster-autoscaler/cloudprovider/exoscale/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md). +A secret of name `-exoscale-cluster-autoscaler` needs to be created, containing the api key and secret, as well as the zone. + +```console +$ kubectl create secret generic my-release-exoscale-cluster-autoscaler \ + --from-literal=api-key="EXOxxxxxxxxxxxxxxxxxxxxxxxx" \ + --from-literal=api-secret="xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --from-literal=api-zone="ch-gva-2" +``` + +After creating the secret, the chart may be installed: + +```console +$ helm install my-release autoscaler/cluster-autoscaler -f values.yaml +``` + +Read [cluster-autoscaler/cloudprovider/exoscale/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md) for further information on the setup without helm. + +### Hetzner Cloud + +The following parameters are required: + +- `cloudProvider=hetzner` +- `extraEnv.HCLOUD_TOKEN=...` +- `autoscalingGroups=...` + +Each autoscaling group requires an additional `instanceType` and `region` key to be set. + +Read [cluster-autoscaler/cloudprovider/hetzner/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/hetzner/README.md) for further information on the setup without helm. + +### Civo + +The following parameters are required: + +- `cloudProvider=civo` +- `autoscalingGroups=...` + +When installing the helm chart to the namespace `kube-system`, you can set `secretKeyRefNameOverride` to `civo-api-access`. +Otherwise specify the following parameters: + +- `civoApiUrl=https://api.civo.com` +- `civoApiKey=...` +- `civoClusterID=...` +- `civoRegion=...` + +Read [cluster-autoscaler/cloudprovider/civo/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/civo/README.md) for further information on the setup without helm. + +## Uninstalling the Chart + +To uninstall `my-release`: + +```console +$ helm uninstall my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +> **Tip**: List all releases using `helm list` or start clean with `helm uninstall my-release` + +## Additional Configuration + +### AWS - IAM + +The worker running the cluster autoscaler will need access to certain resources and actions depending on the version you run and your configuration of it. + +For the up-to-date IAM permissions required, please see the [cluster autoscaler's AWS Cloudprovider Readme](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#iam-policy) and switch to the tag of the cluster autoscaler image you are using. + +### AWS - IAM Roles for Service Accounts (IRSA) + +For Kubernetes clusters that use Amazon EKS, the service account can be configured with an IAM role using [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) to avoid needing to grant access to the worker nodes for AWS resources. + +In order to accomplish this, you will first need to create a new IAM role with the above mentions policies. Take care in [configuring the trust relationship](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html#iam-role-configuration) to restrict access just to the service account used by cluster autoscaler. + +Once you have the IAM role configured, you would then need to `--set rbac.serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::123456789012:role/MyRoleName` when installing. + +### Azure - Using azure workload identity + +You can use the project [Azure workload identity](https://github.com/Azure/azure-workload-identity), to automatically configure the correct setup for your pods to used federated identity with Azure. + +You can also set the correct settings yourself instead of relying on this project. + +For example the following configuration will configure the Autoscaler to use your federated identity: + +```yaml +azureUseWorkloadIdentityExtension: true +extraEnv: + AZURE_CLIENT_ID: USER ASSIGNED IDENTITY CLIENT ID + AZURE_TENANT_ID: USER ASSIGNED IDENTITY TENANT ID + AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/tokens/azure-identity-token + AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ +extraVolumes: +- name: azure-identity-token + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + audience: api://AzureADTokenExchange + expirationSeconds: 3600 + path: azure-identity-token +extraVolumeMounts: +- mountPath: /var/run/secrets/tokens + name: azure-identity-token + readOnly: true +``` + +### Custom arguments + +You can use the `customArgs` value to give any argument to cluster autoscaler command. + +Typical use case is to give an environment variable as an argument which will be interpolated at execution time. + +This is helpful when you need to inject values from configmap or secret. + +## Troubleshooting + +The chart will succeed even if the container arguments are incorrect. A few minutes after starting `kubectl logs -l "app=aws-cluster-autoscaler" --tail=50` should loop through something like + +``` +polling_autoscaler.go:111] Poll finished +static_autoscaler.go:97] Starting main loop +utils.go:435] No pod using affinity / antiaffinity found in cluster, disabling affinity predicate for this loop +static_autoscaler.go:230] Filtering out schedulables +``` + +If not, find a pod that the deployment created and `describe` it, paying close attention to the arguments under `Command`. e.g.: + +``` +Containers: + cluster-autoscaler: + Command: + ./cluster-autoscaler + --cloud-provider=aws +# if specifying ASGs manually + --nodes=1:10:your-scaling-group-name +# if using autodiscovery + --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/ + --v=4 +``` + +### PodSecurityPolicy + +Though enough for the majority of installations, the default PodSecurityPolicy _could_ be too restrictive depending on the specifics of your release. Please make sure to check that the template fits with any customizations made or disable it by setting `rbac.pspEnabled` to `false`. + +### VerticalPodAutoscaler + +The CA Helm Chart can install a [`VerticalPodAutoscaler`](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/README.md) object from Chart version `9.27.0` +onwards for the Cluster Autoscaler Deployment to scale the CA as appropriate, but for that, we +need to install the VPA to the cluster separately. A VPA can help minimize wasted resources +when usage spikes periodically or remediate containers that are being OOMKilled. + +The following example snippet can be used to install VPA that allows scaling down from the default recommendations of the deployment template: + +```yaml +vpa: + enabled: true + containerPolicy: + minAllowed: + cpu: 20m + memory: 50Mi +``` + +{{ template "chart.valuesSection" . }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/NOTES.txt b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/NOTES.txt new file mode 100644 index 000000000..1a87a3d10 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/NOTES.txt @@ -0,0 +1,18 @@ +{{- if or ( or .Values.autoDiscovery.clusterName .Values.autoDiscovery.namespace .Values.autoDiscovery.labels ) .Values.autoscalingGroups }} + +To verify that cluster-autoscaler has started, run: + + kubectl --namespace={{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ template "cluster-autoscaler.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" + +{{- else -}} + +############################################################################## +#### ERROR: You must specify values for either #### +#### autoDiscovery or autoscalingGroups[] #### +############################################################################## + +The deployment and pod will not be created and the installation is not functional +See README: + open https://github.com/kubernetes/autoscaler/tree/master/charts/cluster-autoscaler + +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/_helpers.tpl b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/_helpers.tpl new file mode 100644 index 000000000..c7e80f4d8 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/_helpers.tpl @@ -0,0 +1,160 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "cluster-autoscaler.name" -}} +{{- default (printf "%s-%s" .Values.cloudProvider .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 "cluster-autoscaler.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default (printf "%s-%s" .Values.cloudProvider .Chart.Name) .Values.nameOverride -}} +{{- if ne $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s" $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cluster-autoscaler.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return instance and name labels. +*/}} +{{- define "cluster-autoscaler.instance-name" -}} +app.kubernetes.io/instance: {{ .Release.Name | quote }} +app.kubernetes.io/name: {{ include "cluster-autoscaler.name" . | quote }} +{{- end -}} + + +{{/* +Return labels, including instance and name. +*/}} +{{- define "cluster-autoscaler.labels" -}} +{{ include "cluster-autoscaler.instance-name" . }} +app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +helm.sh/chart: {{ include "cluster-autoscaler.chart" . | quote }} +{{- if .Values.additionalLabels }} +{{ toYaml .Values.additionalLabels }} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "deployment.apiVersion" -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "<1.9-0" $kubeTargetVersion -}} +{{- print "apps/v1beta2" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for podsecuritypolicy. +*/}} +{{- define "podsecuritypolicy.apiVersion" -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "<1.10-0" $kubeTargetVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "policy/v1beta1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for podDisruptionBudget. +*/}} +{{- define "podDisruptionBudget.apiVersion" -}} +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "<1.21-0" $kubeTargetVersion -}} +{{- print "policy/v1beta1" -}} +{{- else -}} +{{- print "policy/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the service account name used by the pod. +*/}} +{{- define "cluster-autoscaler.serviceAccountName" -}} +{{- if .Values.rbac.serviceAccount.create -}} + {{ default (include "cluster-autoscaler.fullname" .) .Values.rbac.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.rbac.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Return true if the priority expander is enabled +*/}} +{{- define "cluster-autoscaler.priorityExpanderEnabled" -}} +{{- $expanders := splitList "," (default "" .Values.extraArgs.expander) -}} +{{- if has "priority" $expanders -}} +{{- true -}} +{{- end -}} +{{- end -}} + +{{/* +autoDiscovery.clusterName for clusterapi. +*/}} +{{- define "cluster-autoscaler.capiAutodiscovery.clusterName" -}} +{{- print "clusterName=" -}}{{ tpl (.Values.autoDiscovery.clusterName) . }} +{{- end -}} + +{{/* +autoDiscovery.namespace for clusterapi. +*/}} +{{- define "cluster-autoscaler.capiAutodiscovery.namespace" -}} +{{- print "namespace=" }}{{ .Values.autoDiscovery.namespace -}} +{{- end -}} + +{{/* +autoDiscovery.labels for clusterapi. +*/}} +{{- define "cluster-autoscaler.capiAutodiscovery.labels" -}} +{{- range $i, $el := .Values.autoDiscovery.labels -}} +{{- if $i -}}{{- print "," -}}{{- end -}} +{{- range $key, $val := $el -}} +{{- $key -}}{{- print "=" -}}{{- $val -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Return the autodiscoveryparameters for clusterapi. +*/}} +{{- define "cluster-autoscaler.capiAutodiscoveryConfig" -}} +{{- if .Values.autoDiscovery.clusterName -}} +{{ include "cluster-autoscaler.capiAutodiscovery.clusterName" . }} + {{- if .Values.autoDiscovery.namespace }} + {{- print "," -}} + {{ include "cluster-autoscaler.capiAutodiscovery.namespace" . }} + {{- end -}} + {{- if .Values.autoDiscovery.labels }} + {{- print "," -}} + {{ include "cluster-autoscaler.capiAutodiscovery.labels" . }} + {{- end -}} +{{- else if .Values.autoDiscovery.namespace -}} +{{ include "cluster-autoscaler.capiAutodiscovery.namespace" . }} + {{- if .Values.autoDiscovery.labels }} + {{- print "," -}} + {{ include "cluster-autoscaler.capiAutodiscovery.labels" . }} + {{- end -}} +{{- else if .Values.autoDiscovery.labels -}} + {{ include "cluster-autoscaler.capiAutodiscovery.labels" . }} +{{- end -}} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/clusterrole.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/clusterrole.yaml new file mode 100644 index 000000000..7e23ec28a --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/clusterrole.yaml @@ -0,0 +1,176 @@ +{{- if and .Values.rbac.create .Values.rbac.clusterScoped -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + name: {{ template "cluster-autoscaler.fullname" . }} +rules: + - apiGroups: + - "" + resources: + - events + - endpoints + verbs: + - create + - patch + - apiGroups: + - "" + resources: + - pods/eviction + verbs: + - create + - apiGroups: + - "" + resources: + - pods/status + verbs: + - update + - apiGroups: + - "" + resources: + - endpoints + resourceNames: + - cluster-autoscaler + verbs: + - get + - update + - apiGroups: + - "" + resources: + - nodes + verbs: + - watch + - list + - create + - delete + - get + - update + - apiGroups: + - "" + resources: + - namespaces + - pods + - services + - replicationcontrollers + - persistentvolumeclaims + - persistentvolumes + verbs: + - watch + - list + - get + - apiGroups: + - batch + resources: + - jobs + - cronjobs + verbs: + - watch + - list + - get + - apiGroups: + - batch + - extensions + resources: + - jobs + verbs: + - get + - list + - patch + - watch + - apiGroups: + - extensions + resources: + - replicasets + - daemonsets + verbs: + - watch + - list + - get + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - watch + - list + - apiGroups: + - apps + resources: + - daemonsets + - replicasets + - statefulsets + verbs: + - watch + - list + - get + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + - csinodes + - csidrivers + - csistoragecapacities + - volumeattachments + verbs: + - watch + - list + - get + - apiGroups: + - "" + resources: + - configmaps + verbs: + - list + - watch + - get + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - coordination.k8s.io + resourceNames: + - cluster-autoscaler + resources: + - leases + verbs: + - get + - update +{{- if .Values.rbac.pspEnabled }} + - apiGroups: + - extensions + - policy + resources: + - podsecuritypolicies + resourceNames: + - {{ template "cluster-autoscaler.fullname" . }} + verbs: + - use +{{- end -}} +{{- if and ( and ( eq .Values.cloudProvider "clusterapi" ) ( .Values.rbac.clusterScoped ) ( or ( eq .Values.clusterAPIMode "incluster-incluster" ) ( eq .Values.clusterAPIMode "kubeconfig-incluster" ) ))}} + - apiGroups: + - cluster.x-k8s.io + resources: + - machinedeployments + - machinepools + - machines + - machinesets + verbs: + - get + - list + - update + - watch + - apiGroups: + - cluster.x-k8s.io + resources: + - machinedeployments/scale + - machinepools/scale + verbs: + - get + - patch + - update +{{- end }} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/clusterrolebinding.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..d2384dc62 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.rbac.create .Values.rbac.clusterScoped -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + name: {{ template "cluster-autoscaler.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cluster-autoscaler.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "cluster-autoscaler.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/configmap.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/configmap.yaml new file mode 100644 index 000000000..6cd0c4064 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/configmap.yaml @@ -0,0 +1,416 @@ +{{- if or (eq .Values.cloudProvider "kwok") }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.kwokConfigMapName | default "kwok-provider-config" }} + namespace: {{ .Release.Namespace }} +data: + config: |- + # if you see '\n' everywhere, remove all the trailing spaces + apiVersion: v1alpha1 + readNodesFrom: configmap # possible values: [cluster,configmap] + nodegroups: + # to specify how to group nodes into a nodegroup + # e.g., you want to treat nodes with same instance type as a nodegroup + # node1: m5.xlarge + # node2: c5.xlarge + # node3: m5.xlarge + # nodegroup1: [node1,node3] + # nodegroup2: [node2] + fromNodeLabelKey: "kwok-nodegroup" + # you can either specify fromNodeLabelKey OR fromNodeAnnotation + # (both are not allowed) + # fromNodeAnnotation: "eks.amazonaws.com/nodegroup" + nodes: + # gpuConfig: + # # to tell kwok provider what label should be considered as GPU label + # gpuLabelKey: "k8s.amazonaws.com/accelerator" + # availableGPUTypes: + # "nvidia-tesla-k80": {} + # "nvidia-tesla-p100": {} + configmap: + name: kwok-provider-templates + kwok: {} # default: fetch latest release of kwok from github and install it + # # you can also manually specify which kwok release you want to install + # # for example: + # kwok: + # release: v0.3.0 + # # you can also disable installing kwok in CA code (and install your own kwok release) + # kwok: + # install: false (true if not specified) +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: kwok-provider-templates + namespace: {{ .Release.Namespace }} +data: + templates: |- + # if you see '\n' everywhere, remove all the trailing spaces + apiVersion: v1 + items: + - apiVersion: v1 + kind: Node + metadata: + annotations: + kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock + node.alpha.kubernetes.io/ttl: "0" + volumes.kubernetes.io/controller-managed-attach-detach: "true" + creationTimestamp: "2023-05-31T04:39:16Z" + labels: + beta.kubernetes.io/arch: amd64 + beta.kubernetes.io/os: linux + kubernetes.io/arch: amd64 + kubernetes.io/hostname: kind-control-plane + kwok-nodegroup: control-plane + kubernetes.io/os: linux + node-role.kubernetes.io/control-plane: "" + node.kubernetes.io/exclude-from-external-load-balancers: "" + name: kind-control-plane + resourceVersion: "506" + uid: 86716ec7-3071-4091-b055-77b4361d1dca + spec: + podCIDR: 10.244.0.0/24 + podCIDRs: + - 10.244.0.0/24 + providerID: kind://docker/kind/kind-control-plane + taints: + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + status: + addresses: + - address: 172.18.0.2 + type: InternalIP + - address: kind-control-plane + type: Hostname + allocatable: + cpu: "12" + ephemeral-storage: 959786032Ki + hugepages-1Gi: "0" + hugepages-2Mi: "0" + memory: 32781516Ki + pods: "110" + capacity: + cpu: "12" + ephemeral-storage: 959786032Ki + hugepages-1Gi: "0" + hugepages-2Mi: "0" + memory: 32781516Ki + pods: "110" + conditions: + - lastHeartbeatTime: "2023-05-31T04:39:58Z" + lastTransitionTime: "2023-05-31T04:39:13Z" + message: kubelet has sufficient memory available + reason: KubeletHasSufficientMemory + status: "False" + type: MemoryPressure + - lastHeartbeatTime: "2023-05-31T04:39:58Z" + lastTransitionTime: "2023-05-31T04:39:13Z" + message: kubelet has no disk pressure + reason: KubeletHasNoDiskPressure + status: "False" + type: DiskPressure + - lastHeartbeatTime: "2023-05-31T04:39:58Z" + lastTransitionTime: "2023-05-31T04:39:13Z" + message: kubelet has sufficient PID available + reason: KubeletHasSufficientPID + status: "False" + type: PIDPressure + - lastHeartbeatTime: "2023-05-31T04:39:58Z" + lastTransitionTime: "2023-05-31T04:39:46Z" + message: kubelet is posting ready status + reason: KubeletReady + status: "True" + type: Ready + daemonEndpoints: + kubeletEndpoint: + Port: 10250 + images: + - names: + - registry.k8s.io/etcd:3.5.6-0 + sizeBytes: 102542580 + - names: + - docker.io/library/import-2023-03-30@sha256:ba097b515c8c40689733c0f19de377e9bf8995964b7d7150c2045f3dfd166657 + - registry.k8s.io/kube-apiserver:v1.26.3 + sizeBytes: 80392681 + - names: + - docker.io/library/import-2023-03-30@sha256:8dbb345de79d1c44f59a7895da702a5f71997ae72aea056609445c397b0c10dc + - registry.k8s.io/kube-controller-manager:v1.26.3 + sizeBytes: 68538487 + - names: + - docker.io/library/import-2023-03-30@sha256:44db4d50a5f9c8efbac0d37ea974d1c0419a5928f90748d3d491a041a00c20b5 + - registry.k8s.io/kube-proxy:v1.26.3 + sizeBytes: 67217404 + - names: + - docker.io/library/import-2023-03-30@sha256:3dd2337f70af979c7362b5e52bbdfcb3a5fd39c78d94d02145150cd2db86ba39 + - registry.k8s.io/kube-scheduler:v1.26.3 + sizeBytes: 57761399 + - names: + - docker.io/kindest/kindnetd:v20230330-48f316cd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af + - docker.io/kindest/kindnetd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af + sizeBytes: 27726335 + - names: + - docker.io/kindest/local-path-provisioner:v0.0.23-kind.0@sha256:f2d0a02831ff3a03cf51343226670d5060623b43a4cfc4808bd0875b2c4b9501 + sizeBytes: 18664669 + - names: + - registry.k8s.io/coredns/coredns:v1.9.3 + sizeBytes: 14837849 + - names: + - docker.io/kindest/local-path-helper:v20230330-48f316cd@sha256:135203f2441f916fb13dad1561d27f60a6f11f50ec288b01a7d2ee9947c36270 + sizeBytes: 3052037 + - names: + - registry.k8s.io/pause:3.7 + sizeBytes: 311278 + nodeInfo: + architecture: amd64 + bootID: 2d71b318-5d07-4de2-9e61-2da28cf5bbf0 + containerRuntimeVersion: containerd://1.6.19-46-g941215f49 + kernelVersion: 5.15.0-72-generic + kubeProxyVersion: v1.26.3 + kubeletVersion: v1.26.3 + machineID: 96f8c8b8c8ae4600a3654341f207586e + operatingSystem: linux + osImage: Ubuntu 22.04.2 LTS + systemUUID: 111aa932-7f99-4bef-aaf7-36aa7fb9b012 + - apiVersion: v1 + kind: Node + metadata: + annotations: + kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock + node.alpha.kubernetes.io/ttl: "0" + volumes.kubernetes.io/controller-managed-attach-detach: "true" + creationTimestamp: "2023-05-31T04:39:57Z" + labels: + beta.kubernetes.io/arch: amd64 + beta.kubernetes.io/os: linux + kubernetes.io/arch: amd64 + kubernetes.io/hostname: kind-worker + kwok-nodegroup: kind-worker + kubernetes.io/os: linux + name: kind-worker + resourceVersion: "577" + uid: 2ac0eb71-e5cf-4708-bbbf-476e8f19842b + spec: + podCIDR: 10.244.2.0/24 + podCIDRs: + - 10.244.2.0/24 + providerID: kind://docker/kind/kind-worker + status: + addresses: + - address: 172.18.0.3 + type: InternalIP + - address: kind-worker + type: Hostname + allocatable: + cpu: "12" + ephemeral-storage: 959786032Ki + hugepages-1Gi: "0" + hugepages-2Mi: "0" + memory: 32781516Ki + pods: "110" + capacity: + cpu: "12" + ephemeral-storage: 959786032Ki + hugepages-1Gi: "0" + hugepages-2Mi: "0" + memory: 32781516Ki + pods: "110" + conditions: + - lastHeartbeatTime: "2023-05-31T04:40:17Z" + lastTransitionTime: "2023-05-31T04:39:57Z" + message: kubelet has sufficient memory available + reason: KubeletHasSufficientMemory + status: "False" + type: MemoryPressure + - lastHeartbeatTime: "2023-05-31T04:40:17Z" + lastTransitionTime: "2023-05-31T04:39:57Z" + message: kubelet has no disk pressure + reason: KubeletHasNoDiskPressure + status: "False" + type: DiskPressure + - lastHeartbeatTime: "2023-05-31T04:40:17Z" + lastTransitionTime: "2023-05-31T04:39:57Z" + message: kubelet has sufficient PID available + reason: KubeletHasSufficientPID + status: "False" + type: PIDPressure + - lastHeartbeatTime: "2023-05-31T04:40:17Z" + lastTransitionTime: "2023-05-31T04:40:05Z" + message: kubelet is posting ready status + reason: KubeletReady + status: "True" + type: Ready + daemonEndpoints: + kubeletEndpoint: + Port: 10250 + images: + - names: + - registry.k8s.io/etcd:3.5.6-0 + sizeBytes: 102542580 + - names: + - docker.io/library/import-2023-03-30@sha256:ba097b515c8c40689733c0f19de377e9bf8995964b7d7150c2045f3dfd166657 + - registry.k8s.io/kube-apiserver:v1.26.3 + sizeBytes: 80392681 + - names: + - docker.io/library/import-2023-03-30@sha256:8dbb345de79d1c44f59a7895da702a5f71997ae72aea056609445c397b0c10dc + - registry.k8s.io/kube-controller-manager:v1.26.3 + sizeBytes: 68538487 + - names: + - docker.io/library/import-2023-03-30@sha256:44db4d50a5f9c8efbac0d37ea974d1c0419a5928f90748d3d491a041a00c20b5 + - registry.k8s.io/kube-proxy:v1.26.3 + sizeBytes: 67217404 + - names: + - docker.io/library/import-2023-03-30@sha256:3dd2337f70af979c7362b5e52bbdfcb3a5fd39c78d94d02145150cd2db86ba39 + - registry.k8s.io/kube-scheduler:v1.26.3 + sizeBytes: 57761399 + - names: + - docker.io/kindest/kindnetd:v20230330-48f316cd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af + - docker.io/kindest/kindnetd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af + sizeBytes: 27726335 + - names: + - docker.io/kindest/local-path-provisioner:v0.0.23-kind.0@sha256:f2d0a02831ff3a03cf51343226670d5060623b43a4cfc4808bd0875b2c4b9501 + sizeBytes: 18664669 + - names: + - registry.k8s.io/coredns/coredns:v1.9.3 + sizeBytes: 14837849 + - names: + - docker.io/kindest/local-path-helper:v20230330-48f316cd@sha256:135203f2441f916fb13dad1561d27f60a6f11f50ec288b01a7d2ee9947c36270 + sizeBytes: 3052037 + - names: + - registry.k8s.io/pause:3.7 + sizeBytes: 311278 + nodeInfo: + architecture: amd64 + bootID: 2d71b318-5d07-4de2-9e61-2da28cf5bbf0 + containerRuntimeVersion: containerd://1.6.19-46-g941215f49 + kernelVersion: 5.15.0-72-generic + kubeProxyVersion: v1.26.3 + kubeletVersion: v1.26.3 + machineID: a98a13ff474d476294935341f1ba9816 + operatingSystem: linux + osImage: Ubuntu 22.04.2 LTS + systemUUID: 5f3c1af8-a385-4776-85e4-73d7f4252b44 + - apiVersion: v1 + kind: Node + metadata: + annotations: + kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock + node.alpha.kubernetes.io/ttl: "0" + volumes.kubernetes.io/controller-managed-attach-detach: "true" + creationTimestamp: "2023-05-31T04:39:57Z" + labels: + beta.kubernetes.io/arch: amd64 + beta.kubernetes.io/os: linux + kubernetes.io/arch: amd64 + kubernetes.io/hostname: kind-worker2 + kwok-nodegroup: kind-worker2 + kubernetes.io/os: linux + name: kind-worker2 + resourceVersion: "578" + uid: edc7df38-feb2-4089-9955-780562bdd21e + spec: + podCIDR: 10.244.1.0/24 + podCIDRs: + - 10.244.1.0/24 + providerID: kind://docker/kind/kind-worker2 + status: + addresses: + - address: 172.18.0.4 + type: InternalIP + - address: kind-worker2 + type: Hostname + allocatable: + cpu: "12" + ephemeral-storage: 959786032Ki + hugepages-1Gi: "0" + hugepages-2Mi: "0" + memory: 32781516Ki + pods: "110" + capacity: + cpu: "12" + ephemeral-storage: 959786032Ki + hugepages-1Gi: "0" + hugepages-2Mi: "0" + memory: 32781516Ki + pods: "110" + conditions: + - lastHeartbeatTime: "2023-05-31T04:40:17Z" + lastTransitionTime: "2023-05-31T04:39:57Z" + message: kubelet has sufficient memory available + reason: KubeletHasSufficientMemory + status: "False" + type: MemoryPressure + - lastHeartbeatTime: "2023-05-31T04:40:17Z" + lastTransitionTime: "2023-05-31T04:39:57Z" + message: kubelet has no disk pressure + reason: KubeletHasNoDiskPressure + status: "False" + type: DiskPressure + - lastHeartbeatTime: "2023-05-31T04:40:17Z" + lastTransitionTime: "2023-05-31T04:39:57Z" + message: kubelet has sufficient PID available + reason: KubeletHasSufficientPID + status: "False" + type: PIDPressure + - lastHeartbeatTime: "2023-05-31T04:40:17Z" + lastTransitionTime: "2023-05-31T04:40:08Z" + message: kubelet is posting ready status + reason: KubeletReady + status: "True" + type: Ready + daemonEndpoints: + kubeletEndpoint: + Port: 10250 + images: + - names: + - registry.k8s.io/etcd:3.5.6-0 + sizeBytes: 102542580 + - names: + - docker.io/library/import-2023-03-30@sha256:ba097b515c8c40689733c0f19de377e9bf8995964b7d7150c2045f3dfd166657 + - registry.k8s.io/kube-apiserver:v1.26.3 + sizeBytes: 80392681 + - names: + - docker.io/library/import-2023-03-30@sha256:8dbb345de79d1c44f59a7895da702a5f71997ae72aea056609445c397b0c10dc + - registry.k8s.io/kube-controller-manager:v1.26.3 + sizeBytes: 68538487 + - names: + - docker.io/library/import-2023-03-30@sha256:44db4d50a5f9c8efbac0d37ea974d1c0419a5928f90748d3d491a041a00c20b5 + - registry.k8s.io/kube-proxy:v1.26.3 + sizeBytes: 67217404 + - names: + - docker.io/library/import-2023-03-30@sha256:3dd2337f70af979c7362b5e52bbdfcb3a5fd39c78d94d02145150cd2db86ba39 + - registry.k8s.io/kube-scheduler:v1.26.3 + sizeBytes: 57761399 + - names: + - docker.io/kindest/kindnetd:v20230330-48f316cd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af + - docker.io/kindest/kindnetd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af + sizeBytes: 27726335 + - names: + - docker.io/kindest/local-path-provisioner:v0.0.23-kind.0@sha256:f2d0a02831ff3a03cf51343226670d5060623b43a4cfc4808bd0875b2c4b9501 + sizeBytes: 18664669 + - names: + - registry.k8s.io/coredns/coredns:v1.9.3 + sizeBytes: 14837849 + - names: + - docker.io/kindest/local-path-helper:v20230330-48f316cd@sha256:135203f2441f916fb13dad1561d27f60a6f11f50ec288b01a7d2ee9947c36270 + sizeBytes: 3052037 + - names: + - registry.k8s.io/pause:3.7 + sizeBytes: 311278 + nodeInfo: + architecture: amd64 + bootID: 2d71b318-5d07-4de2-9e61-2da28cf5bbf0 + containerRuntimeVersion: containerd://1.6.19-46-g941215f49 + kernelVersion: 5.15.0-72-generic + kubeProxyVersion: v1.26.3 + kubeletVersion: v1.26.3 + machineID: fa9f4cd3b3a743bc867b04e44941dcb2 + operatingSystem: linux + osImage: Ubuntu 22.04.2 LTS + systemUUID: f36c0f00-8ba5-4c8c-88bc-2981c8d377b9 + kind: List + metadata: + resourceVersion: "" + + +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/deployment.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/deployment.yaml new file mode 100644 index 000000000..a566a01ce --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/deployment.yaml @@ -0,0 +1,372 @@ +{{- if or ( or .Values.autoDiscovery.clusterName .Values.autoDiscovery.namespace .Values.autoDiscovery.labels ) .Values.autoscalingGroups }} +{{/* one of the above is required */}} +apiVersion: {{ template "deployment.apiVersion" . }} +kind: Deployment +metadata: + annotations: +{{ toYaml .Values.deployment.annotations | indent 4 }} + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + name: {{ template "cluster-autoscaler.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: +{{ include "cluster-autoscaler.instance-name" . | indent 6 }} + {{- if .Values.podLabels }} +{{ toYaml .Values.podLabels | indent 6 }} + {{- end }} +{{- if .Values.updateStrategy }} + strategy: + {{ toYaml .Values.updateStrategy | nindent 4 | trim }} +{{- end }} + template: + metadata: + {{- if .Values.podAnnotations }} + annotations: +{{ toYaml .Values.podAnnotations | indent 8 }} + {{- end }} + labels: +{{ include "cluster-autoscaler.instance-name" . | indent 8 }} + {{- if .Values.additionalLabels }} +{{ toYaml .Values.additionalLabels | indent 8 }} + {{- end }} + {{- if .Values.podLabels }} +{{ toYaml .Values.podLabels | indent 8 }} + {{- end }} + spec: + {{- if .Values.priorityClassName }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.dnsPolicy }} + dnsPolicy: "{{ .Values.dnsPolicy }}" + {{- end }} + {{- if .Values.hostNetwork }} + hostNetwork: {{ .Values.hostNetwork }} + {{- end }} + {{- with .Values.initContainers }} + initContainers: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ template "cluster-autoscaler.name" . }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + command: + - ./cluster-autoscaler + - --cloud-provider={{ .Values.cloudProvider }} + {{- if and (eq .Values.cloudProvider "clusterapi") (eq .Values.clusterAPIMode "kubeconfig-incluster") }} + - --namespace={{ .Values.clusterAPIConfigMapsNamespace | default "kube-system" }} + {{- else }} + - --namespace={{ .Release.Namespace }} + {{- end }} + {{- if .Values.autoscalingGroups }} + {{- range .Values.autoscalingGroups }} + {{- if eq $.Values.cloudProvider "hetzner" }} + - --nodes={{ .minSize }}:{{ .maxSize }}:{{ .instanceType }}:{{ .region }}:{{ .name }} + {{- else }} + - --nodes={{ .minSize }}:{{ .maxSize }}:{{ .name }} + {{- end }} + {{- end }} + {{- end }} + {{- if eq .Values.cloudProvider "rancher" }} + {{- if .Values.cloudConfigPath }} + - --cloud-config={{ .Values.cloudConfigPath }} + {{- end }} + {{- end }} + {{- if eq .Values.cloudProvider "aws" }} + {{- if .Values.autoDiscovery.clusterName }} + - --node-group-auto-discovery=asg:tag={{ tpl (join "," .Values.autoDiscovery.tags) . }} + {{- end }} + {{- if .Values.cloudConfigPath }} + - --cloud-config={{ .Values.cloudConfigPath }} + {{- end }} + {{- else if eq .Values.cloudProvider "gce" }} + {{- if .Values.autoscalingGroupsnamePrefix }} + {{- range .Values.autoscalingGroupsnamePrefix }} + - --node-group-auto-discovery=mig:namePrefix={{ .name }},min={{ .minSize }},max={{ .maxSize }} + {{- end }} + {{- end }} + {{- if eq .Values.cloudProvider "oci" }} + {{- if .Values.cloudConfigPath }} + - --nodes={{ .minSize }}:{{ .maxSize }}:{{ .name }} + - --balance-similar-node-groups + {{- end }} + {{- end }} + {{- else if eq .Values.cloudProvider "magnum" }} + {{- if .Values.autoDiscovery.clusterName }} + - --cluster-name={{ tpl (.Values.autoDiscovery.clusterName) . }} + - --node-group-auto-discovery=magnum:role={{ tpl (join "," .Values.autoDiscovery.roles) . }} + {{- else }} + - --cluster-name={{ tpl (.Values.magnumClusterName) . }} + {{- end }} + {{- else if eq .Values.cloudProvider "clusterapi" }} + {{- if or .Values.autoDiscovery.clusterName .Values.autoDiscovery.labels .Values.autoDiscovery.namespace }} + - --node-group-auto-discovery=clusterapi:{{ template "cluster-autoscaler.capiAutodiscoveryConfig" . }} + {{- end }} + {{- if eq .Values.clusterAPIMode "incluster-kubeconfig"}} + - --cloud-config={{ .Values.clusterAPICloudConfigPath }} + {{- else if eq .Values.clusterAPIMode "kubeconfig-incluster"}} + - --kubeconfig={{ .Values.clusterAPIWorkloadKubeconfigPath }} + - --clusterapi-cloud-config-authoritative + {{- else if eq .Values.clusterAPIMode "kubeconfig-kubeconfig"}} + - --kubeconfig={{ .Values.clusterAPIWorkloadKubeconfigPath }} + - --cloud-config={{ .Values.clusterAPICloudConfigPath }} + {{- else if eq .Values.clusterAPIMode "single-kubeconfig"}} + - --kubeconfig={{ .Values.clusterAPIWorkloadKubeconfigPath }} + {{- end }} + {{- else if eq .Values.cloudProvider "azure" }} + {{- if .Values.autoDiscovery.clusterName }} + - --node-group-auto-discovery=label:cluster-autoscaler-enabled=true,cluster-autoscaler-name={{ tpl (.Values.autoDiscovery.clusterName) . }} + {{- end }} + {{- end }} + {{- if eq .Values.cloudProvider "magnum" }} + - --cloud-config={{ .Values.cloudConfigPath }} + {{- end }} + {{- range $key, $value := .Values.extraArgs }} + {{- if not (kindIs "invalid" $value) }} + - --{{ $key | mustRegexFind "^[^_]+" }}={{ $value }} + {{- else }} + - --{{ $key | mustRegexFind "^[^_]+" }} + {{- end }} + {{- end }} + {{- range .Values.customArgs }} + - {{ . }} + {{- end }} + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + {{- if and (eq .Values.cloudProvider "aws") (ne .Values.awsRegion "") }} + - name: AWS_REGION + value: "{{ .Values.awsRegion }}" + {{- if .Values.awsAccessKeyID }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + key: AwsAccessKeyId + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + {{- end }} + {{- if .Values.awsSecretAccessKey }} + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + key: AwsSecretAccessKey + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + {{- end }} + {{- else if eq .Values.cloudProvider "azure" }} + - name: ARM_SUBSCRIPTION_ID + valueFrom: + secretKeyRef: + key: SubscriptionID + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: ARM_RESOURCE_GROUP + valueFrom: + secretKeyRef: + key: ResourceGroup + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: ARM_VM_TYPE + valueFrom: + secretKeyRef: + key: VMType + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: AZURE_ENABLE_FORCE_DELETE + value: "{{ .Values.azureEnableForceDelete }}" + {{- if .Values.azureUseWorkloadIdentityExtension }} + - name: ARM_USE_WORKLOAD_IDENTITY_EXTENSION + value: "true" + {{- else if .Values.azureUseManagedIdentityExtension }} + - name: ARM_USE_MANAGED_IDENTITY_EXTENSION + value: "true" + - name: ARM_USER_ASSIGNED_IDENTITY_ID + valueFrom: + secretKeyRef: + key: UserAssignedIdentityID + name: {{ template "cluster-autoscaler.fullname" . }} + {{- else }} + - name: ARM_TENANT_ID + valueFrom: + secretKeyRef: + key: TenantID + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: ARM_CLIENT_ID + valueFrom: + secretKeyRef: + key: ClientID + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: ARM_CLIENT_SECRET + valueFrom: + secretKeyRef: + key: ClientSecret + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + {{- end }} + {{- else if eq .Values.cloudProvider "exoscale" }} + - name: EXOSCALE_API_KEY + valueFrom: + secretKeyRef: + key: api-key + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: EXOSCALE_API_SECRET + valueFrom: + secretKeyRef: + key: api-secret + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: EXOSCALE_ZONE + valueFrom: + secretKeyRef: + key: api-zone + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + {{- else if eq .Values.cloudProvider "kwok" }} + - name: KWOK_PROVIDER_CONFIGMAP + value: "{{.Values.kwokConfigMapName | default "kwok-provider-config"}}" + {{- else if eq .Values.cloudProvider "civo" }} + - name: CIVO_API_URL + valueFrom: + secretKeyRef: + key: api-url + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: CIVO_API_KEY + valueFrom: + secretKeyRef: + key: api-key + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: CIVO_CLUSTER_ID + valueFrom: + secretKeyRef: + key: cluster-id + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + - name: CIVO_REGION + valueFrom: + secretKeyRef: + key: region + name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} + {{- end }} + {{- range $key, $value := .Values.extraEnv }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.extraEnvConfigMaps }} + - name: {{ $key }} + valueFrom: + configMapKeyRef: + name: {{ default (include "cluster-autoscaler.fullname" $) $value.name }} + key: {{ required "Must specify key!" $value.key }} + {{- end }} + {{- range $key, $value := .Values.extraEnvSecrets }} + - name: {{ $key }} + valueFrom: + secretKeyRef: + name: {{ default (include "cluster-autoscaler.fullname" $) $value.name }} + key: {{ required "Must specify key!" $value.key }} + {{- end }} + {{- if or .Values.envFromSecret .Values.envFromConfigMap }} + envFrom: + {{- if .Values.envFromSecret }} + - secretRef: + name: {{ .Values.envFromSecret }} + {{- end }} + {{- if .Values.envFromConfigMap }} + - configMapRef: + name: {{ .Values.envFromConfigMap }} + {{- end }} + {{- end }} + livenessProbe: + httpGet: + path: /health-check + port: 8085 + ports: + - containerPort: 8085 + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- if .Values.containerSecurityContext }} + securityContext: + {{ toYaml .Values.containerSecurityContext | nindent 12 | trim }} + {{- end }} + {{- if or (eq .Values.cloudProvider "magnum") .Values.extraVolumeSecrets .Values.extraVolumeMounts .Values.clusterAPIKubeconfigSecret }} + volumeMounts: + {{- if eq .Values.cloudProvider "magnum" }} + - name: cloudconfig + mountPath: {{ .Values.cloudConfigPath }} + readOnly: true + {{- end }} + {{- if and (eq .Values.cloudProvider "magnum") (.Values.magnumCABundlePath) }} + - name: ca-bundle + mountPath: {{ .Values.magnumCABundlePath }} + readOnly: true + {{- end }} + {{- range $key, $value := .Values.extraVolumeSecrets }} + - name: {{ $key }} + mountPath: {{ required "Must specify mountPath!" $value.mountPath }} + readOnly: true + {{- end }} + {{- if .Values.clusterAPIKubeconfigSecret }} + - name: cluster-api-kubeconfig + mountPath: {{ .Values.clusterAPIWorkloadKubeconfigPath | trimSuffix "/value" }} + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.affinity }} + affinity: +{{ toYaml .Values.affinity | indent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} + {{- end }} + serviceAccountName: {{ template "cluster-autoscaler.serviceAccountName" . }} + tolerations: +{{ toYaml .Values.tolerations | indent 8 }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: +{{ toYaml .Values.topologySpreadConstraints | indent 8 }} + {{- end }} + {{- if .Values.securityContext }} + securityContext: + {{ toYaml .Values.securityContext | nindent 8 | trim }} + {{- end }} + {{- if or (eq .Values.cloudProvider "magnum") .Values.extraVolumeSecrets .Values.extraVolumes .Values.clusterAPIKubeconfigSecret }} + volumes: + {{- if eq .Values.cloudProvider "magnum" }} + - name: cloudconfig + hostPath: + path: {{ .Values.cloudConfigPath }} + {{- end }} + {{- if and (eq .Values.cloudProvider "magnum") (.Values.magnumCABundlePath) }} + - name: ca-bundle + hostPath: + path: {{ .Values.magnumCABundlePath }} + {{- end }} + {{- range $key, $value := .Values.extraVolumeSecrets }} + - name: {{ $key }} + secret: + secretName: {{ default (include "cluster-autoscaler.fullname" $) $value.name }} + {{- if $value.items }} + items: + {{- toYaml $value.items | nindent 14 }} + {{- end }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} + {{- if .Values.clusterAPIKubeconfigSecret }} + - name: cluster-api-kubeconfig + secret: + secretName: {{ .Values.clusterAPIKubeconfigSecret }} + {{- end }} + {{- end }} + {{- if .Values.image.pullSecrets }} + imagePullSecrets: + {{- range .Values.image.pullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/extra-manifests.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/extra-manifests.yaml new file mode 100644 index 000000000..a9bb3b6ba --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraObjects }} +--- +{{ tpl (toYaml .) $ }} +{{ end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/pdb.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/pdb.yaml new file mode 100644 index 000000000..8ad782096 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/pdb.yaml @@ -0,0 +1,16 @@ +{{- if .Values.podDisruptionBudget -}} +apiVersion: {{ template "podDisruptionBudget.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + name: {{ template "cluster-autoscaler.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + selector: + matchLabels: +{{ include "cluster-autoscaler.instance-name" . | indent 6 }} +{{- if .Values.podDisruptionBudget }} + {{ toYaml .Values.podDisruptionBudget | nindent 2 }} +{{- end }} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/podsecuritypolicy.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/podsecuritypolicy.yaml new file mode 100644 index 000000000..e3ce59973 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/podsecuritypolicy.yaml @@ -0,0 +1,42 @@ +{{- if .Values.rbac.pspEnabled }} +apiVersion: {{ template "podsecuritypolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "cluster-autoscaler.fullname" . }} + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} +spec: + # Prevents running in privileged mode + privileged: false + # Required to prevent escalations to root. + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + volumes: + - 'configMap' + - 'secret' + - 'hostPath' + - 'emptyDir' + - 'projected' + - 'downwardAPI' + hostNetwork: {{ .Values.hostNetwork }} + hostIPC: false + hostPID: false + runAsUser: + rule: RunAsAny + 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/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/priority-expander-configmap.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/priority-expander-configmap.yaml new file mode 100644 index 000000000..8259f14ff --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/priority-expander-configmap.yaml @@ -0,0 +1,25 @@ +{{- if hasKey .Values.extraArgs "expander" }} +{{- if and (.Values.expanderPriorities) (include "cluster-autoscaler.priorityExpanderEnabled" .) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: cluster-autoscaler-priority-expander + namespace: {{ .Release.Namespace }} + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + {{- if .Values.priorityConfigMapAnnotations }} + annotations: +{{ toYaml .Values.priorityConfigMapAnnotations | indent 4 }} + {{- end }} +data: + priorities: |- +{{- if kindIs "string" .Values.expanderPriorities }} +{{ .Values.expanderPriorities | indent 4 }} +{{- else }} +{{- range $k,$v := .Values.expanderPriorities }} + {{ $k | int }}: + {{- toYaml $v | nindent 6 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/prometheusrule.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/prometheusrule.yaml new file mode 100644 index 000000000..097c969ef --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/prometheusrule.yaml @@ -0,0 +1,15 @@ +{{- if .Values.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "cluster-autoscaler.fullname" . }} + {{- if .Values.prometheusRule.namespace }} + namespace: {{ .Values.prometheusRule.namespace }} + {{- end }} + labels: {{- toYaml .Values.prometheusRule.additionalLabels | nindent 4 }} +spec: + groups: + - name: {{ include "cluster-autoscaler.fullname" . }} + interval: {{ .Values.prometheusRule.interval }} + rules: {{- tpl (toYaml .Values.prometheusRule.rules) . | nindent 8 }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/role.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/role.yaml new file mode 100644 index 000000000..44b1678af --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/role.yaml @@ -0,0 +1,87 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + name: {{ template "cluster-autoscaler.fullname" . }} + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - create +{{- if (include "cluster-autoscaler.priorityExpanderEnabled" .) }} + - list + - watch +{{- end }} + - apiGroups: + - "" + resources: + - configmaps + resourceNames: + - cluster-autoscaler-status +{{- if (include "cluster-autoscaler.priorityExpanderEnabled" .) }} + - cluster-autoscaler-priority-expander +{{- end }} + verbs: + - delete + - get + - update +{{- if (include "cluster-autoscaler.priorityExpanderEnabled" .) }} + - watch +{{- end }} +{{- if eq (default "" (index .Values.extraArgs "leader-elect-resource-lock")) "configmaps" }} + - apiGroups: + - "" + resources: + - configmaps + resourceNames: + - cluster-autoscaler + verbs: + - get + - update +{{- end }} +{{- if and ( and ( eq .Values.cloudProvider "clusterapi" ) ( not .Values.rbac.clusterScoped ) ( or ( eq .Values.clusterAPIMode "incluster-incluster" ) ( eq .Values.clusterAPIMode "kubeconfig-incluster" ) ))}} + - apiGroups: + - cluster.x-k8s.io + resources: + - machinedeployments + - machinepools + - machines + - machinesets + verbs: + - get + - list + - update + - watch + - apiGroups: + - cluster.x-k8s.io + resources: + - machinedeployments/scale + - machinepools/scale + verbs: + - get + - patch + - update +{{- end }} +{{- if ( not .Values.rbac.clusterScoped ) }} + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - coordination.k8s.io + resourceNames: + - cluster-autoscaler + resources: + - leases + verbs: + - get + - update +{{- end }} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/rolebinding.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/rolebinding.yaml new file mode 100644 index 000000000..ba5f03755 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + name: {{ template "cluster-autoscaler.fullname" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cluster-autoscaler.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "cluster-autoscaler.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/secret.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/secret.yaml new file mode 100644 index 000000000..760cc3c5a --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/secret.yaml @@ -0,0 +1,32 @@ +{{- if not .Values.secretKeyRefNameOverride }} +{{- $isAzure := eq .Values.cloudProvider "azure" }} +{{- $isAws := eq .Values.cloudProvider "aws" }} +{{- $awsCredentialsProvided := and .Values.awsAccessKeyID .Values.awsSecretAccessKey }} +{{- $isCivo := eq .Values.cloudProvider "civo" }} + +{{- if or $isAzure (and $isAws $awsCredentialsProvided) $isCivo }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "cluster-autoscaler.fullname" . }} + namespace: {{ .Release.Namespace }} +data: +{{- if $isAzure }} + ClientID: "{{ .Values.azureClientID | b64enc }}" + ClientSecret: "{{ .Values.azureClientSecret | b64enc }}" + ResourceGroup: "{{ .Values.azureResourceGroup | b64enc }}" + SubscriptionID: "{{ .Values.azureSubscriptionID | b64enc }}" + TenantID: "{{ .Values.azureTenantID | b64enc }}" + VMType: "{{ .Values.azureVMType | b64enc }}" + UserAssignedIdentityID: "{{ .Values.azureUserAssignedIdentityID | b64enc }}" +{{- else if $isAws }} + AwsAccessKeyId: "{{ .Values.awsAccessKeyID | b64enc }}" + AwsSecretAccessKey: "{{ .Values.awsSecretAccessKey | b64enc }}" +{{- else if $isCivo }} + api-url: "{{ .Values.civoApiUrl | b64enc }}" + api-key: "{{ .Values.civoApiKey | b64enc }}" + cluster-id: "{{ .Values.civoClusterID | b64enc }}" + region: "{{ .Values.civoRegion | b64enc }}" +{{- end }} +{{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/service.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/service.yaml new file mode 100644 index 000000000..255aea44b --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/service.yaml @@ -0,0 +1,39 @@ +{{- if .Values.service.create }} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.service.annotations }} + annotations: +{{ toYaml .Values.service.annotations | indent 4 }} +{{- end }} + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} +{{- if .Values.service.labels }} +{{ toYaml .Values.service.labels | indent 4 }} +{{- end }} + name: {{ template "cluster-autoscaler.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: +{{- if .Values.service.clusterIP }} + clusterIP: "{{ .Values.service.clusterIP }}" +{{- end }} +{{- if .Values.service.externalIPs }} + externalIPs: +{{ toYaml .Values.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.service.loadBalancerIP }} + loadBalancerIP: "{{ .Values.service.loadBalancerIP }}" +{{- end }} +{{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} +{{- end }} + ports: + - port: {{ .Values.service.servicePort }} + protocol: TCP + targetPort: 8085 + name: {{ .Values.service.portName }} + selector: +{{ include "cluster-autoscaler.instance-name" . | indent 4 }} + type: "{{ .Values.service.type }}" +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/serviceaccount.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/serviceaccount.yaml new file mode 100644 index 000000000..29c2580c2 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.rbac.create .Values.rbac.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + name: {{ template "cluster-autoscaler.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- if .Values.rbac.serviceAccount.annotations }} + annotations: {{ toYaml .Values.rbac.serviceAccount.annotations | nindent 4 }} +{{- end }} +automountServiceAccountToken: {{ .Values.rbac.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/servicemonitor.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/servicemonitor.yaml new file mode 100644 index 000000000..9ce83a2ef --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/servicemonitor.yaml @@ -0,0 +1,36 @@ +{{ if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "cluster-autoscaler.fullname" . }} + {{- if .Values.serviceMonitor.namespace }} + namespace: {{ .Values.serviceMonitor.namespace }} + {{- end }} + {{- if .Values.serviceMonitor.annotations }} + annotations: +{{ toYaml .Values.serviceMonitor.annotations | indent 4 }} + {{- end }} + labels: + {{- range $key, $value := .Values.serviceMonitor.selector }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + selector: + matchLabels: +{{ include "cluster-autoscaler.instance-name" . | indent 6 }} + endpoints: + - port: {{ .Values.service.portName }} + interval: {{ .Values.serviceMonitor.interval }} + path: {{ .Values.serviceMonitor.path }} + {{- if .Values.serviceMonitor.relabelings }} + relabelings: +{{ tpl (toYaml .Values.serviceMonitor.relabelings | indent 6) . }} + {{- end }} + {{- if .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: +{{ tpl (toYaml .Values.serviceMonitor.metricRelabelings | indent 6) . }} + {{- end }} + namespaceSelector: + matchNames: + - {{.Release.Namespace}} +{{ end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/vpa.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/vpa.yaml new file mode 100644 index 000000000..b889beac9 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/templates/vpa.yaml @@ -0,0 +1,20 @@ +{{- if .Values.vpa.enabled -}} +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + labels: +{{ include "cluster-autoscaler.labels" . | indent 4 }} + name: {{ template "cluster-autoscaler.fullname" . }} + namespace: {{ .Release.Namespace }} +spec: + targetRef: + apiVersion: {{ template "deployment.apiVersion" . }} + kind: Deployment + name: {{ template "cluster-autoscaler.fullname" . }} + updatePolicy: + updateMode: {{ .Values.vpa.updateMode | quote }} + resourcePolicy: + containerPolicies: + - containerName: {{ template "cluster-autoscaler.name" . }} + {{- .Values.vpa.containerPolicy | toYaml | nindent 6 }} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/values.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/values.yaml new file mode 100644 index 000000000..663f4f65e --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/cluster-autoscaler/values.yaml @@ -0,0 +1,470 @@ +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +# affinity -- Affinity for pod assignment +affinity: {} + +# additionalLabels -- Labels to add to each object of the chart. +additionalLabels: {} + +autoDiscovery: + # cloudProviders `aws`, `gce`, `azure`, `magnum`, `clusterapi` and `oci` are supported by auto-discovery at this time + # AWS: Set tags as described in https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup + + # autoDiscovery.clusterName -- Enable autodiscovery for `cloudProvider=aws`, for groups matching `autoDiscovery.tags`. + # autoDiscovery.clusterName -- Enable autodiscovery for `cloudProvider=azure`, using tags defined in https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/azure/README.md#auto-discovery-setup. + # Enable autodiscovery for `cloudProvider=clusterapi`, for groups matching `autoDiscovery.labels`. + # Enable autodiscovery for `cloudProvider=gce`, but no MIG tagging required. + # Enable autodiscovery for `cloudProvider=magnum`, for groups matching `autoDiscovery.roles`. + clusterName: # cluster.local + + # autoDiscovery.namespace -- Enable autodiscovery via cluster namespace for for `cloudProvider=clusterapi` + namespace: # default + + # autoDiscovery.tags -- ASG tags to match, run through `tpl`. + tags: + - k8s.io/cluster-autoscaler/enabled + - k8s.io/cluster-autoscaler/{{ .Values.autoDiscovery.clusterName }} + # - kubernetes.io/cluster/{{ .Values.autoDiscovery.clusterName }} + + # autoDiscovery.roles -- Magnum node group roles to match. + roles: + - worker + + # autoDiscovery.labels -- Cluster-API labels to match https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#configuring-node-group-auto-discovery + labels: [] + # - color: green + # - shape: circle +# autoscalingGroups -- For AWS, Azure AKS, Exoscale or Magnum. At least one element is required if not using `autoDiscovery`. For example: +#
+# - name: asg1
+# maxSize: 2
+# minSize: 1 +#
+# For Hetzner Cloud, the `instanceType` and `region` keys are also required. +#
+# - name: mypool
+# maxSize: 2
+# minSize: 1
+# instanceType: CPX21
+# region: FSN1 +#
+autoscalingGroups: [] +# - name: asg1 +# maxSize: 2 +# minSize: 1 +# - name: asg2 +# maxSize: 2 +# minSize: 1 + +# autoscalingGroupsnamePrefix -- For GCE. At least one element is required if not using `autoDiscovery`. For example: +#
+# - name: ig01
+# maxSize: 10
+# minSize: 0 +#
+autoscalingGroupsnamePrefix: [] +# - name: ig01 +# maxSize: 10 +# minSize: 0 +# - name: ig02 +# maxSize: 10 +# minSize: 0 + +# awsAccessKeyID -- AWS access key ID ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials)) +awsAccessKeyID: "" + +# awsRegion -- AWS region (required if `cloudProvider=aws`) +awsRegion: us-east-1 + +# awsSecretAccessKey -- AWS access secret key ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials)) +awsSecretAccessKey: "" + +# azureClientID -- Service Principal ClientID with contributor permission to Cluster and Node ResourceGroup. +# Required if `cloudProvider=azure` +azureClientID: "" + +# azureClientSecret -- Service Principal ClientSecret with contributor permission to Cluster and Node ResourceGroup. +# Required if `cloudProvider=azure` +azureClientSecret: "" + +# azureResourceGroup -- Azure resource group that the cluster is located. +# Required if `cloudProvider=azure` +azureResourceGroup: "" + +# azureSubscriptionID -- Azure subscription where the resources are located. +# Required if `cloudProvider=azure` +azureSubscriptionID: "" + +# azureTenantID -- Azure tenant where the resources are located. +# Required if `cloudProvider=azure` +azureTenantID: "" + +# azureUseManagedIdentityExtension -- Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID, resource group, and azure AKS cluster name are set. You can only use one authentication method at a time, either azureUseWorkloadIdentityExtension or azureUseManagedIdentityExtension should be set. +azureUseManagedIdentityExtension: false + +# azureUserAssignedIdentityID -- When vmss has multiple user assigned identity assigned, azureUserAssignedIdentityID specifies which identity to be used +azureUserAssignedIdentityID: "" + +# azureUseWorkloadIdentityExtension -- Whether to use Azure's workload identity extension for credentials. See the project here: https://github.com/Azure/azure-workload-identity for more details. You can only use one authentication method at a time, either azureUseWorkloadIdentityExtension or azureUseManagedIdentityExtension should be set. +azureUseWorkloadIdentityExtension: false + +# azureVMType -- Azure VM type. +azureVMType: "vmss" + +# azureEnableForceDelete -- Whether to force delete VMs or VMSS instances when scaling down. +azureEnableForceDelete: false + +# civoApiUrl -- URL for the Civo API. +# Required if `cloudProvider=civo` +civoApiUrl: "https://api.civo.com" + +# civoApiKey -- API key for the Civo API. +# Required if `cloudProvider=civo` +civoApiKey: "" + +# civoClusterID -- Cluster ID for the Civo cluster. +# Required if `cloudProvider=civo` +civoClusterID: "" + +# civoRegion -- Region for the Civo cluster. +# Required if `cloudProvider=civo` +civoRegion: "" + +# cloudConfigPath -- Configuration file for cloud provider. +cloudConfigPath: "" + +# cloudProvider -- The cloud provider where the autoscaler runs. +# Currently only `gce`, `aws`, `azure`, `magnum`, `clusterapi` and `civo` are supported. +# `aws` supported for AWS. `gce` for GCE. `azure` for Azure AKS. +# `magnum` for OpenStack Magnum, `clusterapi` for Cluster API. +# `civo` for Civo Cloud. +cloudProvider: aws + +# clusterAPICloudConfigPath -- Path to kubeconfig for connecting to Cluster API Management Cluster, only used if `clusterAPIMode=kubeconfig-kubeconfig or incluster-kubeconfig` +clusterAPICloudConfigPath: /etc/kubernetes/mgmt-kubeconfig + +# clusterAPIConfigMapsNamespace -- Namespace on the workload cluster to store Leader election and status configmaps +clusterAPIConfigMapsNamespace: "" + +# clusterAPIKubeconfigSecret -- Secret containing kubeconfig for connecting to Cluster API managed workloadcluster +# Required if `cloudProvider=clusterapi` and `clusterAPIMode=kubeconfig-kubeconfig,kubeconfig-incluster or incluster-kubeconfig` +clusterAPIKubeconfigSecret: "" + +# clusterAPIMode -- Cluster API mode, see https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#connecting-cluster-autoscaler-to-cluster-api-management-and-workload-clusters +# Syntax: workloadClusterMode-ManagementClusterMode +# for `kubeconfig-kubeconfig`, `incluster-kubeconfig` and `single-kubeconfig` you always must mount the external kubeconfig using either `extraVolumeSecrets` or `extraMounts` and `extraVolumes` +# if you dont set `clusterAPIKubeconfigSecret`and thus use an in-cluster config or want to use a non capi generated kubeconfig you must do so for the workload kubeconfig as well +clusterAPIMode: incluster-incluster # incluster-incluster, incluster-kubeconfig, kubeconfig-incluster, kubeconfig-kubeconfig, single-kubeconfig + +# clusterAPIWorkloadKubeconfigPath -- Path to kubeconfig for connecting to Cluster API managed workloadcluster, only used if `clusterAPIMode=kubeconfig-kubeconfig or kubeconfig-incluster` +clusterAPIWorkloadKubeconfigPath: /etc/kubernetes/value + +# containerSecurityContext -- [Security context for container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +containerSecurityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + +deployment: + # deployment.annotations -- Annotations to add to the Deployment object. + annotations: {} + +# dnsPolicy -- Defaults to `ClusterFirst`. Valid values are: +# `ClusterFirstWithHostNet`, `ClusterFirst`, `Default` or `None`. +# If autoscaler does not depend on cluster DNS, recommended to set this to `Default`. +dnsPolicy: ClusterFirst + +# envFromConfigMap -- ConfigMap name to use as envFrom. +envFromConfigMap: "" + +# envFromSecret -- Secret name to use as envFrom. +envFromSecret: "" + +## Priorities Expander +# expanderPriorities -- The expanderPriorities is used if `extraArgs.expander` contains `priority` and expanderPriorities is also set with the priorities. +# If `extraArgs.expander` contains `priority`, then expanderPriorities is used to define cluster-autoscaler-priority-expander priorities. +# See: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/expander/priority/readme.md +expanderPriorities: {} + +# extraArgs -- Additional container arguments. +# Refer to https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca for the full list of cluster autoscaler +# parameters and their default values. +# Everything after the first _ will be ignored allowing the use of multi-string arguments. +extraArgs: + logtostderr: true + stderrthreshold: info + v: 4 + # write-status-configmap: true + # status-config-map-name: cluster-autoscaler-status + # leader-elect: true + # leader-elect-resource-lock: endpoints + # skip-nodes-with-local-storage: true + # expander: random + # scale-down-enabled: true + # balance-similar-node-groups: true + # min-replica-count: 0 + # scale-down-utilization-threshold: 0.5 + # scale-down-non-empty-candidates-count: 30 + # max-node-provision-time: 15m0s + # scan-interval: 10s + # scale-down-delay-after-add: 10m + # scale-down-delay-after-delete: 0s + # scale-down-delay-after-failure: 3m + # scale-down-unneeded-time: 10m + # node-deletion-delay-timeout: 2m + # node-deletion-batcher-interval: 0s + # skip-nodes-with-system-pods: true + # balancing-ignore-label_1: first-label-to-ignore + # balancing-ignore-label_2: second-label-to-ignore + +# customArgs -- Additional custom container arguments. +# Refer to https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca for the full list of cluster autoscaler +# parameters and their default values. +# List of arguments as strings. +customArgs: [] + +# extraEnv -- Additional container environment variables. +extraEnv: {} + +# extraEnvConfigMaps -- Additional container environment variables from ConfigMaps. +extraEnvConfigMaps: {} + +# extraEnvSecrets -- Additional container environment variables from Secrets. +extraEnvSecrets: {} + +# extraObjects -- Extra K8s manifests to deploy +extraObjects: [] +# - apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: my-configmap +# data: +# key: "value" +# - apiVersion: scheduling.k8s.io/v1 +# kind: PriorityClass +# metadata: +# name: high-priority +# value: 1000000 +# globalDefault: false +# description: "This priority class should be used for XYZ service pods only." + +# extraVolumeMounts -- Additional volumes to mount. +extraVolumeMounts: [] + # - name: ssl-certs + # mountPath: /etc/ssl/certs/ca-certificates.crt + # readOnly: true + +# extraVolumes -- Additional volumes. +extraVolumes: [] + # - name: ssl-certs + # hostPath: + # path: /etc/ssl/certs/ca-bundle.crt + +# extraVolumeSecrets -- Additional volumes to mount from Secrets. +extraVolumeSecrets: {} + # autoscaler-vol: + # mountPath: /data/autoscaler/ + # custom-vol: + # name: custom-secret + # mountPath: /data/custom/ + # items: + # - key: subkey + # path: mypath + +# initContainers -- Any additional init containers. +initContainers: [] + +# fullnameOverride -- String to fully override `cluster-autoscaler.fullname` template. +fullnameOverride: "" + +# hostNetwork -- Whether to expose network interfaces of the host machine to pods. +hostNetwork: false + +image: + # image.repository -- Image repository + repository: registry.k8s.io/autoscaling/cluster-autoscaler + # image.tag -- Image tag + tag: v1.32.0 + # image.pullPolicy -- Image pull policy + 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/ + ## + # image.pullSecrets -- Image pull secrets + pullSecrets: [] + # - myRegistrKeySecretName + +# kubeTargetVersionOverride -- Allow overriding the `.Capabilities.KubeVersion.GitVersion` check. Useful for `helm template` commands. +kubeTargetVersionOverride: "" + +# kwokConfigMapName -- configmap for configuring kwok provider +kwokConfigMapName: "kwok-provider-config" + +# magnumCABundlePath -- Path to the host's CA bundle, from `ca-file` in the cloud-config file. +magnumCABundlePath: "/etc/kubernetes/ca-bundle.crt" + +# magnumClusterName -- Cluster name or ID in Magnum. +# Required if `cloudProvider=magnum` and not setting `autoDiscovery.clusterName`. +magnumClusterName: "" + +# nameOverride -- String to partially override `cluster-autoscaler.fullname` template (will maintain the release name) +nameOverride: "" + +# nodeSelector -- Node labels for pod assignment. Ref: https://kubernetes.io/docs/user-guide/node-selection/. +nodeSelector: {} + +# podAnnotations -- Annotations to add to each pod. +podAnnotations: {} + +# podDisruptionBudget -- Pod disruption budget. +podDisruptionBudget: + maxUnavailable: 1 + # minAvailable: 2 + +# podLabels -- Labels to add to each pod. +podLabels: {} + +# priorityClassName -- priorityClassName +priorityClassName: "system-cluster-critical" + +# priorityConfigMapAnnotations -- Annotations to add to `cluster-autoscaler-priority-expander` ConfigMap. +priorityConfigMapAnnotations: {} + # key1: "value1" + # key2: "value2" + +## 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: + # prometheusRule.enabled -- If true, creates a Prometheus Operator PrometheusRule. + enabled: false + # prometheusRule.additionalLabels -- Additional labels to be set in metadata. + additionalLabels: {} + # prometheusRule.namespace -- Namespace which Prometheus is running in. + namespace: monitoring + # prometheusRule.interval -- How often rules in the group are evaluated (falls back to `global.evaluation_interval` if not set). + interval: null + # prometheusRule.rules -- Rules spec template (see https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#rule). + rules: [] + +rbac: + # rbac.create -- If `true`, create and use RBAC resources. + create: true + # rbac.pspEnabled -- If `true`, creates and uses RBAC resources required in the cluster with [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) enabled. + # Must be used with `rbac.create` set to `true`. + pspEnabled: false + # rbac.clusterScoped -- if set to false will only provision RBAC to alter resources in the current namespace. Most useful for Cluster-API + clusterScoped: true + serviceAccount: + # rbac.serviceAccount.annotations -- Additional Service Account annotations. + annotations: {} + # rbac.serviceAccount.create -- If `true` and `rbac.create` is also true, a Service Account will be created. + create: true + # rbac.serviceAccount.name -- The name of the ServiceAccount to use. If not set and create is `true`, a name is generated using the fullname template. + name: "" + # rbac.serviceAccount.automountServiceAccountToken -- Automount API credentials for a Service Account. + automountServiceAccountToken: true + +# replicaCount -- Desired number of pods +replicaCount: 1 + +# resources -- Pod resource requests and limits. +resources: {} + # limits: + # cpu: 100m + # memory: 300Mi + # requests: + # cpu: 100m + # memory: 300Mi + +# revisionHistoryLimit -- The number of revisions to keep. +revisionHistoryLimit: 10 + +# securityContext -- [Security context for pod](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +securityContext: {} + # runAsNonRoot: true + # runAsUser: 65534 + # runAsGroup: 65534 + # seccompProfile: + # type: RuntimeDefault + +service: + # service.create -- If `true`, a Service will be created. + create: true + # service.annotations -- Annotations to add to service + annotations: {} + # service.labels -- Labels to add to service + labels: {} + # service.externalIPs -- List of IP addresses at which the service is available. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips. + externalIPs: [] + + # service.clusterIP -- IP address to assign to service + clusterIP: "" + + # service.loadBalancerIP -- IP address to assign to load balancer (if supported). + loadBalancerIP: "" + # service.loadBalancerSourceRanges -- List of IP CIDRs allowed access to load balancer (if supported). + loadBalancerSourceRanges: [] + # service.servicePort -- Service port to expose. + servicePort: 8085 + # service.portName -- Name for service port. + portName: http + # service.type -- Type of service to create. + type: ClusterIP + +## Are you using Prometheus Operator? +serviceMonitor: + # serviceMonitor.enabled -- If true, creates a Prometheus Operator ServiceMonitor. + enabled: false + # serviceMonitor.interval -- Interval that Prometheus scrapes Cluster Autoscaler metrics. + interval: 10s + # serviceMonitor.namespace -- Namespace which Prometheus is running in. + namespace: monitoring + ## [Prometheus Selector Label](https://github.com/helm/charts/tree/master/stable/prometheus-operator#prometheus-operator-1) + ## [Kube Prometheus Selector Label](https://github.com/helm/charts/tree/master/stable/prometheus-operator#exporters) + # serviceMonitor.selector -- Default to kube-prometheus install (CoreOS recommended), but should be set according to Prometheus install. + selector: + release: prometheus-operator + # serviceMonitor.path -- The path to scrape for metrics; autoscaler exposes `/metrics` (this is standard) + path: /metrics + # serviceMonitor.annotations -- Annotations to add to service monitor + annotations: {} + ## [RelabelConfig](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.RelabelConfig) + # serviceMonitor.relabelings -- RelabelConfigs to apply to metrics before scraping. + relabelings: {} + ## [RelabelConfig](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.RelabelConfig) + # serviceMonitor.metricRelabelings -- MetricRelabelConfigs to apply to samples before ingestion. + metricRelabelings: {} + +# tolerations -- List of node taints to tolerate (requires Kubernetes >= 1.6). +tolerations: [] + +# topologySpreadConstraints -- You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains such as regions, zones, nodes, and other user-defined topology domains. (requires Kubernetes >= 1.19). +topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: cluster-autoscaler + +# updateStrategy -- [Deployment update strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) +updateStrategy: {} + # rollingUpdate: + # maxSurge: 1 + # maxUnavailable: 0 + # type: RollingUpdate + +# vpa -- Configure a VerticalPodAutoscaler for the cluster-autoscaler Deployment. +vpa: + # vpa.enabled -- If true, creates a VerticalPodAutoscaler. + enabled: false + # vpa.updateMode -- [UpdateMode](https://github.com/kubernetes/autoscaler/blob/vertical-pod-autoscaler/v0.13.0/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L124) + updateMode: "Auto" + # vpa.containerPolicy -- [ContainerResourcePolicy](https://github.com/kubernetes/autoscaler/blob/vertical-pod-autoscaler/v0.13.0/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L159). The containerName is always et to the deployment's container name. This value is required if VPA is enabled. + containerPolicy: {} + +# secretKeyRefNameOverride -- Overrides the name of the Secret to use when loading the secretKeyRef for AWS, Azure and Civo env variables +secretKeyRefNameOverride: "" diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/.helmignore b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/.helmignore new file mode 100644 index 000000000..50af03172 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/.helmignore @@ -0,0 +1,22 @@ +# 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/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/Chart.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/Chart.yaml new file mode 100644 index 000000000..269a870c9 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/Chart.yaml @@ -0,0 +1,23 @@ +apiVersion: v2 +appVersion: v24.9.2 +dependencies: +- condition: nfd.enabled + name: node-feature-discovery + repository: https://kubernetes-sigs.github.io/node-feature-discovery/charts + version: v0.16.6 +description: NVIDIA GPU Operator creates/configures/manages GPUs atop Kubernetes +home: https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/overview.html +icon: https://assets.nvidiagrid.net/ngc/logos/GPUoperator.png +keywords: +- gpu +- cuda +- compute +- operator +- deep learning +- monitoring +- tesla +kubeVersion: '>= 1.16.0-0' +name: gpu-operator +sources: +- https://github.com/NVIDIA/gpu-operator +version: v24.9.2 diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/.helmignore b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/.helmignore @@ -0,0 +1,23 @@ +# 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/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/Chart.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/Chart.yaml new file mode 100644 index 000000000..7656c732f --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +appVersion: v0.16.6 +description: 'Detects hardware features available on each node in a Kubernetes cluster, + and advertises those features using node labels. ' +home: https://github.com/kubernetes-sigs/node-feature-discovery +keywords: +- feature-discovery +- feature-detection +- node-labels +name: node-feature-discovery +sources: +- https://github.com/kubernetes-sigs/node-feature-discovery +type: application +version: 0.16.6 diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/README.md b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/README.md new file mode 100644 index 000000000..93734f8b7 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/README.md @@ -0,0 +1,10 @@ +# Node Feature Discovery + +Node Feature Discovery (NFD) is a Kubernetes add-on for detecting hardware +features and system configuration. Detected features are advertised as node +labels. NFD provides flexible configuration and extension points for a wide +range of vendor and application specific node labeling needs. + +See +[NFD documentation](https://kubernetes-sigs.github.io/node-feature-discovery/v0.16/deployment/helm.html) +for deployment instructions. diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/crds/nfd-api-crds.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/crds/nfd-api-crds.yaml new file mode 100644 index 000000000..0a73c5dca --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/crds/nfd-api-crds.yaml @@ -0,0 +1,710 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: nodefeatures.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeature + listKind: NodeFeatureList + plural: nodefeatures + singular: nodefeature + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + NodeFeature resource holds the features discovered for one node in the + 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 NodeFeature, containing features discovered + for a node. + properties: + features: + description: Features is the full "raw" features data that has been + discovered. + properties: + attributes: + additionalProperties: + description: AttributeFeatureSet is a set of features having + string value. + properties: + elements: + additionalProperties: + type: string + description: Individual features of the feature set. + type: object + required: + - elements + type: object + description: Attributes contains all the attribute-type features + of the node. + type: object + flags: + additionalProperties: + description: FlagFeatureSet is a set of simple features only + containing names without values. + properties: + elements: + additionalProperties: + description: Nil is a dummy empty struct for protobuf + compatibility + type: object + description: Individual features of the feature set. + type: object + required: + - elements + type: object + description: Flags contains all the flag-type features of the + node. + type: object + instances: + additionalProperties: + description: InstanceFeatureSet is a set of features each of + which is an instance having multiple attributes. + properties: + elements: + description: Individual features of the feature set. + items: + description: InstanceFeature represents one instance of + a complex features, e.g. a device. + properties: + attributes: + additionalProperties: + type: string + description: Attributes of the instance feature. + type: object + required: + - attributes + type: object + type: array + required: + - elements + type: object + description: Instances contains all the instance-type features + of the node. + type: object + type: object + labels: + additionalProperties: + type: string + description: Labels is the set of node labels that are requested to + be created. + type: object + type: object + required: + - spec + type: object + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: nodefeaturegroups.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeatureGroup + listKind: NodeFeatureGroupList + plural: nodefeaturegroups + shortNames: + - nfg + singular: nodefeaturegroup + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeFeatureGroup resource holds Node pools by featureGroup + 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: Spec defines the rules to be evaluated. + properties: + featureGroupRules: + description: List of rules to evaluate to determine nodes that belong + in this group. + items: + description: GroupRule defines a rule for nodegroup filtering. + properties: + matchAny: + description: MatchAny specifies a list of matchers one of which + must match. + items: + description: MatchAnyElem specifies one sub-matcher of MatchAny. + properties: + matchFeatures: + description: MatchFeatures specifies a set of matcher + terms all of which must match. + items: + description: |- + FeatureMatcherTerm defines requirements against one feature set. All + requirements (specified as MatchExpressions) are evaluated against each + element in the feature set. + properties: + feature: + description: Feature is the name of the feature + set to match against. + type: string + matchExpressions: + additionalProperties: + description: |- + MatchExpression specifies an expression to evaluate against a set of input + values. It contains an operator that is applied when matching the input and + an array of values that the operator evaluates the input against. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: |- + Value is the list of values that the operand evaluates the input + against. Value should be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly one element if the + operator is Gt or Lt and exactly two elements if the operator is GtLt. + In other cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + description: |- + MatchExpressions is the set of per-element expressions evaluated. These + match against the value of the specified elements. + type: object + matchName: + description: |- + MatchName in an expression that is matched against the name of each + element in the feature set. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: |- + Value is the list of values that the operand evaluates the input + against. Value should be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly one element if the + operator is Gt or Lt and exactly two elements if the operator is GtLt. + In other cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + required: + - feature + type: object + type: array + required: + - matchFeatures + type: object + type: array + matchFeatures: + description: MatchFeatures specifies a set of matcher terms + all of which must match. + items: + description: |- + FeatureMatcherTerm defines requirements against one feature set. All + requirements (specified as MatchExpressions) are evaluated against each + element in the feature set. + properties: + feature: + description: Feature is the name of the feature set to + match against. + type: string + matchExpressions: + additionalProperties: + description: |- + MatchExpression specifies an expression to evaluate against a set of input + values. It contains an operator that is applied when matching the input and + an array of values that the operator evaluates the input against. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: |- + Value is the list of values that the operand evaluates the input + against. Value should be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly one element if the + operator is Gt or Lt and exactly two elements if the operator is GtLt. + In other cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + description: |- + MatchExpressions is the set of per-element expressions evaluated. These + match against the value of the specified elements. + type: object + matchName: + description: |- + MatchName in an expression that is matched against the name of each + element in the feature set. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: |- + Value is the list of values that the operand evaluates the input + against. Value should be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly one element if the + operator is Gt or Lt and exactly two elements if the operator is GtLt. + In other cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + required: + - feature + type: object + type: array + name: + description: Name of the rule. + type: string + required: + - name + type: object + type: array + required: + - featureGroupRules + type: object + status: + description: |- + Status of the NodeFeatureGroup after the most recent evaluation of the + specification. + properties: + nodes: + description: Nodes is a list of FeatureGroupNode in the cluster that + match the featureGroupRules + items: + properties: + name: + description: Name of the node. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: nodefeaturerules.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeatureRule + listKind: NodeFeatureRuleList + plural: nodefeaturerules + shortNames: + - nfr + singular: nodefeaturerule + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + NodeFeatureRule resource specifies a configuration for feature-based + customization of node objects, such as node labeling. + 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: Spec defines the rules to be evaluated. + properties: + rules: + description: Rules is a list of node customization rules. + items: + description: Rule defines a rule for node customization such as + labeling. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to create if the rule matches. + type: object + extendedResources: + additionalProperties: + type: string + description: ExtendedResources to create if the rule matches. + type: object + labels: + additionalProperties: + type: string + description: Labels to create if the rule matches. + type: object + labelsTemplate: + description: |- + LabelsTemplate specifies a template to expand for dynamically generating + multiple labels. Data (after template expansion) must be keys with an + optional value ([=]) separated by newlines. + type: string + matchAny: + description: MatchAny specifies a list of matchers one of which + must match. + items: + description: MatchAnyElem specifies one sub-matcher of MatchAny. + properties: + matchFeatures: + description: MatchFeatures specifies a set of matcher + terms all of which must match. + items: + description: |- + FeatureMatcherTerm defines requirements against one feature set. All + requirements (specified as MatchExpressions) are evaluated against each + element in the feature set. + properties: + feature: + description: Feature is the name of the feature + set to match against. + type: string + matchExpressions: + additionalProperties: + description: |- + MatchExpression specifies an expression to evaluate against a set of input + values. It contains an operator that is applied when matching the input and + an array of values that the operator evaluates the input against. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: |- + Value is the list of values that the operand evaluates the input + against. Value should be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly one element if the + operator is Gt or Lt and exactly two elements if the operator is GtLt. + In other cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + description: |- + MatchExpressions is the set of per-element expressions evaluated. These + match against the value of the specified elements. + type: object + matchName: + description: |- + MatchName in an expression that is matched against the name of each + element in the feature set. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: |- + Value is the list of values that the operand evaluates the input + against. Value should be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly one element if the + operator is Gt or Lt and exactly two elements if the operator is GtLt. + In other cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + required: + - feature + type: object + type: array + required: + - matchFeatures + type: object + type: array + matchFeatures: + description: MatchFeatures specifies a set of matcher terms + all of which must match. + items: + description: |- + FeatureMatcherTerm defines requirements against one feature set. All + requirements (specified as MatchExpressions) are evaluated against each + element in the feature set. + properties: + feature: + description: Feature is the name of the feature set to + match against. + type: string + matchExpressions: + additionalProperties: + description: |- + MatchExpression specifies an expression to evaluate against a set of input + values. It contains an operator that is applied when matching the input and + an array of values that the operator evaluates the input against. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: |- + Value is the list of values that the operand evaluates the input + against. Value should be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly one element if the + operator is Gt or Lt and exactly two elements if the operator is GtLt. + In other cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + description: |- + MatchExpressions is the set of per-element expressions evaluated. These + match against the value of the specified elements. + type: object + matchName: + description: |- + MatchName in an expression that is matched against the name of each + element in the feature set. + properties: + op: + description: Op is the operator to be applied. + enum: + - In + - NotIn + - InRegexp + - Exists + - DoesNotExist + - Gt + - Lt + - GtLt + - IsTrue + - IsFalse + type: string + value: + description: |- + Value is the list of values that the operand evaluates the input + against. Value should be empty if the operator is Exists, DoesNotExist, + IsTrue or IsFalse. Value should contain exactly one element if the + operator is Gt or Lt and exactly two elements if the operator is GtLt. + In other cases Value should contain at least one element. + items: + type: string + type: array + required: + - op + type: object + required: + - feature + type: object + type: array + name: + description: Name of the rule. + type: string + taints: + description: Taints to create if the rule matches. + items: + description: |- + The node this Taint is attached to has the "effect" on + any pod that does not tolerate the Taint. + properties: + effect: + description: |- + Required. The effect of the taint on pods + that do not tolerate the taint. + Valid effects are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Required. The taint key to be applied to + a node. + type: string + timeAdded: + description: |- + TimeAdded represents the time at which the taint was added. + It is only written for NoExecute taints. + format: date-time + type: string + value: + description: The taint value corresponding to the taint + key. + type: string + required: + - effect + - key + type: object + type: array + vars: + additionalProperties: + type: string + description: |- + Vars is the variables to store if the rule matches. Variables do not + directly inflict any changes in the node object. However, they can be + referenced from other rules enabling more complex rule hierarchies, + without exposing intermediary output values as labels. + type: object + varsTemplate: + description: |- + VarsTemplate specifies a template to expand for dynamically generating + multiple variables. Data (after template expansion) must be keys with an + optional value ([=]) separated by newlines. + type: string + required: + - name + type: object + type: array + required: + - rules + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/_helpers.tpl b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/_helpers.tpl new file mode 100644 index 000000000..928ece78f --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/_helpers.tpl @@ -0,0 +1,107 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "node-feature-discovery.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 "node-feature-discovery.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 -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "node-feature-discovery.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "node-feature-discovery.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "node-feature-discovery.labels" -}} +helm.sh/chart: {{ include "node-feature-discovery.chart" . }} +{{ include "node-feature-discovery.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "node-feature-discovery.selectorLabels" -}} +app.kubernetes.io/name: {{ include "node-feature-discovery.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account which the nfd master will use +*/}} +{{- define "node-feature-discovery.master.serviceAccountName" -}} +{{- if .Values.master.serviceAccount.create -}} + {{ default (include "node-feature-discovery.fullname" .) .Values.master.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.master.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which the nfd worker will use +*/}} +{{- define "node-feature-discovery.worker.serviceAccountName" -}} +{{- if .Values.worker.serviceAccount.create -}} + {{ default (printf "%s-worker" (include "node-feature-discovery.fullname" .)) .Values.worker.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.worker.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which topologyUpdater will use +*/}} +{{- define "node-feature-discovery.topologyUpdater.serviceAccountName" -}} +{{- if .Values.topologyUpdater.serviceAccount.create -}} + {{ default (printf "%s-topology-updater" (include "node-feature-discovery.fullname" .)) .Values.topologyUpdater.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.topologyUpdater.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which nfd-gc will use +*/}} +{{- define "node-feature-discovery.gc.serviceAccountName" -}} +{{- if .Values.gc.serviceAccount.create -}} + {{ default (printf "%s-gc" (include "node-feature-discovery.fullname" .)) .Values.gc.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.gc.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/cert-manager-certs.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/cert-manager-certs.yaml new file mode 100644 index 000000000..2d1576022 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/cert-manager-certs.yaml @@ -0,0 +1,80 @@ +{{- if .Values.tls.certManager }} +{{- if .Values.master.enable }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-master-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-master-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-master + dnsNames: + # must match the service name + - {{ include "node-feature-discovery.fullname" . }}-master + # first one is configured for use by the worker; below are for completeness + - {{ include "node-feature-discovery.fullname" . }}-master.{{ include "node-feature-discovery.namespace" . }}.svc + - {{ include "node-feature-discovery.fullname" . }}-master.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: {{ default "nfd-ca-issuer" .Values.tls.certManagerCertificate.issuerName }} + {{- if and .Values.tls.certManagerCertificate.issuerName .Values.tls.certManagerCertificate.issuerKind }} + kind: {{ .Values.tls.certManagerCertificate.issuerKind }} + {{- else }} + kind: Issuer + {{- end }} + group: cert-manager.io +{{- end }} +--- +{{- if .Values.worker.enable }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-worker-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-worker-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-worker + dnsNames: + - {{ include "node-feature-discovery.fullname" . }}-worker.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: {{ default "nfd-ca-issuer" .Values.tls.certManagerCertificate.issuerName }} + {{- if and .Values.tls.certManagerCertificate.issuerName .Values.tls.certManagerCertificate.issuerKind }} + kind: {{ .Values.tls.certManagerCertificate.issuerKind }} + {{- else }} + kind: Issuer + {{- end }} + group: cert-manager.io +{{- end }} + +{{- if .Values.topologyUpdater.enable }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-topology-updater-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-topology-updater-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-topology-updater + dnsNames: + - {{ include "node-feature-discovery.fullname" . }}-topology-updater.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: {{ default "nfd-ca-issuer" .Values.tls.certManagerCertificate.issuerName }} + {{- if and .Values.tls.certManagerCertificate.issuerName .Values.tls.certManagerCertificate.issuerKind }} + kind: {{ .Values.tls.certManagerCertificate.issuerKind }} + {{- else }} + kind: Issuer + {{- end }} + group: cert-manager.io +{{- end }} + +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/cert-manager-issuer.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/cert-manager-issuer.yaml new file mode 100644 index 000000000..874468908 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/cert-manager-issuer.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.tls.certManager (not .Values.tls.certManagerCertificate.issuerName ) }} +# See https://cert-manager.io/docs/configuration/selfsigned/#bootstrapping-ca-issuers +# - Create a self signed issuer +# - Use this to create a CA cert +# - Use this to now create a CA issuer +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: nfd-ca-bootstrap + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + selfSigned: {} + +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-ca-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + isCA: true + secretName: nfd-ca-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-ca-cert + issuerRef: + name: nfd-ca-bootstrap + kind: Issuer + group: cert-manager.io + +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: nfd-ca-issuer + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + ca: + secretName: nfd-ca-cert +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/clusterrole.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/clusterrole.yaml new file mode 100644 index 000000000..f935cfe41 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/clusterrole.yaml @@ -0,0 +1,133 @@ +{{- if and .Values.master.enable .Values.master.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/status + verbs: + - get + - patch + - update + - list +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + - nodefeaturerules + - nodefeaturegroups + verbs: + - get + - list + - watch +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeaturegroups/status + verbs: + - patch + - update +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create +- apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + - "nfd-master.nfd.kubernetes.io" + verbs: + - get + - update +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get +- apiGroups: + - "" + resources: + - nodes/proxy + verbs: + - get +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - topology.node.k8s.io + resources: + - noderesourcetopologies + verbs: + - create + - get + - update +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.rbac.create (or (and .Values.featureGates.NodeFeatureAPI .Values.enableNodeFeatureApi) .Values.topologyUpdater.enable) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - nodes/proxy + verbs: + - get +- apiGroups: + - topology.node.k8s.io + resources: + - noderesourcetopologies + verbs: + - delete + - list +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + verbs: + - delete + - list +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/clusterrolebinding.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..3f717988b --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/clusterrolebinding.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.master.enable .Values.master.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.master.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.rbac.create (or (and .Values.featureGates.NodeFeatureAPI .Values.enableNodeFeatureApi) .Values.topologyUpdater.enable) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }}-gc +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/master.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/master.yaml new file mode 100644 index 000000000..733131a03 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/master.yaml @@ -0,0 +1,152 @@ +{{- if .Values.master.enable }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: master + {{- with .Values.master.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.master.replicaCount }} + revisionHistoryLimit: {{ .Values.master.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: master + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: master + {{- with .Values.master.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "node-feature-discovery.master.serviceAccountName" . }} + enableServiceLinks: false + securityContext: + {{- toYaml .Values.master.podSecurityContext | nindent 8 }} + hostNetwork: {{ .Values.master.hostNetwork }} + containers: + - name: master + securityContext: + {{- toYaml .Values.master.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + livenessProbe: + {{- toYaml .Values.master.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.master.readinessProbe | nindent 12 }} + ports: + - containerPort: {{ .Values.master.port | default "8080" }} + name: grpc + - containerPort: {{ .Values.master.metricsPort | default "8081" }} + name: metrics + - containerPort: {{ .Values.master.healthPort | default "8082" }} + name: health + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- with .Values.master.extraEnvs }} + {{- toYaml . | nindent 8 }} + {{- end}} + command: + - "nfd-master" + resources: + {{- toYaml .Values.master.resources | nindent 12 }} + args: + {{- if .Values.master.instance | empty | not }} + - "-instance={{ .Values.master.instance }}" + {{- end }} + {{- if not (and .Values.featureGates.NodeFeatureAPI .Values.enableNodeFeatureApi) }} + - "-port={{ .Values.master.port | default "8080" }}" + {{- else if gt (int .Values.master.replicaCount) 1 }} + - "-enable-leader-election" + {{- end }} + {{- if .Values.master.extraLabelNs | empty | not }} + - "-extra-label-ns={{- join "," .Values.master.extraLabelNs }}" + {{- end }} + {{- if .Values.master.denyLabelNs | empty | not }} + - "-deny-label-ns={{- join "," .Values.master.denyLabelNs }}" + {{- end }} + {{- if .Values.master.resourceLabels | empty | not }} + - "-resource-labels={{- join "," .Values.master.resourceLabels }}" + {{- end }} + {{- if .Values.master.enableTaints }} + - "-enable-taints" + {{- end }} + {{- if .Values.master.crdController | kindIs "invalid" | not }} + - "-crd-controller={{ .Values.master.crdController }}" + {{- else }} + ## By default, disable crd controller for other than the default instances + - "-crd-controller={{ .Values.master.instance | empty }}" + {{- end }} + {{- if .Values.master.featureRulesController | kindIs "invalid" | not }} + - "-featurerules-controller={{ .Values.master.featureRulesController }}" + {{- end }} + {{- if .Values.master.resyncPeriod }} + - "-resync-period={{ .Values.master.resyncPeriod }}" + {{- end }} + {{- if .Values.master.nfdApiParallelism | empty | not }} + - "-nfd-api-parallelism={{ .Values.master.nfdApiParallelism }}" + {{- end }} + {{- if .Values.tls.enable }} + - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt" + - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key" + - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt" + {{- end }} + # Go over featureGates and add the feature-gate flag + {{- range $key, $value := .Values.featureGates }} + - "-feature-gates={{ $key }}={{ $value }}" + {{- end }} + - "-metrics={{ .Values.master.metricsPort | default "8081" }}" + - "-grpc-health={{ .Values.master.healthPort | default "8082" }}" + volumeMounts: + {{- if .Values.tls.enable }} + - name: nfd-master-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true + {{- end }} + - name: nfd-master-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true + volumes: + {{- if .Values.tls.enable }} + - name: nfd-master-cert + secret: + secretName: nfd-master-cert + {{- end }} + - name: nfd-master-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-master-conf + items: + - key: nfd-master.conf + path: nfd-master.conf + {{- with .Values.master.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-gc.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-gc.yaml new file mode 100644 index 000000000..375f93827 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-gc.yaml @@ -0,0 +1,85 @@ +{{- if and .Values.gc.enable (or (and .Values.featureGates.NodeFeatureAPI .Values.enableNodeFeatureApi) .Values.topologyUpdater.enable) -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: gc + {{- with .Values.gc.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.gc.replicaCount | default 1 }} + revisionHistoryLimit: {{ .Values.gc.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: gc + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: gc + {{- with .Values.gc.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.gc.podSecurityContext | nindent 8 }} + hostNetwork: {{ .Values.gc.hostNetwork }} + containers: + - name: gc + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- with .Values.gc.extraEnvs }} + {{- toYaml . | nindent 8 }} + {{- end}} + command: + - "nfd-gc" + args: + {{- if .Values.gc.interval | empty | not }} + - "-gc-interval={{ .Values.gc.interval }}" + {{- end }} + resources: + {{- toYaml .Values.gc.resources | nindent 12 }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + ports: + - name: metrics + containerPort: {{ .Values.gc.metricsPort | default "8081"}} + + {{- with .Values.gc.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gc.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gc.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-master-conf.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-master-conf.yaml new file mode 100644 index 000000000..9c6e01cde --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-master-conf.yaml @@ -0,0 +1,12 @@ +{{- if .Values.master.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-master.conf: |- + {{- .Values.master.config | toYaml | nindent 4 }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-topologyupdater-conf.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-topologyupdater-conf.yaml new file mode 100644 index 000000000..8d03aa2d8 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-topologyupdater-conf.yaml @@ -0,0 +1,12 @@ +{{- if .Values.topologyUpdater.enable -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-topology-updater.conf: |- + {{- .Values.topologyUpdater.config | toYaml | nindent 4 }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-worker-conf.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-worker-conf.yaml new file mode 100644 index 000000000..a2299dea1 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/nfd-worker-conf.yaml @@ -0,0 +1,12 @@ +{{- if .Values.worker.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-worker.conf: |- + {{- .Values.worker.config | toYaml | nindent 4 }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/post-delete-job.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/post-delete-job.yaml new file mode 100644 index 000000000..4364f1aa2 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/post-delete-job.yaml @@ -0,0 +1,94 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-prune + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-prune + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/status + verbs: + - get + - patch + - update + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-prune + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }}-prune +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.fullname" . }}-prune + namespace: {{ include "node-feature-discovery.namespace" . }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-prune + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-delete + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + template: + metadata: + labels: + {{- include "node-feature-discovery.labels" . | nindent 8 }} + role: prune + spec: + serviceAccountName: {{ include "node-feature-discovery.fullname" . }}-prune + containers: + - name: nfd-master + securityContext: + {{- toYaml .Values.master.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - "nfd-master" + args: + - "-prune" + {{- if .Values.master.instance | empty | not }} + - "-instance={{ .Values.master.instance }}" + {{- end }} + restartPolicy: Never + {{- with .Values.master.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/prometheus.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/prometheus.yaml new file mode 100644 index 000000000..3d680e24e --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/prometheus.yaml @@ -0,0 +1,26 @@ +{{- if .Values.prometheus.enable }} +# Prometheus Monitor Service (Metrics) +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }} + {{- with .Values.prometheus.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + podMetricsEndpoints: + - honorLabels: true + interval: {{ .Values.prometheus.scrapeInterval }} + path: /metrics + port: metrics + scheme: http + namespaceSelector: + matchNames: + - {{ include "node-feature-discovery.namespace" . }} + selector: + matchExpressions: + - {key: app.kubernetes.io/instance, operator: In, values: ["{{ .Release.Name }}"]} + - {key: app.kubernetes.io/name, operator: In, values: ["{{ include "node-feature-discovery.name" . }}"]} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/role.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/role.yaml new file mode 100644 index 000000000..52c69eb19 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/role.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.worker.enable .Values.worker.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + verbs: + - create + - get + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - get +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/rolebinding.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/rolebinding.yaml new file mode 100644 index 000000000..a640d5f8b --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/rolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.worker.enable .Values.worker.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "node-feature-discovery.fullname" . }}-worker +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/service.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/service.yaml new file mode 100644 index 000000000..7191dca70 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/service.yaml @@ -0,0 +1,20 @@ +{{- if and (not (and .Values.featureGates.NodeFeatureAPI .Values.enableNodeFeatureApi)) .Values.master.enable }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: master +spec: + type: {{ .Values.master.service.type }} + ports: + - port: {{ .Values.master.service.port | default "8080" }} + targetPort: grpc + protocol: TCP + name: grpc + selector: + {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }} + role: master +{{- end}} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/serviceaccount.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/serviceaccount.yaml new file mode 100644 index 000000000..59edc5e6c --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/serviceaccount.yaml @@ -0,0 +1,58 @@ +{{- if and .Values.master.enable .Values.master.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.master.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.master.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.topologyUpdater.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.serviceAccount.create (or (and .Values.featureGates.NodeFeatureAPI .Values.enableNodeFeatureApi) .Values.topologyUpdater.enable) }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.gc.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.worker.enable .Values.worker.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.worker.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/topologyupdater-crds.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/topologyupdater-crds.yaml new file mode 100644 index 000000000..b6b919689 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/topologyupdater-crds.yaml @@ -0,0 +1,278 @@ +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.createCRDs -}} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes/enhancements/pull/1870 + controller-gen.kubebuilder.io/version: v0.11.2 + creationTimestamp: null + name: noderesourcetopologies.topology.node.k8s.io +spec: + group: topology.node.k8s.io + names: + kind: NodeResourceTopology + listKind: NodeResourceTopologyList + plural: noderesourcetopologies + shortNames: + - node-res-topo + singular: noderesourcetopology + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeResourceTopology describes node resources and their topology. + 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 + topologyPolicies: + items: + type: string + type: array + zones: + description: ZoneList contains an array of Zone objects. + items: + description: Zone represents a resource topology zone, e.g. socket, + node, die or core. + properties: + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + costs: + description: CostList contains an array of CostInfo objects. + items: + description: CostInfo describes the cost (or distance) between + two Zones. + properties: + name: + type: string + value: + format: int64 + type: integer + required: + - name + - value + type: object + type: array + name: + type: string + parent: + type: string + resources: + description: ResourceInfoList contains an array of ResourceInfo + objects. + items: + description: ResourceInfo contains information about one resource + type. + properties: + allocatable: + anyOf: + - type: integer + - type: string + description: Allocatable quantity of the resource, corresponding + to allocatable in node status, i.e. total amount of this + resource available to be used by pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + available: + anyOf: + - type: integer + - type: string + description: Available is the amount of this resource currently + available for new (to be scheduled) pods, i.e. Allocatable + minus the resources reserved by currently running pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + capacity: + anyOf: + - type: integer + - type: string + description: Capacity of the resource, corresponding to capacity + in node status, i.e. total amount of this resource that + the node has. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + name: + description: Name of the resource. + type: string + required: + - allocatable + - available + - capacity + - name + type: object + type: array + type: + type: string + required: + - name + - type + type: object + type: array + required: + - topologyPolicies + - zones + type: object + served: true + storage: false + - name: v1alpha2 + schema: + openAPIV3Schema: + description: NodeResourceTopology describes node resources and their topology. + 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 + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + 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 + topologyPolicies: + description: 'DEPRECATED (to be removed in v1beta1): use top level attributes + if needed' + items: + type: string + type: array + zones: + description: ZoneList contains an array of Zone objects. + items: + description: Zone represents a resource topology zone, e.g. socket, + node, die or core. + properties: + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + costs: + description: CostList contains an array of CostInfo objects. + items: + description: CostInfo describes the cost (or distance) between + two Zones. + properties: + name: + type: string + value: + format: int64 + type: integer + required: + - name + - value + type: object + type: array + name: + type: string + parent: + type: string + resources: + description: ResourceInfoList contains an array of ResourceInfo + objects. + items: + description: ResourceInfo contains information about one resource + type. + properties: + allocatable: + anyOf: + - type: integer + - type: string + description: Allocatable quantity of the resource, corresponding + to allocatable in node status, i.e. total amount of this + resource available to be used by pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + available: + anyOf: + - type: integer + - type: string + description: Available is the amount of this resource currently + available for new (to be scheduled) pods, i.e. Allocatable + minus the resources reserved by currently running pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + capacity: + anyOf: + - type: integer + - type: string + description: Capacity of the resource, corresponding to capacity + in node status, i.e. total amount of this resource that + the node has. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + name: + description: Name of the resource. + type: string + required: + - allocatable + - available + - capacity + - name + type: object + type: array + type: + type: string + required: + - name + - type + type: object + type: array + required: + - zones + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/topologyupdater.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/topologyupdater.yaml new file mode 100644 index 000000000..ba0214c88 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/topologyupdater.yaml @@ -0,0 +1,171 @@ +{{- if .Values.topologyUpdater.enable -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: topology-updater + {{- with .Values.topologyUpdater.daemonsetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + revisionHistoryLimit: {{ .Values.topologyUpdater.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: topology-updater + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: topology-updater + {{- with .Values.topologyUpdater.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.topologyUpdater.podSecurityContext | nindent 8 }} + hostNetwork: {{ .Values.topologyUpdater.hostNetwork }} + containers: + - name: topology-updater + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + livenessProbe: + {{- toYaml .Values.topologyUpdater.livenessProbe | nindent 10 }} + readinessProbe: + {{- toYaml .Values.topologyUpdater.readinessProbe | nindent 10 }} + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: NODE_ADDRESS + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- with .Values.topologyUpdater.extraEnvs }} + {{- toYaml . | nindent 8 }} + {{- end}} + command: + - "nfd-topology-updater" + args: + - "-podresources-socket=/host-var/lib/kubelet-podresources/kubelet.sock" + {{- if .Values.topologyUpdater.updateInterval | empty | not }} + - "-sleep-interval={{ .Values.topologyUpdater.updateInterval }}" + {{- else }} + - "-sleep-interval=3s" + {{- end }} + {{- if .Values.topologyUpdater.watchNamespace | empty | not }} + - "-watch-namespace={{ .Values.topologyUpdater.watchNamespace }}" + {{- else }} + - "-watch-namespace=*" + {{- end }} + {{- if .Values.tls.enable }} + - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt" + - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key" + - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt" + {{- end }} + {{- if not .Values.topologyUpdater.podSetFingerprint }} + - "-pods-fingerprint=false" + {{- end }} + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - "-kubelet-config-uri=file:///host-var/kubelet-config" + {{- end }} + {{- if .Values.topologyUpdater.kubeletStateDir | empty }} + # Disable kubelet state tracking by giving an empty path + - "-kubelet-state-dir=" + {{- end }} + - -metrics={{ .Values.topologyUpdater.metricsPort | default "8081"}} + - "-grpc-health={{ .Values.topologyUpdater.healthPort | default "8082" }}" + ports: + - containerPort: {{ .Values.topologyUpdater.metricsPort | default "8081"}} + name: metrics + - containerPort: {{ .Values.topologyUpdater.healthPort | default "8082" }} + name: health + volumeMounts: + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - name: kubelet-config + mountPath: /host-var/kubelet-config + {{- end }} + - name: kubelet-podresources-sock + mountPath: /host-var/lib/kubelet-podresources/kubelet.sock + - name: host-sys + mountPath: /host-sys + {{- if .Values.topologyUpdater.kubeletStateDir | empty | not }} + - name: kubelet-state-files + mountPath: /host-var/lib/kubelet + readOnly: true + {{- end }} + {{- if .Values.tls.enable }} + - name: nfd-topology-updater-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true + {{- end }} + - name: nfd-topology-updater-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true + + resources: + {{- toYaml .Values.topologyUpdater.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.topologyUpdater.securityContext | nindent 12 }} + volumes: + - name: host-sys + hostPath: + path: "/sys" + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - name: kubelet-config + hostPath: + path: {{ .Values.topologyUpdater.kubeletConfigPath }} + {{- end }} + - name: kubelet-podresources-sock + hostPath: + {{- if .Values.topologyUpdater.kubeletPodResourcesSockPath | empty | not }} + path: {{ .Values.topologyUpdater.kubeletPodResourcesSockPath }} + {{- else }} + path: /var/lib/kubelet/pod-resources/kubelet.sock + {{- end }} + {{- if .Values.topologyUpdater.kubeletStateDir | empty | not }} + - name: kubelet-state-files + hostPath: + path: {{ .Values.topologyUpdater.kubeletStateDir }} + {{- end }} + - name: nfd-topology-updater-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater-conf + items: + - key: nfd-topology-updater.conf + path: nfd-topology-updater.conf + {{- if .Values.tls.enable }} + - name: nfd-topology-updater-cert + secret: + secretName: nfd-topology-updater-cert + {{- end }} + + + {{- with .Values.topologyUpdater.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologyUpdater.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologyUpdater.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/worker.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/worker.yaml new file mode 100644 index 000000000..755466c75 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/templates/worker.yaml @@ -0,0 +1,186 @@ +{{- if .Values.worker.enable }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: worker + {{- with .Values.worker.daemonsetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + revisionHistoryLimit: {{ .Values.worker.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: worker + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: worker + {{- with .Values.worker.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.worker.podSecurityContext | nindent 8 }} + hostNetwork: {{ .Values.worker.hostNetwork }} + containers: + - name: worker + securityContext: + {{- toYaml .Values.worker.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + livenessProbe: + {{- toYaml .Values.worker.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.worker.readinessProbe | nindent 12 }} + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_UID + valueFrom: + fieldRef: + fieldPath: metadata.uid + {{- with .Values.worker.extraEnvs }} + {{- toYaml . | nindent 8 }} + {{- end}} + resources: + {{- toYaml .Values.worker.resources | nindent 12 }} + command: + - "nfd-worker" + args: +{{- if not (and .Values.featureGates.NodeFeatureAPI .Values.enableNodeFeatureApi) }} + - "-server={{ include "node-feature-discovery.fullname" . }}-master:{{ .Values.master.service.port }}" +{{- end }} +{{- if .Values.tls.enable }} + - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt" + - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key" + - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt" +{{- end }} +# Go over featureGate and add the feature-gate flag +{{- range $key, $value := .Values.featureGates }} + - "-feature-gates={{ $key }}={{ $value }}" +{{- end }} + - "-metrics={{ .Values.worker.metricsPort | default "8081"}}" + - "-grpc-health={{ .Values.worker.healthPort | default "8082" }}" + ports: + - containerPort: {{ .Values.worker.metricsPort | default "8081"}} + name: metrics + - containerPort: {{ .Values.worker.healthPort | default "8082" }} + name: health + volumeMounts: + - name: host-boot + mountPath: "/host-boot" + readOnly: true + - name: host-os-release + mountPath: "/host-etc/os-release" + readOnly: true + - name: host-sys + mountPath: "/host-sys" + readOnly: true + - name: host-usr-lib + mountPath: "/host-usr/lib" + readOnly: true + - name: host-lib + mountPath: "/host-lib" + readOnly: true + - name: host-proc-swaps + mountPath: "/host-proc/swaps" + readOnly: true + {{- if .Values.worker.mountUsrSrc }} + - name: host-usr-src + mountPath: "/host-usr/src" + readOnly: true + {{- end }} + - name: source-d + mountPath: "/etc/kubernetes/node-feature-discovery/source.d/" + readOnly: true + - name: features-d + mountPath: "/etc/kubernetes/node-feature-discovery/features.d/" + readOnly: true + - name: nfd-worker-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true +{{- if .Values.tls.enable }} + - name: nfd-worker-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true +{{- end }} + volumes: + - name: host-boot + hostPath: + path: "/boot" + - name: host-os-release + hostPath: + path: "/etc/os-release" + - name: host-sys + hostPath: + path: "/sys" + - name: host-usr-lib + hostPath: + path: "/usr/lib" + - name: host-lib + hostPath: + path: "/lib" + - name: host-proc-swaps + hostPath: + path: "/proc/swaps" + {{- if .Values.worker.mountUsrSrc }} + - name: host-usr-src + hostPath: + path: "/usr/src" + {{- end }} + - name: source-d + hostPath: + path: "/etc/kubernetes/node-feature-discovery/source.d/" + - name: features-d + hostPath: + path: "/etc/kubernetes/node-feature-discovery/features.d/" + - name: nfd-worker-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-worker-conf + items: + - key: nfd-worker.conf + path: nfd-worker.conf +{{- if .Values.tls.enable }} + - name: nfd-worker-cert + secret: + secretName: nfd-worker-cert +{{- end }} + {{- with .Values.worker.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/values.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/values.yaml new file mode 100644 index 000000000..2d24983db --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/charts/node-feature-discovery/values.yaml @@ -0,0 +1,593 @@ +image: + repository: registry.k8s.io/nfd/node-feature-discovery + # This should be set to 'IfNotPresent' for released version + pullPolicy: IfNotPresent + # tag, if defined will use the given image tag, else Chart.AppVersion will be used + # tag +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" +namespaceOverride: "" + +enableNodeFeatureApi: true + +featureGates: + NodeFeatureAPI: true + NodeFeatureGroupAPI: false + +priorityClassName: "" + +master: + enable: true + extraEnvs: [] + hostNetwork: false + config: ### + # noPublish: false + # autoDefaultNs: true + # extraLabelNs: ["added.ns.io","added.kubernets.io"] + # denyLabelNs: ["denied.ns.io","denied.kubernetes.io"] + # resourceLabels: ["vendor-1.com/feature-1","vendor-2.io/feature-2"] + # enableTaints: false + # labelWhiteList: "foo" + # resyncPeriod: "2h" + # klog: + # addDirHeader: false + # alsologtostderr: false + # logBacktraceAt: + # logtostderr: true + # skipHeaders: false + # stderrthreshold: 2 + # v: 0 + # vmodule: + ## NOTE: the following options are not dynamically run-time configurable + ## and require a nfd-master restart to take effect after being changed + # logDir: + # logFile: + # logFileMaxSize: 1800 + # skipLogHeaders: false + # leaderElection: + # leaseDuration: 15s + # # this value has to be lower than leaseDuration and greater than retryPeriod*1.2 + # renewDeadline: 10s + # # this value has to be greater than 0 + # retryPeriod: 2s + # nfdApiParallelism: 10 + ### + # The TCP port that nfd-master listens for incoming requests. Default: 8080 + # Deprecated this parameter is related to the deprecated gRPC API and will + # be removed with it in a future release + port: 8080 + metricsPort: 8081 + healthPort: 8082 + instance: + featureApi: + resyncPeriod: + denyLabelNs: [] + extraLabelNs: [] + resourceLabels: [] + enableTaints: false + crdController: null + featureRulesController: null + nfdApiParallelism: null + deploymentAnnotations: {} + replicaCount: 1 + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + # runAsUser: 1000 + + 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: + + # specify how many old ReplicaSets for the Deployment to retain. + revisionHistoryLimit: + + rbac: + create: true + + service: + type: ClusterIP + port: 8080 + + resources: + limits: + memory: 4Gi + requests: + cpu: 100m + # You may want to use the same value for `requests.memory` and `limits.memory`. The โ€œrequestsโ€ value affects scheduling to accommodate pods on nodes. + # If there is a large difference between โ€œrequestsโ€ and โ€œlimitsโ€ and nodes experience memory pressure, the kernel may invoke + # the OOM Killer, even if the memory does not exceed the โ€œlimitsโ€ threshold. This can cause unexpected pod evictions. Memory + # cannot be compressed and once allocated to a pod, it can only be reclaimed by killing the pod. + # Natan Yellin 22/09/2022 https://home.robusta.dev/blog/kubernetes-memory-limit + memory: 128Mi + + nodeSelector: {} + + tolerations: + - key: "node-role.kubernetes.io/master" + operator: "Equal" + value: "" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/control-plane" + operator: "Equal" + value: "" + effect: "NoSchedule" + + annotations: {} + + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: "node-role.kubernetes.io/master" + operator: In + values: [""] + - weight: 1 + preference: + matchExpressions: + - key: "node-role.kubernetes.io/control-plane" + operator: In + values: [""] + + livenessProbe: + grpc: + port: 8082 + initialDelaySeconds: 10 + # failureThreshold: 3 + # periodSeconds: 10 + readinessProbe: + grpc: + port: 8082 + initialDelaySeconds: 5 + failureThreshold: 10 + # periodSeconds: 10 + +worker: + enable: true + extraEnvs: [] + hostNetwork: false + config: ### + #core: + # labelWhiteList: + # noPublish: false + # sleepInterval: 60s + # featureSources: [all] + # labelSources: [all] + # klog: + # addDirHeader: false + # alsologtostderr: false + # logBacktraceAt: + # logtostderr: true + # skipHeaders: false + # stderrthreshold: 2 + # v: 0 + # vmodule: + ## NOTE: the following options are not dynamically run-time configurable + ## and require a nfd-worker restart to take effect after being changed + # logDir: + # logFile: + # logFileMaxSize: 1800 + # skipLogHeaders: false + #sources: + # cpu: + # cpuid: + ## NOTE: whitelist has priority over blacklist + # attributeBlacklist: + # - "AVX10" + # - "BMI1" + # - "BMI2" + # - "CLMUL" + # - "CMOV" + # - "CX16" + # - "ERMS" + # - "F16C" + # - "HTT" + # - "LZCNT" + # - "MMX" + # - "MMXEXT" + # - "NX" + # - "POPCNT" + # - "RDRAND" + # - "RDSEED" + # - "RDTSCP" + # - "SGX" + # - "SSE" + # - "SSE2" + # - "SSE3" + # - "SSE4" + # - "SSE42" + # - "SSSE3" + # - "TDX_GUEST" + # attributeWhitelist: + # kernel: + # kconfigFile: "/path/to/kconfig" + # configOpts: + # - "NO_HZ" + # - "X86" + # - "DMI" + # pci: + # deviceClassWhitelist: + # - "0200" + # - "03" + # - "12" + # deviceLabelFields: + # - "class" + # - "vendor" + # - "device" + # - "subsystem_vendor" + # - "subsystem_device" + # usb: + # deviceClassWhitelist: + # - "0e" + # - "ef" + # - "fe" + # - "ff" + # deviceLabelFields: + # - "class" + # - "vendor" + # - "device" + # local: + # hooksEnabled: false + # custom: + # # The following feature demonstrates the capabilities of the matchFeatures + # - name: "my custom rule" + # labels: + # "vendor.io/my-ng-feature": "true" + # # matchFeatures implements a logical AND over all matcher terms in the + # # list (i.e. all of the terms, or per-feature matchers, must match) + # matchFeatures: + # - feature: cpu.cpuid + # matchExpressions: + # AVX512F: {op: Exists} + # - feature: cpu.cstate + # matchExpressions: + # enabled: {op: IsTrue} + # - feature: cpu.pstate + # matchExpressions: + # no_turbo: {op: IsFalse} + # scaling_governor: {op: In, value: ["performance"]} + # - feature: cpu.rdt + # matchExpressions: + # RDTL3CA: {op: Exists} + # - feature: cpu.sst + # matchExpressions: + # bf.enabled: {op: IsTrue} + # - feature: cpu.topology + # matchExpressions: + # hardware_multithreading: {op: IsFalse} + # + # - feature: kernel.config + # matchExpressions: + # X86: {op: Exists} + # LSM: {op: InRegexp, value: ["apparmor"]} + # - feature: kernel.loadedmodule + # matchExpressions: + # e1000e: {op: Exists} + # - feature: kernel.selinux + # matchExpressions: + # enabled: {op: IsFalse} + # - feature: kernel.version + # matchExpressions: + # major: {op: In, value: ["5"]} + # minor: {op: Gt, value: ["10"]} + # + # - feature: storage.block + # matchExpressions: + # rotational: {op: In, value: ["0"]} + # dax: {op: In, value: ["0"]} + # + # - feature: network.device + # matchExpressions: + # operstate: {op: In, value: ["up"]} + # speed: {op: Gt, value: ["100"]} + # + # - feature: memory.numa + # matchExpressions: + # node_count: {op: Gt, value: ["2"]} + # - feature: memory.nv + # matchExpressions: + # devtype: {op: In, value: ["nd_dax"]} + # mode: {op: In, value: ["memory"]} + # + # - feature: system.osrelease + # matchExpressions: + # ID: {op: In, value: ["fedora", "centos"]} + # - feature: system.name + # matchExpressions: + # nodename: {op: InRegexp, value: ["^worker-X"]} + # + # - feature: local.label + # matchExpressions: + # custom-feature-knob: {op: Gt, value: ["100"]} + # + # # The following feature demonstrates the capabilities of the matchAny + # - name: "my matchAny rule" + # labels: + # "vendor.io/my-ng-feature-2": "my-value" + # # matchAny implements a logical IF over all elements (sub-matchers) in + # # the list (i.e. at least one feature matcher must match) + # matchAny: + # - matchFeatures: + # - feature: kernel.loadedmodule + # matchExpressions: + # driver-module-X: {op: Exists} + # - feature: pci.device + # matchExpressions: + # vendor: {op: In, value: ["8086"]} + # class: {op: In, value: ["0200"]} + # - matchFeatures: + # - feature: kernel.loadedmodule + # matchExpressions: + # driver-module-Y: {op: Exists} + # - feature: usb.device + # matchExpressions: + # vendor: {op: In, value: ["8086"]} + # class: {op: In, value: ["02"]} + # + # - name: "avx wildcard rule" + # labels: + # "my-avx-feature": "true" + # matchFeatures: + # - feature: cpu.cpuid + # matchName: {op: InRegexp, value: ["^AVX512"]} + # + # # The following features demonstreate label templating capabilities + # - name: "my template rule" + # labelsTemplate: | + # {{ range .system.osrelease }}vendor.io/my-system-feature.{{ .Name }}={{ .Value }} + # {{ end }} + # matchFeatures: + # - feature: system.osrelease + # matchExpressions: + # ID: {op: InRegexp, value: ["^open.*"]} + # VERSION_ID.major: {op: In, value: ["13", "15"]} + # + # - name: "my template rule 2" + # labelsTemplate: | + # {{ range .pci.device }}vendor.io/my-pci-device.{{ .class }}-{{ .device }}=with-cpuid + # {{ end }} + # matchFeatures: + # - feature: pci.device + # matchExpressions: + # class: {op: InRegexp, value: ["^06"]} + # vendor: ["8086"] + # - feature: cpu.cpuid + # matchExpressions: + # AVX: {op: Exists} + # + # # The following examples demonstrate vars field and back-referencing + # # previous labels and vars + # - name: "my dummy kernel rule" + # labels: + # "vendor.io/my.kernel.feature": "true" + # matchFeatures: + # - feature: kernel.version + # matchExpressions: + # major: {op: Gt, value: ["2"]} + # + # - name: "my dummy rule with no labels" + # vars: + # "my.dummy.var": "1" + # matchFeatures: + # - feature: cpu.cpuid + # matchExpressions: {} + # + # - name: "my rule using backrefs" + # labels: + # "vendor.io/my.backref.feature": "true" + # matchFeatures: + # - feature: rule.matched + # matchExpressions: + # vendor.io/my.kernel.feature: {op: IsTrue} + # my.dummy.var: {op: Gt, value: ["0"]} + # + # - name: "kconfig template rule" + # labelsTemplate: | + # {{ range .kernel.config }}kconfig-{{ .Name }}={{ .Value }} + # {{ end }} + # matchFeatures: + # - feature: kernel.config + # matchName: {op: In, value: ["SWAP", "X86", "ARM"]} +### + + metricsPort: 8081 + healthPort: 8082 + daemonsetAnnotations: {} + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + # runAsUser: 1000 + + livenessProbe: + grpc: + port: 8082 + initialDelaySeconds: 10 + # failureThreshold: 3 + # periodSeconds: 10 + readinessProbe: + grpc: + port: 8082 + initialDelaySeconds: 5 + failureThreshold: 10 + # periodSeconds: 10 + + serviceAccount: + # Specifies whether a service account should be created. + # We create this by default to make it easier for downstream users to apply PodSecurityPolicies. + 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: + + # specify how many old ControllerRevisions for the DaemonSet to retain. + revisionHistoryLimit: + + rbac: + create: true + + # Allow users to mount the hostPath /usr/src, useful for RHCOS on s390x + # Does not work on systems without /usr/src AND a read-only /usr, such as Talos + mountUsrSrc: false + + resources: + limits: + memory: 512Mi + requests: + cpu: 5m + memory: 64Mi + + nodeSelector: {} + + tolerations: [] + + annotations: {} + + affinity: {} + + priorityClassName: "" + +topologyUpdater: + config: ### + ## key = node name, value = list of resources to be excluded. + ## use * to exclude from all nodes. + ## an example for how the exclude list should looks like + #excludeList: + # node1: [cpu] + # node2: [memory, example/deviceA] + # *: [hugepages-2Mi] +### + + enable: false + createCRDs: false + extraEnvs: [] + hostNetwork: false + + serviceAccount: + create: true + annotations: {} + name: + + # specify how many old ControllerRevisions for the DaemonSet to retain. + revisionHistoryLimit: + + rbac: + create: true + + metricsPort: 8081 + healthPort: 8082 + kubeletConfigPath: + kubeletPodResourcesSockPath: + updateInterval: 60s + watchNamespace: "*" + kubeletStateDir: /var/lib/kubelet + + podSecurityContext: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsUser: 0 + + livenessProbe: + grpc: + port: 8082 + initialDelaySeconds: 10 + # failureThreshold: 3 + # periodSeconds: 10 + readinessProbe: + grpc: + port: 8082 + initialDelaySeconds: 5 + failureThreshold: 10 + # periodSeconds: 10 + + resources: + limits: + memory: 60Mi + requests: + cpu: 50m + memory: 40Mi + + nodeSelector: {} + tolerations: [] + annotations: {} + daemonsetAnnotations: {} + affinity: {} + podSetFingerprint: true + +gc: + enable: true + extraEnvs: [] + hostNetwork: false + replicaCount: 1 + + serviceAccount: + create: true + annotations: {} + name: + rbac: + create: true + + interval: 1h + + podSecurityContext: {} + + resources: + limits: + memory: 1Gi + requests: + cpu: 10m + memory: 128Mi + + metricsPort: 8081 + + nodeSelector: {} + tolerations: [] + annotations: {} + deploymentAnnotations: {} + affinity: {} + + # specify how many old ReplicaSets for the Deployment to retain. + revisionHistoryLimit: + +# Optionally use encryption for worker <--> master comms +# TODO: verify hostname is not yet supported +# +# If you do not enable certManager (and have it installed) you will +# need to manually, or otherwise, provision the TLS certs as secrets +tls: + enable: false + certManager: false + certManagerCertificate: + issuerKind: + issuerName: + +prometheus: + enable: false + scrapeInterval: 10s + labels: {} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/crds/nvidia.com_clusterpolicies.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/crds/nvidia.com_clusterpolicies.yaml new file mode 100644 index 000000000..8ee8e9a8a --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/crds/nvidia.com_clusterpolicies.yaml @@ -0,0 +1,2384 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: clusterpolicies.nvidia.com +spec: + group: nvidia.com + names: + kind: ClusterPolicy + listKind: ClusterPolicyList + plural: clusterpolicies + singular: clusterpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: string + name: v1 + schema: + openAPIV3Schema: + description: ClusterPolicy is the Schema for the clusterpolicies API + 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: ClusterPolicySpec defines the desired state of ClusterPolicy + properties: + ccManager: + description: CCManager component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + defaultMode: + description: Default CC mode setting for compatible GPUs on the + node + enum: + - "on" + - "off" + - devtools + type: string + enabled: + description: Enabled indicates if deployment of CC Manager is + enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: CC Manager image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: CC Manager image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: CC Manager image tag + type: string + type: object + cdi: + description: CDI configures how the Container Device Interface is + used in the cluster + properties: + default: + default: false + description: Default indicates whether to use CDI as the default + mechanism for providing GPU access to containers. + type: boolean + enabled: + default: false + description: Enabled indicates whether CDI can be used to make + GPUs accessible to containers. + type: boolean + type: object + daemonsets: + description: Daemonset defines common configuration for all Daemonsets + properties: + annotations: + additionalProperties: + type: string + description: |- + Optional: 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. + type: object + labels: + additionalProperties: + type: string + description: |- + Optional: 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. + type: object + priorityClassName: + type: string + rollingUpdate: + description: 'Optional: Configuration for rolling update of all + DaemonSet pods' + properties: + maxUnavailable: + type: string + type: object + tolerations: + description: 'Optional: Set tolerations' + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching 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 + updateStrategy: + default: RollingUpdate + enum: + - RollingUpdate + - OnDelete + type: string + type: object + dcgm: + description: DCGM component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if deployment of NVIDIA DCGM Hostengine + as a separate pod is enabled. + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + hostPort: + description: 'Deprecated: HostPort represents host port that needs + to be bound for DCGM engine (Default: 5555)' + format: int32 + type: integer + image: + description: NVIDIA DCGM image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA DCGM image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: NVIDIA DCGM image tag + type: string + type: object + dcgmExporter: + description: DCGMExporter spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + config: + description: 'Optional: Custom metrics configuration for NVIDIA + DCGM Exporter' + properties: + name: + description: ConfigMap name with file dcgm-metrics.csv for + metrics to be collected by NVIDIA DCGM Exporter + type: string + type: object + enabled: + description: Enabled indicates if deployment of NVIDIA DCGM Exporter + through operator is enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA DCGM Exporter image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA DCGM Exporter image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + serviceMonitor: + description: 'Optional: ServiceMonitor configuration for NVIDIA + DCGM Exporter' + properties: + additionalLabels: + additionalProperties: + type: string + description: AdditionalLabels to add to ServiceMonitor instance + for NVIDIA DCGM Exporter + type: object + enabled: + description: Enabled indicates if ServiceMonitor is deployed + for NVIDIA DCGM Exporter + type: boolean + honorLabels: + description: HonorLabels chooses the metricโ€™s labels on collisions + with target labels. + type: boolean + interval: + description: |- + Interval which metrics should be scraped from NVIDIA DCGM Exporter. If not specified Prometheusโ€™ global scrape interval is used. + Supported units: y, w, d, h, m, s, ms + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + relabelings: + description: Relabelings allows to rewrite labels on metric + sets for NVIDIA DCGM Exporter + items: + description: |- + RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + scraped samples and remote write samples. + + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + properties: + action: + default: replace + description: |- + Action to perform based on the regex matching. + + `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + + Default: "Replace" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: |- + Modulus to take of the hash of the source label values. + + Only applicable when the action is `HashMod`. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: |- + Replacement value against which a Replace action is performed if the + regular expression matches. + + Regex capture groups are available. + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + 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. + items: + description: |- + LabelName is a valid Prometheus label name which may only contain ASCII + letters, numbers, as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: |- + Label to which the resulting string is written in a replacement. + + It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + `KeepEqual` and `DropEqual` actions. + + Regex capture groups are available. + type: string + type: object + type: array + type: object + version: + description: NVIDIA DCGM Exporter image tag + type: string + type: object + devicePlugin: + description: DevicePlugin component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + config: + description: 'Optional: Configuration for the NVIDIA Device Plugin + via the ConfigMap' + properties: + default: + description: Default config name within the ConfigMap for + the NVIDIA Device Plugin config + type: string + name: + description: ConfigMap name for NVIDIA Device Plugin config + including shared config between plugin and GFD + type: string + type: object + enabled: + description: Enabled indicates if deployment of NVIDIA Device + Plugin through operator is enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA Device Plugin image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + mps: + description: 'Optional: MPS related configuration for the NVIDIA + Device Plugin' + properties: + root: + default: /run/nvidia/mps + description: Root defines the MPS root path on the host + type: string + type: object + repository: + description: NVIDIA Device Plugin image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: NVIDIA Device Plugin image tag + type: string + type: object + driver: + description: Driver component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + certConfig: + description: 'Optional: Custom certificates configuration for + NVIDIA Driver container' + properties: + name: + type: string + type: object + enabled: + description: Enabled indicates if deployment of NVIDIA Driver + through operator is enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA Driver image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + kernelModuleConfig: + description: 'Optional: Kernel module configuration parameters + for the NVIDIA Driver' + properties: + name: + type: string + type: object + licensingConfig: + description: 'Optional: Licensing configuration for NVIDIA vGPU + licensing' + properties: + configMapName: + type: string + nlsEnabled: + description: NLSEnabled indicates if NVIDIA Licensing System + is used for licensing. + type: boolean + type: object + livenessProbe: + description: NVIDIA Driver container liveness probe settings + properties: + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + 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 + minimum: 1 + 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 + minimum: 1 + type: integer + 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 + minimum: 1 + type: integer + type: object + manager: + description: Manager represents configuration for NVIDIA Driver + Manager initContainer + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: Image represents NVIDIA Driver Manager image + name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: Repository represents Driver Managerrepository + path + type: string + version: + description: Version represents NVIDIA Driver Manager image + tag(version) + type: string + type: object + rdma: + description: GPUDirectRDMASpec defines the properties for nvidia-peermem + deployment + properties: + enabled: + description: Enabled indicates if GPUDirect RDMA is enabled + through GPU operator + type: boolean + useHostMofed: + description: UseHostMOFED indicates to use MOFED drivers directly + installed on the host to enable GPUDirect RDMA + type: boolean + type: object + readinessProbe: + description: NVIDIA Driver container readiness probe settings + properties: + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + 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 + minimum: 1 + 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 + minimum: 1 + type: integer + 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 + minimum: 1 + type: integer + type: object + repoConfig: + description: 'Optional: Custom repo configuration for NVIDIA Driver + container' + properties: + configMapName: + type: string + type: object + repository: + description: NVIDIA Driver image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + startupProbe: + description: NVIDIA Driver container startup probe settings + properties: + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + 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 + minimum: 1 + 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 + minimum: 1 + type: integer + 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 + minimum: 1 + type: integer + type: object + upgradePolicy: + description: Driver auto-upgrade settings + properties: + autoUpgrade: + default: false + description: |- + AutoUpgrade is a global switch for automatic upgrade feature + if set to false all other options are ignored + type: boolean + drain: + description: DrainSpec describes configuration for node drain + during automatic upgrade + properties: + deleteEmptyDir: + default: false + description: |- + DeleteEmptyDir indicates if should continue even if there are pods using emptyDir + (local data that will be deleted when the node is drained) + type: boolean + enable: + default: false + description: Enable indicates if node draining is allowed + during upgrade + type: boolean + force: + default: false + description: Force indicates if force draining is allowed + type: boolean + podSelector: + description: |- + PodSelector specifies a label selector to filter pods on the node that need to be drained + For more details on label selectors, see: + https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors + type: string + timeoutSeconds: + default: 300 + description: TimeoutSecond specifies the length of time + in seconds to wait before giving up drain, zero means + infinite + minimum: 0 + type: integer + type: object + maxParallelUpgrades: + default: 1 + description: |- + MaxParallelUpgrades indicates how many nodes can be upgraded in parallel + 0 means no limit, all nodes will be upgraded in parallel + minimum: 0 + type: integer + maxUnavailable: + anyOf: + - type: integer + - type: string + default: 25% + description: |- + MaxUnavailable is the maximum number of nodes with the driver installed, that can be unavailable during the upgrade. + Value can be an absolute number (ex: 5) or a percentage of total nodes at the start of upgrade (ex: 10%). + Absolute number is calculated from percentage by rounding up. + By default, a fixed value of 25% is used. + x-kubernetes-int-or-string: true + podDeletion: + description: PodDeletionSpec describes configuration for deletion + of pods using special resources during automatic upgrade + properties: + deleteEmptyDir: + default: false + description: |- + DeleteEmptyDir indicates if should continue even if there are pods using emptyDir + (local data that will be deleted when the pod is deleted) + type: boolean + force: + default: false + description: Force indicates if force deletion is allowed + type: boolean + timeoutSeconds: + default: 300 + description: |- + TimeoutSecond specifies the length of time in seconds to wait before giving up on pod termination, zero means + infinite + minimum: 0 + type: integer + type: object + waitForCompletion: + description: WaitForCompletionSpec describes the configuration + for waiting on job completions + properties: + podSelector: + description: |- + PodSelector specifies a label selector for the pods to wait for completion + For more details on label selectors, see: + https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors + type: string + timeoutSeconds: + default: 0 + description: |- + TimeoutSecond specifies the length of time in seconds to wait before giving up on pod termination, zero means + infinite + minimum: 0 + type: integer + type: object + type: object + useNvidiaDriverCRD: + description: UseNvidiaDriverCRD indicates if the deployment of + NVIDIA Driver is managed by the NVIDIADriver CRD type + type: boolean + useOpenKernelModules: + description: UseOpenKernelModules indicates if the open GPU kernel + modules should be used + type: boolean + usePrecompiled: + description: UsePrecompiled indicates if deployment of NVIDIA + Driver using pre-compiled modules is enabled + type: boolean + version: + description: NVIDIA Driver image tag + type: string + virtualTopology: + description: 'Optional: Virtual Topology Daemon configuration + for NVIDIA vGPU drivers' + properties: + config: + description: 'Optional: Config name representing virtual topology + daemon configuration file nvidia-topologyd.conf' + type: string + type: object + type: object + gdrcopy: + description: GDRCopy component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if GDRCopy is enabled through GPU + Operator + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA GDRCopy driver image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA GDRCopy driver image repository + type: string + version: + description: NVIDIA GDRCopy driver image tag + type: string + type: object + gds: + description: GPUDirectStorage defines the spec for GDS components(Experimental) + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if GPUDirect Storage is enabled + through GPU operator + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA GPUDirect Storage Driver image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA GPUDirect Storage Driver image repository + type: string + version: + description: NVIDIA GPUDirect Storage Driver image tag + type: string + type: object + gfd: + description: GPUFeatureDiscovery spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if deployment of GPU Feature Discovery + Plugin is enabled. + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: GFD image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: GFD image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: GFD image tag + type: string + type: object + hostPaths: + description: HostPaths defines various paths on the host needed by + GPU Operator components + properties: + driverInstallDir: + description: |- + DriverInstallDir represents the root at which driver files including libraries, + config files, and executables can be found. + type: string + rootFS: + description: |- + RootFS represents the path to the root filesystem of the host. + This is used by components that need to interact with the host filesystem + and as such this must be a chroot-able filesystem. + Examples include the MIG Manager and Toolkit Container which may need to + stop, start, or restart systemd services. + type: string + type: object + kataManager: + description: KataManager component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + config: + description: Kata Manager config + properties: + artifactsDir: + default: /opt/nvidia-gpu-operator/artifacts/runtimeclasses + description: |- + ArtifactsDir is the directory where kata artifacts (e.g. kernel / guest images, configuration, etc.) + are placed on the local filesystem. + type: string + runtimeClasses: + description: RuntimeClasses is a list of kata runtime classes + to configure. + items: + description: RuntimeClass defines the configuration for + a kata RuntimeClass + properties: + artifacts: + description: Artifacts are the kata artifacts associated + with the runtime class. + properties: + pullSecret: + description: PullSecret is the secret used to pull + the OCI artifact. + type: string + url: + description: |- + URL is the path to the OCI artifact (payload) containing all artifacts + associated with a kata runtime class. + type: string + required: + - url + type: object + name: + description: Name is the name of the kata runtime class. + type: string + nodeSelector: + additionalProperties: + type: string + description: |- + NodeSelector specifies the nodeSelector for the RuntimeClass object. + This ensures pods running with the RuntimeClass only get scheduled + onto nodes which support it. + type: object + required: + - artifacts + - name + type: object + type: array + type: object + enabled: + description: Enabled indicates if deployment of Kata Manager is + enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: Kata Manager image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: Kata Manager image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: Kata Manager image tag + type: string + type: object + mig: + description: MIG spec + properties: + strategy: + description: 'Optional: MIGStrategy to apply for GFD and NVIDIA + Device Plugin' + enum: + - none + - single + - mixed + type: string + type: object + migManager: + description: MIGManager for configuration to deploy MIG Manager + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + config: + description: 'Optional: Custom mig-parted configuration for NVIDIA + MIG Manager container' + properties: + default: + default: all-disabled + description: Default MIG config to be applied on the node, + when there is no config specified with the node label nvidia.com/mig.config + enum: + - all-disabled + - "" + type: string + name: + default: default-mig-parted-config + description: ConfigMap name + type: string + type: object + enabled: + description: Enabled indicates if deployment of NVIDIA MIG Manager + is enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + gpuClientsConfig: + description: 'Optional: Custom gpu-clients configuration for NVIDIA + MIG Manager container' + properties: + name: + description: ConfigMap name + type: string + type: object + image: + description: NVIDIA MIG Manager image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA MIG Manager image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: NVIDIA MIG Manager image tag + type: string + type: object + nodeStatusExporter: + description: NodeStatusExporter spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if deployment of Node Status Exporter + is enabled. + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: Node Status Exporter image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: Node Status Exporterimage repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: Node Status Exporterimage tag + type: string + type: object + operator: + description: Operator component spec + properties: + annotations: + additionalProperties: + type: string + description: |- + Optional: 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. + type: object + defaultRuntime: + default: docker + description: Runtime defines container runtime type + enum: + - docker + - crio + - containerd + type: string + initContainer: + description: InitContainerSpec describes configuration for initContainer + image used with all components + properties: + image: + description: Image represents image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: Repository represents image repository path + type: string + version: + description: Version represents image tag(version) + type: string + type: object + labels: + additionalProperties: + type: string + description: |- + Optional: 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. + type: object + runtimeClass: + default: nvidia + type: string + use_ocp_driver_toolkit: + description: UseOpenShiftDriverToolkit indicates if DriverToolkit + image should be used on OpenShift to build and install driver + modules + type: boolean + required: + - defaultRuntime + type: object + psa: + description: PSA defines spec for PodSecurityAdmission configuration + properties: + enabled: + description: Enabled indicates if PodSecurityAdmission configuration + needs to be enabled for all Pods + type: boolean + type: object + psp: + description: |- + Deprecated: Pod Security Policies are no longer supported. Please use PodSecurityAdmission instead + PSP defines spec for handling PodSecurityPolicies + properties: + enabled: + description: Enabled indicates if PodSecurityPolicies needs to + be enabled for all Pods + type: boolean + type: object + sandboxDevicePlugin: + description: SandboxDevicePlugin component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if deployment of NVIDIA Sandbox + Device Plugin through operator is enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA Sandbox Device Plugin image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA Sandbox Device Plugin image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: NVIDIA Sandbox Device Plugin image tag + type: string + type: object + sandboxWorkloads: + description: SandboxWorkloads defines the spec for handling sandbox + workloads (i.e. Virtual Machines) + properties: + defaultWorkload: + default: container + description: |- + DefaultWorkload indicates the default GPU workload type to configure + worker nodes in the cluster for + enum: + - container + - vm-passthrough + - vm-vgpu + type: string + enabled: + description: |- + Enabled indicates if the GPU Operator should manage additional operands required + for sandbox workloads (i.e. VFIO Manager, vGPU Manager, and additional device plugins) + type: boolean + type: object + toolkit: + description: Toolkit component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if deployment of NVIDIA Container + Toolkit through operator is enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA Container Toolkit image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + installDir: + default: /usr/local/nvidia + description: Toolkit install directory on the host + type: string + repository: + description: NVIDIA Container Toolkit image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: NVIDIA Container Toolkit image tag + type: string + type: object + validator: + description: Validator defines the spec for operator-validator daemonset + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + cuda: + description: CUDA validator spec + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + type: object + driver: + description: Toolkit validator spec + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + type: object + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: Validator image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + plugin: + description: Plugin validator spec + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + type: object + repository: + description: Validator image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + toolkit: + description: Toolkit validator spec + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + type: object + version: + description: Validator image tag + type: string + vfioPCI: + description: VfioPCI validator spec + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + type: object + vgpuDevices: + description: VGPUDevices validator spec + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + type: object + vgpuManager: + description: VGPUManager validator spec + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + type: object + type: object + vfioManager: + description: VFIOManager for configuration to deploy VFIO-PCI Manager + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + driverManager: + description: DriverManager represents configuration for NVIDIA + Driver Manager + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: Image represents NVIDIA Driver Manager image + name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: Repository represents Driver Managerrepository + path + type: string + version: + description: Version represents NVIDIA Driver Manager image + tag(version) + type: string + type: object + enabled: + description: Enabled indicates if deployment of VFIO Manager is + enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: VFIO Manager image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: VFIO Manager image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: VFIO Manager image tag + type: string + type: object + vgpuDeviceManager: + description: VGPUDeviceManager spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + config: + description: NVIDIA vGPU devices configuration for NVIDIA vGPU + Device Manager container + properties: + default: + default: default + description: Default config name within the ConfigMap + type: string + name: + description: ConfigMap name + type: string + type: object + enabled: + description: Enabled indicates if deployment of NVIDIA vGPU Device + Manager is enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA vGPU Device Manager image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA vGPU Device Manager image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: NVIDIA vGPU Device Manager image tag + type: string + type: object + vgpuManager: + description: VGPUManager component spec + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + driverManager: + description: DriverManager represents configuration for NVIDIA + Driver Manager initContainer + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: Image represents NVIDIA Driver Manager image + name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: Repository represents Driver Managerrepository + path + type: string + version: + description: Version represents NVIDIA Driver Manager image + tag(version) + type: string + type: object + enabled: + description: Enabled indicates if deployment of NVIDIA vGPU Manager + through operator is enabled + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA vGPU Manager image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA vGPU Manager image repository + type: string + resources: + description: 'Optional: Define resources requests and limits for + each pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + version: + description: NVIDIA vGPU Manager image tag + type: string + type: object + required: + - daemonsets + - dcgm + - dcgmExporter + - devicePlugin + - driver + - gfd + - nodeStatusExporter + - operator + - toolkit + type: object + status: + description: ClusterPolicyStatus defines the observed state of ClusterPolicy + properties: + conditions: + description: Conditions is a list of conditions representing the ClusterPolicy's + current state. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + namespace: + description: Namespace indicates a namespace in which the operator + is installed + type: string + state: + description: State indicates status of ClusterPolicy + enum: + - ignored + - ready + - notReady + type: string + required: + - state + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/crds/nvidia.com_nvidiadrivers.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/crds/nvidia.com_nvidiadrivers.yaml new file mode 100644 index 000000000..072155768 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/crds/nvidia.com_nvidiadrivers.yaml @@ -0,0 +1,797 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: nvidiadrivers.nvidia.com +spec: + group: nvidia.com + names: + kind: NVIDIADriver + listKind: NVIDIADriverList + plural: nvidiadrivers + shortNames: + - nvd + - nvdriver + - nvdrivers + singular: nvidiadriver + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: NVIDIADriver is the Schema for the nvidiadrivers API + 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: NVIDIADriverSpec defines the desired state of NVIDIADriver + properties: + annotations: + additionalProperties: + type: string + description: |- + Optional: 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. + type: object + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + certConfig: + description: 'Optional: Custom certificates configuration for NVIDIA + Driver container' + properties: + name: + type: string + type: object + driverType: + default: gpu + description: DriverType defines NVIDIA driver type + enum: + - gpu + - vgpu + - vgpu-host-manager + type: string + x-kubernetes-validations: + - message: driverType is an immutable field. Please create a new NvidiaDriver + resource instead when you want to change this setting. + rule: self == oldSelf + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + gdrcopy: + description: GDRCopy defines the spec for GDRCopy driver + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if GDRCopy is enabled through GPU + operator + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: GDRCopy driver image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: GDRCopy diver image repository + type: string + version: + description: GDRCopy driver image tag + type: string + type: object + gds: + description: GPUDirectStorage defines the spec for GDS driver + properties: + args: + description: 'Optional: List of arguments' + items: + type: string + type: array + enabled: + description: Enabled indicates if GPUDirect Storage is enabled + through GPU operator + type: boolean + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: NVIDIA GPUDirect Storage Driver image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: NVIDIA GPUDirect Storage Driver image repository + type: string + version: + description: NVIDIA GPUDirect Storage Driver image tag + type: string + type: object + image: + default: nvcr.io/nvidia/driver + description: NVIDIA Driver container image name + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + kernelModuleConfig: + description: 'Optional: Kernel module configuration parameters for + the NVIDIA Driver' + properties: + name: + type: string + type: object + labels: + additionalProperties: + type: string + description: |- + Optional: 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. + type: object + licensingConfig: + description: 'Optional: Licensing configuration for NVIDIA vGPU licensing' + properties: + name: + type: string + nlsEnabled: + description: NLSEnabled indicates if NVIDIA Licensing System is + used for licensing. + type: boolean + type: object + livenessProbe: + description: NVIDIA Driver container liveness probe settings + properties: + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + 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 + minimum: 1 + 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 + minimum: 1 + type: integer + 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 + minimum: 1 + type: integer + type: object + manager: + description: Manager represents configuration for NVIDIA Driver Manager + initContainer + properties: + env: + description: 'Optional: List of environment variables' + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. + type: string + value: + description: Value of the environment variable. + type: string + required: + - name + type: object + type: array + image: + description: Image represents NVIDIA Driver Manager image name + pattern: '[a-zA-Z0-9\-]+' + type: string + imagePullPolicy: + description: Image pull policy + type: string + imagePullSecrets: + description: Image pull secrets + items: + type: string + type: array + repository: + description: Repository represents Driver Managerrepository path + type: string + version: + description: Version represents NVIDIA Driver Manager image tag(version) + type: string + type: object + nodeAffinity: + description: Affinity specifies node affinity rules for driver pods + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + 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 + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + nodeSelector: + additionalProperties: + type: string + description: NodeSelector specifies a selector for installation of + NVIDIA driver + type: object + priorityClassName: + description: 'Optional: Set priorityClassName' + type: string + rdma: + description: GPUDirectRDMA defines the spec for NVIDIA Peer Memory + driver + properties: + enabled: + description: Enabled indicates if GPUDirect RDMA is enabled through + GPU operator + type: boolean + useHostMofed: + description: UseHostMOFED indicates to use MOFED drivers directly + installed on the host to enable GPUDirect RDMA + type: boolean + type: object + readinessProbe: + description: NVIDIA Driver container readiness probe settings + properties: + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + 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 + minimum: 1 + 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 + minimum: 1 + type: integer + 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 + minimum: 1 + type: integer + type: object + repoConfig: + description: 'Optional: Custom repo configuration for NVIDIA Driver + container' + properties: + name: + type: string + type: object + repository: + description: NVIDIA Driver repository + type: string + resources: + description: 'Optional: Define resources requests and limits for each + pod' + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + startupProbe: + description: NVIDIA Driver container startup probe settings + properties: + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + 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 + minimum: 1 + 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 + minimum: 1 + type: integer + 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 + minimum: 1 + type: integer + type: object + tolerations: + description: 'Optional: Set tolerations' + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching 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 + useOpenKernelModules: + description: UseOpenKernelModules indicates if the open GPU kernel + modules should be used + type: boolean + usePrecompiled: + description: UsePrecompiled indicates if deployment of NVIDIA Driver + using pre-compiled modules is enabled + type: boolean + x-kubernetes-validations: + - message: usePrecompiled is an immutable field. Please create a new + NvidiaDriver resource instead when you want to change this setting. + rule: self == oldSelf + version: + description: NVIDIA Driver version (or just branch for precompiled + drivers) + type: string + virtualTopologyConfig: + description: 'Optional: Virtual Topology Daemon configuration for + NVIDIA vGPU drivers' + properties: + name: + description: 'Optional: Config name representing virtual topology + daemon configuration file nvidia-topologyd.conf' + type: string + type: object + required: + - driverType + - image + type: object + status: + description: NVIDIADriverStatus defines the observed state of NVIDIADriver + properties: + conditions: + description: Conditions is a list of conditions representing the NVIDIADriver's + current state. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + namespace: + description: Namespace indicates a namespace in which the operator + and driver are installed + type: string + state: + description: |- + INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + Important: Run "make" to regenerate code after modifying this file + State indicates status of NVIDIADriver instance + enum: + - ignored + - ready + - notReady + type: string + required: + - state + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/_helpers.tpl b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/_helpers.tpl new file mode 100644 index 000000000..305c9d1fe --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/_helpers.tpl @@ -0,0 +1,80 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "gpu-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 "gpu-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 "gpu-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} + +{{- define "gpu-operator.labels" -}} +app.kubernetes.io/name: {{ include "gpu-operator.name" . }} +helm.sh/chart: {{ include "gpu-operator.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.operator.labels }} +{{ toYaml .Values.operator.labels }} +{{- end }} +{{- end -}} + +{{- define "gpu-operator.operand-labels" -}} +helm.sh/chart: {{ include "gpu-operator.chart" . }} +app.kubernetes.io/managed-by: {{ include "gpu-operator.name" . }} +{{- if .Values.daemonsets.labels }} +{{ toYaml .Values.daemonsets.labels }} +{{- end }} +{{- end -}} + +{{- define "gpu-operator.matchLabels" -}} +app.kubernetes.io/name: {{ include "gpu-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Full image name with tag +*/}} +{{- define "gpu-operator.fullimage" -}} +{{- .Values.operator.repository -}}/{{- .Values.operator.image -}}:{{- .Values.operator.version | default .Chart.AppVersion -}} +{{- end }} + +{{/* +Full image name with tag +*/}} +{{- define "driver-manager.fullimage" -}} +{{- .Values.driver.manager.repository -}}/{{- .Values.driver.manager.image -}}:{{- .Values.driver.manager.version -}} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/cleanup_crd.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/cleanup_crd.yaml new file mode 100644 index 000000000..fd0c1b799 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/cleanup_crd.yaml @@ -0,0 +1,45 @@ +{{- if .Values.operator.cleanupCRD }} +apiVersion: batch/v1 +kind: Job +metadata: + name: gpu-operator-cleanup-crd + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" +spec: + template: + metadata: + name: gpu-operator-cleanup-crd + labels: + {{- include "gpu-operator.labels" . | nindent 8 }} + app.kubernetes.io/component: "gpu-operator" + spec: + serviceAccountName: gpu-operator + {{- if .Values.operator.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.operator.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.operator.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cleanup-crd + image: {{ include "gpu-operator.fullimage" . }} + imagePullPolicy: {{ .Values.operator.imagePullPolicy }} + command: + - /bin/sh + - -c + - > + kubectl delete clusterpolicy cluster-policy; + kubectl delete crd clusterpolicies.nvidia.com; + + restartPolicy: OnFailure +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterpolicy.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterpolicy.yaml new file mode 100644 index 000000000..af9e87c38 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterpolicy.yaml @@ -0,0 +1,683 @@ +apiVersion: nvidia.com/v1 +kind: ClusterPolicy +metadata: + name: cluster-policy + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" + {{- if .Values.operator.cleanupCRD }} + # CR cleanup is handled during pre-delete hook + # Add below annotation so that helm doesn't attempt to cleanup CR twice + annotations: + "helm.sh/resource-policy": keep + {{- end }} +spec: + hostPaths: + rootFS: {{ .Values.hostPaths.rootFS }} + driverInstallDir: {{ .Values.hostPaths.driverInstallDir }} + operator: + {{- if .Values.operator.defaultRuntime }} + defaultRuntime: {{ .Values.operator.defaultRuntime }} + {{- end }} + {{- if .Values.operator.runtimeClass }} + runtimeClass: {{ .Values.operator.runtimeClass }} + {{- end }} + {{- if .Values.operator.defaultGPUMode }} + defaultGPUMode: {{ .Values.operator.defaultGPUMode }} + {{- end }} + {{- if .Values.operator.initContainer }} + initContainer: + {{- if .Values.operator.initContainer.repository }} + repository: {{ .Values.operator.initContainer.repository }} + {{- end }} + {{- if .Values.operator.initContainer.image }} + image: {{ .Values.operator.initContainer.image }} + {{- end }} + {{- if .Values.operator.initContainer.version }} + version: {{ .Values.operator.initContainer.version | quote }} + {{- end }} + {{- if .Values.operator.initContainer.imagePullPolicy }} + imagePullPolicy: {{ .Values.operator.initContainer.imagePullPolicy }} + {{- end }} + {{- if .Values.operator.initContainer.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.operator.initContainer.imagePullSecrets | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.operator.use_ocp_driver_toolkit }} + use_ocp_driver_toolkit: {{ .Values.operator.use_ocp_driver_toolkit }} + {{- end }} + daemonsets: + labels: + {{- include "gpu-operator.operand-labels" . | nindent 6 }} + {{- if .Values.daemonsets.annotations }} + annotations: {{ toYaml .Values.daemonsets.annotations | nindent 6 }} + {{- end }} + {{- if .Values.daemonsets.tolerations }} + tolerations: {{ toYaml .Values.daemonsets.tolerations | nindent 6 }} + {{- end }} + {{- if .Values.daemonsets.priorityClassName }} + priorityClassName: {{ .Values.daemonsets.priorityClassName }} + {{- end }} + {{- if .Values.daemonsets.updateStrategy }} + updateStrategy: {{ .Values.daemonsets.updateStrategy }} + {{- end }} + {{- if .Values.daemonsets.rollingUpdate }} + rollingUpdate: + maxUnavailable: {{ .Values.daemonsets.rollingUpdate.maxUnavailable | quote }} + {{- end }} + validator: + {{- if .Values.validator.repository }} + repository: {{ .Values.validator.repository }} + {{- end }} + {{- if .Values.validator.image }} + image: {{ .Values.validator.image }} + {{- end }} + version: {{ .Values.validator.version | default .Chart.AppVersion | quote }} + {{- if .Values.validator.imagePullPolicy }} + imagePullPolicy: {{ .Values.validator.imagePullPolicy }} + {{- end }} + {{- if .Values.validator.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.validator.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.validator.resources }} + resources: {{ toYaml .Values.validator.resources | nindent 6 }} + {{- end }} + {{- if .Values.validator.env }} + env: {{ toYaml .Values.validator.env | nindent 6 }} + {{- end }} + {{- if .Values.validator.args }} + args: {{ toYaml .Values.validator.args | nindent 6 }} + {{- end }} + {{- if .Values.validator.plugin }} + plugin: + {{- if .Values.validator.plugin.env }} + env: {{ toYaml .Values.validator.plugin.env | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.validator.cuda }} + cuda: + {{- if .Values.validator.cuda.env }} + env: {{ toYaml .Values.validator.cuda.env | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.validator.driver }} + driver: + {{- if .Values.validator.driver.env }} + env: {{ toYaml .Values.validator.driver.env | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.validator.toolkit }} + toolkit: + {{- if .Values.validator.toolkit.env }} + env: {{ toYaml .Values.validator.toolkit.env | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.validator.vfioPCI }} + vfioPCI: + {{- if .Values.validator.vfioPCI.env }} + env: {{ toYaml .Values.validator.vfioPCI.env | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.validator.vgpuManager }} + vgpuManager: + {{- if .Values.validator.vgpuManager.env }} + env: {{ toYaml .Values.validator.vgpuManager.env | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.validator.vgpuDevices }} + vgpuDevices: + {{- if .Values.validator.vgpuDevices.env }} + env: {{ toYaml .Values.validator.vgpuDevices.env | nindent 8 }} + {{- end }} + {{- end }} + + mig: + {{- if .Values.mig.strategy }} + strategy: {{ .Values.mig.strategy }} + {{- end }} + psa: + enabled: {{ .Values.psa.enabled }} + cdi: + enabled: {{ .Values.cdi.enabled }} + default: {{ .Values.cdi.default }} + driver: + enabled: {{ .Values.driver.enabled }} + useNvidiaDriverCRD: {{ .Values.driver.nvidiaDriverCRD.enabled }} + useOpenKernelModules: {{ .Values.driver.useOpenKernelModules }} + usePrecompiled: {{ .Values.driver.usePrecompiled }} + {{- if .Values.driver.repository }} + repository: {{ .Values.driver.repository }} + {{- end }} + {{- if .Values.driver.image }} + image: {{ .Values.driver.image }} + {{- end }} + {{- if .Values.driver.version }} + version: {{ .Values.driver.version | quote }} + {{- end }} + {{- if .Values.driver.imagePullPolicy }} + imagePullPolicy: {{ .Values.driver.imagePullPolicy }} + {{- end }} + {{- if .Values.driver.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.driver.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.driver.startupProbe }} + startupProbe: {{ toYaml .Values.driver.startupProbe | nindent 6 }} + {{- end }} + {{- if .Values.driver.livenessProbe }} + livenessProbe: {{ toYaml .Values.driver.livenessProbe | nindent 6 }} + {{- end }} + {{- if .Values.driver.readinessProbe }} + readinessProbe: {{ toYaml .Values.driver.readinessProbe | nindent 6 }} + {{- end }} + rdma: + enabled: {{ .Values.driver.rdma.enabled }} + useHostMofed: {{ .Values.driver.rdma.useHostMofed }} + manager: + {{- if .Values.driver.manager.repository }} + repository: {{ .Values.driver.manager.repository }} + {{- end }} + {{- if .Values.driver.manager.image }} + image: {{ .Values.driver.manager.image }} + {{- end }} + {{- if .Values.driver.manager.version }} + version: {{ .Values.driver.manager.version | quote }} + {{- end }} + {{- if .Values.driver.manager.imagePullPolicy }} + imagePullPolicy: {{ .Values.driver.manager.imagePullPolicy }} + {{- end }} + {{- if .Values.driver.manager.env }} + env: {{ toYaml .Values.driver.manager.env | nindent 8 }} + {{- end }} + {{- if .Values.driver.repoConfig }} + repoConfig: {{ toYaml .Values.driver.repoConfig | nindent 6 }} + {{- end }} + {{- if .Values.driver.certConfig }} + certConfig: {{ toYaml .Values.driver.certConfig | nindent 6 }} + {{- end }} + {{- if .Values.driver.licensingConfig }} + licensingConfig: {{ toYaml .Values.driver.licensingConfig | nindent 6 }} + {{- end }} + {{- if .Values.driver.virtualTopology }} + virtualTopology: {{ toYaml .Values.driver.virtualTopology | nindent 6 }} + {{- end }} + {{- if .Values.driver.kernelModuleConfig }} + kernelModuleConfig: {{ toYaml .Values.driver.kernelModuleConfig | nindent 6 }} + {{- end }} + {{- if .Values.driver.resources }} + resources: {{ toYaml .Values.driver.resources | nindent 6 }} + {{- end }} + {{- if .Values.driver.env }} + env: {{ toYaml .Values.driver.env | nindent 6 }} + {{- end }} + {{- if .Values.driver.args }} + args: {{ toYaml .Values.driver.args | nindent 6 }} + {{- end }} + {{- if .Values.driver.upgradePolicy }} + upgradePolicy: + autoUpgrade: {{ .Values.driver.upgradePolicy.autoUpgrade | default false }} + maxParallelUpgrades: {{ .Values.driver.upgradePolicy.maxParallelUpgrades | default 0 }} + maxUnavailable : {{ .Values.driver.upgradePolicy.maxUnavailable | default "25%" }} + waitForCompletion: + timeoutSeconds: {{ .Values.driver.upgradePolicy.waitForCompletion.timeoutSeconds }} + {{- if .Values.driver.upgradePolicy.waitForCompletion.podSelector }} + podSelector: {{ .Values.driver.upgradePolicy.waitForCompletion.podSelector }} + {{- end }} + podDeletion: + force: {{ .Values.driver.upgradePolicy.gpuPodDeletion.force | default false }} + timeoutSeconds: {{ .Values.driver.upgradePolicy.gpuPodDeletion.timeoutSeconds }} + deleteEmptyDir: {{ .Values.driver.upgradePolicy.gpuPodDeletion.deleteEmptyDir | default false }} + drain: + enable: {{ .Values.driver.upgradePolicy.drain.enable | default false }} + force: {{ .Values.driver.upgradePolicy.drain.force | default false }} + {{- if .Values.driver.upgradePolicy.drain.podSelector }} + podSelector: {{ .Values.driver.upgradePolicy.drain.podSelector }} + {{- end }} + timeoutSeconds: {{ .Values.driver.upgradePolicy.drain.timeoutSeconds }} + deleteEmptyDir: {{ .Values.driver.upgradePolicy.drain.deleteEmptyDir | default false}} + {{- end }} + vgpuManager: + enabled: {{ .Values.vgpuManager.enabled }} + {{- if .Values.vgpuManager.repository }} + repository: {{ .Values.vgpuManager.repository }} + {{- end }} + {{- if .Values.vgpuManager.image }} + image: {{ .Values.vgpuManager.image }} + {{- end }} + {{- if .Values.vgpuManager.version }} + version: {{ .Values.vgpuManager.version | quote }} + {{- end }} + {{- if .Values.vgpuManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.vgpuManager.imagePullPolicy }} + {{- end }} + {{- if .Values.vgpuManager.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.vgpuManager.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.vgpuManager.resources }} + resources: {{ toYaml .Values.vgpuManager.resources | nindent 6 }} + {{- end }} + {{- if .Values.vgpuManager.env }} + env: {{ toYaml .Values.vgpuManager.env | nindent 6 }} + {{- end }} + {{- if .Values.vgpuManager.args }} + args: {{ toYaml .Values.vgpuManager.args | nindent 6 }} + {{- end }} + driverManager: + {{- if .Values.vgpuManager.driverManager.repository }} + repository: {{ .Values.vgpuManager.driverManager.repository }} + {{- end }} + {{- if .Values.vgpuManager.driverManager.image }} + image: {{ .Values.vgpuManager.driverManager.image }} + {{- end }} + {{- if .Values.vgpuManager.driverManager.version }} + version: {{ .Values.vgpuManager.driverManager.version | quote }} + {{- end }} + {{- if .Values.vgpuManager.driverManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.vgpuManager.driverManager.imagePullPolicy }} + {{- end }} + {{- if .Values.vgpuManager.driverManager.env }} + env: {{ toYaml .Values.vgpuManager.driverManager.env | nindent 8 }} + {{- end }} + kataManager: + enabled: {{ .Values.kataManager.enabled }} + config: {{ toYaml .Values.kataManager.config | nindent 6 }} + {{- if .Values.kataManager.repository }} + repository: {{ .Values.kataManager.repository }} + {{- end }} + {{- if .Values.kataManager.image }} + image: {{ .Values.kataManager.image }} + {{- end }} + {{- if .Values.kataManager.version }} + version: {{ .Values.kataManager.version | quote }} + {{- end }} + {{- if .Values.kataManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.kataManager.imagePullPolicy }} + {{- end }} + {{- if .Values.kataManager.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.kataManager.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.kataManager.resources }} + resources: {{ toYaml .Values.kataManager.resources | nindent 6 }} + {{- end }} + {{- if .Values.kataManager.env }} + env: {{ toYaml .Values.kataManager.env | nindent 6 }} + {{- end }} + {{- if .Values.kataManager.args }} + args: {{ toYaml .Values.kataManager.args | nindent 6 }} + {{- end }} + vfioManager: + enabled: {{ .Values.vfioManager.enabled }} + {{- if .Values.vfioManager.repository }} + repository: {{ .Values.vfioManager.repository }} + {{- end }} + {{- if .Values.vfioManager.image }} + image: {{ .Values.vfioManager.image }} + {{- end }} + {{- if .Values.vfioManager.version }} + version: {{ .Values.vfioManager.version | quote }} + {{- end }} + {{- if .Values.vfioManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.vfioManager.imagePullPolicy }} + {{- end }} + {{- if .Values.vfioManager.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.vfioManager.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.vfioManager.resources }} + resources: {{ toYaml .Values.vfioManager.resources | nindent 6 }} + {{- end }} + {{- if .Values.vfioManager.env }} + env: {{ toYaml .Values.vfioManager.env | nindent 6 }} + {{- end }} + {{- if .Values.vfioManager.args }} + args: {{ toYaml .Values.vfioManager.args | nindent 6 }} + {{- end }} + driverManager: + {{- if .Values.vfioManager.driverManager.repository }} + repository: {{ .Values.vfioManager.driverManager.repository }} + {{- end }} + {{- if .Values.vfioManager.driverManager.image }} + image: {{ .Values.vfioManager.driverManager.image }} + {{- end }} + {{- if .Values.vfioManager.driverManager.version }} + version: {{ .Values.vfioManager.driverManager.version | quote }} + {{- end }} + {{- if .Values.vfioManager.driverManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.vfioManager.driverManager.imagePullPolicy }} + {{- end }} + {{- if .Values.vfioManager.driverManager.env }} + env: {{ toYaml .Values.vfioManager.driverManager.env | nindent 8 }} + {{- end }} + vgpuDeviceManager: + enabled: {{ .Values.vgpuDeviceManager.enabled }} + {{- if .Values.vgpuDeviceManager.repository }} + repository: {{ .Values.vgpuDeviceManager.repository }} + {{- end }} + {{- if .Values.vgpuDeviceManager.image }} + image: {{ .Values.vgpuDeviceManager.image }} + {{- end }} + {{- if .Values.vgpuDeviceManager.version }} + version: {{ .Values.vgpuDeviceManager.version | quote }} + {{- end }} + {{- if .Values.vgpuDeviceManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.vgpuDeviceManager.imagePullPolicy }} + {{- end }} + {{- if .Values.vgpuDeviceManager.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.vgpuDeviceManager.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.vgpuDeviceManager.resources }} + resources: {{ toYaml .Values.vgpuDeviceManager.resources | nindent 6 }} + {{- end }} + {{- if .Values.vgpuDeviceManager.env }} + env: {{ toYaml .Values.vgpuDeviceManager.env | nindent 6 }} + {{- end }} + {{- if .Values.vgpuDeviceManager.args }} + args: {{ toYaml .Values.vgpuDeviceManager.args | nindent 6 }} + {{- end }} + {{- if .Values.vgpuDeviceManager.config }} + config: {{ toYaml .Values.vgpuDeviceManager.config | nindent 6 }} + {{- end }} + ccManager: + enabled: {{ .Values.ccManager.enabled }} + defaultMode: {{ .Values.ccManager.defaultMode | quote }} + {{- if .Values.ccManager.repository }} + repository: {{ .Values.ccManager.repository }} + {{- end }} + {{- if .Values.ccManager.image }} + image: {{ .Values.ccManager.image }} + {{- end }} + {{- if .Values.ccManager.version }} + version: {{ .Values.ccManager.version | quote }} + {{- end }} + {{- if .Values.ccManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.ccManager.imagePullPolicy }} + {{- end }} + {{- if .Values.ccManager.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.ccManager.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.ccManager.resources }} + resources: {{ toYaml .Values.ccManager.resources | nindent 6 }} + {{- end }} + {{- if .Values.ccManager.env }} + env: {{ toYaml .Values.vfioManager.env | nindent 6 }} + {{- end }} + {{- if .Values.ccManager.args }} + args: {{ toYaml .Values.ccManager.args | nindent 6 }} + {{- end }} + toolkit: + enabled: {{ .Values.toolkit.enabled }} + {{- if .Values.toolkit.repository }} + repository: {{ .Values.toolkit.repository }} + {{- end }} + {{- if .Values.toolkit.image }} + image: {{ .Values.toolkit.image }} + {{- end }} + {{- if .Values.toolkit.version }} + version: {{ .Values.toolkit.version | quote }} + {{- end }} + {{- if .Values.toolkit.imagePullPolicy }} + imagePullPolicy: {{ .Values.toolkit.imagePullPolicy }} + {{- end }} + {{- if .Values.toolkit.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.toolkit.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.toolkit.resources }} + resources: {{ toYaml .Values.toolkit.resources | nindent 6 }} + {{- end }} + {{- if .Values.toolkit.env }} + env: {{ toYaml .Values.toolkit.env | nindent 6 }} + {{- end }} + {{- if .Values.toolkit.installDir }} + installDir: {{ .Values.toolkit.installDir }} + {{- end }} + devicePlugin: + enabled: {{ .Values.devicePlugin.enabled }} + {{- if .Values.devicePlugin.repository }} + repository: {{ .Values.devicePlugin.repository }} + {{- end }} + {{- if .Values.devicePlugin.image }} + image: {{ .Values.devicePlugin.image }} + {{- end }} + {{- if .Values.devicePlugin.version }} + version: {{ .Values.devicePlugin.version | quote }} + {{- end }} + {{- if .Values.devicePlugin.imagePullPolicy }} + imagePullPolicy: {{ .Values.devicePlugin.imagePullPolicy }} + {{- end }} + {{- if .Values.devicePlugin.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.devicePlugin.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.devicePlugin.resources }} + resources: {{ toYaml .Values.devicePlugin.resources | nindent 6 }} + {{- end }} + {{- if .Values.devicePlugin.env }} + env: {{ toYaml .Values.devicePlugin.env | nindent 6 }} + {{- end }} + {{- if .Values.devicePlugin.args }} + args: {{ toYaml .Values.devicePlugin.args | nindent 6 }} + {{- end }} + {{- if .Values.devicePlugin.config.name }} + config: + name: {{ .Values.devicePlugin.config.name }} + default: {{ .Values.devicePlugin.config.default }} + {{- end }} + dcgm: + enabled: {{ .Values.dcgm.enabled }} + {{- if .Values.dcgm.repository }} + repository: {{ .Values.dcgm.repository }} + {{- end }} + {{- if .Values.dcgm.image }} + image: {{ .Values.dcgm.image }} + {{- end }} + {{- if .Values.dcgm.version }} + version: {{ .Values.dcgm.version | quote }} + {{- end }} + {{- if .Values.dcgm.imagePullPolicy }} + imagePullPolicy: {{ .Values.dcgm.imagePullPolicy }} + {{- end }} + {{- if .Values.dcgm.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.dcgm.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.dcgm.resources }} + resources: {{ toYaml .Values.dcgm.resources | nindent 6 }} + {{- end }} + {{- if .Values.dcgm.env }} + env: {{ toYaml .Values.dcgm.env | nindent 6 }} + {{- end }} + {{- if .Values.dcgm.args }} + args: {{ toYaml .Values.dcgm.args | nindent 6 }} + {{- end }} + dcgmExporter: + enabled: {{ .Values.dcgmExporter.enabled }} + {{- if .Values.dcgmExporter.repository }} + repository: {{ .Values.dcgmExporter.repository }} + {{- end }} + {{- if .Values.dcgmExporter.image }} + image: {{ .Values.dcgmExporter.image }} + {{- end }} + {{- if .Values.dcgmExporter.version }} + version: {{ .Values.dcgmExporter.version | quote }} + {{- end }} + {{- if .Values.dcgmExporter.imagePullPolicy }} + imagePullPolicy: {{ .Values.dcgmExporter.imagePullPolicy }} + {{- end }} + {{- if .Values.dcgmExporter.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.dcgmExporter.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.dcgmExporter.resources }} + resources: {{ toYaml .Values.dcgmExporter.resources | nindent 6 }} + {{- end }} + {{- if .Values.dcgmExporter.env }} + env: {{ toYaml .Values.dcgmExporter.env | nindent 6 }} + {{- end }} + {{- if .Values.dcgmExporter.args }} + args: {{ toYaml .Values.dcgmExporter.args | nindent 6 }} + {{- end }} + {{- if and (.Values.dcgmExporter.config) (.Values.dcgmExporter.config.name) }} + config: + name: {{ .Values.dcgmExporter.config.name }} + {{- end }} + {{- if .Values.dcgmExporter.serviceMonitor }} + serviceMonitor: {{ toYaml .Values.dcgmExporter.serviceMonitor | nindent 6 }} + {{- end }} + gfd: + enabled: {{ .Values.gfd.enabled }} + {{- if .Values.gfd.repository }} + repository: {{ .Values.gfd.repository }} + {{- end }} + {{- if .Values.gfd.image }} + image: {{ .Values.gfd.image }} + {{- end }} + {{- if .Values.gfd.version }} + version: {{ .Values.gfd.version | quote }} + {{- end }} + {{- if .Values.gfd.imagePullPolicy }} + imagePullPolicy: {{ .Values.gfd.imagePullPolicy }} + {{- end }} + {{- if .Values.gfd.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.gfd.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.gfd.resources }} + resources: {{ toYaml .Values.gfd.resources | nindent 6 }} + {{- end }} + {{- if .Values.gfd.env }} + env: {{ toYaml .Values.gfd.env | nindent 6 }} + {{- end }} + {{- if .Values.gfd.args }} + args: {{ toYaml .Values.gfd.args | nindent 6 }} + {{- end }} + migManager: + enabled: {{ .Values.migManager.enabled }} + {{- if .Values.migManager.repository }} + repository: {{ .Values.migManager.repository }} + {{- end }} + {{- if .Values.migManager.image }} + image: {{ .Values.migManager.image }} + {{- end }} + {{- if .Values.migManager.version }} + version: {{ .Values.migManager.version | quote }} + {{- end }} + {{- if .Values.migManager.imagePullPolicy }} + imagePullPolicy: {{ .Values.migManager.imagePullPolicy }} + {{- end }} + {{- if .Values.migManager.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.migManager.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.migManager.resources }} + resources: {{ toYaml .Values.migManager.resources | nindent 6 }} + {{- end }} + {{- if .Values.migManager.env }} + env: {{ toYaml .Values.migManager.env | nindent 6 }} + {{- end }} + {{- if .Values.migManager.args }} + args: {{ toYaml .Values.migManager.args | nindent 6 }} + {{- end }} + {{- if .Values.migManager.config }} + config: + name: {{ .Values.migManager.config.name }} + default: {{ .Values.migManager.config.default }} + {{- end }} + {{- if .Values.migManager.gpuClientsConfig }} + gpuClientsConfig: {{ toYaml .Values.migManager.gpuClientsConfig | nindent 6 }} + {{- end }} + nodeStatusExporter: + enabled: {{ .Values.nodeStatusExporter.enabled }} + {{- if .Values.nodeStatusExporter.repository }} + repository: {{ .Values.nodeStatusExporter.repository }} + {{- end }} + {{- if .Values.nodeStatusExporter.image }} + image: {{ .Values.nodeStatusExporter.image }} + {{- end }} + version: {{ .Values.nodeStatusExporter.version | default .Chart.AppVersion | quote }} + {{- if .Values.nodeStatusExporter.imagePullPolicy }} + imagePullPolicy: {{ .Values.nodeStatusExporter.imagePullPolicy }} + {{- end }} + {{- if .Values.nodeStatusExporter.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.nodeStatusExporter.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.nodeStatusExporter.resources }} + resources: {{ toYaml .Values.nodeStatusExporter.resources | nindent 6 }} + {{- end }} + {{- if .Values.nodeStatusExporter.env }} + env: {{ toYaml .Values.nodeStatusExporter.env | nindent 6 }} + {{- end }} + {{- if .Values.nodeStatusExporter.args }} + args: {{ toYaml .Values.nodeStatusExporter.args | nindent 6 }} + {{- end }} + {{- if .Values.gds.enabled }} + gds: + enabled: {{ .Values.gds.enabled }} + {{- if .Values.gds.repository }} + repository: {{ .Values.gds.repository }} + {{- end }} + {{- if .Values.gds.image }} + image: {{ .Values.gds.image }} + {{- end }} + version: {{ .Values.gds.version | quote }} + {{- if .Values.gds.imagePullPolicy }} + imagePullPolicy: {{ .Values.gds.imagePullPolicy }} + {{- end }} + {{- if .Values.gds.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.gds.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.gds.env }} + env: {{ toYaml .Values.gds.env | nindent 6 }} + {{- end }} + {{- if .Values.gds.args }} + args: {{ toYaml .Values.gds.args | nindent 6 }} + {{- end }} + {{- end }} + {{- if .Values.gdrcopy }} + gdrcopy: + enabled: {{ .Values.gdrcopy.enabled | default false }} + {{- if .Values.gdrcopy.repository }} + repository: {{ .Values.gdrcopy.repository }} + {{- end }} + {{- if .Values.gdrcopy.image }} + image: {{ .Values.gdrcopy.image }} + {{- end }} + version: {{ .Values.gdrcopy.version | quote }} + {{- if .Values.gdrcopy.imagePullPolicy }} + imagePullPolicy: {{ .Values.gdrcopy.imagePullPolicy }} + {{- end }} + {{- if .Values.gdrcopy.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.gdrcopy.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.gdrcopy.env }} + env: {{ toYaml .Values.gdrcopy.env | nindent 6 }} + {{- end }} + {{- if .Values.gdrcopy.args }} + args: {{ toYaml .Values.gdrcopy.args | nindent 6 }} + {{- end }} + {{- end }} + sandboxWorkloads: + enabled: {{ .Values.sandboxWorkloads.enabled }} + {{- if .Values.sandboxWorkloads.defaultWorkload }} + defaultWorkload: {{ .Values.sandboxWorkloads.defaultWorkload }} + {{- end }} + sandboxDevicePlugin: + {{- if .Values.sandboxDevicePlugin.enabled }} + enabled: {{ .Values.sandboxDevicePlugin.enabled }} + {{- end }} + {{- if .Values.sandboxDevicePlugin.repository }} + repository: {{ .Values.sandboxDevicePlugin.repository }} + {{- end }} + {{- if .Values.sandboxDevicePlugin.image }} + image: {{ .Values.sandboxDevicePlugin.image }} + {{- end }} + {{- if .Values.sandboxDevicePlugin.version }} + version: {{ .Values.sandboxDevicePlugin.version | quote }} + {{- end }} + {{- if .Values.sandboxDevicePlugin.imagePullPolicy }} + imagePullPolicy: {{ .Values.sandboxDevicePlugin.imagePullPolicy }} + {{- end }} + {{- if .Values.sandboxDevicePlugin.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.sandboxDevicePlugin.imagePullSecrets | nindent 6 }} + {{- end }} + {{- if .Values.sandboxDevicePlugin.resources }} + resources: {{ toYaml .Values.sandboxDevicePlugin.resources | nindent 6 }} + {{- end }} + {{- if .Values.sandboxDevicePlugin.env }} + env: {{ toYaml .Values.sandboxDevicePlugin.env | nindent 6 }} + {{- end }} + {{- if .Values.sandboxDevicePlugin.args }} + args: {{ toYaml .Values.sandboxDevicePlugin.args | nindent 6 }} + {{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterrole.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterrole.yaml new file mode 100644 index 000000000..4acbcf29c --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterrole.yaml @@ -0,0 +1,146 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: gpu-operator + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" +rules: +- apiGroups: + - config.openshift.io + resources: + - clusterversions + - proxies + verbs: + - get + - list + - watch +- apiGroups: + - image.openshift.io + resources: + - imagestreams + verbs: + - get + - list + - watch +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - create + - get + - list + - watch + - update + - patch + - delete + - use +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - update + - patch +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - create + - watch + - update + - patch +- apiGroups: + - "" + resources: + - events + - pods + - pods/eviction + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - apps + resources: + - daemonsets + verbs: + - get + - list + - watch +- apiGroups: + - nvidia.com + resources: + - clusterpolicies + - clusterpolicies/finalizers + - clusterpolicies/status + - nvidiadrivers + - nvidiadrivers/finalizers + - nvidiadrivers/status + verbs: + - create + - get + - list + - watch + - update + - patch + - delete + - deletecollection +- apiGroups: + - scheduling.k8s.io + resources: + - priorityclasses + verbs: + - get + - list + - watch + - create +- apiGroups: + - node.k8s.io + resources: + - runtimeclasses + verbs: + - get + - list + - create + - update + - watch + - delete +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch + - update + - patch + - create +{{- if .Values.operator.cleanupCRD }} + - delete +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterrolebinding.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..08b87fbce --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/clusterrolebinding.yaml @@ -0,0 +1,18 @@ +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: gpu-operator + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" +subjects: +- kind: ServiceAccount + name: gpu-operator + namespace: {{ $.Release.Namespace }} +- kind: ServiceAccount + name: node-feature-discovery + namespace: {{ $.Release.Namespace }} +roleRef: + kind: ClusterRole + name: gpu-operator + apiGroup: rbac.authorization.k8s.io diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/dcgm_exporter_config.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/dcgm_exporter_config.yaml new file mode 100644 index 000000000..c4bf6dcc8 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/dcgm_exporter_config.yaml @@ -0,0 +1,14 @@ +{{- if .Values.dcgmExporter.config }} +{{- if and (.Values.dcgmExporter.config.create) (not (empty .Values.dcgmExporter.config.data)) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.dcgmExporter.config.name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} +data: + dcgm-metrics.csv: | +{{- .Values.dcgmExporter.config.data | nindent 4 }} +{{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/mig_config.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/mig_config.yaml new file mode 100644 index 000000000..2ceb04779 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/mig_config.yaml @@ -0,0 +1,10 @@ +{{- if and (.Values.migManager.config.create) (not (empty .Values.migManager.config.data)) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.migManager.config.name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} +data: {{ toYaml .Values.migManager.config.data | nindent 2 }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/nodefeaturerules.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/nodefeaturerules.yaml new file mode 100644 index 000000000..6076b3d31 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/nodefeaturerules.yaml @@ -0,0 +1,107 @@ +{{- if .Values.nfd.nodefeaturerules }} +apiVersion: nfd.k8s-sigs.io/v1alpha1 +kind: NodeFeatureRule +metadata: + name: nvidia-nfd-nodefeaturerules +spec: + rules: + - name: "TDX rule" + labels: + tdx.enabled: "true" + matchFeatures: + - feature: cpu.security + matchExpressions: + tdx.enabled: {op: IsTrue} + - name: "TDX total keys rule" + extendedResources: + tdx.total_keys: "@cpu.security.tdx.total_keys" + matchFeatures: + - feature: cpu.security + matchExpressions: + tdx.enabled: {op: IsTrue} + - name: "SEV-SNP rule" + labels: + sev.snp.enabled: "true" + matchFeatures: + - feature: cpu.security + matchExpressions: + sev.snp.enabled: + op: IsTrue + - name: "SEV-ES rule" + labels: + sev.es.enabled: "true" + matchFeatures: + - feature: cpu.security + matchExpressions: + sev.es.enabled: + op: IsTrue + - name: SEV system capacities + extendedResources: + sev_asids: '@cpu.security.sev.asids' + sev_es: '@cpu.security.sev.encrypted_state_ids' + matchFeatures: + - feature: cpu.security + matchExpressions: + sev.enabled: + op: Exists + - name: "NVIDIA H100" + labels: + "nvidia.com/gpu.H100": "true" + "nvidia.com/gpu.family": "hopper" + matchFeatures: + - feature: pci.device + matchExpressions: + vendor: {op: In, value: ["10de"]} + device: {op: In, value: ["2339"]} + - name: "NVIDIA H100 PCIe" + labels: + "nvidia.com/gpu.H100.pcie": "true" + "nvidia.com/gpu.family": "hopper" + matchFeatures: + - feature: pci.device + matchExpressions: + vendor: {op: In, value: ["10de"]} + device: {op: In, value: ["2331"]} + - name: "NVIDIA H100 80GB HBM3" + labels: + "nvidia.com/gpu.H100.HBM3": "true" + "nvidia.com/gpu.family": "hopper" + matchFeatures: + - feature: pci.device + matchExpressions: + vendor: {op: In, value: ["10de"]} + device: {op: In, value: ["2330"]} + - name: "NVIDIA H800" + labels: + "nvidia.com/gpu.H800": "true" + "nvidia.com/gpu.family": "hopper" + matchFeatures: + - feature: pci.device + matchExpressions: + vendor: {op: In, value: ["10de"]} + device: {op: In, value: ["2324"]} + - name: "NVIDIA H800 PCIE" + labels: + "nvidia.com/gpu.H800.pcie": "true" + "nvidia.com/gpu.family": "hopper" + matchFeatures: + - feature: pci.device + matchExpressions: + vendor: {op: In, value: ["10de"]} + device: {op: In, value: ["2322"]} + - name: "NVIDIA CC Enabled" + labels: + "nvidia.com/cc.capable": "true" + matchAny: # TDX/SEV + Hopper GPU + - matchFeatures: + - feature: rule.matched + matchExpressions: + nvidia.com/gpu.family: {op: In, value: ["hopper"]} + sev.snp.enabled: {op: IsTrue} + - matchFeatures: + - feature: rule.matched + matchExpressions: + nvidia.com/gpu.family: {op: In, value: ["hopper"]} + tdx.enabled: {op: IsTrue} +{{- end }} + diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/nvidiadriver.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/nvidiadriver.yaml new file mode 100644 index 000000000..31660c025 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/nvidiadriver.yaml @@ -0,0 +1,119 @@ +{{- if and .Values.driver.nvidiaDriverCRD.enabled .Values.driver.nvidiaDriverCRD.deployDefaultCR }} +apiVersion: nvidia.com/v1alpha1 +kind: NVIDIADriver +metadata: + name: default +spec: + repository: {{ .Values.driver.repository }} + image: {{ .Values.driver.image }} + version: {{ .Values.driver.version }} + useOpenKernelModules: {{ .Values.driver.useOpenKernelModules }} + usePrecompiled: {{ .Values.driver.usePrecompiled }} + driverType: {{ .Values.driver.nvidiaDriverCRD.driverType | default "gpu" }} + {{- if .Values.daemonsets.annotations }} + annotations: {{ toYaml .Values.daemonsets.annotations | nindent 6 }} + {{- end }} + {{- if .Values.daemonsets.labels }} + labels: {{ toYaml .Values.daemonsets.labels | nindent 6 }} + {{- end }} + {{- if .Values.driver.nvidiaDriverCRD.nodeSelector }} + nodeSelector: {{ toYaml .Values.driver.nvidiaDriverCRD.nodeSelector | nindent 6 }} + {{- end }} + {{- if .Values.driver.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.driver.imagePullSecrets | nindent 4 }} + {{- end }} + {{- if .Values.driver.manager }} + manager: {{ toYaml .Values.driver.manager | nindent 4 }} + {{- end }} + {{- if .Values.driver.startupProbe }} + startupProbe: {{ toYaml .Values.driver.startupProbe | nindent 4 }} + {{- end }} + {{- if .Values.driver.livenessProbe }} + livenessProbe: {{ toYaml .Values.driver.livenessProbe | nindent 4 }} + {{- end }} + {{- if .Values.driver.readinessProbe }} + readinessProbe: {{ toYaml .Values.driver.readinessProbe | nindent 4 }} + {{- end }} + rdma: + enabled: {{ .Values.driver.rdma.enabled }} + useHostMofed: {{ .Values.driver.rdma.useHostMofed }} + {{- if .Values.daemonsets.tolerations }} + tolerations: {{ toYaml .Values.daemonsets.tolerations | nindent 6 }} + {{- end }} + {{- if .Values.driver.repoConfig.configMapName }} + repoConfig: + name: {{ .Values.driver.repoConfig.configMapName }} + {{- end }} + {{- if .Values.driver.certConfig.name }} + certConfig: + name: {{ .Values.driver.certConfig.name }} + {{- end }} + {{- if .Values.driver.licensingConfig.configMapName }} + licensingConfig: + name: {{ .Values.driver.licensingConfig.configMapName }} + nlsEnabled: {{ .Values.driver.licensingConfig.nlsEnabled | default true }} + {{- end }} + {{- if .Values.driver.virtualTopology.config }} + virtualTopologyConfig: + name: {{ .Values.driver.virtualTopology.config }} + {{- end }} + {{- if .Values.driver.kernelModuleConfig.name }} + kernelModuleConfig: + name: {{ .Values.driver.kernelModuleConfig.name }} + {{- end }} + {{- if .Values.driver.resources }} + resources: {{ toYaml .Values.driver.resources | nindent 6 }} + {{- end }} + {{- if .Values.driver.env }} + env: {{ toYaml .Values.driver.env | nindent 6 }} + {{- end }} + {{- if .Values.driver.args }} + args: {{ toYaml .Values.driver.args | nindent 6 }} + {{- end }} + {{- if .Values.gds.enabled }} + gds: + enabled: {{ .Values.gds.enabled }} + {{- if .Values.gds.repository }} + repository: {{ .Values.gds.repository }} + {{- end }} + {{- if .Values.gds.image }} + image: {{ .Values.gds.image }} + {{- end }} + version: {{ .Values.gds.version | quote }} + {{- if .Values.gds.imagePullPolicy }} + imagePullPolicy: {{ .Values.gds.imagePullPolicy }} + {{- end }} + {{- if .Values.gds.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.gds.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.gds.env }} + env: {{ toYaml .Values.gds.env | nindent 6 }} + {{- end }} + {{- if .Values.gds.args }} + args: {{ toYaml .Values.gds.args | nindent 6 }} + {{- end }} + {{- end }} + {{- if .Values.gdrcopy }} + gdrcopy: + enabled: {{ .Values.gdrcopy.enabled | default false }} + {{- if .Values.gdrcopy.repository }} + repository: {{ .Values.gdrcopy.repository }} + {{- end }} + {{- if .Values.gdrcopy.image }} + image: {{ .Values.gdrcopy.image }} + {{- end }} + version: {{ .Values.gdrcopy.version | quote }} + {{- if .Values.gdrcopy.imagePullPolicy }} + imagePullPolicy: {{ .Values.gdrcopy.imagePullPolicy }} + {{- end }} + {{- if .Values.gdrcopy.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.gdrcopy.imagePullSecrets | nindent 8 }} + {{- end }} + {{- if .Values.gdrcopy.env }} + env: {{ toYaml .Values.gdrcopy.env | nindent 6 }} + {{- end }} + {{- if .Values.gdrcopy.args }} + args: {{ toYaml .Values.gdrcopy.args | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/operator.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/operator.yaml new file mode 100644 index 000000000..6f4848263 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/operator.yaml @@ -0,0 +1,99 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gpu-operator + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" + nvidia.com/gpu-driver-upgrade-drain.skip: "true" +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: "gpu-operator" + app: "gpu-operator" + template: + metadata: + labels: + {{- include "gpu-operator.labels" . | nindent 8 }} + app.kubernetes.io/component: "gpu-operator" + app: "gpu-operator" + nvidia.com/gpu-driver-upgrade-drain.skip: "true" + annotations: + {{- toYaml .Values.operator.annotations | nindent 8 }} + spec: + serviceAccountName: gpu-operator + {{- if .Values.operator.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.operator.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + {{- if .Values.operator.priorityClassName }} + priorityClassName: {{ .Values.operator.priorityClassName }} + {{- end }} + containers: + - name: gpu-operator + image: {{ include "gpu-operator.fullimage" . }} + imagePullPolicy: {{ .Values.operator.imagePullPolicy }} + command: ["gpu-operator"] + args: + - --leader-elect + {{- if .Values.operator.logging.develMode }} + - --zap-devel + {{- else }} + {{- if .Values.operator.logging.timeEncoding }} + - --zap-time-encoding={{- .Values.operator.logging.timeEncoding }} + {{- end }} + {{- if .Values.operator.logging.level }} + - --zap-log-level={{- .Values.operator.logging.level }} + {{- end }} + {{- end }} + env: + - name: WATCH_NAMESPACE + value: "" + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: "DRIVER_MANAGER_IMAGE" + value: "{{ include "driver-manager.fullimage" . }}" + volumeMounts: + - name: host-os-release + mountPath: "/host-etc/os-release" + readOnly: true + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + {{- with .Values.operator.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + ports: + - name: metrics + containerPort: 8080 + volumes: + - name: host-os-release + hostPath: + path: "/etc/os-release" + {{- with .Values.operator.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.operator.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.operator.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/plugin_config.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/plugin_config.yaml new file mode 100644 index 000000000..21c2d9ab2 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/plugin_config.yaml @@ -0,0 +1,11 @@ +{{- if and (.Values.devicePlugin.config.create) (not (empty .Values.devicePlugin.config.data)) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.devicePlugin.config.name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} +data: {{ toYaml .Values.devicePlugin.config.data | nindent 2 }} +{{- end }} + \ No newline at end of file diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/readonlyfs_scc.openshift.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/readonlyfs_scc.openshift.yaml new file mode 100644 index 000000000..ff492d3d2 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/readonlyfs_scc.openshift.yaml @@ -0,0 +1,49 @@ +{{- if .Values.platform.openshift }} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" + annotations: + kubernetes.io/description: restricted denies access to all host features and requires + pods to be run with a UID, read-only root filesystem and SELinux context that are + allocated to the namespace. This SCC is more restrictive than the default + restrictive SCC and it is used by default for authenticated users and operators and operands. + name: restricted-readonly +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: true +allowPrivilegedContainer: false +allowedCapabilities: [] +defaultAddCapabilities: [] +fsGroup: + type: MustRunAs +groups: +- system:authenticated +priority: 0 +readOnlyRootFilesystem: true +requiredDropCapabilities: +- KILL +- MKNOD +- SETUID +- SETGID +runAsUser: + type: MustRunAsRange +seLinuxContext: + type: MustRunAs +supplementalGroups: + type: RunAsAny +users: +- system:serviceaccount:{{ $.Release.Namespace }}:gpu-operator +volumes: +- configMap +- downwardAPI +- emptyDir +- persistentVolumeClaim +- projected +- secret +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/role.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/role.yaml new file mode 100644 index 000000000..9e5bcede3 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/role.yaml @@ -0,0 +1,84 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: gpu-operator + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" +rules: +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + - rolebindings + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - apps + resources: + - controllerrevisions + verbs: + - get + - list + - watch +- apiGroups: + - apps + resources: + - daemonsets + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps + - endpoints + - pods + - pods/eviction + - secrets + - services + - services/finalizers + - serviceaccounts + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + - prometheusrules + verbs: + - get + - list + - create + - watch + - update + - delete diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/rolebinding.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/rolebinding.yaml new file mode 100644 index 000000000..c915a4659 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/rolebinding.yaml @@ -0,0 +1,15 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: gpu-operator + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" +subjects: +- kind: ServiceAccount + name: gpu-operator + namespace: {{ $.Release.Namespace }} +roleRef: + kind: Role + name: gpu-operator + apiGroup: rbac.authorization.k8s.io diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/serviceaccount.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/serviceaccount.yaml new file mode 100644 index 000000000..50555e53b --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: gpu-operator + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/upgrade_crd.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/upgrade_crd.yaml new file mode 100644 index 000000000..6552558af --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/templates/upgrade_crd.yaml @@ -0,0 +1,95 @@ +{{- if .Values.operator.upgradeCRD }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: gpu-operator-upgrade-crd-hook-sa + annotations: + helm.sh/hook: pre-upgrade + helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation + helm.sh/hook-weight: "0" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: gpu-operator-upgrade-crd-hook-role + annotations: + helm.sh/hook: pre-upgrade + helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation + helm.sh/hook-weight: "0" +rules: + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - create + - get + - list + - watch + - patch + - update +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: gpu-operator-upgrade-crd-hook-binding + annotations: + helm.sh/hook: pre-upgrade + helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation + helm.sh/hook-weight: "0" +subjects: + - kind: ServiceAccount + name: gpu-operator-upgrade-crd-hook-sa + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: gpu-operator-upgrade-crd-hook-role + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: gpu-operator-upgrade-crd + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-upgrade + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation + labels: + {{- include "gpu-operator.labels" . | nindent 4 }} + app.kubernetes.io/component: "gpu-operator" +spec: + template: + metadata: + name: gpu-operator-upgrade-crd + labels: + {{- include "gpu-operator.labels" . | nindent 8 }} + app.kubernetes.io/component: "gpu-operator" + spec: + serviceAccountName: gpu-operator-upgrade-crd-hook-sa + {{- if .Values.operator.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.operator.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + {{- with .Values.operator.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: upgrade-crd + image: {{ include "gpu-operator.fullimage" . }} + imagePullPolicy: {{ .Values.operator.imagePullPolicy }} + command: + - /bin/sh + - -c + - > + kubectl apply -f /opt/gpu-operator/nvidia.com_clusterpolicies.yaml; + kubectl apply -f /opt/gpu-operator/nvidia.com_nvidiadrivers.yaml; + {{- if .Values.nfd.enabled }} + kubectl apply -f /opt/gpu-operator/nfd-api-crds.yaml; + {{- end }} + restartPolicy: OnFailure +{{- end }} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/values.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/values.yaml new file mode 100644 index 000000000..cfddca21b --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/gpu-operator/values.yaml @@ -0,0 +1,602 @@ +# Default values for gpu-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +platform: + openshift: false + +nfd: + enabled: true + nodefeaturerules: false + +psa: + enabled: false + +cdi: + enabled: false + default: false + +sandboxWorkloads: + enabled: false + defaultWorkload: "container" + +hostPaths: + # rootFS represents the path to the root filesystem of the host. + # This is used by components that need to interact with the host filesystem + # and as such this must be a chroot-able filesystem. + # Examples include the MIG Manager and Toolkit Container which may need to + # stop, start, or restart systemd services + rootFS: "/" + + # driverInstallDir represents the root at which driver files including libraries, + # config files, and executables can be found. + driverInstallDir: "/run/nvidia/driver" + +daemonsets: + labels: {} + annotations: {} + priorityClassName: system-node-critical + tolerations: + - key: nvidia.com/gpu + operator: Exists + effect: NoSchedule + # configuration for controlling update strategy("OnDelete" or "RollingUpdate") of GPU Operands + # note that driver Daemonset is always set with OnDelete to avoid unintended disruptions + updateStrategy: "RollingUpdate" + # configuration for controlling rolling update of GPU Operands + rollingUpdate: + # maximum number of nodes to simultaneously apply pod updates on. + # can be specified either as number or percentage of nodes. Default 1. + maxUnavailable: "1" + +validator: + repository: nvcr.io/nvidia/cloud-native + image: gpu-operator-validator + # If version is not specified, then default is to use chart.AppVersion + #version: "" + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: [] + args: [] + resources: {} + plugin: + env: + - name: WITH_WORKLOAD + value: "false" + +operator: + repository: nvcr.io/nvidia + image: gpu-operator + # If version is not specified, then default is to use chart.AppVersion + #version: "" + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + priorityClassName: system-node-critical + defaultRuntime: docker + runtimeClass: nvidia + use_ocp_driver_toolkit: false + # cleanup CRD on chart un-install + cleanupCRD: false + # upgrade CRD on chart upgrade, requires --disable-openapi-validation flag + # to be passed during helm upgrade. + upgradeCRD: true + initContainer: + image: cuda + repository: nvcr.io/nvidia + version: 12.6.3-base-ubi9 + imagePullPolicy: IfNotPresent + tolerations: + - key: "node-role.kubernetes.io/master" + operator: "Equal" + value: "" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/control-plane" + operator: "Equal" + value: "" + effect: "NoSchedule" + annotations: + openshift.io/scc: restricted-readonly + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: "node-role.kubernetes.io/master" + operator: In + values: [""] + - weight: 1 + preference: + matchExpressions: + - key: "node-role.kubernetes.io/control-plane" + operator: In + values: [""] + logging: + # Zap time encoding (one of 'epoch', 'millis', 'nano', 'iso8601', 'rfc3339' or 'rfc3339nano') + timeEncoding: epoch + # Zap Level to configure the verbosity of logging. Can be one of 'debug', 'info', 'error', or any integer value > 0 which corresponds to custom debug levels of increasing verbosity + level: info + # Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn) + # Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) + develMode: false + resources: + limits: + cpu: 500m + memory: 350Mi + requests: + cpu: 200m + memory: 100Mi + +mig: + strategy: single + +driver: + enabled: true + nvidiaDriverCRD: + enabled: false + deployDefaultCR: true + driverType: gpu + nodeSelector: {} + useOpenKernelModules: false + # use pre-compiled packages for NVIDIA driver installation. + # only supported for as a tech-preview feature on ubuntu22.04 kernels. + usePrecompiled: false + repository: nvcr.io/nvidia + image: driver + version: "550.144.03" + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + startupProbe: + initialDelaySeconds: 60 + periodSeconds: 10 + # nvidia-smi can take longer than 30s in some cases + # ensure enough timeout is set + timeoutSeconds: 60 + failureThreshold: 120 + rdma: + enabled: false + useHostMofed: false + upgradePolicy: + # global switch for automatic upgrade feature + # if set to false all other options are ignored + autoUpgrade: true + # how many nodes can be upgraded in parallel + # 0 means no limit, all nodes will be upgraded in parallel + maxParallelUpgrades: 1 + # maximum number of nodes with the driver installed, that can be unavailable during + # the upgrade. Value can be an absolute number (ex: 5) or + # a percentage of total nodes at the start of upgrade (ex: + # 10%). Absolute number is calculated from percentage by rounding + # up. By default, a fixed value of 25% is used.' + maxUnavailable: 25% + # options for waiting on pod(job) completions + waitForCompletion: + timeoutSeconds: 0 + podSelector: "" + # options for gpu pod deletion + gpuPodDeletion: + force: false + timeoutSeconds: 300 + deleteEmptyDir: false + # options for node drain (`kubectl drain`) before the driver reload + # this is required only if default GPU pod deletions done by the operator + # are not sufficient to re-install the driver + drain: + enable: false + force: false + podSelector: "" + # It's recommended to set a timeout to avoid infinite drain in case non-fatal error keeps happening on retries + timeoutSeconds: 300 + deleteEmptyDir: false + manager: + image: k8s-driver-manager + repository: nvcr.io/nvidia/cloud-native + # When choosing a different version of k8s-driver-manager, DO NOT downgrade to a version lower than v0.6.4 + # to ensure k8s-driver-manager stays compatible with gpu-operator starting from v24.3.0 + version: v0.7.0 + imagePullPolicy: IfNotPresent + env: + - name: ENABLE_GPU_POD_EVICTION + value: "true" + - name: ENABLE_AUTO_DRAIN + value: "false" + - name: DRAIN_USE_FORCE + value: "false" + - name: DRAIN_POD_SELECTOR_LABEL + value: "" + - name: DRAIN_TIMEOUT_SECONDS + value: "0s" + - name: DRAIN_DELETE_EMPTYDIR_DATA + value: "false" + env: [] + resources: {} + # Private mirror repository configuration + repoConfig: + configMapName: "" + # custom ssl key/certificate configuration + certConfig: + name: "" + # vGPU licensing configuration + licensingConfig: + configMapName: "" + nlsEnabled: true + # vGPU topology daemon configuration + virtualTopology: + config: "" + # kernel module configuration for NVIDIA driver + kernelModuleConfig: + name: "" + +toolkit: + enabled: true + repository: nvcr.io/nvidia/k8s + image: container-toolkit + version: v1.17.4-ubuntu20.04 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: [] + resources: {} + installDir: "/usr/local/nvidia" + +devicePlugin: + enabled: true + repository: nvcr.io/nvidia + image: k8s-device-plugin + version: v0.17.0 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + args: [] + env: + - name: PASS_DEVICE_SPECS + value: "true" + - name: FAIL_ON_INIT_ERROR + value: "true" + - name: DEVICE_LIST_STRATEGY + value: envvar + - name: DEVICE_ID_STRATEGY + value: uuid + - name: NVIDIA_VISIBLE_DEVICES + value: all + - name: NVIDIA_DRIVER_CAPABILITIES + value: all + resources: {} + # Plugin configuration + # Use "name" to either point to an existing ConfigMap or to create a new one with a list of configurations(i.e with create=true). + # Use "data" to build an integrated ConfigMap from a set of configurations as + # part of this helm chart. An example of setting "data" might be: + # config: + # name: device-plugin-config + # create: true + # data: + # default: |- + # version: v1 + # flags: + # migStrategy: none + # mig-single: |- + # version: v1 + # flags: + # migStrategy: single + # mig-mixed: |- + # version: v1 + # flags: + # migStrategy: mixed + config: + # Create a ConfigMap (default: false) + create: false + # ConfigMap name (either existing or to create a new one with create=true above) + name: "" + # Default config name within the ConfigMap + default: "" + # Data section for the ConfigMap to create (i.e only applies when create=true) + data: {} + # MPS related configuration for the plugin + mps: + # MPS root path on the host + root: "/run/nvidia/mps" + +# standalone dcgm hostengine +dcgm: + # disabled by default to use embedded nv-hostengine by exporter + enabled: false + repository: nvcr.io/nvidia/cloud-native + image: dcgm + version: 3.3.9-1-ubuntu22.04 + imagePullPolicy: IfNotPresent + args: [] + env: [] + resources: {} + +dcgmExporter: + enabled: true + repository: nvcr.io/nvidia/k8s + image: dcgm-exporter + version: 3.3.9-3.6.1-ubuntu22.04 + imagePullPolicy: IfNotPresent + env: + - name: DCGM_EXPORTER_LISTEN + value: ":9400" + - name: DCGM_EXPORTER_KUBERNETES + value: "true" + - name: DCGM_EXPORTER_COLLECTORS + value: "/etc/dcgm-exporter/dcp-metrics-included.csv" + resources: {} + serviceMonitor: + enabled: false + interval: 15s + honorLabels: false + additionalLabels: {} + relabelings: [] + # - source_labels: + # - __meta_kubernetes_pod_node_name + # regex: (.*) + # target_label: instance + # replacement: $1 + # action: replace + # DCGM Exporter configuration + # This block is used to configure DCGM Exporter to emit a customized list of metrics. + # Use "name" to either point to an existing ConfigMap or to create a new one with a + # list of configurations (i.e with create=true). + # When pointing to an existing ConfigMap, the ConfigMap must exist in the same namespace as the release. + # The metrics are expected to be listed under a key called `dcgm-metrics.csv`. + # Use "data" to build an integrated ConfigMap from a set of custom metrics as + # part of the chart. An example of some custom metrics are shown below. Note that + # the contents of "data" must be in CSV format and be valid DCGM Exporter metric configurations. + # config: + # name: custom-dcgm-exporter-metrics + # create: true + # data: |- + # Format + # If line starts with a '#' it is considered a comment + # DCGM FIELD, Prometheus metric type, help message + + # Clocks + # DCGM_FI_DEV_SM_CLOCK, gauge, SM clock frequency (in MHz). + # DCGM_FI_DEV_MEM_CLOCK, gauge, Memory clock frequency (in MHz). +gfd: + enabled: true + repository: nvcr.io/nvidia + image: k8s-device-plugin + version: v0.17.0 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: + - name: GFD_SLEEP_INTERVAL + value: 60s + - name: GFD_FAIL_ON_INIT_ERROR + value: "true" + resources: {} + +migManager: + enabled: true + repository: nvcr.io/nvidia/cloud-native + image: k8s-mig-manager + version: v0.10.0-ubuntu20.04 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: + - name: WITH_REBOOT + value: "false" + resources: {} + # MIG configuration + # Use "name" to either point to an existing ConfigMap or to create a new one with a list of configurations(i.e with create=true). + # Use "data" to build an integrated ConfigMap from a set of configurations as + # part of this helm chart. An example of setting "data" might be: + # config: + # name: custom-mig-parted-configs + # create: true + # data: |- + # config.yaml: |- + # version: v1 + # mig-configs: + # all-disabled: + # - devices: all + # mig-enabled: false + # custom-mig: + # - devices: [0] + # mig-enabled: false + # - devices: [1] + # mig-enabled: true + # mig-devices: + # "1g.10gb": 7 + # - devices: [2] + # mig-enabled: true + # mig-devices: + # "2g.20gb": 2 + # "3g.40gb": 1 + # - devices: [3] + # mig-enabled: true + # mig-devices: + # "3g.40gb": 1 + # "4g.40gb": 1 + config: + default: "all-disabled" + # Create a ConfigMap (default: false) + create: false + # ConfigMap name (either existing or to create a new one with create=true above) + name: "" + # Data section for the ConfigMap to create (i.e only applies when create=true) + data: {} + gpuClientsConfig: + name: "" + +nodeStatusExporter: + enabled: false + repository: nvcr.io/nvidia/cloud-native + image: gpu-operator-validator + # If version is not specified, then default is to use chart.AppVersion + #version: "" + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + resources: {} + +gds: + enabled: false + repository: nvcr.io/nvidia/cloud-native + image: nvidia-fs + version: "2.20.5" + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: [] + args: [] + +gdrcopy: + enabled: false + repository: nvcr.io/nvidia/cloud-native + image: gdrdrv + version: "v2.4.1-2" + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: [] + args: [] + +vgpuManager: + enabled: false + repository: "" + image: vgpu-manager + version: "" + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: [] + resources: {} + driverManager: + image: k8s-driver-manager + repository: nvcr.io/nvidia/cloud-native + # When choosing a different version of k8s-driver-manager, DO NOT downgrade to a version lower than v0.6.4 + # to ensure k8s-driver-manager stays compatible with gpu-operator starting from v24.3.0 + version: v0.7.0 + imagePullPolicy: IfNotPresent + env: + - name: ENABLE_GPU_POD_EVICTION + value: "false" + - name: ENABLE_AUTO_DRAIN + value: "false" + +vgpuDeviceManager: + enabled: true + repository: nvcr.io/nvidia/cloud-native + image: vgpu-device-manager + version: v0.2.8 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: [] + config: + name: "" + default: "default" + +vfioManager: + enabled: true + repository: nvcr.io/nvidia + image: cuda + version: 12.6.3-base-ubi9 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: [] + resources: {} + driverManager: + image: k8s-driver-manager + repository: nvcr.io/nvidia/cloud-native + # When choosing a different version of k8s-driver-manager, DO NOT downgrade to a version lower than v0.6.4 + # to ensure k8s-driver-manager stays compatible with gpu-operator starting from v24.3.0 + version: v0.7.0 + imagePullPolicy: IfNotPresent + env: + - name: ENABLE_GPU_POD_EVICTION + value: "false" + - name: ENABLE_AUTO_DRAIN + value: "false" + +kataManager: + enabled: false + config: + artifactsDir: "/opt/nvidia-gpu-operator/artifacts/runtimeclasses" + runtimeClasses: + - name: kata-nvidia-gpu + nodeSelector: {} + artifacts: + url: nvcr.io/nvidia/cloud-native/kata-gpu-artifacts:ubuntu22.04-535.54.03 + pullSecret: "" + - name: kata-nvidia-gpu-snp + nodeSelector: + "nvidia.com/cc.capable": "true" + artifacts: + url: nvcr.io/nvidia/cloud-native/kata-gpu-artifacts:ubuntu22.04-535.86.10-snp + pullSecret: "" + repository: nvcr.io/nvidia/cloud-native + image: k8s-kata-manager + version: v0.2.2 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: [] + resources: {} + +sandboxDevicePlugin: + enabled: true + repository: nvcr.io/nvidia + image: kubevirt-gpu-device-plugin + version: v1.2.10 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + args: [] + env: [] + resources: {} + +ccManager: + enabled: false + defaultMode: "off" + repository: nvcr.io/nvidia/cloud-native + image: k8s-cc-manager + version: v0.1.1 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + env: + - name: CC_CAPABLE_DEVICE_IDS + value: "0x2339,0x2331,0x2330,0x2324,0x2322,0x233d" + resources: {} + +node-feature-discovery: + enableNodeFeatureApi: true + priorityClassName: system-node-critical + gc: + enable: true + replicaCount: 1 + serviceAccount: + name: node-feature-discovery + create: false + worker: + serviceAccount: + name: node-feature-discovery + # disable creation to avoid duplicate serviceaccount creation by master spec below + create: false + tolerations: + - key: "node-role.kubernetes.io/master" + operator: "Equal" + value: "" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/control-plane" + operator: "Equal" + value: "" + effect: "NoSchedule" + - key: nvidia.com/gpu + operator: Exists + effect: NoSchedule + config: + sources: + pci: + deviceClassWhitelist: + - "02" + - "0200" + - "0207" + - "0300" + - "0302" + deviceLabelFields: + - vendor + master: + serviceAccount: + name: node-feature-discovery + create: true + config: + extraLabelNs: ["nvidia.com"] + # noPublish: false + # resourceLabels: ["nvidia.com/feature-1","nvidia.com/feature-2"] + # enableTaints: false + # labelWhiteList: "nvidia.com/gpu" diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/.editorconfig b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/.editorconfig new file mode 100644 index 000000000..f5ee2f461 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[files/dashboards/*.json] +indent_size = 2 +indent_style = space \ No newline at end of file diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/.helmignore b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/.helmignore new file mode 100644 index 000000000..9bdbec92b --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/.helmignore @@ -0,0 +1,29 @@ +# 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 + +unittests/ +files/dashboards/ diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/CONTRIBUTING.md b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/CONTRIBUTING.md new file mode 100644 index 000000000..f6ce2a323 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/CONTRIBUTING.md @@ -0,0 +1,12 @@ +# 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/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/Chart.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/Chart.yaml new file mode 100644 index 000000000..33cd434a9 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/Chart.yaml @@ -0,0 +1,65 @@ +annotations: + artifacthub.io/license: Apache-2.0 + 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: v0.74.0 +dependencies: +- condition: crds.enabled + name: crds + repository: "" + version: 0.0.0 +- condition: kubeStateMetrics.enabled + name: kube-state-metrics + repository: https://prometheus-community.github.io/helm-charts + version: 5.20.* +- condition: nodeExporter.enabled + name: prometheus-node-exporter + repository: https://prometheus-community.github.io/helm-charts + version: 4.36.* +- condition: grafana.enabled + name: grafana + repository: https://grafana.github.io/helm-charts + version: 8.2.* +- condition: windowsMonitoring.enabled + name: prometheus-windows-exporter + repository: https://prometheus-community.github.io/helm-charts + version: 0.3.* +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.19.0-0' +maintainers: +- email: andrew@quadcorps.co.uk + name: andrewgkew +- email: gianrubio@gmail.com + name: gianrubio +- email: github.gkarthiks@gmail.com + name: gkarthiks +- email: kube-prometheus-stack@sisti.pt + name: GMartinez-Sisti +- email: github@jkroepke.de + name: jkroepke +- email: scott@r6by.com + name: scottrigby +- email: miroslav.hadzhiev@gmail.com + name: Xtigyro +- email: quentin.bisson@gmail.com + name: QuentinBisson +name: kube-prometheus-stack +sources: +- https://github.com/prometheus-community/helm-charts +- https://github.com/prometheus-operator/kube-prometheus +type: application +version: 60.5.0 diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/README.md b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/README.md new file mode 100644 index 000000000..cd5ae206c --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/README.md @@ -0,0 +1,1090 @@ +# 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.19+ +- Helm 3+ + +## Get Helm Repository 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 Helm Chart + +```console +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: + +- [prometheus-community/kube-state-metrics](https://github.com/prometheus-community/helm-charts/tree/main/charts/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 Helm Chart + +```console +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 prometheusagents.monitoring.coreos.com +kubectl delete crd prometheuses.monitoring.coreos.com +kubectl delete crd prometheusrules.monitoring.coreos.com +kubectl delete crd scrapeconfigs.monitoring.coreos.com +kubectl delete crd servicemonitors.monitoring.coreos.com +kubectl delete crd thanosrulers.monitoring.coreos.com +``` + +## Upgrading Chart + +```console +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 59.x to 60.x + +This version upgrades the Grafana chart to v8.0.x which introduces Grafana 11. This new major version of Grafana contains some breaking changes described in [Breaking changes in Grafana v11.0](https://grafana.com/docs/grafana/latest/breaking-changes/breaking-changes-v11-0/). + +### From 58.x to 59.x + +This version upgrades Prometheus-Operator to v0.74.0 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 57.x to 58.x + +This version upgrades Prometheus-Operator to v0.73.0 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.73.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 56.x to 57.x + +This version upgrades Prometheus-Operator to v0.72.0 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.72.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 55.x to 56.x + +This version upgrades Prometheus-Operator to v0.71.0, Prometheus to 2.49.1 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.71.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 54.x to 55.x + +This version upgrades Prometheus-Operator to v0.70.0 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.70.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 53.x to 54.x + +Grafana Helm Chart has bumped to version 7 + +Please note Grafana Helm Chart [changelog](https://github.com/grafana/helm-charts/tree/main/charts/grafana#to-700). + +### From 52.x to 53.x + +This version upgrades Prometheus-Operator to v0.69.1, Prometheus to 2.47.2 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.69.1/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 51.x to 52.x + +This includes the ability to select between using existing secrets or create new secret objects for various thanos config. The defaults have not changed but if you were setting: + +- `thanosRuler.thanosRulerSpec.alertmanagersConfig` or +- `thanosRuler.thanosRulerSpec.objectStorageConfig` or +- `thanosRuler.thanosRulerSpec.queryConfig` or +- `prometheus.prometheusSpec.thanos.objectStorageConfig` + +you will have to need to set `existingSecret` or `secret` based on your requirement + +For instance, the `thanosRuler.thanosRulerSpec.alertmanagersConfig` used to be configured as follow: + +```yaml +thanosRuler: + thanosRulerSpec: + alertmanagersConfig: + alertmanagers: + - api_version: v2 + http_config: + basic_auth: + username: some_user + password: some_pass + static_configs: + - alertmanager.thanos.io + scheme: http + timeout: 10s +``` + +But it now moved to: + +```yaml +thanosRuler: + thanosRulerSpec: + alertmanagersConfig: + secret: + alertmanagers: + - api_version: v2 + http_config: + basic_auth: + username: some_user + password: some_pass + static_configs: + - alertmanager.thanos.io + scheme: http + timeout: 10s +``` + +or the `thanosRuler.thanosRulerSpec.objectStorageConfig` used to be configured as follow: + +```yaml +thanosRuler: + thanosRulerSpec: + objectStorageConfig: + name: existing-secret-not-created-by-this-chart + key: object-storage-configs.yaml +``` + +But it now moved to: + +```yaml +thanosRuler: + thanosRulerSpec: + objectStorageConfig: + existingSecret: + name: existing-secret-not-created-by-this-chart + key: object-storage-configs.yaml +``` + +### From 50.x to 51.x + +This version upgrades Prometheus-Operator to v0.68.0, Prometheus to 2.47.0 and Thanos to v0.32.2 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.68.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 49.x to 50.x + +This version requires Kubernetes 1.19+. + +We do not expect any breaking changes in this version. + +### From 48.x to 49.x + +This version upgrades Prometheus-Operator to v0.67.1, 0, Alertmanager to v0.26.0, Prometheus to 2.46.0 and Thanos to v0.32.0 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.67.1/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 47.x to 48.x + +This version moved all CRDs into a dedicated sub-chart. No new CRDs are introduced in this version. +See [#3548](https://github.com/prometheus-community/helm-charts/issues/3548) for more context. + +We do not expect any breaking changes in this version. + +### From 46.x to 47.x + +This version upgrades Prometheus-Operator to v0.66.0 with new CRDs (PrometheusAgent and ScrapeConfig). + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.66.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 45.x to 46.x + +This version upgrades Prometheus-Operator to v0.65.1 with new CRDs (PrometheusAgent and ScrapeConfig), Prometheus to v2.44.0 and Thanos to v0.31.0. + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_scrapeconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.65.1/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 44.x to 45.x + +This version upgrades Prometheus-Operator to v0.63.0, Prometheus to v2.42.0 and Thanos to v0.30.2. + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.63.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.63.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.63.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.63.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.63.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.63.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.63.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.63.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 43.x to 44.x + +This version upgrades Prometheus-Operator to v0.62.0, Prometheus to v2.41.0 and Thanos to v0.30.1. + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.62.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.62.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.62.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.62.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.62.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.62.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.62.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.62.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +If you have explicitly set `prometheusOperator.admissionWebhooks.failurePolicy`, this value is now always used even when `.prometheusOperator.admissionWebhooks.patch.enabled` is `true` (the default). + +The values for `prometheusOperator.image.tag` & `prometheusOperator.prometheusConfigReloader.image.tag` are now empty by default and the Chart.yaml `appVersion` field is used instead. + +### From 42.x to 43.x + +This version upgrades Prometheus-Operator to v0.61.1, Prometheus to v2.40.5 and Thanos to v0.29.0. + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.61.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.61.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.61.1/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.61.1/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.61.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.61.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.61.1/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.61.1/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 41.x to 42.x + +This includes the overridability of container registry for all containers at the global level using `global.imageRegistry` or per container image. The defaults have not changed but if you were using a custom image, you will have to override the registry of said custom container image before you upgrade. + +For instance, the prometheus-config-reloader used to be configured as follow: + +```yaml + image: + repository: quay.io/prometheus-operator/prometheus-config-reloader + tag: v0.60.1 + sha: "" +``` + +But it now moved to: + +```yaml + image: + registry: quay.io + repository: prometheus-operator/prometheus-config-reloader + tag: v0.60.1 + sha: "" +``` + +### From 40.x to 41.x + +This version upgrades Prometheus-Operator to v0.60.1, Prometheus to v2.39.1 and Thanos to v0.28.1. +This version also upgrades the Helm charts of kube-state-metrics to 4.20.2, prometheus-node-exporter to 4.3.0 and Grafana to 6.40.4. + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.60.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.60.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.60.1/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.60.1/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.60.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.60.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.60.1/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.60.1/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +This version splits kubeScheduler recording and altering rules in separate config values. +Instead of `defaultRules.rules.kubeScheduler` the 2 new variables `defaultRules.rules.kubeSchedulerAlerting` and `defaultRules.rules.kubeSchedulerRecording` are used. + +### From 39.x to 40.x + +This version upgrades Prometheus-Operator to v0.59.1, Prometheus to v2.38.0, kube-state-metrics to v2.6.0 and Thanos to v0.28.0. +This version also upgrades the Helm charts of kube-state-metrics to 4.18.0 and prometheus-node-exporter to 4.2.0. + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.59.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.59.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.59.1/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.59.1/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.59.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.59.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.59.1/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.59.1/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +Starting from prometheus-node-exporter version 4.0.0, the `node exporter` chart is using the [Kubernetes recommended labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/). Therefore you have to delete the daemonset before you upgrade. + +```console +kubectl delete daemonset -l app=prometheus-node-exporter +helm upgrade -i kube-prometheus-stack prometheus-community/kube-prometheus-stack +``` + +If you use your own custom [ServiceMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#servicemonitor) or [PodMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#podmonitor), please ensure to upgrade their `selector` fields accordingly to the new labels. + +### From 38.x to 39.x + +This upgraded prometheus-operator to v0.58.0 and prometheus to v2.37.0 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.58.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.58.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.58.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.58.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.58.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.58.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.58.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.58.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 37.x to 38.x + +Reverted one of the default metrics relabelings for cAdvisor added in 36.x, due to it breaking container_network_* and various other statistics. If you do not want this change, you will need to override the `kubelet.cAdvisorMetricRelabelings`. + +### From 36.x to 37.x + +This includes some default metric relabelings for cAdvisor and apiserver metrics to reduce cardinality. If you do not want these defaults, you will need to override the `kubeApiServer.metricRelabelings` and or `kubelet.cAdvisorMetricRelabelings`. + +### From 35.x to 36.x + +This upgraded prometheus-operator to v0.57.0 and prometheus to v2.36.1 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.57.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.57.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.57.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.57.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.57.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.57.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.57.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.57.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 34.x to 35.x + +This upgraded prometheus-operator to v0.56.0 and prometheus to v2.35.0 + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.56.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.56.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.56.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.56.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.56.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.56.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.56.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.56.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 33.x to 34.x + +This upgrades to prometheus-operator to v0.55.0 and prometheus to v2.33.5. + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.55.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.55.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.55.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.55.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.55.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.55.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.55.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.55.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 32.x to 33.x + +This upgrades the prometheus-node-exporter Chart to v3.0.0. Please review the changes to this subchart if you make customizations to hostMountPropagation. + +### From 31.x to 32.x + +This upgrades to prometheus-operator to v0.54.0 and prometheus to v2.33.1. It also changes the default for `grafana.serviceMonitor.enabled` to `true. + +Run these commands to update the CRDs before applying the upgrade. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.54.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.54.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.54.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.54.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.54.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.54.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.54.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.54.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 30.x to 31.x + +This version removes the built-in grafana ServiceMonitor and instead relies on the ServiceMonitor of the sub-chart. +`grafana.serviceMonitor.enabled` must be set instead of `grafana.serviceMonitor.selfMonitor` and the old ServiceMonitor may +need to be manually cleaned up after deploying the new release. + +### From 29.x to 30.x + +This version updates kube-state-metrics to 4.3.0 and uses the new option `kube-state-metrics.releaseLabel=true` which adds the "release" label to kube-state-metrics labels, making scraping of the metrics by kube-prometheus-stack work out of the box again, independent of the used kube-prometheus-stack release name. If you already set the "release" label via `kube-state-metrics.customLabels` you might have to remove that and use it via the new option. + +### From 28.x to 29.x + +This version makes scraping port for kube-controller-manager and kube-scheduler dynamic to reflect changes to default serving ports +for those components in Kubernetes versions v1.22 and v1.23 respectively. + +If you deploy on clusters using version v1.22+, kube-controller-manager will be scraped over HTTPS on port 10257. + +If you deploy on clusters running version v1.23+, kube-scheduler will be scraped over HTTPS on port 10259. + +### From 27.x to 28.x + +This version disables PodSecurityPolicies by default because they are deprecated in Kubernetes 1.21 and will be removed in Kubernetes 1.25. + +If you are using PodSecurityPolicies you can enable the previous behaviour by setting `kube-state-metrics.podSecurityPolicy.enabled`, `prometheus-node-exporter.rbac.pspEnabled`, `grafana.rbac.pspEnabled` and `global.rbac.pspEnabled` to `true`. + +### From 26.x to 27.x + +This version splits prometheus-node-exporter chart recording and altering rules in separate config values. +Instead of `defaultRules.rules.node` the 2 new variables `defaultRules.rules.nodeExporterAlerting` and `defaultRules.rules.nodeExporterRecording` are used. + +Also the following defaultRules.rules has been removed as they had no effect: `kubeApiserverError`, `kubePrometheusNodeAlerting`, `kubernetesAbsent`, `time`. + +The ability to set a rubookUrl via `defaultRules.rules.rubookUrl` was reintroduced. + +### From 25.x to 26.x + +This version enables the prometheus-node-exporter subchart servicemonitor by default again, by setting `prometheus-node-exporter.prometheus.monitor.enabled` to `true`. + +### From 24.x to 25.x + +This version upgrade to prometheus-operator v0.53.1. It removes support for setting a runbookUrl, since the upstream format for runbooks changed. + +```console +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.53.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.53.1/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.53.1/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.53.1/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.53.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.53.1/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.53.1/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.53.1/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 23.x to 24.x + +The custom `ServiceMonitor` for the _kube-state-metrics_ & _prometheus-node-exporter_ charts have been removed in favour of the built-in sub-chart `ServiceMonitor`; for both sub-charts this means that `ServiceMonitor` customisations happen via the values passed to the chart. If you haven't directly customised this behaviour then there are no changes required to upgrade, but if you have please read the following. + +For _kube-state-metrics_ the `ServiceMonitor` customisation is now set via `kube-state-metrics.prometheus.monitor` and the `kubeStateMetrics.serviceMonitor.selfMonitor.enabled` value has moved to `kube-state-metrics.selfMonitor.enabled`. + +For _prometheus-node-exporter_ the `ServiceMonitor` customisation is now set via `prometheus-node-exporter.prometheus.monitor` and the `nodeExporter.jobLabel` values has moved to `prometheus-node-exporter.prometheus.monitor.jobLabel`. + +### From 22.x to 23.x + +Port names have been renamed for Istio's +[explicit protocol selection](https://istio.io/latest/docs/ops/configuration/traffic-management/protocol-selection/#explicit-protocol-selection). + +| | old value | new value | +|-|-----------|-----------| +| `alertmanager.alertmanagerSpec.portName` | `web` | `http-web` | +| `grafana.service.portName` | `service` | `http-web` | +| `prometheus-node-exporter.service.portName` | `metrics` (hardcoded) | `http-metrics` | +| `prometheus.prometheusSpec.portName` | `web` | `http-web` | + +### From 21.x to 22.x + +Due to the upgrade of the `kube-state-metrics` chart, removal of its deployment/stateful needs to done manually prior to upgrading: + +```console +kubectl delete deployments.apps -l app.kubernetes.io/instance=prometheus-operator,app.kubernetes.io/name=kube-state-metrics --cascade=orphan +``` + +or if you use autosharding: + +```console +kubectl delete statefulsets.apps -l app.kubernetes.io/instance=prometheus-operator,app.kubernetes.io/name=kube-state-metrics --cascade=orphan +``` + +### From 20.x to 21.x + +The config reloader values have been refactored. All the values have been moved to the key `prometheusConfigReloader` and the limits and requests can now be set separately. + +### From 19.x to 20.x + +Version 20 upgrades prometheus-operator from 0.50.x to 0.52.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRDs manually before updating: + +```console +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.52.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.52.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.52.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.52.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.52.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.52.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.52.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.52.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 18.x to 19.x + +`kubeStateMetrics.serviceMonitor.namespaceOverride` was removed. +Please use `kube-state-metrics.namespaceOverride` instead. + +### From 17.x to 18.x + +Version 18 upgrades prometheus-operator from 0.49.x to 0.50.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRDs manually before updating: + +```console +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.50.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.50.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.50.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.50.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.50.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.50.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.50.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.50.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 16.x to 17.x + +Version 17 upgrades prometheus-operator from 0.48.x to 0.49.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRDs manually before updating: + +```console +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusrules.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.49.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 15.x to 16.x + +Version 16 upgrades kube-state-metrics to v2.0.0. This includes changed command-line arguments and removed metrics, see this [blog post](https://kubernetes.io/blog/2021/04/13/kube-state-metrics-v-2-0/). This version also removes Grafana dashboards that supported Kubernetes 1.14 or earlier. + +### From 14.x to 15.x + +Version 15 upgrades prometheus-operator from 0.46.x to 0.47.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRDs manually before updating: + +```console +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.47.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 13.x to 14.x + +Version 14 upgrades prometheus-operator from 0.45.x to 0.46.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRDs manually before updating: + +```console +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_probes.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.46.0/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +``` + +### From 12.x to 13.x + +Version 13 upgrades prometheus-operator from 0.44.x to 0.45.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRD manually before updating: + +```console +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.45.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.45.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.45.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +``` + +### From 11.x to 12.x + +Version 12 upgrades prometheus-operator from 0.43.x to 0.44.x. Helm does not automatically upgrade or install new CRDs on a chart upgrade, so you have to install the CRD manually before updating: + +```console +kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/release-0.44/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +``` + +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. + +You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `prometheusOperator.admissionWebhooks.certManager.enabled` value to true. + +### 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 repository](https://github.com/prometheus-operator/kube-prometheus/blob/main/docs/customizations/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/main/Documentation/user-guides/getting-started.md#include-servicemonitors) +- [PodMonitors](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md#include-podmonitors) +- [Running Exporters](https://github.com/prometheus-operator/prometheus-operator/blob/main/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/ -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/ -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/ --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/grafana/helm-charts/blob/main/charts/grafana/README.md) + +#### 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.kubernetes.io/name: 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/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/Chart.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/Chart.yaml new file mode 100644 index 000000000..adb9e4a5d --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: crds +version: 0.0.0 diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/README.md b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/README.md new file mode 100644 index 000000000..02092b964 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/README.md @@ -0,0 +1,3 @@ +# crds subchart + +See: [https://github.com/prometheus-community/helm-charts/issues/3548](https://github.com/prometheus-community/helm-charts/issues/3548) diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-alertmanagerconfigs.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-alertmanagerconfigs.yaml new file mode 100644 index 000000000..e8c9fbcd0 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-alertmanagerconfigs.yaml @@ -0,0 +1,5866 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.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.14.0 + operator.prometheus.io/version: 0.74.0 + name: alertmanagerconfigs.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: AlertmanagerConfig + listKind: AlertmanagerConfigList + plural: alertmanagerconfigs + shortNames: + - amcfg + singular: alertmanagerconfig + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AlertmanagerConfig configures the Prometheus Alertmanager, + specifying how alerts should be grouped, inhibited and notified to external systems. + 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: + matchType: + description: |- + Match operation available with AlertManager >= v0.22.0 and + takes precedence over Regex (deprecated) if non-empty. + enum: + - '!=' + - = + - =~ + - '!~' + type: string + name: + description: Label to match. + minLength: 1 + type: string + regex: + description: |- + Whether to match on equality (false) or regular-expression (true). + Deprecated: for AlertManager >= v0.22.0, `matchType` should be used instead. + type: boolean + value: + description: Label value to match. + type: string + required: + - name + 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: + matchType: + description: |- + Match operation available with AlertManager >= v0.22.0 and + takes precedence over Regex (deprecated) if non-empty. + enum: + - '!=' + - = + - =~ + - '!~' + type: string + name: + description: Label to match. + minLength: 1 + type: string + regex: + description: |- + Whether to match on equality (false) or regular-expression (true). + Deprecated: for AlertManager >= v0.22.0, `matchType` should be used instead. + type: boolean + value: + description: Label value to match. + type: string + required: + - name + type: object + type: array + type: object + type: array + muteTimeIntervals: + description: List of MuteTimeInterval specifying when the routes should + be muted. + items: + description: MuteTimeInterval specifies the periods in time when + notifications will be muted + properties: + name: + description: Name of the time interval + type: string + timeIntervals: + description: TimeIntervals is a list of TimeInterval + items: + description: TimeInterval describes intervals of time + properties: + daysOfMonth: + description: DaysOfMonth is a list of DayOfMonthRange + items: + description: DayOfMonthRange is an inclusive range of + days of the month beginning at 1 + properties: + end: + description: End of the inclusive range + maximum: 31 + minimum: -31 + type: integer + start: + description: Start of the inclusive range + maximum: 31 + minimum: -31 + type: integer + type: object + type: array + months: + description: Months is a list of MonthRange + items: + description: |- + MonthRange is an inclusive range of months of the year beginning in January + Months can be specified by name (e.g 'January') by numerical month (e.g '1') or as an inclusive range (e.g 'January:March', '1:3', '1:March') + pattern: ^((?i)january|february|march|april|may|june|july|august|september|october|november|december|1[0-2]|[1-9])(?:((:((?i)january|february|march|april|may|june|july|august|september|october|november|december|1[0-2]|[1-9]))$)|$) + type: string + type: array + times: + description: Times is a list of TimeRange + items: + description: TimeRange defines a start and end time + in 24hr format + properties: + endTime: + description: EndTime is the end time in 24hr format. + pattern: ^((([01][0-9])|(2[0-3])):[0-5][0-9])$|(^24:00$) + type: string + startTime: + description: StartTime is the start time in 24hr + format. + pattern: ^((([01][0-9])|(2[0-3])):[0-5][0-9])$|(^24:00$) + type: string + type: object + type: array + weekdays: + description: Weekdays is a list of WeekdayRange + items: + description: |- + WeekdayRange is an inclusive range of days of the week beginning on Sunday + Days can be specified by name (e.g 'Sunday') or as an inclusive range (e.g 'Monday:Friday') + pattern: ^((?i)sun|mon|tues|wednes|thurs|fri|satur)day(?:((:(sun|mon|tues|wednes|thurs|fri|satur)day)$)|$) + type: string + type: array + years: + description: Years is a list of YearRange + items: + description: YearRange is an inclusive range of years + pattern: ^2\d{3}(?::2\d{3}|$) + type: string + type: array + type: object + type: array + type: object + type: array + receivers: + description: List of receivers. + items: + description: Receiver defines one or more notification integrations. + properties: + discordConfigs: + description: List of Discord configurations. + items: + description: |- + DiscordConfig configures notifications via Discord. + See https://prometheus.io/docs/alerting/latest/configuration/#discord_config + properties: + apiURL: + description: |- + The secret's key that contains the Discord 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 + x-kubernetes-map-type: atomic + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + message: + description: The template of the message's body. + type: string + sendResolved: + description: Whether or not to notify about resolved alerts. + type: boolean + title: + description: The template of the message's title. + type: string + required: + - apiURL + type: object + type: array + emailConfigs: + description: List of Email configurations. + items: + description: EmailConfig configures notifications via Email. + properties: + authIdentity: + description: The identity to use for authentication. + type: string + authPassword: + description: |- + The secret's key that contains the password to use 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 + x-kubernetes-map-type: atomic + authSecret: + description: |- + The secret's key that contains the CRAM-MD5 secret. + 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 + x-kubernetes-map-type: atomic + authUsername: + description: The username to use for authentication. + 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. + minLength: 1 + 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 and port through which emails + are sent. E.g. example.com:25 + type: string + text: + description: The text body of the email notification. + type: string + tlsConfig: + description: TLS configuration + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when doing + client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + msteamsConfigs: + description: |- + List of MSTeams configurations. + It requires Alertmanager >= 0.26.0. + items: + description: |- + MSTeamsConfig configures notifications via Microsoft Teams. + It requires Alertmanager >= 0.26.0. + properties: + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + sendResolved: + description: Whether to notify about resolved alerts. + type: boolean + summary: + description: |- + Message summary template. + It requires Alertmanager >= 0.27.0. + type: string + text: + description: Message body template. + type: string + title: + description: Message title template. + type: string + webhookUrl: + description: MSTeams webhook URL. + 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 + x-kubernetes-map-type: atomic + required: + - webhookUrl + type: object + type: array + name: + description: Name of the receiver. Must be unique across all + items from the list. + minLength: 1 + 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: + actions: + description: Comma separated list of actions that will + be available for the alert. + type: string + 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 + x-kubernetes-map-type: atomic + 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. + minLength: 1 + type: string + value: + description: Value of the tuple. + type: string + required: + - key + - value + type: object + type: array + entity: + description: Optional field that can be used to specify + which domain alert is related to. + type: string + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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. + minLength: 1 + type: string + username: + description: Username of the responder. + type: string + required: + - type + 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 + updateAlerts: + description: |- + Whether to update message and description of the alert in OpsGenie if it already exists + By default, the alert is never updated in OpsGenie, the new message only appears in activity log. + type: boolean + 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. + minLength: 1 + 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: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + pagerDutyImageConfigs: + description: A list of image details to attach that provide + further detail about an incident. + items: + description: PagerDutyImageConfig attaches images to + an incident + properties: + alt: + description: Alt is the optional alternative text + for the image. + type: string + href: + description: Optional URL; makes the image a clickable + link. + type: string + src: + description: Src of the image being attached to + the incident + type: string + type: object + type: array + pagerDutyLinkConfigs: + description: A list of link details to attach that provide + further detail about an incident. + items: + description: PagerDutyLinkConfig attaches text links + to an incident + properties: + alt: + description: Text that describes the purpose of + the link, and can be used as the link's text. + type: string + href: + description: Href is the URL of the link to be attached + type: string + type: object + type: array + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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: + device: + description: The name of a device to send the notification + to + type: string + expire: + description: |- + How long your notification will continue to be retried for, unless the user + acknowledges the notification. + pattern: ^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$ + type: string + html: + description: Whether notification message is HTML or plain + text. + type: boolean + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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. + pattern: ^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$ + 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: |- + The secret's key that contains the registered application's API token, see https://pushover.net/apps. + The secret needs to be in the same namespace as the AlertmanagerConfig + object and accessible by the Prometheus Operator. + Either `token` or `tokenFile` is required. + 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 + x-kubernetes-map-type: atomic + tokenFile: + description: |- + The token file that contains the registered application's API token, see https://pushover.net/apps. + Either `token` or `tokenFile` is required. + It requires Alertmanager >= v0.26.0. + type: string + 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 secret's key that contains the recipient user's user key. + The secret needs to be in the same namespace as the AlertmanagerConfig + object and accessible by the Prometheus Operator. + Either `userKey` or `userKeyFile` is required. + 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 + x-kubernetes-map-type: atomic + userKeyFile: + description: |- + The user key file that contains the recipient user's user key. + Either `userKey` or `userKeyFile` is required. + It requires Alertmanager >= v0.26.0. + type: string + 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: + minLength: 1 + type: string + title: + type: string + required: + - text + type: object + name: + type: string + style: + type: string + text: + minLength: 1 + type: string + type: + minLength: 1 + 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 + x-kubernetes-map-type: atomic + 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: + minLength: 1 + type: string + value: + minLength: 1 + type: string + required: + - title + - value + type: object + type: array + footer: + type: string + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + snsConfigs: + description: List of SNS configurations + items: + description: |- + SNSConfig configures notifications via AWS SNS. + See https://prometheus.io/docs/alerting/latest/configuration/#sns_configs + properties: + apiURL: + description: |- + The SNS API URL i.e. https://sns.us-east-2.amazonaws.com. + If not specified, the SNS API URL from the SNS SDK will be used. + type: string + attributes: + additionalProperties: + type: string + description: SNS message attributes. + type: object + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + message: + description: The message content of the SNS notification. + type: string + phoneNumber: + description: |- + Phone number if message is delivered via SMS in E.164 format. + If you don't specify this value, you must specify a value for the TopicARN or TargetARN. + type: string + sendResolved: + description: Whether or not to notify about resolved alerts. + type: boolean + sigv4: + description: Configures AWS's Signature Verification 4 + signing process to sign requests. + properties: + accessKey: + description: |- + AccessKey is the AWS API key. If not specified, the environment variable + `AWS_ACCESS_KEY_ID` is used. + 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 + x-kubernetes-map-type: atomic + profile: + description: Profile is the named AWS profile used + to authenticate. + type: string + region: + description: Region is the AWS region. If blank, the + region from the default credentials chain used. + type: string + roleArn: + description: RoleArn is the named AWS profile used + to authenticate. + type: string + secretKey: + description: |- + SecretKey is the AWS API secret. If not specified, the environment + variable `AWS_SECRET_ACCESS_KEY` is used. + 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 + x-kubernetes-map-type: atomic + type: object + subject: + description: Subject line when the message is delivered + to email endpoints. + type: string + targetARN: + description: |- + The mobile platform endpoint ARN if message is delivered via mobile notifications. + If you don't specify this value, you must specify a value for the topic_arn or PhoneNumber. + type: string + topicARN: + description: |- + SNS topic ARN, i.e. arn:aws:sns:us-east-2:698519295917:My-Topic + If you don't specify this value, you must specify a value for the PhoneNumber or TargetARN. + type: string + type: object + type: array + telegramConfigs: + description: List of Telegram configurations. + items: + description: |- + TelegramConfig configures notifications via Telegram. + See https://prometheus.io/docs/alerting/latest/configuration/#telegram_config + properties: + apiURL: + description: |- + The Telegram API URL i.e. https://api.telegram.org. + If not specified, default API URL will be used. + type: string + botToken: + description: |- + Telegram bot token. It is mutually exclusive with `botTokenFile`. + The secret needs to be in the same namespace as the AlertmanagerConfig + object and accessible by the Prometheus Operator. + + + Either `botToken` or `botTokenFile` is required. + 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 + x-kubernetes-map-type: atomic + botTokenFile: + description: |- + File to read the Telegram bot token from. It is mutually exclusive with `botToken`. + Either `botToken` or `botTokenFile` is required. + + + It requires Alertmanager >= v0.26.0. + type: string + chatID: + description: The Telegram chat ID. + format: int64 + type: integer + disableNotifications: + description: Disable telegram notifications + type: boolean + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + message: + description: Message template + type: string + parseMode: + description: Parse mode for telegram message + enum: + - MarkdownV2 + - Markdown + - HTML + type: string + sendResolved: + description: Whether to notify about resolved alerts. + type: boolean + 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 secret's key that contains the API key to use when talking to the VictorOps API. + 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 + x-kubernetes-map-type: atomic + 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. + minLength: 1 + 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: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + type: object + type: array + webexConfigs: + description: List of Webex configurations. + items: + description: |- + WebexConfig configures notification via Cisco Webex + See https://prometheus.io/docs/alerting/latest/configuration/#webex_config + properties: + apiURL: + description: |- + The Webex Teams API URL i.e. https://webexapis.com/v1/messages + Provide if different from the default API URL. + pattern: ^https?://.+$ + type: string + httpConfig: + description: |- + The HTTP client's configuration. + You must supply the bot token via the `httpConfig.authorization` field. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the + targets. + type: string + type: object + type: object + message: + description: Message template + type: string + roomID: + description: ID of the Webex Teams room where to send + the messages. + minLength: 1 + type: string + sendResolved: + description: Whether to notify about resolved alerts. + type: boolean + required: + - roomID + 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: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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. When 0, all alerts are included. + format: int32 + minimum: 0 + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + apiURL: + description: The WeChat API URL. + type: string + corpID: + description: The corp id for authentication. + type: string + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the + namespace that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the + client should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch + a token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes + used for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to + fetch the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when + doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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. If present, it will be added to the generated Alertmanager + configuration as a first-level route. + properties: + activeTimeIntervals: + description: ActiveTimeIntervals is a list of MuteTimeInterval + names when this route should be active. + items: + type: string + type: array + 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. + Labels must not be repeated (unique list). + Special label "..." (aggregate by all possible labels), if provided, must be the only element in the list. + items: + type: string + type: array + groupInterval: + description: |- + How long to wait before sending an updated notification. + Must match the regular expression`^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$` + Example: "5m" + type: string + groupWait: + description: |- + How long to wait before sending the initial notification. + Must match the regular expression`^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$` + Example: "30s" + 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: ` matcher. + items: + description: Matcher defines how to match on alert's labels. + properties: + matchType: + description: |- + Match operation available with AlertManager >= v0.22.0 and + takes precedence over Regex (deprecated) if non-empty. + enum: + - '!=' + - = + - =~ + - '!~' + type: string + name: + description: Label to match. + minLength: 1 + type: string + regex: + description: |- + Whether to match on equality (false) or regular-expression (true). + Deprecated: for AlertManager >= v0.22.0, `matchType` should be used instead. + type: boolean + value: + description: Label value to match. + type: string + required: + - name + type: object + type: array + muteTimeIntervals: + description: |- + Note: this comment applies to the field definition above but appears + below otherwise it gets included in the generated manifest. + CRD schema doesn't support self-referential types for now (see + https://github.com/kubernetes/kubernetes/issues/62872). We have to use + an alternative type to circumvent the limitation. The downside is that + the Kube API can't validate the data beyond the fact that it is a valid + JSON representation. + MuteTimeIntervals is a list of MuteTimeInterval names that will mute this route when matched, + items: + type: string + type: array + receiver: + description: |- + Name of the receiver for this route. If not empty, it should be listed in + the `receivers` field. + type: string + repeatInterval: + description: |- + How long to wait before repeating the last notification. + Must match the regular expression`^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$` + Example: "4h" + 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 diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-alertmanagers.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-alertmanagers.yaml new file mode 100644 index 000000000..bc344481b --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-alertmanagers.yaml @@ -0,0 +1,7839 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.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.14.0 + operator.prometheus.io/version: 0.74.0 + name: alertmanagers.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: Alertmanager + listKind: AlertmanagerList + plural: alertmanagers + shortNames: + - am + singular: alertmanager + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The version of Alertmanager + jsonPath: .spec.version + name: Version + type: string + - description: The number of desired replicas + jsonPath: .spec.replicas + name: Replicas + type: integer + - description: The number of ready replicas + jsonPath: .status.availableReplicas + name: Ready + type: integer + - jsonPath: .status.conditions[?(@.type == 'Reconciled')].status + name: Reconciled + type: string + - jsonPath: .status.conditions[?(@.type == 'Available')].status + name: Available + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: Whether the resource reconciliation is paused or not + jsonPath: .status.paused + name: Paused + priority: 1 + type: boolean + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + 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. + If it's null, this PodAffinityTerm matches with no 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector 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 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. + If it's null, this PodAffinityTerm matches with no 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector 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. + If it's null, this PodAffinityTerm matches with no 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector 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 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. + If it's null, this PodAffinityTerm matches with no 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector 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 + alertmanagerConfigMatcherStrategy: + description: |- + The AlertmanagerConfigMatcherStrategy defines how AlertmanagerConfig objects match the alerts. + In the future more options may be added. + properties: + type: + default: OnNamespace + description: |- + If set to `OnNamespace`, the operator injects a label matcher matching the namespace of the AlertmanagerConfig object for all its routes and inhibition rules. + `None` will not add any additional matchers other than the ones specified in the AlertmanagerConfig. + Default is `OnNamespace`. + enum: + - OnNamespace + - None + type: string + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + alertmanagerConfiguration: + description: |- + alertmanagerConfiguration specifies the configuration of Alertmanager. + + + If defined, it takes precedence over the `configSecret` field. + + + This is an *experimental feature*, it may change in any upcoming release + in a breaking way. + properties: + global: + description: Defines the global parameters of the Alertmanager + configuration. + properties: + httpConfig: + description: HTTP client configuration. + properties: + authorization: + description: |- + Authorization header configuration for the client. + This is mutually exclusive with BasicAuth and is only available starting from Alertmanager v0.22+. + properties: + credentials: + description: Selects a key of a Secret in the namespace + that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth for the client. + This is mutually exclusive with Authorization. If both are defined, BasicAuth takes precedence. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 Alertmanager + 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 + x-kubernetes-map-type: atomic + followRedirects: + description: FollowRedirects specifies whether the client + should follow HTTP 3xx redirects. + type: boolean + oauth2: + description: OAuth2 client credentials used to fetch a + token for the targets. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes used + for the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to fetch + the token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + proxyURL: + description: Optional proxy URL. + type: string + tlsConfig: + description: TLS configuration for the client. + properties: + ca: + description: Certificate authority used when verifying + server certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when doing + client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + type: object + opsGenieApiKey: + description: The default OpsGenie API 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 + x-kubernetes-map-type: atomic + opsGenieApiUrl: + description: The default OpsGenie API URL. + 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 + x-kubernetes-map-type: atomic + pagerdutyUrl: + description: The default Pagerduty URL. + type: string + resolveTimeout: + description: |- + ResolveTimeout is the default value used by alertmanager if the alert does + not include EndsAt, after this time passes it can declare the alert as resolved if it has not been updated. + This has no impact on alerts from Prometheus, as they always include EndsAt. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + slackApiUrl: + description: The default Slack API URL. + 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 + x-kubernetes-map-type: atomic + smtp: + description: Configures global SMTP parameters. + properties: + authIdentity: + description: SMTP Auth using PLAIN + type: string + authPassword: + description: SMTP Auth using LOGIN and PLAIN. + 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 + x-kubernetes-map-type: atomic + authSecret: + description: SMTP Auth using CRAM-MD5. + 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 + x-kubernetes-map-type: atomic + authUsername: + description: SMTP Auth using CRAM-MD5, LOGIN and PLAIN. + If empty, Alertmanager doesn't authenticate to the SMTP + server. + type: string + from: + description: The default SMTP From header field. + type: string + hello: + description: The default hostname to identify to the SMTP + server. + type: string + requireTLS: + description: |- + The default SMTP TLS requirement. + Note that Go does not support unencrypted connections to remote SMTP endpoints. + type: boolean + smartHost: + description: The default SMTP smarthost used for sending + emails. + properties: + host: + description: Defines the host's address, it can be + a DNS name or a literal IP address. + minLength: 1 + type: string + port: + description: Defines the host's port, it can be a + literal port number or a port name. + minLength: 1 + type: string + required: + - host + - port + type: object + type: object + type: object + name: + description: |- + The name of the AlertmanagerConfig resource which is used to generate the Alertmanager configuration. + It must be defined in the same namespace as the Alertmanager object. + The operator will not enforce a `namespace` label for routes and inhibition rules. + minLength: 1 + type: string + templates: + description: Custom notification templates. + items: + description: SecretOrConfigMap allows to specify data as a Secret + or ConfigMap. Fields are mutually exclusive. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + type: array + type: object + automountServiceAccountToken: + description: |- + AutomountServiceAccountToken indicates whether a service account token should be automatically mounted in the pod. + If the service account has `automountServiceAccountToken: true`, set the field to `false` to opt out of automounting API credentials. + type: boolean + 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. + pattern: ^(0|(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + clusterLabel: + description: |- + Defines the identifier that uniquely identifies the Alertmanager cluster. + You should only set it when the Alertmanager cluster includes Alertmanager instances which are external to this Alertmanager resource. In practice, the addresses of the external instances are provided via the `.spec.additionalPeers` field. + type: string + clusterPeerTimeout: + description: Timeout for cluster peering. + pattern: ^(0|(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + clusterPushpullInterval: + description: Interval between pushpull attempts. + pattern: ^(0|(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + 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. + Each ConfigMap is added to the StatefulSet definition as a volume named `configmap-`. + The ConfigMaps are mounted into `/etc/alertmanager/configmaps/` in the 'alertmanager' container. + 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 the configuration for this Alertmanager + instance. If empty, it defaults to `alertmanager-`. + + + The Alertmanager configuration should be available under the + `alertmanager.yaml` key. Additional keys from the original secret are + copied to the generated secret and mounted into the + `/etc/alertmanager/config` directory in the `alertmanager` container. + + + If either the secret or the `alertmanager.yaml` key is missing, the + operator provisions a minimal Alertmanager configuration with one empty + receiver (effectively dropping alert notifications). + 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 container 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(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 container 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(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 previously 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: |- + Container 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: 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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 + sleep: + description: Sleep represents the duration that the + container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for the backward compatibility. There are no validation of this field and + lifecycle hooks will fail in runtime when tcp handler is specified. + 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 Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). 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: 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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 + sleep: + description: Sleep represents the duration that the + container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for the backward compatibility. There are no validation of this field and + lifecycle hooks will fail in runtime when tcp handler is specified. + 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: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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. 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. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + 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: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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 + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + 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 + Note that this field cannot be set when spec.os.name is windows. + type: boolean + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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 + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + 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. + Note that this field cannot be set when spec.os.name is linux. + 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 + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + 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. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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 + enableFeatures: + description: |- + Enable access to Alertmanager feature flags. By default, no features are enabled. + Enabling features which are disabled by default 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. + + + It requires Alertmanager >= 0.27.0. + items: + type: string + 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 + hostAliases: + description: Pods' hostAliases configuration + items: + description: |- + HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the + pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + required: + - hostnames + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + 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 + imagePullPolicy: + description: |- + Image pull policy for the 'alertmanager', 'init-config-reloader' and 'config-reloader' containers. + See https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy for more details. + enum: + - "" + - Always + - Never + - IfNotPresent + 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 + x-kubernetes-map-type: atomic + 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/ + InitContainers described here modify an operator + generated init containers if they share the same name and modifications are + done via a strategic merge patch. The current init container name is: + `init-config-reloader`. Overriding init 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 container 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(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 container 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(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 previously 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: |- + Container 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: 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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 + sleep: + description: Sleep represents the duration that the + container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for the backward compatibility. There are no validation of this field and + lifecycle hooks will fail in runtime when tcp handler is specified. + 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 Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). 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: 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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 + sleep: + description: Sleep represents the duration that the + container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for the backward compatibility. There are no validation of this field and + lifecycle hooks will fail in runtime when tcp handler is specified. + 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: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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. 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. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + 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: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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 + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + 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 + Note that this field cannot be set when spec.os.name is windows. + type: boolean + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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 + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + 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. + Note that this field cannot be set when spec.os.name is linux. + 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 + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + 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. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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. + enum: + - "" + - logfmt + - json + type: string + logLevel: + description: Log level for Alertmanager to be configured with. + enum: + - "" + - debug + - info + - warn + - error + type: string + minReadySeconds: + description: |- + Minimum number of seconds for which a newly created pod should be ready + without any of its container crashing for it to be considered available. + Defaults to 0 (pod will be considered available as soon as it is ready) + This is an alpha field from kubernetes 1.22 until 1.24 which requires enabling the StatefulSetMinReadySeconds feature gate. + format: int32 + type: integer + 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. + + + The following items are reserved and cannot be overridden: + * "alertmanager" label, set to the name of the Alertmanager instance. + * "app.kubernetes.io/instance" label, set to the name of the Alertmanager instance. + * "app.kubernetes.io/managed-by" label, set to "prometheus-operator". + * "app.kubernetes.io/name" label, set to "alertmanager". + * "app.kubernetes.io/version" label, set to the Alertmanager version. + * "kubectl.kubernetes.io/default-container" annotation, set to "alertmanager". + 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: + default: web + description: |- + Port name used for the pods and governing service. + 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: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + retention: + default: 120h + 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). + pattern: ^(0|(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + 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. + Each Secret is added to the StatefulSet definition as a volume named `secret-`. + The Secrets are mounted into `/etc/alertmanager/secrets/` in the 'alertmanager' container. + 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: + + + 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---- + + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + 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, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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 + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + 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, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is linux. + 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 + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + 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 removed in a future + release.' + type: boolean + emptyDir: + description: |- + EmptyDirVolumeSource to be used by the StatefulSet. + If specified, it takes precedence over `ephemeral` and `volumeClaimTemplate`. + More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir + properties: + medium: + description: |- + medium represents 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: |- + sizeLimit is the 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: https://kubernetes.io/docs/concepts/storage/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 + ephemeral: + description: |- + EphemeralVolumeSource to be used by the StatefulSet. + This is a beta field in k8s 1.21 and GA in 1.15. + For lower versions, starting with k8s 1.19, it requires enabling the GenericEphemeralVolume feature gate. + More info: https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes + properties: + volumeClaimTemplate: + description: |- + Will be used to create a stand-alone PVC to provision the volume. + The pod in which this EphemeralVolumeSource is embedded will be the + owner of the PVC, i.e. the PVC will be deleted together with the + pod. The name of the PVC will be `-` where + `` is the name from the `PodSpec.Volumes` array + entry. Pod validation will reject the pod if the concatenated name + is not valid for a PVC (for example, too long). + + + An existing PVC with that name that is not owned by the pod + will *not* be used for the pod to avoid using an unrelated + volume by mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created PVC is + meant to be used by the pod, the PVC has to updated with an + owner reference to the pod once the pod exists. Normally + this should not be necessary, but it may be useful when + manually reconstructing a broken cluster. + + + This field is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. + + + Required, must not be nil. + properties: + metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. No other fields are allowed and will be rejected during + validation. + type: object + spec: + description: |- + The specification for the PersistentVolumeClaim. The entire content is + copied unchanged into the PVC that gets created from this + template. The same fields as in a PersistentVolumeClaim + are also valid here. + 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: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + 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. + When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, + and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not be copied to dataSource. + 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 + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed if the type of + the specified object matches some installed volume populator or dynamic + provisioner. + This field will replace the functionality of the dataSource field and as such + if both fields are non-empty, they must have the same value. For backwards + compatibility, when namespace isn't specified in dataSourceRef, + both fields (dataSource and dataSourceRef) will be set to the same + value automatically if one of them is empty and the other is non-empty. + When namespace is specified in dataSourceRef, + dataSource isn't set to the same value and must be empty. + There are three important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping them), dataSourceRef + preserves all values, and generates an error if a disallowed value is + specified. + * While dataSource only allows local objects, dataSourceRef allows objects + in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. + (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + 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 + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is 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 + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + 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 + required: + - spec + type: object + type: object + volumeClaimTemplate: + description: |- + Defines the PVC spec to be used by the Prometheus StatefulSets. + The easiest way to use a volume that cannot be automatically provisioned + is to use a label selector alongside manually created PersistentVolumes. + 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: |- + 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: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + 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. + When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, + and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not be copied to dataSource. + 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 + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed if the type of + the specified object matches some installed volume populator or dynamic + provisioner. + This field will replace the functionality of the dataSource field and as such + if both fields are non-empty, they must have the same value. For backwards + compatibility, when namespace isn't specified in dataSourceRef, + both fields (dataSource and dataSourceRef) will be set to the same + value automatically if one of them is empty and the other is non-empty. + When namespace is specified in dataSourceRef, + dataSource isn't set to the same value and must be empty. + There are three important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping them), dataSourceRef + preserves all values, and generates an error if a disallowed value is + specified. + * While dataSource only allows local objects, dataSourceRef allows objects + in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. + (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + 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 + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is 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 + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + 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: 'Deprecated: this field is never set.' + 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 + allocatedResourceStatuses: + additionalProperties: + description: |- + When a controller receives persistentvolume claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore that update and let other controllers + handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC.\nKey names + follow standard Kubernetes label syntax. Valid values + are either:\n\t* Un-prefixed keys:\n\t\t- storage - + the capacity of the volume.\n\t* Custom resources must + use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart + from above values - keys that are unprefixed or have + kubernetes.io prefix are considered\nreserved and hence + may not be used.\n\n\nClaimResourceStatus can be in + any of following states:\n\t- ControllerResizeInProgress:\n\t\tState + set when resize controller starts resizing the volume + in control-plane.\n\t- ControllerResizeFailed:\n\t\tState + set when resize has failed in resize controller with + a terminal error.\n\t- NodeResizePending:\n\t\tState + set when resize controller has finished resizing the + volume but further resizing of\n\t\tvolume is needed + on the node.\n\t- NodeResizeInProgress:\n\t\tState set + when kubelet starts resizing the volume.\n\t- NodeResizeFailed:\n\t\tState + set when resizing has failed in kubelet with a terminal + error. Transient errors don't set\n\t\tNodeResizeFailed.\nFor + example: if expanding a PVC for more capacity - this + field can be one of the following states:\n\t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\"\n - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\"\n - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\"\n - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\"\nWhen this field is not set, + it means that no resize operation is in progress for + the given PVC.\n\n\nA controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus\nshould + ignore the update for the purpose it was designed. For + example - a controller that\nonly is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid\nresources associated with PVC.\n\n\nThis + is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + x-kubernetes-map-type: granular + allocatedResources: + 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: "allocatedResources tracks the resources + allocated to a PVC including its capacity.\nKey names + follow standard Kubernetes label syntax. Valid values + are either:\n\t* Un-prefixed keys:\n\t\t- storage - + the capacity of the volume.\n\t* Custom resources must + use implementation-defined prefixed names such as \"example.com/my-custom-resource\"\nApart + from above values - keys that are unprefixed or have + kubernetes.io prefix are considered\nreserved and hence + may not be used.\n\n\nCapacity reported here may be + larger than the actual capacity when a volume expansion + operation\nis requested.\nFor storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used.\nIf allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation.\nIf a volume expansion + capacity request is lowered, allocatedResources is only\nlowered + if there are no expansion operations in progress and + if the actual volume capacity\nis equal or lower than + the requested capacity.\n\n\nA controller that receives + PVC update with previously unknown resourceName\nshould + ignore the update for the purpose it was designed. For + example - a controller that\nonly is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid\nresources associated with PVC.\n\n\nThis + is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + 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: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: |- + conditions is the current Condition of persistent volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: |- + reason is a 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 + currentVolumeAttributesClassName: + description: |- + currentVolumeAttributesClassName is the current name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied to this PersistentVolumeClaim + This is an alpha field and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: |- + ModifyVolumeStatus represents the status object of ControllerModifyVolume operation. + When this is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states:\n + - Pending\n Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as\n the specified VolumeAttributesClass not existing.\n + - InProgress\n InProgress indicates that the volume + is being modified.\n - Infeasible\n Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To\n\t resolve the error, + a valid VolumeAttributesClass needs to be specified.\nNote: + New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object + 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 using the matching 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + Keys that don't exist in the incoming pod labels will + be ignored. A null or empty list means only match against labelSelector. + + + This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same + labelSelector spread as 2/2/1: + In this case, the global minimum is 1. + | zone1 | zone2 | zone3 | + | P P | P P | P | + - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; + scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) + violate MaxSkew(1). + - if MaxSkew is 2, incoming pod can be scheduled onto any zone. + When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence + to topologies that satisfy it. + It's a required field. Default value is 1 and 0 is not allowed. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + As a result, when the number of eligible domains is less than minDomains, + scheduler won't schedule more than maxSkew Pods to those domains. + If value is nil, the constraint behaves as if MinDomains is equal to 1. + Valid values are integers greater than 0. + When value is not nil, WhenUnsatisfiable must be DoNotSchedule. + + + For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same + labelSelector spread as 2/2/2: + | zone1 | zone2 | zone3 | + | P P | P P | P P | + The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. + In this situation, new pod with the same labelSelector cannot be scheduled, + because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, + it will violate MaxSkew. + + + This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default). + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + + If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + + If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + 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 as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. + And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. + 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 schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + 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: |- + fsType is the 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: |- + partition is 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: |- + readOnly value true will force the readOnly setting in VolumeMounts. + More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + type: boolean + volumeID: + description: |- + volumeID is 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: 'cachingMode is the Host Caching mode: None, + Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in the + blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the blob + storage + type: string + fsType: + description: |- + fsType is 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: 'kind expected values are 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: |- + readOnly 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: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that contains + Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure 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: |- + monitors is 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: 'path is Optional: Used as the mounted root, + rather than the full Ceph tree, default is /' + type: string + readOnly: + description: |- + readOnly is 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: |- + secretFile is 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: |- + secretRef is 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 + x-kubernetes-map-type: atomic + user: + description: |- + user is 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: |- + fsType is the 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: |- + readOnly 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: |- + secretRef is 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 + x-kubernetes-map-type: atomic + volumeID: + description: |- + volumeID 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: |- + defaultMode is optional: mode bits used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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 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: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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: |- + path is 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: optional specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents ephemeral + storage that is handled by certain external CSI drivers (Beta + 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: |- + fsType 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 + x-kubernetes-map-type: atomic + readOnly: + description: |- + readOnly 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 + Optional: mode bits used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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 + x-kubernetes-map-type: atomic + mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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 + x-kubernetes-map-type: atomic + 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: |- + medium represents 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: |- + sizeLimit is the 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: https://kubernetes.io/docs/concepts/storage/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 + ephemeral: + description: |- + ephemeral represents a volume that is handled by a cluster storage driver. + The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, + and deleted when the pod is removed. + + + Use this if: + a) the volume is only needed while the pod runs, + b) features of normal volumes like restoring from snapshot or capacity + tracking are needed, + c) the storage driver is specified through a storage class, and + d) the storage driver supports dynamic volume provisioning through + a PersistentVolumeClaim (see EphemeralVolumeSource for more + information on the connection between this volume type + and PersistentVolumeClaim). + + + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the lifecycle + of an individual pod. + + + Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to + be used that way - see the documentation of the driver for + more information. + + + A pod can use both types of ephemeral volumes and + persistent volumes at the same time. + properties: + volumeClaimTemplate: + description: |- + Will be used to create a stand-alone PVC to provision the volume. + The pod in which this EphemeralVolumeSource is embedded will be the + owner of the PVC, i.e. the PVC will be deleted together with the + pod. The name of the PVC will be `-` where + `` is the name from the `PodSpec.Volumes` array + entry. Pod validation will reject the pod if the concatenated name + is not valid for a PVC (for example, too long). + + + An existing PVC with that name that is not owned by the pod + will *not* be used for the pod to avoid using an unrelated + volume by mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created PVC is + meant to be used by the pod, the PVC has to updated with an + owner reference to the pod once the pod exists. Normally + this should not be necessary, but it may be useful when + manually reconstructing a broken cluster. + + + This field is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. + + + Required, must not be nil. + properties: + metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. No other fields are allowed and will be rejected during + validation. + type: object + spec: + description: |- + The specification for the PersistentVolumeClaim. The entire content is + copied unchanged into the PVC that gets created from this + template. The same fields as in a PersistentVolumeClaim + are also valid here. + 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: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + 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. + When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, + and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not be copied to dataSource. + 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 + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed if the type of + the specified object matches some installed volume populator or dynamic + provisioner. + This field will replace the functionality of the dataSource field and as such + if both fields are non-empty, they must have the same value. For backwards + compatibility, when namespace isn't specified in dataSourceRef, + both fields (dataSource and dataSourceRef) will be set to the same + value automatically if one of them is empty and the other is non-empty. + When namespace is specified in dataSourceRef, + dataSource isn't set to the same value and must be empty. + There are three important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping them), dataSourceRef + preserves all values, and generates an error if a disallowed value is + specified. + * While dataSource only allows local objects, dataSourceRef allows objects + in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. + (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + 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 + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is 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 + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + 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 + required: + - spec + type: object + 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: |- + fsType is the 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: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: |- + wwids 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: |- + fsType is the 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: 'options is Optional: this field holds extra + command options if any.' + type: object + readOnly: + description: |- + readOnly is Optional: defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef is 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 + x-kubernetes-map-type: atomic + 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: |- + datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker + should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the 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: |- + fsType is 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: |- + partition is 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: |- + pdName is 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: |- + directory is the 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 is the URL + type: string + revision: + description: revision is the 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: |- + endpoints 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: chapAuthDiscovery defines whether support iSCSI + Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support iSCSI + Session CHAP authentication + type: boolean + fsType: + description: |- + fsType is the 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: |- + initiatorName is the custom iSCSI Initiator Name. + If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface + : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: |- + iscsiInterface is the interface Name that uses an iSCSI transport. + Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: |- + portals is the 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: secretRef is the 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 + x-kubernetes-map-type: atomic + targetPortal: + description: |- + targetPortal is 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: |- + name of the volume. + 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: |- + readOnly 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: |- + fsType is the 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: pdID is the 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: |- + readOnly 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: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: |- + defaultMode are the mode bits used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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: sources is the list of volume projections + items: + description: Projection that may be projected along with + other supported volume types + properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + 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 + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume root + to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: |- + items 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: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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: |- + path is 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: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI 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 + x-kubernetes-map-type: atomic + mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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 + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret data + to project + properties: + items: + description: |- + items 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: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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: |- + path is 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: optional field specify whether the + Secret or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + description: serviceAccountToken is 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 + 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: |- + fsType is the 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: |- + image is 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: |- + monitors is 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: |- + pool is 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 + x-kubernetes-map-type: atomic + user: + description: |- + user is 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: |- + fsType is the 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: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: |- + readOnly 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 + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: |- + storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool associated + with the protection domain. + type: string + system: + description: system is the name of the storage system as + configured in ScaleIO. + type: string + volumeName: + description: |- + volumeName is 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: |- + defaultMode is Optional: mode bits used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values + for mode bits. 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 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: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + 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: |- + path is 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: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: |- + secretName is the 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: |- + fsType is the 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: |- + readOnly 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 + x-kubernetes-map-type: atomic + 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: |- + fsType is 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: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy Based + Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies vSphere + volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + web: + description: Defines the web command line flags when starting Alertmanager. + properties: + getConcurrency: + description: |- + Maximum number of GET requests processed concurrently. This corresponds to the + Alertmanager's `--web.get-concurrency` flag. + format: int32 + type: integer + httpConfig: + description: Defines HTTP parameters for web server. + properties: + headers: + description: List of headers that can be added to HTTP responses. + properties: + contentSecurityPolicy: + description: |- + Set the Content-Security-Policy header to HTTP responses. + Unset if blank. + type: string + strictTransportSecurity: + description: |- + Set the Strict-Transport-Security header to HTTP responses. + Unset if blank. + Please make sure that you use this with care as this header might force + browsers to load Prometheus and the other applications hosted on the same + domain and subdomains over HTTPS. + https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security + type: string + xContentTypeOptions: + description: |- + Set the X-Content-Type-Options header to HTTP responses. + Unset if blank. Accepted value is nosniff. + https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options + enum: + - "" + - NoSniff + type: string + xFrameOptions: + description: |- + Set the X-Frame-Options header to HTTP responses. + Unset if blank. Accepted values are deny and sameorigin. + https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options + enum: + - "" + - Deny + - SameOrigin + type: string + xXSSProtection: + description: |- + Set the X-XSS-Protection header to all responses. + Unset if blank. + https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection + type: string + type: object + http2: + description: |- + Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS. + When TLSConfig is not configured, HTTP/2 will be disabled. + Whenever the value of the field changes, a rolling update will be triggered. + type: boolean + type: object + timeout: + description: |- + Timeout for HTTP requests. This corresponds to the Alertmanager's + `--web.timeout` flag. + format: int32 + type: integer + tlsConfig: + description: Defines the TLS parameters for HTTPS. + properties: + cert: + description: Contains the TLS certificate for the server. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cipherSuites: + description: |- + List of supported cipher suites for TLS versions up to TLS 1.2. If empty, + Go default cipher suites are used. Available cipher suites are documented + in the go documentation: https://golang.org/pkg/crypto/tls/#pkg-constants + items: + type: string + type: array + client_ca: + description: Contains the CA certificate for client certificate + authentication to the server. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientAuthType: + description: |- + Server policy for client authentication. Maps to ClientAuth Policies. + For more detail on clientAuth options: + https://golang.org/pkg/crypto/tls/#ClientAuthType + type: string + curvePreferences: + description: |- + Elliptic curves that will be used in an ECDHE handshake, in preference + order. Available curves are documented in the go documentation: + https://golang.org/pkg/crypto/tls/#CurveID + items: + type: string + type: array + keySecret: + description: Secret containing the TLS key for the server. + 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 + x-kubernetes-map-type: atomic + maxVersion: + description: Maximum TLS version that is acceptable. Defaults + to TLS13. + type: string + minVersion: + description: Minimum TLS version that is acceptable. Defaults + to TLS12. + type: string + preferServerCipherSuites: + description: |- + Controls whether the server selects the + client's most preferred cipher suite, or the server's most preferred + cipher suite. If true then the server's preference, as expressed in + the order of elements in cipherSuites, is used. + type: boolean + required: + - cert + - keySecret + type: object + type: object + type: object + status: + description: |- + Most recent observed status of the Alertmanager cluster. Read-only. + 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 + conditions: + description: The current state of the Alertmanager object. + items: + description: |- + Condition represents the state of the resources associated with the + Prometheus, Alertmanager or ThanosRuler resource. + properties: + lastTransitionTime: + description: lastTransitionTime is the time of the last update + to the current status property. + format: date-time + type: string + message: + description: Human-readable message indicating details for the + condition's last transition. + type: string + observedGeneration: + description: |- + ObservedGeneration represents the .metadata.generation that the + condition was set based upon. For instance, if `.metadata.generation` is + currently 12, but the `.status.conditions[].observedGeneration` is 9, the + condition is out of date with respect to the current state of the + instance. + format: int64 + type: integer + reason: + description: Reason for the condition's last transition. + type: string + status: + description: Status of the condition. + type: string + type: + description: Type of the condition being reported. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + 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 + object (their labels match the selector). + format: int32 + type: integer + unavailableReplicas: + description: Total number of unavailable pods targeted by this Alertmanager + object. + format: int32 + type: integer + updatedReplicas: + description: |- + Total number of non-terminated pods targeted by this Alertmanager + object 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: {} diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-podmonitors.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-podmonitors.yaml new file mode 100644 index 000000000..1db48b269 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-podmonitors.yaml @@ -0,0 +1,905 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.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.14.0 + operator.prometheus.io/version: 0.74.0 + name: podmonitors.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: PodMonitor + listKind: PodMonitorList + plural: podmonitors + shortNames: + - pmon + 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: + attachMetadata: + description: |- + `attachMetadata` defines additional metadata which is added to the + discovered targets. + + + It requires Prometheus >= v2.37.0. + properties: + node: + description: |- + When set to true, Prometheus must have the `get` permission on the + `Nodes` objects. + type: boolean + type: object + bodySizeLimit: + description: |- + When defined, bodySizeLimit specifies a job level limit on the size + of uncompressed response body that will be accepted by Prometheus. + + + It requires Prometheus >= v2.28.0. + pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ + type: string + jobLabel: + description: |- + The label to use to retrieve the job name from. + `jobLabel` selects the label from the associated Kubernetes `Pod` + object which will be used as the `job` label for all metrics. + + + For example if `jobLabel` is set to `foo` and the Kubernetes `Pod` + object is labeled with `foo: bar`, then Prometheus adds the `job="bar"` + label to all ingested metrics. + + + If the value of this field is empty, the `job` label of the metrics + defaults to the namespace and name of the PodMonitor object (e.g. `/`). + type: string + keepDroppedTargets: + description: |- + Per-scrape limit on the number of targets dropped by relabeling + that will be kept in memory. 0 means no limit. + + + It requires Prometheus >= v2.47.0. + format: int64 + type: integer + labelLimit: + description: |- + Per-scrape limit on number of labels that will be accepted for a sample. + + + It requires Prometheus >= v2.27.0. + format: int64 + type: integer + labelNameLengthLimit: + description: |- + Per-scrape limit on length of labels name that will be accepted for a sample. + + + It requires Prometheus >= v2.27.0. + format: int64 + type: integer + labelValueLengthLimit: + description: |- + Per-scrape limit on length of labels value that will be accepted for a sample. + + + It requires Prometheus >= v2.27.0. + format: int64 + type: integer + namespaceSelector: + description: |- + Selector to select which namespaces the Kubernetes `Pods` 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 to select from. + items: + type: string + type: array + type: object + podMetricsEndpoints: + description: List of endpoints part of this PodMonitor. + items: + description: |- + PodMetricsEndpoint defines an endpoint serving Prometheus metrics to be scraped by + Prometheus. + properties: + authorization: + description: |- + `authorization` configures the Authorization header credentials to use when + scraping the target. + + + Cannot be set at the same time as `basicAuth`, or `oauth2`. + properties: + credentials: + description: Selects a key of a Secret in the namespace + that contains the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + `basicAuth` configures the Basic Authentication credentials to use when + scraping the target. + + + Cannot be set at the same time as `authorization`, or `oauth2`. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + type: object + bearerTokenSecret: + description: |- + `bearerTokenSecret` specifies a key of a Secret containing the bearer + token for scraping targets. The secret needs to be in the same namespace + as the PodMonitor object and readable by the Prometheus Operator. + + + Deprecated: use `authorization` instead. + 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 + x-kubernetes-map-type: atomic + enableHttp2: + description: '`enableHttp2` can be used to disable HTTP2 when + scraping the target.' + type: boolean + filterRunning: + description: |- + When true, the pods which are not running (e.g. either in Failed or + Succeeded state) are dropped during the target discovery. + + + If unset, the filtering is enabled. + + + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase + type: boolean + followRedirects: + description: |- + `followRedirects` defines whether the scrape requests should follow HTTP + 3xx redirects. + type: boolean + honorLabels: + description: |- + When true, `honorLabels` preserves the metric's labels when they collide + with the target's labels. + type: boolean + honorTimestamps: + description: |- + `honorTimestamps` controls whether Prometheus preserves the timestamps + when exposed by the target. + type: boolean + interval: + description: |- + Interval at which Prometheus scrapes the metrics from the target. + + + If empty, Prometheus uses the global scrape interval. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + metricRelabelings: + description: |- + `metricRelabelings` configures the relabeling rules to apply to the + samples before ingestion. + items: + description: |- + RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + scraped samples and remote write samples. + + + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + properties: + action: + default: replace + description: |- + Action to perform based on the regex matching. + + + `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + + + Default: "Replace" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: |- + Modulus to take of the hash of the source label values. + + + Only applicable when the action is `HashMod`. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: |- + Replacement value against which a Replace action is performed if the + regular expression matches. + + + Regex capture groups are available. + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + 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. + items: + description: |- + LabelName is a valid Prometheus label name which may only contain ASCII + letters, numbers, as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: |- + Label to which the resulting string is written in a replacement. + + + It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + `KeepEqual` and `DropEqual` actions. + + + Regex capture groups are available. + type: string + type: object + type: array + oauth2: + description: |- + `oauth2` configures the OAuth2 settings to use when scraping the target. + + + It requires Prometheus >= 2.27.0. + + + Cannot be set at the same time as `authorization`, or `basicAuth`. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes used for + the token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to fetch the + token from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + params: + additionalProperties: + items: + type: string + type: array + description: '`params` define optional HTTP URL parameters.' + type: object + path: + description: |- + HTTP path from which to scrape for metrics. + + + If empty, Prometheus uses the default value (e.g. `/metrics`). + type: string + port: + description: |- + Name of the Pod port which this endpoint refers to. + + + It takes precedence over `targetPort`. + type: string + proxyUrl: + description: |- + `proxyURL` configures the HTTP Proxy URL (e.g. + "http://proxyserver:2195") to go through when scraping the target. + type: string + relabelings: + description: |- + `relabelings` configures the relabeling rules to apply the target's + metadata labels. + + + The Operator automatically adds relabelings for a few standard Kubernetes fields. + + + The original scrape job's name is available via the `__tmp_prometheus_job_name` label. + + + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + items: + description: |- + RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + scraped samples and remote write samples. + + + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + properties: + action: + default: replace + description: |- + Action to perform based on the regex matching. + + + `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + + + Default: "Replace" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: |- + Modulus to take of the hash of the source label values. + + + Only applicable when the action is `HashMod`. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: |- + Replacement value against which a Replace action is performed if the + regular expression matches. + + + Regex capture groups are available. + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + 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. + items: + description: |- + LabelName is a valid Prometheus label name which may only contain ASCII + letters, numbers, as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: |- + Label to which the resulting string is written in a replacement. + + + It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + `KeepEqual` and `DropEqual` actions. + + + Regex capture groups are available. + type: string + type: object + type: array + scheme: + description: |- + HTTP scheme to use for scraping. + + + `http` and `https` are the expected values unless you rewrite the + `__scheme__` label via relabeling. + + + If empty, Prometheus uses the default value `http`. + enum: + - http + - https + type: string + scrapeTimeout: + description: |- + Timeout after which Prometheus considers the scrape to be failed. + + + If empty, Prometheus uses the global scrape timeout unless it is less + than the target's scrape interval value in which the latter is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetPort: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the target port of the `Pod` object behind the Service, the + port must be specified with container port property. + + + Deprecated: use 'port' instead. + x-kubernetes-int-or-string: true + tlsConfig: + description: TLS configuration to use when scraping the target. + properties: + ca: + description: Certificate authority used when verifying server + certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + trackTimestampsStaleness: + description: |- + `trackTimestampsStaleness` defines whether Prometheus tracks staleness of + the metrics that have an explicit timestamp present in scraped data. + Has no effect if `honorTimestamps` is false. + + + It requires Prometheus >= v2.48.0. + type: boolean + type: object + type: array + podTargetLabels: + description: |- + `podTargetLabels` defines the labels which are transferred from the + associated Kubernetes `Pod` object onto the ingested metrics. + items: + type: string + type: array + sampleLimit: + description: |- + `sampleLimit` defines a per-scrape limit on the number of scraped samples + that will be accepted. + format: int64 + type: integer + scrapeClass: + description: The scrape class to apply. + minLength: 1 + type: string + scrapeProtocols: + description: |- + `scrapeProtocols` defines the protocols to negotiate during a scrape. It tells clients the + protocols supported by Prometheus in order of preference (from most to least preferred). + + + If unset, Prometheus uses its default value. + + + It requires Prometheus >= v2.49.0. + items: + description: |- + ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. + Supported values are: + * `OpenMetricsText0.0.1` + * `OpenMetricsText1.0.0` + * `PrometheusProto` + * `PrometheusText0.0.4` + enum: + - PrometheusProto + - OpenMetricsText0.0.1 + - OpenMetricsText1.0.0 + - PrometheusText0.0.4 + type: string + type: array + x-kubernetes-list-type: set + selector: + description: Label selector to select the Kubernetes `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 + x-kubernetes-map-type: atomic + targetLimit: + description: |- + `targetLimit` defines a limit on the number of scraped targets that will + be accepted. + format: int64 + type: integer + required: + - selector + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-probes.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-probes.yaml new file mode 100644 index 000000000..e65f976c1 --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-probes.yaml @@ -0,0 +1,881 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.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.14.0 + operator.prometheus.io/version: 0.74.0 + name: probes.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: Probe + listKind: ProbeList + plural: probes + shortNames: + - prb + 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: + authorization: + description: Authorization section for this endpoint + properties: + credentials: + description: Selects a key of a Secret in the namespace that contains + the credentials 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 + x-kubernetes-map-type: atomic + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth allow an endpoint to authenticate over basic authentication. + More info: https://prometheus.io/docs/operating/configuration/#endpoint + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + 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 probe 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 + x-kubernetes-map-type: atomic + interval: + description: |- + Interval at which targets are probed using the configured prober. + If not specified Prometheus' global scrape interval is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + jobName: + description: The job name assigned to scraped metrics by default. + type: string + keepDroppedTargets: + description: |- + Per-scrape limit on the number of targets dropped by relabeling + that will be kept in memory. 0 means no limit. + + + It requires Prometheus >= v2.47.0. + format: int64 + type: integer + labelLimit: + description: |- + Per-scrape limit on number of labels that will be accepted for a sample. + Only valid in Prometheus versions 2.27.0 and newer. + format: int64 + type: integer + labelNameLengthLimit: + description: |- + Per-scrape limit on length of labels name that will be accepted for a sample. + Only valid in Prometheus versions 2.27.0 and newer. + format: int64 + type: integer + labelValueLengthLimit: + description: |- + Per-scrape limit on length of labels value that will be accepted for a sample. + Only valid in Prometheus versions 2.27.0 and newer. + format: int64 + type: integer + metricRelabelings: + description: MetricRelabelConfigs to apply to samples before ingestion. + items: + description: |- + RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + scraped samples and remote write samples. + + + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + properties: + action: + default: replace + description: |- + Action to perform based on the regex matching. + + + `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + + + Default: "Replace" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: |- + Modulus to take of the hash of the source label values. + + + Only applicable when the action is `HashMod`. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: |- + Replacement value against which a Replace action is performed if the + regular expression matches. + + + Regex capture groups are available. + type: string + separator: + description: Separator is the string between concatenated SourceLabels. + 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. + items: + description: |- + LabelName is a valid Prometheus label name which may only contain ASCII + letters, numbers, as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: |- + Label to which the resulting string is written in a replacement. + + + It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + `KeepEqual` and `DropEqual` actions. + + + Regex capture groups are available. + type: string + type: object + type: array + 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 + oauth2: + description: OAuth2 for the URL. Only valid in Prometheus versions + 2.27.0 and newer. + properties: + clientId: + description: |- + `clientId` specifies a key of a Secret or ConfigMap containing the + OAuth2 client's ID. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + clientSecret: + description: |- + `clientSecret` specifies a key of a Secret containing the OAuth2 + client's 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 + x-kubernetes-map-type: atomic + endpointParams: + additionalProperties: + type: string + description: |- + `endpointParams` configures the HTTP parameters to append to the token + URL. + type: object + scopes: + description: '`scopes` defines the OAuth2 scopes used for the + token request.' + items: + type: string + type: array + tokenUrl: + description: '`tokenURL` configures the URL to fetch the token + from.' + minLength: 1 + type: string + required: + - clientId + - clientSecret + - tokenUrl + type: object + 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: + default: /probe + description: |- + Path to collect metrics from. + Defaults to `/probe`. + type: string + proxyUrl: + description: Optional ProxyURL. + type: string + scheme: + description: |- + HTTP scheme to use for scraping. + `http` and `https` are the expected values unless you rewrite the `__scheme__` label via relabeling. + If empty, Prometheus uses the default value `http`. + enum: + - http + - https + type: string + url: + description: Mandatory URL of the prober. + type: string + required: + - url + type: object + sampleLimit: + description: SampleLimit defines per-scrape limit on number of scraped + samples that will be accepted. + format: int64 + type: integer + scrapeClass: + description: The scrape class to apply. + minLength: 1 + type: string + scrapeProtocols: + description: |- + `scrapeProtocols` defines the protocols to negotiate during a scrape. It tells clients the + protocols supported by Prometheus in order of preference (from most to least preferred). + + + If unset, Prometheus uses its default value. + + + It requires Prometheus >= v2.49.0. + items: + description: |- + ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. + Supported values are: + * `OpenMetricsText0.0.1` + * `OpenMetricsText1.0.0` + * `PrometheusProto` + * `PrometheusText0.0.4` + enum: + - PrometheusProto + - OpenMetricsText0.0.1 + - OpenMetricsText1.0.0 + - PrometheusText0.0.4 + type: string + type: array + x-kubernetes-list-type: set + scrapeTimeout: + description: |- + Timeout for scraping metrics from the Prometheus exporter. + If not specified, the Prometheus global scrape timeout is used. + pattern: ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$ + type: string + targetLimit: + description: TargetLimit defines a limit on the number of scraped + targets that will be accepted. + format: int64 + type: integer + targets: + description: Targets defines a set of static or dynamically discovered + targets to probe. + properties: + ingress: + description: |- + ingress defines the Ingress objects to probe and the relabeling + configuration. + If `staticConfig` is also defined, `staticConfig` takes precedence. + properties: + namespaceSelector: + description: From which namespaces to select Ingress objects. + 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 to select from. + items: + type: string + type: array + type: object + relabelingConfigs: + description: |- + RelabelConfigs to apply to the label set of the target before it gets + scraped. + The original ingress address is available via the + `__tmp_prometheus_ingress_address` label. It can be used to customize the + probed URL. + The original scrape job's name is available via the `__tmp_prometheus_job_name` label. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + items: + description: |- + RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + scraped samples and remote write samples. + + + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + properties: + action: + default: replace + description: |- + Action to perform based on the regex matching. + + + `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + + + Default: "Replace" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: |- + Modulus to take of the hash of the source label values. + + + Only applicable when the action is `HashMod`. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: |- + Replacement value against which a Replace action is performed if the + regular expression matches. + + + Regex capture groups are available. + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + 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. + items: + description: |- + LabelName is a valid Prometheus label name which may only contain ASCII + letters, numbers, as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: |- + Label to which the resulting string is written in a replacement. + + + It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + `KeepEqual` and `DropEqual` actions. + + + Regex capture groups are available. + type: string + type: object + type: array + selector: + description: Selector to select the Ingress 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 + x-kubernetes-map-type: atomic + type: object + staticConfig: + description: |- + staticConfig defines the static list of targets to probe and the + relabeling configuration. + If `ingress` is also defined, `staticConfig` takes precedence. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config. + properties: + labels: + additionalProperties: + type: string + description: Labels assigned to all metrics scraped from the + targets. + type: object + relabelingConfigs: + description: |- + RelabelConfigs to apply to the label set of the targets before it gets + scraped. + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + items: + description: |- + RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + scraped samples and remote write samples. + + + More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + properties: + action: + default: replace + description: |- + Action to perform based on the regex matching. + + + `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + + + Default: "Replace" + enum: + - replace + - Replace + - keep + - Keep + - drop + - Drop + - hashmod + - HashMod + - labelmap + - LabelMap + - labeldrop + - LabelDrop + - labelkeep + - LabelKeep + - lowercase + - Lowercase + - uppercase + - Uppercase + - keepequal + - KeepEqual + - dropequal + - DropEqual + type: string + modulus: + description: |- + Modulus to take of the hash of the source label values. + + + Only applicable when the action is `HashMod`. + format: int64 + type: integer + regex: + description: Regular expression against which the extracted + value is matched. + type: string + replacement: + description: |- + Replacement value against which a Replace action is performed if the + regular expression matches. + + + Regex capture groups are available. + type: string + separator: + description: Separator is the string between concatenated + SourceLabels. + 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. + items: + description: |- + LabelName is a valid Prometheus label name which may only contain ASCII + letters, numbers, as well as underscores. + pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$ + type: string + type: array + targetLabel: + description: |- + Label to which the resulting string is written in a replacement. + + + It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + `KeepEqual` and `DropEqual` actions. + + + Regex capture groups are available. + type: string + type: object + type: array + static: + description: The list of hosts to probe. + items: + type: string + type: array + type: object + type: object + tlsConfig: + description: TLS configuration to use when scraping the endpoint. + properties: + ca: + description: Certificate authority used when verifying server + certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + cert: + description: Client certificate to present when doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-prometheusagents.yaml b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-prometheusagents.yaml new file mode 100644 index 000000000..caa24793b --- /dev/null +++ b/backend/charts/deepgram-self-hosted/nova-3/charts/kube-prometheus-stack/charts/crds/crds/crd-prometheusagents.yaml @@ -0,0 +1,9525 @@ +# https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.74.0/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + operator.prometheus.io/version: 0.74.0 + name: prometheusagents.monitoring.coreos.com +spec: + group: monitoring.coreos.com + names: + categories: + - prometheus-operator + kind: PrometheusAgent + listKind: PrometheusAgentList + plural: prometheusagents + shortNames: + - promagent + singular: prometheusagent + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The version of Prometheus agent + jsonPath: .spec.version + name: Version + type: string + - description: The number of desired replicas + jsonPath: .spec.replicas + name: Desired + type: integer + - description: The number of ready replicas + jsonPath: .status.availableReplicas + name: Ready + type: integer + - jsonPath: .status.conditions[?(@.type == 'Reconciled')].status + name: Reconciled + type: string + - jsonPath: .status.conditions[?(@.type == 'Available')].status + name: Available + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: Whether the resource reconciliation is paused or not + jsonPath: .status.paused + name: Paused + priority: 1 + type: boolean + name: v1alpha1 + schema: + openAPIV3Schema: + description: PrometheusAgent defines a Prometheus agent 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 agent. More info: + https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + properties: + additionalArgs: + description: |- + AdditionalArgs allows setting additional arguments for the 'prometheus' container. + + + It is intended for e.g. activating hidden flags which are not supported by + the dedicated configuration options yet. The arguments are passed as-is to the + Prometheus container which may cause issues if they are invalid or not supported + by the given Prometheus version. + + + In case of an argument conflict (e.g. an argument which is already set by the + operator itself) or when providing an invalid argument, the reconciliation will + fail and an error will be logged. + items: + description: Argument as part of the AdditionalArgs list. + properties: + name: + description: Name of the argument, e.g. "scrape.discovery-reload-interval". + minLength: 1 + type: string + value: + description: Argument value, e.g. 30s. Can be empty for name-only + arguments (e.g. --storage.tsdb.no-lockfile) + type: string + required: + - name + type: object + type: array + 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 + x-kubernetes-map-type: atomic + affinity: + description: Defines the Pods' affinity scheduling rules if specified. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + 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. + If it's null, this PodAffinityTerm matches with no 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector 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 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. + If it's null, this PodAffinityTerm matches with no 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector 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. + If it's null, this PodAffinityTerm matches with no 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector 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 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. + If it's null, this PodAffinityTerm matches with no 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 + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. + Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + 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 + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector 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 + apiserverConfig: + description: |- + APIServerConfig allows specifying a host and auth methods to access the + Kuberntees API server. + If null, Prometheus is assumed to run inside of the cluster: it will + discover the API servers automatically and use the Pod's CA certificate + and bearer token file at /var/run/secrets/kubernetes.io/serviceaccount/. + properties: + authorization: + description: |- + Authorization section for the API server. + + + Cannot be set at the same time as `basicAuth`, `bearerToken`, or + `bearerTokenFile`. + properties: + credentials: + description: Selects a key of a Secret in the namespace that + contains the credentials 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 + x-kubernetes-map-type: atomic + credentialsFile: + description: File to read a secret from, mutually exclusive + with `credentials`. + type: string + type: + description: |- + Defines the authentication type. The value is case-insensitive. + + + "Basic" is not a supported value. + + + Default: "Bearer" + type: string + type: object + basicAuth: + description: |- + BasicAuth configuration for the API server. + + + Cannot be set at the same time as `authorization`, `bearerToken`, or + `bearerTokenFile`. + properties: + password: + description: |- + `password` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + username: + description: |- + `username` specifies a key of a Secret containing 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 + x-kubernetes-map-type: atomic + type: object + bearerToken: + description: |- + *Warning: this field shouldn't be used because the token value appears + in clear-text. Prefer using `authorization`.* + + + Deprecated: this will be removed in a future release. + type: string + bearerTokenFile: + description: |- + File to read bearer token for accessing apiserver. + + + Cannot be set at the same time as `basicAuth`, `authorization`, or `bearerToken`. + + + Deprecated: this will be removed in a future release. Prefer using `authorization`. + type: string + host: + description: |- + Kubernetes API address consisting of a hostname or IP address followed + by an optional port number. + type: string + tlsConfig: + description: TLS Config to use for the API server. + properties: + ca: + description: Certificate authority used when verifying server + certificates. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + caFile: + description: Path to the CA cert in the Prometheus container + to use for the targets. + type: string + cert: + description: Client certificate to present when doing client-authentication. + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + serverName: + description: Used to verify the hostname for the targets. + type: string + type: object + required: + - host + type: object + arbitraryFSAccessThroughSMs: + description: |- + When true, ServiceMonitor, PodMonitor and Probe object are forbidden to + reference arbitrary files on the file system of the 'prometheus' + container. + When a ServiceMonitor's endpoint specifies a `bearerTokenFile` value + (e.g. '/var/run/secrets/kubernetes.io/serviceaccount/token'), a + malicious target can get access to the Prometheus service account's + token in the Prometheus' scrape request. Setting + `spec.arbitraryFSAccessThroughSM` to 'true' would prevent the attack. + Users should instead provide the credentials using the + `spec.bearerTokenSecret` field. + properties: + deny: + type: boolean + type: object + automountServiceAccountToken: + description: |- + AutomountServiceAccountToken indicates whether a service account token should be automatically mounted in the pod. + If the field isn't set, the operator mounts the service account token by default. + + + **Warning:** be aware that by default, Prometheus requires the service account token for Kubernetes service discovery. + It is possible to use strategic merge patch to project the service account token into the 'prometheus' container. + type: boolean + bodySizeLimit: + description: |- + BodySizeLimit defines per-scrape on response body size. + Only valid in Prometheus versions 2.45.0 and newer. + pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ + 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. + Each ConfigMap is added to the StatefulSet definition as a volume named `configmap-`. + The ConfigMaps are mounted into /etc/prometheus/configmaps/ in the 'prometheus' container. + 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 the Pods 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 names of containers managed by the operator are: + * `prometheus` + * `config-reloader` + * `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 container 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(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 container 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(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 previously 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: |- + Container 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: 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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 + sleep: + description: Sleep represents the duration that the + container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for the backward compatibility. There are no validation of this field and + lifecycle hooks will fail in runtime when tcp handler is specified. + 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 Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). 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: 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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 + sleep: + description: Sleep represents the duration that the + container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for the backward compatibility. There are no validation of this field and + lifecycle hooks will fail in runtime when tcp handler is specified. + 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: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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. 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. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + 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: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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 + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + 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 + Note that this field cannot be set when spec.os.name is windows. + type: boolean + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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 + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + 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. + Note that this field cannot be set when spec.os.name is linux. + 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 + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + 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. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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 + enableFeatures: + description: |- + Enable access to Prometheus feature flags. By default, no features are enabled. + + + Enabling features which are disabled by default 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. + + + For more information see https://prometheus.io/docs/prometheus/latest/feature_flags/ + items: + minLength: 1 + type: string + type: array + x-kubernetes-list-type: set + enableRemoteWriteReceiver: + description: |- + Enable Prometheus to be used as a receiver for the Prometheus remote + write protocol. + + + WARNING: This is not considered an efficient way of ingesting samples. + Use it with caution for specific low-volume use cases. + It is not suitable for replacing the ingestion via scraping and turning + Prometheus into a push-based metrics collection system. + For more information see https://prometheus.io/docs/prometheus/latest/querying/api/#remote-write-receiver + + + It requires Prometheus >= v2.33.0. + type: boolean + enforcedBodySizeLimit: + description: |- + When defined, enforcedBodySizeLimit specifies a global limit on the size + of uncompressed response body that will be accepted by Prometheus. + Targets responding with a body larger than this many bytes will cause + the scrape to fail. + + + It requires Prometheus >= v2.28.0. + pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$ + type: string + enforcedKeepDroppedTargets: + description: |- + When defined, enforcedKeepDroppedTargets specifies a global limit on the number of targets + dropped by relabeling that will be kept in memory. The value overrides + any `spec.keepDroppedTargets` set by + ServiceMonitor, PodMonitor, Probe objects unless `spec.keepDroppedTargets` is + greater than zero and less than `spec.enforcedKeepDroppedTargets`. + + + It requires Prometheus >= v2.47.0. + format: int64 + type: integer + enforcedLabelLimit: + description: |- + When defined, enforcedLabelLimit specifies a global limit on the number + of labels per sample. The value overrides any `spec.labelLimit` set by + ServiceMonitor, PodMonitor, Probe objects unless `spec.labelLimit` is + greater than zero and less than `spec.enforcedLabelLimit`. + + + It requires Prometheus >= v2.27.0. + format: int64 + type: integer + enforcedLabelNameLengthLimit: + description: |- + When defined, enforcedLabelNameLengthLimit specifies a global limit on the length + of labels name per sample. The value overrides any `spec.labelNameLengthLimit` set by + ServiceMonitor, PodMonitor, Probe objects unless `spec.labelNameLengthLimit` is + greater than zero and less than `spec.enforcedLabelNameLengthLimit`. + + + It requires Prometheus >= v2.27.0. + format: int64 + type: integer + enforcedLabelValueLengthLimit: + description: |- + When not null, enforcedLabelValueLengthLimit defines a global limit on the length + of labels value per sample. The value overrides any `spec.labelValueLengthLimit` set by + ServiceMonitor, PodMonitor, Probe objects unless `spec.labelValueLengthLimit` is + greater than zero and less than `spec.enforcedLabelValueLengthLimit`. + + + It requires Prometheus >= v2.27.0. + format: int64 + type: integer + enforcedNamespaceLabel: + description: |- + When not empty, a label will be added to: + + + 1. All metrics scraped from `ServiceMonitor`, `PodMonitor`, `Probe` and `ScrapeConfig` objects. + 2. All metrics generated from recording rules defined in `PrometheusRule` objects. + 3. All alerts generated from alerting rules defined in `PrometheusRule` objects. + 4. All vector selectors of PromQL expressions defined in `PrometheusRule` objects. + + + The label will not added for objects referenced in `spec.excludedFromEnforcement`. + + + The label's name is this field's value. + The label's value is the namespace of the `ServiceMonitor`, + `PodMonitor`, `Probe`, `PrometheusRule` or `ScrapeConfig` object. + type: string + enforcedSampleLimit: + description: |- + When defined, enforcedSampleLimit specifies a global limit on the number + of scraped samples that will be accepted. This overrides any + `spec.sampleLimit` set by ServiceMonitor, PodMonitor, Probe objects + unless `spec.sampleLimit` is greater than zero and less than + `spec.enforcedSampleLimit`. + + + It is meant to be used by admins to keep the overall number of + samples/series under a desired limit. + format: int64 + type: integer + enforcedTargetLimit: + description: |- + When defined, enforcedTargetLimit specifies a global limit on the number + of scraped targets. The value overrides any `spec.targetLimit` set by + ServiceMonitor, PodMonitor, Probe objects unless `spec.targetLimit` is + greater than zero and less than `spec.enforcedTargetLimit`. + + + It is meant to be used by admins to to keep the overall number of + targets under a desired limit. + format: int64 + type: integer + excludedFromEnforcement: + description: |- + List of references to PodMonitor, ServiceMonitor, Probe and PrometheusRule objects + to be excluded from enforcing a namespace label of origin. + + + It is only applicable if `spec.enforcedNamespaceLabel` set to true. + items: + description: ObjectReference references a PodMonitor, ServiceMonitor, + Probe or PrometheusRule object. + properties: + group: + default: monitoring.coreos.com + description: Group of the referent. When not specified, it defaults + to `monitoring.coreos.com` + enum: + - monitoring.coreos.com + type: string + name: + description: Name of the referent. When not set, all resources + in the namespace are matched. + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + minLength: 1 + type: string + resource: + description: Resource of the referent. + enum: + - prometheusrules + - servicemonitors + - podmonitors + - probes + - scrapeconfigs + type: string + required: + - namespace + - resource + type: object + type: array + externalLabels: + additionalProperties: + type: string + description: |- + The labels to add to any time series or alerts when communicating with + external systems (federation, remote storage, Alertmanager). + Labels defined by `spec.replicaExternalLabelName` and + `spec.prometheusExternalLabelName` take precedence over this list. + type: object + externalUrl: + description: |- + The external URL under which the Prometheus service is externally + available. This is necessary to generate correct URLs (for instance if + Prometheus is accessible behind an Ingress resource). + type: string + hostAliases: + description: |- + Optional list of hosts and IPs that will be injected into the Pod's + hosts file if specified. + items: + description: |- + HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the + pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + required: + - hostnames + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostNetwork: + description: |- + Use the host's network namespace if true. + + + Make sure to understand the security implications if you want to enable + it (https://kubernetes.io/docs/concepts/configuration/overview/). + + + When hostNetwork is enabled, this will set the DNS policy to + `ClusterFirstWithHostNet` automatically. + type: boolean + ignoreNamespaceSelectors: + description: |- + When true, `spec.namespaceSelector` from all PodMonitor, ServiceMonitor + and Probe objects will be ignored. They will only discover targets + within the namespace of the PodMonitor, ServiceMonitor and Probe + object. + type: boolean + image: + description: |- + Container image name for Prometheus. If specified, it takes precedence + over the `spec.baseImage`, `spec.tag` and `spec.sha` fields. + + + Specifying `spec.version` is still necessary to ensure the Prometheus + Operator knows which version of Prometheus is being configured. + + + If neither `spec.image` nor `spec.baseImage` are defined, the operator + will use the latest upstream version of Prometheus available at the time + when the operator was released. + type: string + imagePullPolicy: + description: |- + Image pull policy for the 'prometheus', 'init-config-reloader' and 'config-reloader' containers. + See https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy for more details. + enum: + - "" + - Always + - Never + - IfNotPresent + type: string + imagePullSecrets: + description: |- + An optional list of references to Secrets in the same namespace + to use for pulling 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 + x-kubernetes-map-type: atomic + type: array + initContainers: + description: |- + InitContainers allows injecting 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/ + InitContainers described here modify an operator generated init + containers if they share the same name and modifications are done via a + strategic merge patch. + + + The names of init container name managed by the operator are: + * `init-config-reloader`. + + + Overriding init 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 container 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(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 container 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(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 previously 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. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + 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 + x-kubernetes-map-type: atomic + type: object + type: array + image: + description: |- + Container 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: 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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 + sleep: + description: Sleep represents the duration that the + container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for the backward compatibility. There are no validation of this field and + lifecycle hooks will fail in runtime when tcp handler is specified. + 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 Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). 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: 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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 + sleep: + description: Sleep represents the duration that the + container should sleep before being terminated. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for the backward compatibility. There are no validation of this field and + lifecycle hooks will fail in runtime when tcp handler is specified. + 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: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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. 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. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + 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: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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 + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + 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 + Note that this field cannot be set when spec.os.name is windows. + type: boolean + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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. + Note that this field cannot be set when spec.os.name is windows. + 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 + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + 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. + Note that this field cannot be set when spec.os.name is linux. + 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 + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + 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. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: 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 + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + format: int32 + type: integer + service: + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + 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. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + 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. + 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 + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + 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 + keepDroppedTargets: + description: |- + Per-scrape limit on the number of targets dropped by relabeling + that will be kept in memory. 0 means no limit. + + + It requires Prometheus >= v2.47.0. + format: int64 + type: integer + labelLimit: + description: |- + Per-scrape limit on number of labels that will be accepted for a sample. + Only valid in Prometheus versions 2.45.0 and newer. + format: int64 + type: integer + labelNameLengthLimit: + description: |- + Per-scrape limit on length of labels name that will be accepted for a sample. + Only valid in Prometheus versions 2.45.0 and newer. + format: int64 + type: integer + labelValueLengthLimit: + description: |- + Per-scrape limit on length of labels value that will be accepted for a sample. + Only valid in Prometheus versions 2.45.0 and newer. + format: int64 + type: integer + listenLocal: + description: |- + When true, the Prometheus server listens on the loopback address + instead of the Pod IP's address. + type: boolean + logFormat: + description: Log format for Log level for Prometheus and the config-reloader + sidecar. + enum: + - "" + - logfmt + - json + type: string + logLevel: + description: Log level for Prometheus and the config-reloader sidecar. + enum: + - "" + - debug + - info + - warn + - error + type: string + maximumStartupDurationSeconds: + description: |- + Defines the maximum time that the `prometheus` container's startup probe will wait before being considered failed. The startup probe will return success after the WAL replay is complete. + If set, the value should be greater than 60 (seconds). Otherwise it will be equal to 600 seconds (15 minutes). + format: int32 + minimum: 60 + type: integer + minReadySeconds: + description: |- + Minimum number of seconds for which a newly created Pod should be ready + without any of its container crashing for it to be considered available. + Defaults to 0 (pod will be considered available as soon as it is ready) + + + This is an alpha field from kubernetes 1.22 until 1.24 which requires + enabling the StatefulSetMinReadySeconds feature gate. + format: int32 + type: integer + nodeSelector: + additionalProperties: + type: string + description: Defines on which Nodes the Pods are scheduled. + type: object + overrideHonorLabels: + description: |- + When true, Prometheus resolves label conflicts by renaming the labels in + the scraped data to "exported_