diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index 2de01160..347bfd30 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -71,11 +71,17 @@ jobs: name: pr-patch path: _out/assets/pr.patch - - name: Upload installer + - name: Upload CRDs uses: actions/upload-artifact@v4 with: - name: cozystack-installer - path: _out/assets/cozystack-installer.yaml + name: cozystack-crds + path: _out/assets/cozystack-crds.yaml + + - name: Upload operator + uses: actions/upload-artifact@v4 + with: + name: cozystack-operator + path: _out/assets/cozystack-operator.yaml - name: Upload Talos image uses: actions/upload-artifact@v4 @@ -88,8 +94,9 @@ jobs: runs-on: ubuntu-latest if: contains(github.event.pull_request.labels.*.name, 'release') outputs: - installer_id: ${{ steps.fetch_assets.outputs.installer_id }} - disk_id: ${{ steps.fetch_assets.outputs.disk_id }} + crds_id: ${{ steps.fetch_assets.outputs.crds_id }} + operator_id: ${{ steps.fetch_assets.outputs.operator_id }} + disk_id: ${{ steps.fetch_assets.outputs.disk_id }} steps: - name: Checkout code @@ -132,19 +139,22 @@ jobs: return; } const find = (n) => draft.assets.find(a => a.name === n)?.id; - const installerId = find('cozystack-installer.yaml'); - const diskId = find('nocloud-amd64.raw.xz'); - if (!installerId || !diskId) { + const crdsId = find('cozystack-crds.yaml'); + const operatorId = find('cozystack-operator.yaml'); + const diskId = find('nocloud-amd64.raw.xz'); + if (!crdsId || !operatorId || !diskId) { core.setFailed('Required assets missing in draft release'); return; } - core.setOutput('installer_id', installerId); - core.setOutput('disk_id', diskId); + core.setOutput('crds_id', crdsId); + core.setOutput('operator_id', operatorId); + core.setOutput('disk_id', diskId); - prepare_env: - name: "Prepare environment" - runs-on: [self-hosted] + e2e: + name: "E2E Tests" + runs-on: [oracle-vm-24cpu-96gb-x86-64] + #runs-on: [oracle-vm-32cpu-128gb-x86-64] permissions: contents: read packages: read @@ -164,6 +174,20 @@ jobs: name: talos-image path: _out/assets + - name: "Download CRDs (regular PR)" + if: "!contains(github.event.pull_request.labels.*.name, 'release')" + uses: actions/download-artifact@v4 + with: + name: cozystack-crds + path: _out/assets + + - name: "Download operator (regular PR)" + if: "!contains(github.event.pull_request.labels.*.name, 'release')" + uses: actions/download-artifact@v4 + with: + name: cozystack-operator + path: _out/assets + - name: Download PR patch if: "!contains(github.event.pull_request.labels.*.name, 'release')" uses: actions/download-artifact@v4 @@ -184,13 +208,19 @@ jobs: curl -sSL -H "Authorization: token ${GH_PAT}" -H "Accept: application/octet-stream" \ -o _out/assets/nocloud-amd64.raw.xz \ "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/assets/${{ needs.resolve_assets.outputs.disk_id }}" + curl -sSL -H "Authorization: token ${GH_PAT}" -H "Accept: application/octet-stream" \ + -o _out/assets/cozystack-crds.yaml \ + "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/assets/${{ needs.resolve_assets.outputs.crds_id }}" + curl -sSL -H "Authorization: token ${GH_PAT}" -H "Accept: application/octet-stream" \ + -o _out/assets/cozystack-operator.yaml \ + "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/assets/${{ needs.resolve_assets.outputs.operator_id }}" env: GH_PAT: ${{ secrets.GH_PAT }} - name: Set sandbox ID run: echo "SANDBOX_NAME=cozy-e2e-sandbox-$(echo "${GITHUB_REPOSITORY}:${GITHUB_WORKFLOW}:${GITHUB_REF}" | sha256sum | cut -c1-10)" >> $GITHUB_ENV - # ▸ Start actual job steps + # ▸ Prepare environment - name: Prepare workspace run: | rm -rf /tmp/$SANDBOX_NAME @@ -210,47 +240,7 @@ jobs: done echo "✅ The task completed successfully after $attempt attempts" - install_cozystack: - name: "Install Cozystack" - runs-on: [self-hosted] - permissions: - contents: read - packages: read - needs: ["prepare_env", "resolve_assets"] - if: ${{ always() && needs.prepare_env.result == 'success' }} - - steps: - - name: Prepare _out/assets directory - run: mkdir -p _out/assets - - # ▸ Regular PR path – download artefacts produced by the *build* job - - name: "Download installer (regular PR)" - if: "!contains(github.event.pull_request.labels.*.name, 'release')" - uses: actions/download-artifact@v4 - with: - name: cozystack-installer - path: _out/assets - - # ▸ Release PR path – fetch artefacts from the corresponding draft release - - name: Download assets from draft release (release PR) - if: contains(github.event.pull_request.labels.*.name, 'release') - run: | - mkdir -p _out/assets - curl -sSL -H "Authorization: token ${GH_PAT}" -H "Accept: application/octet-stream" \ - -o _out/assets/cozystack-installer.yaml \ - "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/assets/${{ needs.resolve_assets.outputs.installer_id }}" - env: - GH_PAT: ${{ secrets.GH_PAT }} - - # ▸ Start actual job steps - - name: Set sandbox ID - run: echo "SANDBOX_NAME=cozy-e2e-sandbox-$(echo "${GITHUB_REPOSITORY}:${GITHUB_WORKFLOW}:${GITHUB_REF}" | sha256sum | cut -c1-10)" >> $GITHUB_ENV - - - name: Sync _out/assets directory - run: | - mkdir -p /tmp/$SANDBOX_NAME/_out/assets - mv _out/assets/* /tmp/$SANDBOX_NAME/_out/assets/ - + # ▸ Install Cozystack - name: Install Cozystack into sandbox run: | cd /tmp/$SANDBOX_NAME @@ -263,107 +253,77 @@ jobs: fi echo "❌ Attempt $attempt failed, retrying..." done - echo "✅ The task completed successfully after $attempt attempts." + echo "✅ The task completed successfully after $attempt attempts" - name: Run OpenAPI tests run: | cd /tmp/$SANDBOX_NAME make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME test-openapi - detect_test_matrix: - name: "Detect e2e test matrix" - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.set.outputs.matrix }} - - steps: - - uses: actions/checkout@v4 - - id: set - run: | - apps=$(ls hack/e2e-apps/*.bats | cut -f3 -d/ | cut -f1 -d. | jq -R | jq -cs) - echo "matrix={\"app\":$apps}" >> "$GITHUB_OUTPUT" - - test_apps: - strategy: - fail-fast: false - matrix: ${{ fromJson(needs.detect_test_matrix.outputs.matrix) }} - name: Test ${{ matrix.app }} - runs-on: [self-hosted] - needs: [install_cozystack,detect_test_matrix] - if: ${{ always() && (needs.install_cozystack.result == 'success' && needs.detect_test_matrix.result == 'success') }} - - steps: - - name: Set sandbox ID - run: echo "SANDBOX_NAME=cozy-e2e-sandbox-$(echo "${GITHUB_REPOSITORY}:${GITHUB_WORKFLOW}:${GITHUB_REF}" | sha256sum | cut -c1-10)" >> $GITHUB_ENV - - - name: E2E Apps + # ▸ Run E2E tests + - name: Run E2E tests + id: e2e_tests run: | cd /tmp/$SANDBOX_NAME - attempt=0 - until make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME test-apps-${{ matrix.app }}; do - attempt=$((attempt + 1)) - if [ $attempt -ge 3 ]; then - echo "❌ Attempt $attempt failed, exiting..." - exit 1 + failed_tests="" + for app in $(ls hack/e2e-apps/*.bats | xargs -n1 basename | cut -d. -f1); do + echo "::group::Testing $app" + attempt=0 + success=false + until [ $attempt -ge 3 ]; do + if make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME test-apps-$app; then + success=true + break + fi + attempt=$((attempt + 1)) + echo "❌ Attempt $attempt failed, retrying..." + done + if [ "$success" = true ]; then + echo "✅ Test $app completed successfully" + else + echo "❌ Test $app failed after $attempt attempts" + failed_tests="$failed_tests $app" fi - echo "❌ Attempt $attempt failed, retrying..." + echo "::endgroup::" done - echo "✅ The task completed successfully after $attempt attempts" - - collect_debug_information: - name: Collect debug information - runs-on: [self-hosted] - needs: [test_apps] - if: ${{ always() }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set sandbox ID - run: echo "SANDBOX_NAME=cozy-e2e-sandbox-$(echo "${GITHUB_REPOSITORY}:${GITHUB_WORKFLOW}:${GITHUB_REF}" | sha256sum | cut -c1-10)" >> $GITHUB_ENV + if [ -n "$failed_tests" ]; then + echo "❌ Failed tests:$failed_tests" + exit 1 + fi + echo "✅ All E2E tests passed" + # ▸ Collect debug information (always runs) - name: Collect report + if: always() run: | cd /tmp/$SANDBOX_NAME - make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME collect-report + make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME collect-report || true - name: Upload cozyreport.tgz + if: always() uses: actions/upload-artifact@v4 with: name: cozyreport path: /tmp/${{ env.SANDBOX_NAME }}/_out/cozyreport.tgz - name: Collect images list + if: always() run: | cd /tmp/$SANDBOX_NAME - make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME collect-images + make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME collect-images || true - name: Upload image list + if: always() uses: actions/upload-artifact@v4 with: name: image-list path: /tmp/${{ env.SANDBOX_NAME }}/_out/images.txt - cleanup: - name: Tear down environment - runs-on: [self-hosted] - needs: [collect_debug_information] - if: ${{ always() && needs.test_apps.result == 'success' }} - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - fetch-tags: true - - - name: Set sandbox ID - run: echo "SANDBOX_NAME=cozy-e2e-sandbox-$(echo "${GITHUB_REPOSITORY}:${GITHUB_WORKFLOW}:${GITHUB_REF}" | sha256sum | cut -c1-10)" >> $GITHUB_ENV - + # ▸ Tear down environment (always runs) - name: Tear down sandbox - run: make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME delete + if: always() + run: make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME delete || true - name: Remove workspace + if: always() run: rm -rf /tmp/$SANDBOX_NAME - - diff --git a/Makefile b/Makefile index d0f5dd69..c66f8c03 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -.PHONY: manifests repos assets unit-tests helm-unit-tests +.PHONY: manifests assets unit-tests helm-unit-tests + +include hack/common-envs.mk build-deps: @command -V find docker skopeo jq gh helm > /dev/null @@ -16,6 +18,7 @@ build: build-deps make -C packages/system/cozystack-api image make -C packages/system/cozystack-controller image make -C packages/system/backup-controller image + make -C packages/system/backupstrategy-controller image make -C packages/system/lineage-controller-webhook image make -C packages/system/cilium image make -C packages/system/linstor image @@ -24,27 +27,54 @@ build: build-deps make -C packages/system/dashboard image make -C packages/system/metallb image make -C packages/system/kamaji image + make -C packages/system/kilo image make -C packages/system/bucket image make -C packages/system/objectstorage-controller image + make -C packages/system/grafana-operator image make -C packages/core/testing image make -C packages/core/talos image - make -C packages/core/platform image make -C packages/core/installer image make manifests -repos: - rm -rf _out - make -C packages/system repo - make -C packages/apps repo - make -C packages/extra repo - manifests: mkdir -p _out/assets - (cd packages/core/installer/; helm template -n cozy-installer installer .) > _out/assets/cozystack-installer.yaml + helm template installer packages/core/installer -n cozy-system \ + -s templates/crds.yaml \ + > _out/assets/cozystack-crds.yaml + # Talos variant (default) + helm template installer packages/core/installer -n cozy-system \ + -s templates/cozystack-operator.yaml \ + -s templates/packagesource.yaml \ + > _out/assets/cozystack-operator.yaml + # Generic Kubernetes variant (k3s, kubeadm, RKE2) + helm template installer packages/core/installer -n cozy-system \ + -s templates/cozystack-operator-generic.yaml \ + -s templates/packagesource.yaml \ + > _out/assets/cozystack-operator-generic.yaml + # Hosted variant (managed Kubernetes) + helm template installer packages/core/installer -n cozy-system \ + -s templates/cozystack-operator-hosted.yaml \ + -s templates/packagesource.yaml \ + > _out/assets/cozystack-operator-hosted.yaml -assets: +cozypkg: + go build -ldflags "-X github.com/cozystack/cozystack/cmd/cozypkg/cmd.Version=v$(COZYSTACK_VERSION)" -o _out/bin/cozypkg ./cmd/cozypkg + +assets: assets-talos assets-cozypkg + +assets-talos: make -C packages/core/talos assets +assets-cozypkg: assets-cozypkg-linux-amd64 assets-cozypkg-linux-arm64 assets-cozypkg-darwin-amd64 assets-cozypkg-darwin-arm64 assets-cozypkg-windows-amd64 assets-cozypkg-windows-arm64 + (cd _out/assets/ && sha256sum cozypkg-*.tar.gz) > _out/assets/cozypkg-checksums.txt + +assets-cozypkg-%: + $(eval EXT := $(if $(filter windows,$(firstword $(subst -, ,$*))),.exe,)) + mkdir -p _out/assets + GOOS=$(firstword $(subst -, ,$*)) GOARCH=$(lastword $(subst -, ,$*)) go build -ldflags "-X github.com/cozystack/cozystack/cmd/cozypkg/cmd.Version=v$(COZYSTACK_VERSION)" -o _out/bin/cozypkg-$*/cozypkg$(EXT) ./cmd/cozypkg + cp LICENSE _out/bin/cozypkg-$*/LICENSE + tar -C _out/bin/cozypkg-$* -czf _out/assets/cozypkg-$*.tar.gz LICENSE cozypkg$(EXT) + test: make -C packages/core/testing apply make -C packages/core/testing test diff --git a/api/backups/v1alpha1/DESIGN.md b/api/backups/v1alpha1/DESIGN.md index 455dab59..bab753b2 100644 --- a/api/backups/v1alpha1/DESIGN.md +++ b/api/backups/v1alpha1/DESIGN.md @@ -100,13 +100,13 @@ Describe **when**, **how**, and **where** to back up a specific managed applicat ```go type PlanSpec struct { // Application to back up. + // If apiGroup is not specified, it defaults to "apps.cozystack.io". ApplicationRef corev1.TypedLocalObjectReference `json:"applicationRef"` - // Where backups should be stored. - StorageRef corev1.TypedLocalObjectReference `json:"storageRef"` - - // Driver-specific BackupStrategy to use. - StrategyRef corev1.TypedLocalObjectReference `json:"strategyRef"` + // BackupClassName references a BackupClass that contains strategy and other parameters (e.g. storage reference). + // The BackupClass will be resolved to determine the appropriate strategy and parameters + // based on the ApplicationRef. + BackupClassName string `json:"backupClassName"` // When backups should run. Schedule PlanSchedule `json:"schedule"` @@ -145,12 +145,12 @@ Core Plan controller: * Create a `BackupJob` in the same namespace: * `spec.planRef.name = plan.Name` - * `spec.applicationRef = plan.spec.applicationRef` - * `spec.storageRef = plan.spec.storageRef` - * `spec.strategyRef = plan.spec.strategyRef` - * `spec.triggeredBy = "Plan"` + * `spec.applicationRef = plan.spec.applicationRef` (normalized with default apiGroup if not specified) + * `spec.backupClassName = plan.spec.backupClassName` * Set `ownerReferences` so the `BackupJob` is owned by the `Plan`. +**Note:** The `BackupJob` controller resolves the `BackupClass` to determine the appropriate strategy and parameters, based on the `ApplicationRef`. The strategy template is processed with a context containing the `Application` object and `Parameters` from the `BackupClass`. + The Plan controller does **not**: * Execute backups itself. @@ -159,17 +159,64 @@ The Plan controller does **not**: --- -### 4.2 Storage +### 4.2 BackupClass -**API Shape** +**Group/Kind** +`backups.cozystack.io/v1alpha1, Kind=BackupClass` -TBD +**Purpose** +Define a class of backup configurations that encapsulate strategy and parameters per application type. `BackupClass` is a cluster-scoped resource that allows admins to configure backup strategies and parameters in a reusable way. -**Storage usage** +**Key fields (spec)** -* `Plan` and `BackupJob` reference `Storage` via `TypedLocalObjectReference`. -* Drivers read `Storage` to know how/where to store or read artifacts. -* Core treats `Storage` spec as opaque; it does not directly talk to S3 or buckets. +```go +type BackupClassSpec struct { + // Strategies is a list of backup strategies, each matching a specific application type. + Strategies []BackupClassStrategy `json:"strategies"` +} + +type BackupClassStrategy struct { + // StrategyRef references the driver-specific BackupStrategy (e.g., Velero). + StrategyRef corev1.TypedLocalObjectReference `json:"strategyRef"` + + // Application specifies which application types this strategy applies to. + // If apiGroup is not specified, it defaults to "apps.cozystack.io". + Application ApplicationSelector `json:"application"` + + // Parameters holds strategy-specific parameters, like storage reference. + // Common parameters include: + // - backupStorageLocationName: Name of Velero BackupStorageLocation + // +optional + Parameters map[string]string `json:"parameters,omitempty"` +} + +type ApplicationSelector struct { + // APIGroup is the API group of the application. + // If not specified, defaults to "apps.cozystack.io". + // +optional + APIGroup *string `json:"apiGroup,omitempty"` + + // Kind is the kind of the application (e.g., VirtualMachine, MySQL). + Kind string `json:"kind"` +} +``` + +**BackupClass resolution** + +* When a `BackupJob` or `Plan` references a `BackupClass` via `backupClassName`, the controller: + 1. Fetches the `BackupClass` by name. + 2. Matches the `ApplicationRef` against strategies in the `BackupClass`: + * Normalizes `ApplicationRef.apiGroup` (defaults to `"apps.cozystack.io"` if not specified). + * Finds a strategy where `ApplicationSelector` matches the `ApplicationRef` (apiGroup and kind). + 3. Returns the matched `StrategyRef` and `Parameters`. +* Strategy templates (e.g., Velero's `backupTemplate.spec`) are processed with a context containing: + * `Application`: The application object being backed up. + * `Parameters`: The parameters from the matched `BackupClassStrategy`. + +**Parameters** + +* Parameters are passed via `Parameters` in the `BackupClass` (e.g., `backupStorageLocationName` for Velero). +* The driver uses these parameters to resolve the actual resources (e.g., Velero's `BackupStorageLocation` CRD). --- @@ -189,16 +236,13 @@ type BackupJobSpec struct { PlanRef *corev1.LocalObjectReference `json:"planRef,omitempty"` // Application to back up. + // If apiGroup is not specified, it defaults to "apps.cozystack.io". ApplicationRef corev1.TypedLocalObjectReference `json:"applicationRef"` - // Storage to use. - StorageRef corev1.TypedLocalObjectReference `json:"storageRef"` - - // Driver-specific BackupStrategy to use. - StrategyRef corev1.TypedLocalObjectReference `json:"strategyRef"` - - // Informational: what triggered this run ("Plan", "Manual", etc.). - TriggeredBy string `json:"triggeredBy,omitempty"` + // BackupClassName references a BackupClass that contains strategy and related parameters + // The BackupClass will be resolved to determine the appropriate strategy and parameters + // based on the ApplicationRef. + BackupClassName string `json:"backupClassName"` } ``` @@ -223,7 +267,9 @@ type BackupJobStatus struct { * Each driver controller: * Watches `BackupJob`. - * Reconciles runs where `spec.strategyRef.apiGroup/kind` matches its **strategy type(s)**. + * Resolves the `BackupClass` referenced by `spec.backupClassName`. + * Matches the `ApplicationRef` against strategies in the `BackupClass` to find the appropriate strategy. + * Reconciles runs where the resolved strategy's `apiGroup/kind` matches its **strategy type(s)**. * Driver responsibilities: 1. On first reconcile: @@ -232,7 +278,12 @@ type BackupJobStatus struct { * Set `status.phase = Running`. 2. Resolve inputs: - * Read `Strategy` (driver-owned CRD), `Storage`, `Application`, optionally `Plan`. + * Resolve `BackupClass` from `spec.backupClassName`. + * Match `ApplicationRef` against `BackupClass` strategies to get `StrategyRef` and `Parameters`. + * Read `Strategy` (driver-owned CRD) from `StrategyRef`. + * Read `Application` from `ApplicationRef`. + * Extract parameters from `Parameters` (e.g., `backupStorageLocationName` for Velero). + * Process strategy template with context: `Application` object and `Parameters` from `BackupClass`. 3. Execute backup logic (implementation-specific). 4. On success: @@ -264,13 +315,14 @@ Represent a single **backup artifact** for a given application, decoupled from a type BackupSpec struct { ApplicationRef corev1.TypedLocalObjectReference `json:"applicationRef"` PlanRef *corev1.LocalObjectReference `json:"planRef,omitempty"` - StorageRef corev1.TypedLocalObjectReference `json:"storageRef"` StrategyRef corev1.TypedLocalObjectReference `json:"strategyRef"` TakenAt metav1.Time `json:"takenAt"` DriverMetadata map[string]string `json:"driverMetadata,omitempty"` } ``` +**Note:** Parameters are not stored directly in `Backup`. Instead, they are resolved from `BackupClass` parameters when the backup was created. The storage location is managed by the driver (e.g., Velero's `BackupStorageLocation`) and referenced via parameters in the `BackupClass`. + **Key fields (status)** ```go @@ -290,7 +342,8 @@ type BackupStatus struct { * Creates a `Backup` in the same namespace (typically owned by the `BackupJob`). * Populates `spec` fields with: - * The application, storage, strategy references. + * The application reference. + * The strategy reference (resolved from `BackupClass` during `BackupJob` execution). * `takenAt`. * Optional `driverMetadata`. * Sets `status` with: @@ -306,6 +359,8 @@ type BackupStatus struct { * Anchor `RestoreJob` operations. * Implement higher-level policies (retention) if needed. +**Note:** Parameters are resolved from `BackupClass` when the `BackupJob` is created. The driver uses these parameters to determine where to store backups. The storage location itself is managed by the driver (e.g., Velero's `BackupStorageLocation` CRD) and is not directly referenced in the `Backup` resource. When restoring, the driver resolves the storage location from the original `BackupClass` parameters or from the driver's own metadata. + --- ### 4.5 RestoreJob @@ -353,13 +408,13 @@ type RestoreJobStatus struct { * Determines effective: * **Strategy**: `backup.spec.strategyRef`. - * **Storage**: `backup.spec.storageRef`. + * **Storage**: Resolved from driver metadata or `BackupClass` parameters (e.g., `backupStorageLocationName` stored in `driverMetadata` or resolved from the original `BackupClass`). * **Target application**: `spec.targetApplicationRef` or `backup.spec.applicationRef`. * If effective strategy’s GVK is one of its supported strategy types → driver is responsible. 3. Behaviour: * On first reconcile, set `status.startedAt` and `phase = Running`. - * Resolve `Backup`, `Storage`, `Strategy`, target application. + * Resolve `Backup`, storage location (from driver metadata or `BackupClass`), `Strategy`, target application. * Execute restore logic (implementation-specific). * On success: @@ -414,8 +469,10 @@ The Cozystack backups core API: * Uses a single group, `backups.cozystack.io`, for all core CRDs. * Cleanly separates: - * **When & where** (Plan + Storage) – core-owned. + * **When** (Plan schedule) – core-owned. + * **How & where** (BackupClass) – central configuration unit that encapsulates strategy and parameters (e.g., storage reference) per application type, resolved per BackupJob/Plan. + * **Execution** (BackupJob) – created by Plan when schedule fires, resolves BackupClass to get strategy and parameters, then delegates to driver. * **What backup artifacts exist** (Backup) – driver-created but cluster-visible. - * **Execution lifecycle** (BackupJob, RestoreJob) – shared contract boundary. + * **Restore lifecycle** (RestoreJob) – shared contract boundary. * Allows multiple strategy drivers to implement backup/restore logic without entangling their implementation with the core API. diff --git a/api/backups/v1alpha1/backup_types.go b/api/backups/v1alpha1/backup_types.go index 2f18b34f..9371c27f 100644 --- a/api/backups/v1alpha1/backup_types.go +++ b/api/backups/v1alpha1/backup_types.go @@ -57,10 +57,6 @@ type BackupSpec struct { // +optional PlanRef *corev1.LocalObjectReference `json:"planRef,omitempty"` - // StorageRef refers to the Storage object that describes where the backup - // artifact is stored. - StorageRef corev1.TypedLocalObjectReference `json:"storageRef"` - // StrategyRef refers to the driver-specific BackupStrategy that was used // to create this backup. This allows the driver to later perform restores. StrategyRef corev1.TypedLocalObjectReference `json:"strategyRef"` diff --git a/api/backups/v1alpha1/backupclass_types.go b/api/backups/v1alpha1/backupclass_types.go new file mode 100644 index 00000000..19bcfd52 --- /dev/null +++ b/api/backups/v1alpha1/backupclass_types.go @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: Apache-2.0 +// Package v1alpha1 defines backups.cozystack.io API types. +// +// Group: backups.cozystack.io +// Version: v1alpha1 +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +func init() { + SchemeBuilder.Register(func(s *runtime.Scheme) error { + s.AddKnownTypes(GroupVersion, + &BackupClass{}, + &BackupClassList{}, + ) + return nil + }) +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:subresource:status + +// BackupClass defines a class of backup configurations that can be referenced +// by BackupJob and Plan resources. It encapsulates strategy and storage configuration +// per application type. +type BackupClass struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec BackupClassSpec `json:"spec,omitempty"` + Status BackupClassStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// BackupClassList contains a list of BackupClasses. +type BackupClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BackupClass `json:"items"` +} + +// BackupClassSpec defines the desired state of a BackupClass. +type BackupClassSpec struct { + // Strategies is a list of backup strategies, each matching a specific application type. + Strategies []BackupClassStrategy `json:"strategies"` +} + +// BackupClassStrategy defines a backup strategy for a specific application type. +type BackupClassStrategy struct { + // StrategyRef references the driver-specific BackupStrategy (e.g., Velero). + StrategyRef corev1.TypedLocalObjectReference `json:"strategyRef"` + + // Application specifies which application types this strategy applies to. + Application ApplicationSelector `json:"application"` + + // Parameters holds strategy-specific and storage-specific parameters. + // Common parameters include: + // - backupStorageLocationName: Name of Velero BackupStorageLocation + // +optional + Parameters map[string]string `json:"parameters,omitempty"` +} + +// ApplicationSelector specifies which application types a strategy applies to. +type ApplicationSelector struct { + // APIGroup is the API group of the application. + // If not specified, defaults to "apps.cozystack.io". + // +optional + APIGroup *string `json:"apiGroup,omitempty"` + + // Kind is the kind of the application (e.g., VirtualMachine, MySQL). + Kind string `json:"kind"` +} + +// BackupClassStatus defines the observed state of a BackupClass. +type BackupClassStatus struct { + // Conditions represents the latest available observations of a BackupClass's state. + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` +} diff --git a/api/backups/v1alpha1/backupjob_types.go b/api/backups/v1alpha1/backupjob_types.go index c27b5347..7b251ceb 100644 --- a/api/backups/v1alpha1/backupjob_types.go +++ b/api/backups/v1alpha1/backupjob_types.go @@ -24,6 +24,10 @@ func init() { const ( OwningJobNameLabel = thisGroup + "/owned-by.BackupJobName" OwningJobNamespaceLabel = thisGroup + "/owned-by.BackupJobNamespace" + + // DefaultApplicationAPIGroup is the default API group for applications + // when not specified in ApplicationRef or ApplicationSelector. + DefaultApplicationAPIGroup = "apps.cozystack.io" ) // BackupJobPhase represents the lifecycle phase of a BackupJob. @@ -46,15 +50,15 @@ type BackupJobSpec struct { // ApplicationRef holds a reference to the managed application whose state // is being backed up. + // If apiGroup is not specified, it defaults to "apps.cozystack.io". ApplicationRef corev1.TypedLocalObjectReference `json:"applicationRef"` - // StorageRef holds a reference to the Storage object that describes where - // the backup will be stored. - StorageRef corev1.TypedLocalObjectReference `json:"storageRef"` - - // StrategyRef holds a reference to the driver-specific BackupStrategy object - // that describes how the backup should be created. - StrategyRef corev1.TypedLocalObjectReference `json:"strategyRef"` + // BackupClassName references a BackupClass that contains strategy and storage configuration. + // The BackupClass will be resolved to determine the appropriate strategy and storage + // based on the ApplicationRef. + // This field is immutable once the BackupJob is created. + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="backupClassName is immutable" + BackupClassName string `json:"backupClassName"` } // BackupJobStatus represents the observed state of a BackupJob. @@ -114,3 +118,13 @@ type BackupJobList struct { metav1.ListMeta `json:"metadata,omitempty"` Items []BackupJob `json:"items"` } + +// NormalizeApplicationRef sets the default apiGroup to DefaultApplicationAPIGroup if it's not specified. +// This function is exported so it can be used by other packages (e.g., controllers, factories). +func NormalizeApplicationRef(ref corev1.TypedLocalObjectReference) corev1.TypedLocalObjectReference { + if ref.APIGroup == nil || *ref.APIGroup == "" { + apiGroup := DefaultApplicationAPIGroup + ref.APIGroup = &apiGroup + } + return ref +} diff --git a/api/backups/v1alpha1/backupjob_webhook.go b/api/backups/v1alpha1/backupjob_webhook.go new file mode 100644 index 00000000..064605c2 --- /dev/null +++ b/api/backups/v1alpha1/backupjob_webhook.go @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 +package v1alpha1 + +import ( + "context" + "fmt" + "strings" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// SetupWebhookWithManager registers the BackupJob webhook with the manager. +func SetupBackupJobWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&BackupJob{}). + Complete() +} + +// +kubebuilder:webhook:path=/mutate-backups-cozystack-io-v1alpha1-backupjob,mutating=true,failurePolicy=fail,sideEffects=None,groups=backups.cozystack.io,resources=backupjobs,verbs=create;update,versions=v1alpha1,name=mbackupjob.kb.io,admissionReviewVersions=v1 + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (j *BackupJob) Default() { + j.Spec.ApplicationRef = NormalizeApplicationRef(j.Spec.ApplicationRef) +} + +// +kubebuilder:webhook:path=/validate-backups-cozystack-io-v1alpha1-backupjob,mutating=false,failurePolicy=fail,sideEffects=None,groups=backups.cozystack.io,resources=backupjobs,verbs=create;update,versions=v1alpha1,name=vbackupjob.kb.io,admissionReviewVersions=v1 + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (j *BackupJob) ValidateCreate() (admission.Warnings, error) { + logger := log.FromContext(context.Background()) + logger.Info("validating BackupJob creation", "name", j.Name, "namespace", j.Namespace) + + // Validate that backupClassName is set + if strings.TrimSpace(j.Spec.BackupClassName) == "" { + return nil, fmt.Errorf("backupClassName is required and cannot be empty") + } + + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (j *BackupJob) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + logger := log.FromContext(context.Background()) + logger.Info("validating BackupJob update", "name", j.Name, "namespace", j.Namespace) + + oldJob, ok := old.(*BackupJob) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a BackupJob but got a %T", old)) + } + + // Enforce immutability of backupClassName + if oldJob.Spec.BackupClassName != j.Spec.BackupClassName { + return nil, fmt.Errorf("backupClassName is immutable and cannot be changed from %q to %q", oldJob.Spec.BackupClassName, j.Spec.BackupClassName) + } + + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (j *BackupJob) ValidateDelete() (admission.Warnings, error) { + // No validation needed for deletion + return nil, nil +} diff --git a/api/backups/v1alpha1/backupjob_webhook_test.go b/api/backups/v1alpha1/backupjob_webhook_test.go new file mode 100644 index 00000000..d143c5be --- /dev/null +++ b/api/backups/v1alpha1/backupjob_webhook_test.go @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: Apache-2.0 +package v1alpha1 + +import ( + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +func TestBackupJob_ValidateCreate(t *testing.T) { + tests := []struct { + name string + job *BackupJob + wantErr bool + errMsg string + }{ + { + name: "valid BackupJob with backupClassName", + job: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", + }, + }, + wantErr: false, + }, + { + name: "BackupJob with empty backupClassName should be rejected", + job: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "", + }, + }, + wantErr: true, + errMsg: "backupClassName is required and cannot be empty", + }, + { + name: "BackupJob with whitespace-only backupClassName should be rejected", + job: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: " ", + }, + }, + wantErr: true, + errMsg: "backupClassName is required and cannot be empty", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + warnings, err := tt.job.ValidateCreate() + if (err != nil) != tt.wantErr { + t.Errorf("ValidateCreate() error = %v, wantErr %v", err, tt.wantErr) + return + } + if tt.wantErr && err != nil { + if tt.errMsg != "" && err.Error() != tt.errMsg { + t.Errorf("ValidateCreate() error message = %v, want %v", err.Error(), tt.errMsg) + } + } + if warnings != nil && len(warnings) > 0 { + t.Logf("ValidateCreate() warnings = %v", warnings) + } + }) + } +} + +func TestBackupJob_ValidateUpdate(t *testing.T) { + baseJob := &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", + }, + } + + tests := []struct { + name string + old runtime.Object + new *BackupJob + wantErr bool + errMsg string + }{ + { + name: "update with same backupClassName should succeed", + old: baseJob, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", // Same as old + }, + }, + wantErr: false, + }, + { + name: "update changing backupClassName should be rejected", + old: baseJob, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "different-class", // Changed! + }, + }, + wantErr: true, + errMsg: "backupClassName is immutable and cannot be changed from \"velero\" to \"different-class\"", + }, + { + name: "update changing other fields but keeping backupClassName should succeed", + old: baseJob, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + Labels: map[string]string{ + "new-label": "value", + }, + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm2", // Changed application + }, + BackupClassName: "velero", // Same as old + }, + }, + wantErr: false, + }, + { + name: "update when old backupClassName is empty should be rejected", + old: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "", // Empty in old + }, + }, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", // Setting it for the first time + }, + }, + wantErr: true, + errMsg: "backupClassName is immutable", + }, + { + name: "update changing from non-empty to different non-empty should be rejected", + old: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "class-a", + }, + }, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "class-b", // Changed from class-a + }, + }, + wantErr: true, + errMsg: "backupClassName is immutable and cannot be changed from \"class-a\" to \"class-b\"", + }, + { + name: "update with invalid old object type should be rejected", + old: &corev1.Pod{ // Wrong type - will be cast to runtime.Object in test + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + }, + new: baseJob, + wantErr: true, + errMsg: "expected a BackupJob but got a", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + warnings, err := tt.new.ValidateUpdate(tt.old) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateUpdate() error = %v, wantErr %v", err, tt.wantErr) + if err != nil { + t.Logf("Error message: %v", err.Error()) + } + return + } + if tt.wantErr && err != nil { + if tt.errMsg != "" { + if tt.errMsg != "" && !contains(err.Error(), tt.errMsg) { + t.Errorf("ValidateUpdate() error message = %v, want contains %v", err.Error(), tt.errMsg) + } + } + } + if warnings != nil && len(warnings) > 0 { + t.Logf("ValidateUpdate() warnings = %v", warnings) + } + }) + } +} + +func TestBackupJob_ValidateDelete(t *testing.T) { + job := &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", + }, + } + + warnings, err := job.ValidateDelete() + if err != nil { + t.Errorf("ValidateDelete() should never return an error, got %v", err) + } + if warnings != nil && len(warnings) > 0 { + t.Logf("ValidateDelete() warnings = %v", warnings) + } +} + +func TestBackupJob_Default(t *testing.T) { + job := &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", + }, + } + + // Default() should not panic and should not modify the object + originalClassName := job.Spec.BackupClassName + job.Default() + if job.Spec.BackupClassName != originalClassName { + t.Errorf("Default() should not modify backupClassName, got %v, want %v", job.Spec.BackupClassName, originalClassName) + } +} + +// Helper function to check if a string contains a substring +func contains(s, substr string) bool { + if len(substr) == 0 { + return true + } + if len(s) < len(substr) { + return false + } + for i := 0; i <= len(s)-len(substr); i++ { + if s[i:i+len(substr)] == substr { + return true + } + } + return false +} diff --git a/api/backups/v1alpha1/plan_types.go b/api/backups/v1alpha1/plan_types.go index c59d5eab..df807eb5 100644 --- a/api/backups/v1alpha1/plan_types.go +++ b/api/backups/v1alpha1/plan_types.go @@ -65,15 +65,13 @@ type PlanList struct { type PlanSpec struct { // ApplicationRef holds a reference to the managed application, // whose state and configuration must be backed up. + // If apiGroup is not specified, it defaults to "apps.cozystack.io". ApplicationRef corev1.TypedLocalObjectReference `json:"applicationRef"` - // StorageRef holds a reference to the Storage object that - // describes the location where the backup will be stored. - StorageRef corev1.TypedLocalObjectReference `json:"storageRef"` - - // StrategyRef holds a reference to the Strategy object that - // describes, how a backup copy is to be created. - StrategyRef corev1.TypedLocalObjectReference `json:"strategyRef"` + // BackupClassName references a BackupClass that contains strategy and storage configuration. + // The BackupClass will be resolved to determine the appropriate strategy and storage + // based on the ApplicationRef. + BackupClassName string `json:"backupClassName"` // Schedule specifies when backup copies are created. Schedule PlanSchedule `json:"schedule"` diff --git a/api/backups/v1alpha1/zz_generated.deepcopy.go b/api/backups/v1alpha1/zz_generated.deepcopy.go index fe825947..b2e4a680 100644 --- a/api/backups/v1alpha1/zz_generated.deepcopy.go +++ b/api/backups/v1alpha1/zz_generated.deepcopy.go @@ -26,6 +26,26 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationSelector) DeepCopyInto(out *ApplicationSelector) { + *out = *in + if in.APIGroup != nil { + in, out := &in.APIGroup, &out.APIGroup + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSelector. +func (in *ApplicationSelector) DeepCopy() *ApplicationSelector { + if in == nil { + return nil + } + out := new(ApplicationSelector) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Backup) DeepCopyInto(out *Backup) { *out = *in @@ -68,6 +88,133 @@ func (in *BackupArtifact) DeepCopy() *BackupArtifact { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupClass) DeepCopyInto(out *BackupClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupClass. +func (in *BackupClass) DeepCopy() *BackupClass { + if in == nil { + return nil + } + out := new(BackupClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackupClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupClassList) DeepCopyInto(out *BackupClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BackupClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupClassList. +func (in *BackupClassList) DeepCopy() *BackupClassList { + if in == nil { + return nil + } + out := new(BackupClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackupClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupClassSpec) DeepCopyInto(out *BackupClassSpec) { + *out = *in + if in.Strategies != nil { + in, out := &in.Strategies, &out.Strategies + *out = make([]BackupClassStrategy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupClassSpec. +func (in *BackupClassSpec) DeepCopy() *BackupClassSpec { + if in == nil { + return nil + } + out := new(BackupClassSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupClassStatus) DeepCopyInto(out *BackupClassStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupClassStatus. +func (in *BackupClassStatus) DeepCopy() *BackupClassStatus { + if in == nil { + return nil + } + out := new(BackupClassStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupClassStrategy) DeepCopyInto(out *BackupClassStrategy) { + *out = *in + in.StrategyRef.DeepCopyInto(&out.StrategyRef) + in.Application.DeepCopyInto(&out.Application) + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupClassStrategy. +func (in *BackupClassStrategy) DeepCopy() *BackupClassStrategy { + if in == nil { + return nil + } + out := new(BackupClassStrategy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupJob) DeepCopyInto(out *BackupJob) { *out = *in @@ -136,8 +283,6 @@ func (in *BackupJobSpec) DeepCopyInto(out *BackupJobSpec) { **out = **in } in.ApplicationRef.DeepCopyInto(&out.ApplicationRef) - in.StorageRef.DeepCopyInto(&out.StorageRef) - in.StrategyRef.DeepCopyInto(&out.StrategyRef) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupJobSpec. @@ -226,7 +371,6 @@ func (in *BackupSpec) DeepCopyInto(out *BackupSpec) { *out = new(v1.LocalObjectReference) **out = **in } - in.StorageRef.DeepCopyInto(&out.StorageRef) in.StrategyRef.DeepCopyInto(&out.StrategyRef) in.TakenAt.DeepCopyInto(&out.TakenAt) if in.DriverMetadata != nil { @@ -353,8 +497,6 @@ func (in *PlanSchedule) DeepCopy() *PlanSchedule { func (in *PlanSpec) DeepCopyInto(out *PlanSpec) { *out = *in in.ApplicationRef.DeepCopyInto(&out.ApplicationRef) - in.StorageRef.DeepCopyInto(&out.StorageRef) - in.StrategyRef.DeepCopyInto(&out.StrategyRef) out.Schedule = in.Schedule } diff --git a/api/v1alpha1/cozystackresourcedefinitions_types.go b/api/v1alpha1/applicationdefinitions_types.go similarity index 69% rename from api/v1alpha1/cozystackresourcedefinitions_types.go rename to api/v1alpha1/applicationdefinitions_types.go index 2f25fb2d..4a4cd226 100644 --- a/api/v1alpha1/cozystackresourcedefinitions_types.go +++ b/api/v1alpha1/applicationdefinitions_types.go @@ -17,69 +17,52 @@ limitations under the License. package v1alpha1 import ( + helmv2 "github.com/fluxcd/helm-controller/api/v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // +kubebuilder:object:root=true // +kubebuilder:resource:scope=Cluster -// CozystackResourceDefinition is the Schema for the cozystackresourcedefinitions API -type CozystackResourceDefinition struct { +// ApplicationDefinition is the Schema for the applicationdefinitions API +type ApplicationDefinition struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec CozystackResourceDefinitionSpec `json:"spec,omitempty"` + Spec ApplicationDefinitionSpec `json:"spec,omitempty"` } // +kubebuilder:object:root=true -// CozystackResourceDefinitionList contains a list of CozystackResourceDefinitions -type CozystackResourceDefinitionList struct { +// ApplicationDefinitionList contains a list of ApplicationDefinitions +type ApplicationDefinitionList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` - Items []CozystackResourceDefinition `json:"items"` + Items []ApplicationDefinition `json:"items"` } func init() { - SchemeBuilder.Register(&CozystackResourceDefinition{}, &CozystackResourceDefinitionList{}) + SchemeBuilder.Register(&ApplicationDefinition{}, &ApplicationDefinitionList{}) } -type CozystackResourceDefinitionSpec struct { +type ApplicationDefinitionSpec struct { // Application configuration - Application CozystackResourceDefinitionApplication `json:"application"` + Application ApplicationDefinitionApplication `json:"application"` // Release configuration - Release CozystackResourceDefinitionRelease `json:"release"` + Release ApplicationDefinitionRelease `json:"release"` // Secret selectors - Secrets CozystackResourceDefinitionResources `json:"secrets,omitempty"` + Secrets ApplicationDefinitionResources `json:"secrets,omitempty"` // Service selectors - Services CozystackResourceDefinitionResources `json:"services,omitempty"` + Services ApplicationDefinitionResources `json:"services,omitempty"` // Ingress selectors - Ingresses CozystackResourceDefinitionResources `json:"ingresses,omitempty"` + Ingresses ApplicationDefinitionResources `json:"ingresses,omitempty"` // Dashboard configuration for this resource - Dashboard *CozystackResourceDefinitionDashboard `json:"dashboard,omitempty"` + Dashboard *ApplicationDefinitionDashboard `json:"dashboard,omitempty"` } -type CozystackResourceDefinitionChart struct { - // Name of the Helm chart - Name string `json:"name"` - // Source reference for the Helm chart - SourceRef SourceRef `json:"sourceRef"` -} - -type SourceRef struct { - // Kind of the source reference - // +kubebuilder:default:="HelmRepository" - Kind string `json:"kind"` - // Name of the source reference - Name string `json:"name"` - // Namespace of the source reference - // +kubebuilder:default:="cozy-public" - Namespace string `json:"namespace"` -} - -type CozystackResourceDefinitionApplication struct { +type ApplicationDefinitionApplication struct { // Kind of the application, used for UI and API Kind string `json:"kind"` // OpenAPI schema for the application, used for API validation @@ -90,17 +73,16 @@ type CozystackResourceDefinitionApplication struct { Singular string `json:"singular"` } -type CozystackResourceDefinitionRelease struct { - // Helm chart configuration - // +optional - Chart CozystackResourceDefinitionChart `json:"chart,omitempty"` +type ApplicationDefinitionRelease struct { + // Reference to the chart source + ChartRef *helmv2.CrossNamespaceSourceReference `json:"chartRef"` // Labels for the release Labels map[string]string `json:"labels,omitempty"` // Prefix for the release name Prefix string `json:"prefix"` } -// CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support. +// ApplicationDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support. // A resource matches this selector only if it satisfies ALL criteria: // - Label selector conditions (matchExpressions and matchLabels) // - AND has a name that matches one of the names in resourceNames (if specified) @@ -123,7 +105,7 @@ type CozystackResourceDefinitionRelease struct { // - "{{ .name }}-secret" // - "{{ .kind }}-{{ .name }}-tls" // - "specificname" -type CozystackResourceDefinitionResourceSelector struct { +type ApplicationDefinitionResourceSelector struct { metav1.LabelSelector `json:",inline"` // ResourceNames is a list of resource names to match // If specified, the resource must have one of these exact names to match the selector @@ -131,16 +113,16 @@ type CozystackResourceDefinitionResourceSelector struct { ResourceNames []string `json:"resourceNames,omitempty"` } -type CozystackResourceDefinitionResources struct { +type ApplicationDefinitionResources struct { // Exclude contains an array of resource selectors that target resources. // If a resource matches the selector in any of the elements in the array, it is // hidden from the user, regardless of the matches in the include array. - Exclude []*CozystackResourceDefinitionResourceSelector `json:"exclude,omitempty"` + Exclude []*ApplicationDefinitionResourceSelector `json:"exclude,omitempty"` // Include contains an array of resource selectors that target resources. // If a resource matches the selector in any of the elements in the array, and // matches none of the selectors in the exclude array that resource is marked // as a tenant resource and is visible to users. - Include []*CozystackResourceDefinitionResourceSelector `json:"include,omitempty"` + Include []*ApplicationDefinitionResourceSelector `json:"include,omitempty"` } // ---- Dashboard types ---- @@ -157,8 +139,8 @@ const ( DashboardTabYAML DashboardTab = "yaml" ) -// CozystackResourceDefinitionDashboard describes how this resource appears in the UI. -type CozystackResourceDefinitionDashboard struct { +// ApplicationDefinitionDashboard describes how this resource appears in the UI. +type ApplicationDefinitionDashboard struct { // Human-readable name shown in the UI (e.g., "Bucket") Singular string `json:"singular"` // Plural human-readable name (e.g., "Buckets") diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 7fe4f3e2..c1adf95c 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -21,12 +21,232 @@ limitations under the License. package v1alpha1 import ( + "github.com/fluxcd/helm-controller/api/v2" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDefinition) DeepCopyInto(out *ApplicationDefinition) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDefinition. +func (in *ApplicationDefinition) DeepCopy() *ApplicationDefinition { + if in == nil { + return nil + } + out := new(ApplicationDefinition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ApplicationDefinition) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDefinitionApplication) DeepCopyInto(out *ApplicationDefinitionApplication) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDefinitionApplication. +func (in *ApplicationDefinitionApplication) DeepCopy() *ApplicationDefinitionApplication { + if in == nil { + return nil + } + out := new(ApplicationDefinitionApplication) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDefinitionDashboard) DeepCopyInto(out *ApplicationDefinitionDashboard) { + *out = *in + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Tabs != nil { + in, out := &in.Tabs, &out.Tabs + *out = make([]DashboardTab, len(*in)) + copy(*out, *in) + } + if in.KeysOrder != nil { + in, out := &in.KeysOrder, &out.KeysOrder + *out = make([][]string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = make([]string, len(*in)) + copy(*out, *in) + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDefinitionDashboard. +func (in *ApplicationDefinitionDashboard) DeepCopy() *ApplicationDefinitionDashboard { + if in == nil { + return nil + } + out := new(ApplicationDefinitionDashboard) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDefinitionList) DeepCopyInto(out *ApplicationDefinitionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ApplicationDefinition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDefinitionList. +func (in *ApplicationDefinitionList) DeepCopy() *ApplicationDefinitionList { + if in == nil { + return nil + } + out := new(ApplicationDefinitionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ApplicationDefinitionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDefinitionRelease) DeepCopyInto(out *ApplicationDefinitionRelease) { + *out = *in + if in.ChartRef != nil { + in, out := &in.ChartRef, &out.ChartRef + *out = new(v2.CrossNamespaceSourceReference) + **out = **in + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDefinitionRelease. +func (in *ApplicationDefinitionRelease) DeepCopy() *ApplicationDefinitionRelease { + if in == nil { + return nil + } + out := new(ApplicationDefinitionRelease) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDefinitionResourceSelector) DeepCopyInto(out *ApplicationDefinitionResourceSelector) { + *out = *in + in.LabelSelector.DeepCopyInto(&out.LabelSelector) + if in.ResourceNames != nil { + in, out := &in.ResourceNames, &out.ResourceNames + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDefinitionResourceSelector. +func (in *ApplicationDefinitionResourceSelector) DeepCopy() *ApplicationDefinitionResourceSelector { + if in == nil { + return nil + } + out := new(ApplicationDefinitionResourceSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDefinitionResources) DeepCopyInto(out *ApplicationDefinitionResources) { + *out = *in + if in.Exclude != nil { + in, out := &in.Exclude, &out.Exclude + *out = make([]*ApplicationDefinitionResourceSelector, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(ApplicationDefinitionResourceSelector) + (*in).DeepCopyInto(*out) + } + } + } + if in.Include != nil { + in, out := &in.Include, &out.Include + *out = make([]*ApplicationDefinitionResourceSelector, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(ApplicationDefinitionResourceSelector) + (*in).DeepCopyInto(*out) + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDefinitionResources. +func (in *ApplicationDefinitionResources) DeepCopy() *ApplicationDefinitionResources { + if in == nil { + return nil + } + out := new(ApplicationDefinitionResources) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationDefinitionSpec) DeepCopyInto(out *ApplicationDefinitionSpec) { + *out = *in + out.Application = in.Application + in.Release.DeepCopyInto(&out.Release) + in.Secrets.DeepCopyInto(&out.Secrets) + in.Services.DeepCopyInto(&out.Services) + in.Ingresses.DeepCopyInto(&out.Ingresses) + if in.Dashboard != nil { + in, out := &in.Dashboard, &out.Dashboard + *out = new(ApplicationDefinitionDashboard) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDefinitionSpec. +func (in *ApplicationDefinitionSpec) DeepCopy() *ApplicationDefinitionSpec { + if in == nil { + return nil + } + out := new(ApplicationDefinitionSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Component) DeepCopyInto(out *Component) { *out = *in @@ -77,237 +297,6 @@ func (in *ComponentInstall) DeepCopy() *ComponentInstall { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinition) DeepCopyInto(out *CozystackResourceDefinition) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinition. -func (in *CozystackResourceDefinition) DeepCopy() *CozystackResourceDefinition { - if in == nil { - return nil - } - out := new(CozystackResourceDefinition) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *CozystackResourceDefinition) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinitionApplication) DeepCopyInto(out *CozystackResourceDefinitionApplication) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionApplication. -func (in *CozystackResourceDefinitionApplication) DeepCopy() *CozystackResourceDefinitionApplication { - if in == nil { - return nil - } - out := new(CozystackResourceDefinitionApplication) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinitionChart) DeepCopyInto(out *CozystackResourceDefinitionChart) { - *out = *in - out.SourceRef = in.SourceRef -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionChart. -func (in *CozystackResourceDefinitionChart) DeepCopy() *CozystackResourceDefinitionChart { - if in == nil { - return nil - } - out := new(CozystackResourceDefinitionChart) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinitionDashboard) DeepCopyInto(out *CozystackResourceDefinitionDashboard) { - *out = *in - if in.Tags != nil { - in, out := &in.Tags, &out.Tags - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Tabs != nil { - in, out := &in.Tabs, &out.Tabs - *out = make([]DashboardTab, len(*in)) - copy(*out, *in) - } - if in.KeysOrder != nil { - in, out := &in.KeysOrder, &out.KeysOrder - *out = make([][]string, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = make([]string, len(*in)) - copy(*out, *in) - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionDashboard. -func (in *CozystackResourceDefinitionDashboard) DeepCopy() *CozystackResourceDefinitionDashboard { - if in == nil { - return nil - } - out := new(CozystackResourceDefinitionDashboard) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinitionList) DeepCopyInto(out *CozystackResourceDefinitionList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]CozystackResourceDefinition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionList. -func (in *CozystackResourceDefinitionList) DeepCopy() *CozystackResourceDefinitionList { - if in == nil { - return nil - } - out := new(CozystackResourceDefinitionList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *CozystackResourceDefinitionList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinitionRelease) DeepCopyInto(out *CozystackResourceDefinitionRelease) { - *out = *in - out.Chart = in.Chart - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionRelease. -func (in *CozystackResourceDefinitionRelease) DeepCopy() *CozystackResourceDefinitionRelease { - if in == nil { - return nil - } - out := new(CozystackResourceDefinitionRelease) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinitionResourceSelector) DeepCopyInto(out *CozystackResourceDefinitionResourceSelector) { - *out = *in - in.LabelSelector.DeepCopyInto(&out.LabelSelector) - if in.ResourceNames != nil { - in, out := &in.ResourceNames, &out.ResourceNames - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionResourceSelector. -func (in *CozystackResourceDefinitionResourceSelector) DeepCopy() *CozystackResourceDefinitionResourceSelector { - if in == nil { - return nil - } - out := new(CozystackResourceDefinitionResourceSelector) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinitionResources) DeepCopyInto(out *CozystackResourceDefinitionResources) { - *out = *in - if in.Exclude != nil { - in, out := &in.Exclude, &out.Exclude - *out = make([]*CozystackResourceDefinitionResourceSelector, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(CozystackResourceDefinitionResourceSelector) - (*in).DeepCopyInto(*out) - } - } - } - if in.Include != nil { - in, out := &in.Include, &out.Include - *out = make([]*CozystackResourceDefinitionResourceSelector, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(CozystackResourceDefinitionResourceSelector) - (*in).DeepCopyInto(*out) - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionResources. -func (in *CozystackResourceDefinitionResources) DeepCopy() *CozystackResourceDefinitionResources { - if in == nil { - return nil - } - out := new(CozystackResourceDefinitionResources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CozystackResourceDefinitionSpec) DeepCopyInto(out *CozystackResourceDefinitionSpec) { - *out = *in - out.Application = in.Application - in.Release.DeepCopyInto(&out.Release) - in.Secrets.DeepCopyInto(&out.Secrets) - in.Services.DeepCopyInto(&out.Services) - in.Ingresses.DeepCopyInto(&out.Ingresses) - if in.Dashboard != nil { - in, out := &in.Dashboard, &out.Dashboard - *out = new(CozystackResourceDefinitionDashboard) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CozystackResourceDefinitionSpec. -func (in *CozystackResourceDefinitionSpec) DeepCopy() *CozystackResourceDefinitionSpec { - if in == nil { - return nil - } - out := new(CozystackResourceDefinitionSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DependencyStatus) DeepCopyInto(out *DependencyStatus) { *out = *in @@ -622,21 +611,6 @@ func (in Selector) DeepCopy() Selector { return *out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SourceRef) DeepCopyInto(out *SourceRef) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceRef. -func (in *SourceRef) DeepCopy() *SourceRef { - if in == nil { - return nil - } - out := new(SourceRef) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Variant) DeepCopyInto(out *Variant) { *out = *in diff --git a/cmd/backup-controller/main.go b/cmd/backup-controller/main.go index d8436659..fcc31d71 100644 --- a/cmd/backup-controller/main.go +++ b/cmd/backup-controller/main.go @@ -29,6 +29,8 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/metrics/filters" @@ -130,6 +132,11 @@ func main() { HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "core.backups.cozystack.io", + Cache: cache.Options{ + ByObject: map[client.Object]cache.ByObject{ + &backupsv1alpha1.BackupClass{}: {}, + }, + }, // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily // when the Manager ends. This requires the binary to immediately end when the // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly @@ -155,6 +162,21 @@ func main() { os.Exit(1) } + if err = (&backupcontroller.BackupJobReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Recorder: mgr.GetEventRecorderFor("backup-controller"), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "BackupJob") + os.Exit(1) + } + + // Register BackupJob webhook for validation (immutability of backupClassName) + if err = backupsv1alpha1.SetupBackupJobWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "BackupJob") + os.Exit(1) + } + // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/cmd/backupstrategy-controller/main.go b/cmd/backupstrategy-controller/main.go index b9968826..6c0ee2e6 100644 --- a/cmd/backupstrategy-controller/main.go +++ b/cmd/backupstrategy-controller/main.go @@ -29,6 +29,8 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/metrics/filters" @@ -134,6 +136,11 @@ func main() { HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "strategy.backups.cozystack.io", + Cache: cache.Options{ + ByObject: map[client.Object]cache.ByObject{ + &backupsv1alpha1.BackupClass{}: {}, + }, + }, // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily // when the Manager ends. This requires the binary to immediately end when the // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly diff --git a/cmd/cozypkg/cmd/root.go b/cmd/cozypkg/cmd/root.go index 62bd54aa..69b0ea6d 100644 --- a/cmd/cozypkg/cmd/root.go +++ b/cmd/cozypkg/cmd/root.go @@ -23,6 +23,9 @@ import ( "github.com/spf13/cobra" ) +// Version is set at build time via -ldflags. +var Version = "dev" + // rootCmd represents the base command when called without any subcommands. var rootCmd = &cobra.Command{ Use: "cozypkg", @@ -44,6 +47,6 @@ func Execute() error { } func init() { - // Commands are registered in their respective init() functions + rootCmd.Version = Version } diff --git a/cmd/cozystack-assets-server/main.go b/cmd/cozystack-assets-server/main.go deleted file mode 100644 index 75563712..00000000 --- a/cmd/cozystack-assets-server/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "flag" - "log" - "net/http" - "path/filepath" -) - -func main() { - addr := flag.String("address", ":8123", "Address to listen on") - dir := flag.String("dir", "/cozystack/assets", "Directory to serve files from") - flag.Parse() - - absDir, err := filepath.Abs(*dir) - if err != nil { - log.Fatalf("Error getting absolute path for %s: %v", *dir, err) - } - - fs := http.FileServer(http.Dir(absDir)) - http.Handle("/", fs) - - log.Printf("Server starting on %s, serving directory %s", *addr, absDir) - - err = http.ListenAndServe(*addr, nil) - if err != nil { - log.Fatalf("Server failed to start: %v", err) - } -} diff --git a/cmd/cozystack-controller/main.go b/cmd/cozystack-controller/main.go index 0e7199d3..82fc673c 100644 --- a/cmd/cozystack-controller/main.go +++ b/cmd/cozystack-controller/main.go @@ -68,7 +68,6 @@ func main() { var disableTelemetry bool var telemetryEndpoint string var telemetryInterval string - var cozystackVersion string var reconcileDeployment bool var tlsOpts []func(*tls.Config) flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ @@ -87,8 +86,6 @@ func main() { "Endpoint for sending telemetry data") flag.StringVar(&telemetryInterval, "telemetry-interval", "15m", "Interval between telemetry data collection (e.g. 15m, 1h)") - flag.StringVar(&cozystackVersion, "cozystack-version", "unknown", - "Version of Cozystack") flag.BoolVar(&reconcileDeployment, "reconcile-deployment", false, "If set, the Cozystack API server is assumed to run as a Deployment, else as a DaemonSet.") opts := zap.Options{ @@ -106,10 +103,9 @@ func main() { // Configure telemetry telemetryConfig := telemetry.Config{ - Disabled: disableTelemetry, - Endpoint: telemetryEndpoint, - Interval: interval, - CozystackVersion: cozystackVersion, + Disabled: disableTelemetry, + Endpoint: telemetryEndpoint, + Interval: interval, } ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) @@ -204,20 +200,20 @@ func main() { if reconcileDeployment { cozyAPIKind = "Deployment" } - if err = (&controller.CozystackResourceDefinitionReconciler{ + if err = (&controller.ApplicationDefinitionReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), CozystackAPIKind: cozyAPIKind, }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "CozystackResourceDefinitionReconciler") + setupLog.Error(err, "unable to create controller", "controller", "ApplicationDefinitionReconciler") os.Exit(1) } - if err = (&controller.CozystackResourceDefinitionHelmReconciler{ + if err = (&controller.ApplicationDefinitionHelmReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "CozystackResourceDefinitionHelmReconciler") + setupLog.Error(err, "unable to create controller", "controller", "ApplicationDefinitionHelmReconciler") os.Exit(1) } diff --git a/cmd/cozystack-operator/main.go b/cmd/cozystack-operator/main.go index 13921f0c..188ce160 100644 --- a/cmd/cozystack-operator/main.go +++ b/cmd/cozystack-operator/main.go @@ -52,6 +52,7 @@ import ( "github.com/cozystack/cozystack/internal/cozyvaluesreplicator" "github.com/cozystack/cozystack/internal/fluxinstall" "github.com/cozystack/cozystack/internal/operator" + "github.com/cozystack/cozystack/internal/telemetry" // +kubebuilder:scaffold:imports ) @@ -77,7 +78,9 @@ func main() { var secureMetrics bool var enableHTTP2 bool var installFlux bool - var cozystackVersion string + var disableTelemetry bool + var telemetryEndpoint string + var telemetryInterval string var cozyValuesSecretName string var cozyValuesSecretNamespace string var cozyValuesNamespaceSelector string @@ -95,8 +98,12 @@ func main() { flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers") flag.BoolVar(&installFlux, "install-flux", false, "Install Flux components before starting reconcile loop") - flag.StringVar(&cozystackVersion, "cozystack-version", "unknown", - "Version of Cozystack") + flag.BoolVar(&disableTelemetry, "disable-telemetry", false, + "Disable telemetry collection") + flag.StringVar(&telemetryEndpoint, "telemetry-endpoint", "https://telemetry.cozystack.io", + "Endpoint for sending telemetry data") + flag.StringVar(&telemetryInterval, "telemetry-interval", "15m", + "Interval between telemetry data collection (e.g. 15m, 1h)") flag.StringVar(&platformSourceURL, "platform-source-url", "", "Platform source URL (oci:// or https://). If specified, generates OCIRepository or GitRepository resource.") flag.StringVar(&platformSourceName, "platform-source-name", "cozystack-packages", "Name for the generated platform source resource (default: cozystack-packages)") flag.StringVar(&platformSourceRef, "platform-source-ref", "", "Reference specification as key=value pairs (e.g., 'branch=main' or 'digest=sha256:...,tag=v1.0'). For OCI: digest, semver, semverFilter, tag. For Git: branch, tag, semver, name, commit.") @@ -240,6 +247,34 @@ func main() { os.Exit(1) } + // Parse telemetry interval + interval, err := time.ParseDuration(telemetryInterval) + if err != nil { + setupLog.Error(err, "invalid telemetry interval") + os.Exit(1) + } + + // Configure telemetry + telemetryConfig := telemetry.Config{ + Disabled: disableTelemetry, + Endpoint: telemetryEndpoint, + Interval: interval, + } + + // Initialize telemetry collector + // Use APIReader (non-cached) because the manager's cache is filtered + // and doesn't include resources needed for telemetry (e.g., kube-system namespace, nodes, etc.) + collector, err := telemetry.NewOperatorCollector(mgr.GetAPIReader(), &telemetryConfig, config) + if err != nil { + setupLog.V(1).Info("unable to create telemetry collector, telemetry will be disabled", "error", err) + } + + if collector != nil { + if err := mgr.Add(collector); err != nil { + setupLog.V(1).Info("unable to set up telemetry collector, continuing without telemetry", "error", err) + } + } + setupLog.Info("Starting controller manager") mgrCtx := ctrl.SetupSignalHandler() if err := mgr.Start(mgrCtx); err != nil { diff --git a/cmd/flux-plunger/main.go b/cmd/flux-plunger/main.go new file mode 100644 index 00000000..13fe88cd --- /dev/null +++ b/cmd/flux-plunger/main.go @@ -0,0 +1,151 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "crypto/tls" + "flag" + "os" + + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" + + helmv2 "github.com/fluxcd/helm-controller/api/v2" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + + "github.com/cozystack/cozystack/internal/controller/fluxplunger" + // +kubebuilder:scaffold:imports +) + +var ( + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(helmv2.AddToScheme(scheme)) + + // +kubebuilder:scaffold:scheme +} + +func main() { + var metricsAddr string + var enableLeaderElection bool + var probeAddr string + var secureMetrics bool + var enableHTTP2 bool + var tlsOpts []func(*tls.Config) + + flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ + "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.BoolVar(&enableLeaderElection, "leader-elect", false, + "Enable leader election for controller manager. "+ + "Enabling this will ensure there is only one active controller manager.") + flag.BoolVar(&secureMetrics, "metrics-secure", true, + "If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.") + flag.BoolVar(&enableHTTP2, "enable-http2", false, + "If set, HTTP/2 will be enabled for the metrics server") + + opts := zap.Options{ + Development: false, + } + opts.BindFlags(flag.CommandLine) + flag.Parse() + + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + + // if the enable-http2 flag is false (the default), http/2 should be disabled + // due to its vulnerabilities. More specifically, disabling http/2 will + // prevent from being vulnerable to the HTTP/2 Stream Cancellation and + // Rapid Reset CVEs. For more information see: + // - https://github.com/advisories/GHSA-qppj-fm5r-hxr3 + // - https://github.com/advisories/GHSA-4374-p667-p6c8 + disableHTTP2 := func(c *tls.Config) { + setupLog.Info("disabling http/2") + c.NextProtos = []string{"http/1.1"} + } + + if !enableHTTP2 { + tlsOpts = append(tlsOpts, disableHTTP2) + } + + // Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server. + // More info: + // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/metrics/server + // - https://book.kubebuilder.io/reference/metrics.html + metricsServerOptions := metricsserver.Options{ + BindAddress: metricsAddr, + SecureServing: secureMetrics, + TLSOpts: tlsOpts, + } + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + Metrics: metricsServerOptions, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "flux-plunger.cozystack.io", + // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily + // when the Manager ends. This requires the binary to immediately end when the + // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly + // speeds up voluntary leader transitions as the new leader don't have to wait + // LeaseDuration time first. + // + // In the default scaffold provided, the program ends immediately after + // the manager stops, so would be fine to enable this option. However, + // if you are doing or is intended to do any operation such as perform cleanups + // after the manager stops then its usage might be unsafe. + // LeaderElectionReleaseOnCancel: true, + }) + if err != nil { + setupLog.Error(err, "unable to create manager") + os.Exit(1) + } + + if err = (&fluxplunger.FluxPlunger{ + Client: mgr.GetClient(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "FluxPlunger") + os.Exit(1) + } + + // +kubebuilder:scaffold:builder + + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up ready check") + os.Exit(1) + } + + setupLog.Info("starting manager") + if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + setupLog.Error(err, "problem running manager") + os.Exit(1) + } +} diff --git a/dashboards/hubble/dns-namespace.json b/dashboards/hubble/dns-namespace.json new file mode 100644 index 00000000..57f804cf --- /dev/null +++ b/dashboards/hubble/dns-namespace.json @@ -0,0 +1,602 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "panel", + "id": "bargauge", + "name": "Bar gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.4.7" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 16612, + "graphTooltip": 0, + "id": null, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "cilium-overview" + ], + "targetBlank": false, + "title": "Cilium Overviews", + "tooltip": "", + "type": "dashboards", + "url": "" + }, + { + "asDropdown": true, + "icon": "external link", + "includeVars": false, + "keepTime": true, + "tags": [ + "hubble" + ], + "targetBlank": false, + "title": "Hubble", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [], + "title": "DNS", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 37, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(hubble_dns_queries_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])) by (source) > 0", + "legendFormat": "{{source}}", + "range": true, + "refId": "A" + } + ], + "title": "DNS queries", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 41, + "options": { + "displayMode": "gradient", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(10, sum(rate(hubble_dns_queries_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])*60) by (query))", + "legendFormat": "{{query}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 DNS queries", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 39, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "round(sum(rate(hubble_dns_queries_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])) by (source) - sum(label_replace(sum(rate(hubble_dns_responses_total{cluster=~\"$cluster\", source_namespace=~\"$destination_namespace\", destination_namespace=~\"$source_namespace\"}[$__rate_interval])) by (destination), \"source\", \"$1\", \"destination\", \"(.*)\")) without (destination), 0.001) > 0", + "legendFormat": "{{source}}", + "range": true, + "refId": "A" + } + ], + "title": "Missing DNS responses", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 43, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(hubble_dns_responses_total{cluster=~\"$cluster\", source_namespace=~\"$destination_namespace\", destination_namespace=~\"$source_namespace\", rcode!=\"No Error\"}[$__rate_interval])) by (destination, rcode) > 0", + "legendFormat": "{{destination}}: {{rcode}}", + "range": true, + "refId": "A" + } + ], + "title": "DNS errors", + "type": "timeseries" + } + ], + "refresh": "", + "revision": 1, + "schemaVersion": 38, + "style": "dark", + "tags": [ + "kubecon-demo" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "Data Source", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "(?!grafanacloud-usage|grafanacloud-ml-metrics).+", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(cilium_version, cluster)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(cilium_version, cluster)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(source_namespace)", + "hide": 0, + "includeAll": true, + "label": "Source Namespace", + "multi": true, + "name": "source_namespace", + "options": [], + "query": { + "query": "label_values(source_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(destination_namespace)", + "hide": 0, + "includeAll": true, + "label": "Destination Namespace", + "multi": true, + "name": "destination_namespace", + "options": [], + "query": { + "query": "label_values(destination_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Hubble / DNS Overview (Namespace)", + "uid": "_f0DUpY4k", + "version": 26, + "weekStart": "" + } + \ No newline at end of file diff --git a/dashboards/hubble/l7-http-metrics.json b/dashboards/hubble/l7-http-metrics.json new file mode 100644 index 00000000..b21004a6 --- /dev/null +++ b/dashboards/hubble/l7-http-metrics.json @@ -0,0 +1,1394 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.4.7" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 14, + "panels": [], + "title": "General", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 16, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "round(sum(rate(hubble_http_requests_total{reporter=~\"${reporter}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\"}[$__rate_interval])), 0.001)", + "refId": "A" + } + ], + "title": "Incoming Request Volume", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 1 + }, + "id": 17, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", status!~\"5.*\"}[$__rate_interval]))\n/\nsum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\"}[$__rate_interval]))", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ source_namespace }}/{{ source_workload }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Request Success Rate (non-5xx responses)", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 18, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.0.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.50, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\"}[$__rate_interval])) by (le))", + "interval": "", + "legendFormat": "P50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.95, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\"}[$__rate_interval])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "P95", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.99, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\"}[$__rate_interval])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "P99", + "range": true, + "refId": "C" + } + ], + "title": "Request Duration", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 6, + "panels": [], + "title": "Requests by Source", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "max", + "mean", + "sum", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "round(sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload, status), 0.001)", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ source_namespace }}/{{ source_workload }}: {{ status }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Requests by Source and Response Code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 7, + "options": { + "legend": { + "calcs": [ + "mean", + "min", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\",status!~\"5.*\"}[$__rate_interval])) by (cluster, source_namespace, source_workload)\n/\nsum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload)", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ source_namespace }}/{{ source_workload }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Request Success Rate (non-5xx responses) By Source", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.50, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload, le))", + "interval": "", + "legendFormat": "{{ cluster }} {{ source_namespace }}/{{ source_workload }} P50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload, le))", + "hide": false, + "interval": "", + "legendFormat": "{{ cluster }} {{ source_namespace }}/{{ source_workload }} P95", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, source_namespace, source_workload, le))", + "hide": false, + "interval": "", + "legendFormat": "{{ cluster }} {{ source_namespace }}/{{ source_workload }} P99", + "range": true, + "refId": "C" + } + ], + "title": "HTTP Request Duration by Source", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 20, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=~\"${cluster}\", namespace=~\"${destination_namespace}\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=~\"${cluster}\", namespace=~\"${destination_namespace}\", workload=~\"${source_workload}\"}\n) by (namespace, workload)", + "interval": "", + "legendFormat": "{{ cluster }} {{ namespace }}/{{ workload }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Usage by Source", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 27 + }, + "id": 9, + "panels": [], + "title": "Requests by Destination", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 28 + }, + "id": 10, + "options": { + "legend": { + "calcs": [ + "max", + "mean", + "sum", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "round(sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload, status), 0.001)", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ destination_namespace }}/{{ destination_workload }}: {{ status }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Requests by Destination and Response Code", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 28 + }, + "id": 11, + "options": { + "legend": { + "calcs": [ + "mean", + "min", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\",status!~\"5.*\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload)\n/\nsum(rate(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload)", + "interval": "", + "legendFormat": "{{ cluster }} {{ method }} {{ destination_namespace }}/{{ destination_workload }}", + "range": true, + "refId": "A" + } + ], + "title": "Incoming Request Success Rate (non-5xx responses) By Destination", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 38 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.50, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload, le))", + "interval": "", + "legendFormat": "{{ cluster }} {{ destination_namespace }}/{{ destination_workload }} P50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.95, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload, le))", + "hide": false, + "interval": "", + "legendFormat": "{{ cluster }} {{ destination_namespace }}/{{ destination_workload }} P95", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "histogram_quantile(0.99, sum(rate(hubble_http_request_duration_seconds_bucket{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", reporter=\"${reporter}\", source_namespace=~\"${source_namespace}\", source_workload=~\"${source_workload}\"}[$__rate_interval])) by (cluster, destination_namespace, destination_workload, le))", + "hide": false, + "interval": "", + "legendFormat": "{{ cluster }} {{ destination_namespace }}/{{ destination_workload }} P99", + "range": true, + "refId": "C" + } + ], + "title": "HTTP Request Duration by Destination", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 38 + }, + "id": 19, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(\n node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{cluster=~\"${cluster}\", namespace=~\"${destination_namespace}\"}\n * on(namespace,pod)\n group_left(workload, workload_type) namespace_workload_pod:kube_pod_owner:relabel{cluster=~\"${cluster}\", namespace=~\"${destination_namespace}\", workload=\"${destination_workload}\"}\n) by (namespace, workload)", + "interval": "", + "legendFormat": "{{ cluster }} {{ namespace }}/{{ workload }}", + "range": true, + "refId": "A" + } + ], + "title": "CPU Usage by Destination", + "type": "timeseries" + } + ], + "refresh": "30s", + "revision": 1, + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": {}, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total, cluster)", + "hide": 0, + "includeAll": false, + "label": "Cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total, cluster)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\"}, destination_namespace)", + "description": "", + "hide": 0, + "includeAll": false, + "label": "Destination Namespace", + "multi": false, + "name": "destination_namespace", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\"}, destination_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\"}, destination_workload)", + "hide": 0, + "includeAll": false, + "label": "Destination Workload", + "multi": false, + "name": "destination_workload", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\"}, destination_workload)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 2, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total, reporter)", + "hide": 0, + "includeAll": false, + "label": "Reporter", + "multi": false, + "name": "reporter", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total, reporter)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\"}, source_namespace)", + "hide": 0, + "includeAll": true, + "label": "Source Namespace", + "multi": true, + "name": "source_namespace", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\"}, source_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", source_namespace=~\"${source_namespace}\"}, source_workload)", + "hide": 0, + "includeAll": true, + "label": "Source Workload", + "multi": true, + "name": "source_workload", + "options": [], + "query": { + "query": "label_values(hubble_http_requests_total{cluster=~\"${cluster}\", destination_namespace=~\"${destination_namespace}\", destination_workload=~\"${destination_workload}\", source_namespace=~\"${source_namespace}\"}, source_workload)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Hubble L7 HTTP Metrics by Workload", + "uid": "3g264CZVz", + "version": 3, + "weekStart": "" +} diff --git a/dashboards/hubble/network-overview.json b/dashboards/hubble/network-overview.json new file mode 100644 index 00000000..cddb473d --- /dev/null +++ b/dashboards/hubble/network-overview.json @@ -0,0 +1,1001 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "panel", + "id": "bargauge", + "name": "Bar gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.4.7" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 16612, + "graphTooltip": 0, + "id": null, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "cilium-overview" + ], + "targetBlank": false, + "title": "Cilium Overviews", + "tooltip": "", + "type": "dashboards", + "url": "" + }, + { + "asDropdown": true, + "icon": "external link", + "includeVars": false, + "keepTime": true, + "tags": [ + "hubble" + ], + "targetBlank": false, + "title": "Hubble", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "panels": [], + "title": "Flows processed", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(hubble_flows_processed_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])) by (type, subtype)", + "legendFormat": "{{type}}/{{subtype}}", + "range": true, + "refId": "A" + } + ], + "title": "Flows processed by type", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 35, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(hubble_flows_processed_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])) by (verdict)", + "legendFormat": "{{verdict}}", + "range": true, + "refId": "A" + } + ], + "title": "Flows processed by verdict", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 36, + "options": { + "displayMode": "gradient", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(10, sum(rate(hubble_flows_processed_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])) by (source))", + "legendFormat": "{{source}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 sources", + "type": "bargauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 37, + "options": { + "displayMode": "gradient", + "minVizHeight": 10, + "minVizWidth": 0, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true + }, + "pluginVersion": "9.4.7", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "topk(10, sum(rate(hubble_flows_processed_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])) by (destination))", + "legendFormat": "{{source}}", + "range": true, + "refId": "A" + } + ], + "title": "Top 10 destinations", + "type": "bargauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 10, + "panels": [], + "title": "Connection drops", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 23, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(hubble_tcp_flags_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\", flag=\"SYN\"}[$__rate_interval])) by (source) - sum(label_replace(sum(rate(hubble_tcp_flags_total{cluster=~\"$cluster\", source_namespace=~\"$destination_namespace\", destination_namespace=~\"$source_namespace\", flag=\"SYN-ACK\"}[$__rate_interval])) by (destination), \"source\", \"$1\", \"destination\", \"(.*)\")) without (destination) > 0", + "hide": false, + "legendFormat": "{{source}}", + "range": true, + "refId": "A" + } + ], + "title": "Missing TCP SYN-ACKs", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 34, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(hubble_icmp_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\", type=\"EchoRequest\"}[$__rate_interval])) by (source) - sum(label_replace(sum(rate(hubble_icmp_total{cluster=~\"$cluster\", source_namespace=~\"$destination_namespace\", destination_namespace=~\"$source_namespace\", type=\"EchoReply\"}[$__rate_interval])) by (destination), \"source\", \"$1\", \"destination\", \"(.*)\")) without (destination) > 0", + "legendFormat": "{{source}}", + "range": true, + "refId": "A" + } + ], + "title": "Missing ICMP Echo Replys", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 6, + "panels": [], + "title": "Network Policy drops", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 29, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(hubble_drop_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])) by (source, reason) > 0", + "legendFormat": "{{source}}: {{reason}}", + "range": true, + "refId": "A" + } + ], + "title": "Network Policy drops by source", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "kube-dns-7d44cdb5d5-g85vg: UNSUPPORTED_PROTOCOL_FOR_NAT_MASQUERADE" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 30, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(hubble_drop_total{cluster=~\"$cluster\", source_namespace=~\"$source_namespace\", destination_namespace=~\"$destination_namespace\"}[$__rate_interval])) by (destination, reason) > 0", + "legendFormat": "{{destination}}: {{reason}}", + "range": true, + "refId": "A" + } + ], + "title": "Network Policy drops by destination", + "type": "timeseries" + } + ], + "refresh": "", + "revision": 1, + "schemaVersion": 38, + "style": "dark", + "tags": [ + "kubecon-demo" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "Data Source", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "(?!grafanacloud-usage|grafanacloud-ml-metrics).+", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(cilium_version, cluster)", + "hide": 0, + "includeAll": true, + "multi": true, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(cilium_version, cluster)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(source_namespace)", + "hide": 0, + "includeAll": true, + "label": "Source Namespace", + "multi": true, + "name": "source_namespace", + "options": [], + "query": { + "query": "label_values(source_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(destination_namespace)", + "hide": 0, + "includeAll": true, + "label": "Destination Namespace", + "multi": true, + "name": "destination_namespace", + "options": [], + "query": { + "query": "label_values(destination_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Hubble / Network Overview (Namespace)", + "uid": "nlsO8tYVz", + "version": 18, + "weekStart": "" + } + \ No newline at end of file diff --git a/dashboards/hubble/overview.json b/dashboards/hubble/overview.json new file mode 100644 index 00000000..783aa131 --- /dev/null +++ b/dashboards/hubble/overview.json @@ -0,0 +1,3357 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 3, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 14, + "panels": [], + "title": "General Processing", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "max", + "fillBelowTo": "avg", + "lines": false + }, + { + "alias": "avg", + "fill": 0, + "fillBelowTo": "min" + }, + { + "alias": "min", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(sum(rate(hubble_flows_processed_total[1m])) by (pod))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "avg", + "refId": "A" + }, + { + "expr": "min(sum(rate(hubble_flows_processed_total[1m])) by (pod))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "min", + "refId": "B" + }, + { + "expr": "max(sum(rate(hubble_flows_processed_total[1m])) by (pod))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "max", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Flows processed Per Node", + "tooltip": { + "shared": true, + "sort": 1, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 32, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_flows_processed_total[1m])) by (pod, type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Flows Types", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 59, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_flows_processed_total{type=\"L7\"}[1m])) by (pod, subtype)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{subtype}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "L7 Flow Distribution", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 60, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_flows_processed_total{type=\"Trace\"}[1m])) by (pod, subtype)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{subtype}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Trace Flow Distribution", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 16, + "panels": [], + "title": "Network", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 33, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_flows_processed_total[1m])) by (pod, verdict)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{verdict}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forwarded vs Dropped", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_drop_total[1m])) by (pod, reason)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Drop Reason", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 34, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": true, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum (rate(hubble_port_distribution_total[1m])) by (pod, protocol)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{protocol}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Protocol Usage", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum (rate(hubble_port_distribution_total{port!=\"0\"}[1m])) by (pod, port, protocol))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{port}}/{{protocol}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Top 10 Port Distribution", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 22 + }, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fin", + "yaxis": 1 + }, + { + "alias": "FIN", + "yaxis": 2 + }, + { + "alias": "RST", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_tcp_flags_total{family=\"IPv4\"}[1m])) by (pod, flag)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{flag}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCPv4", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 0.2 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Missing TCP SYN-ACK", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 22 + }, + "id": 62, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fin", + "yaxis": 1 + }, + { + "alias": "FIN", + "yaxis": 2 + }, + { + "alias": "RST", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_tcp_flags_total{family=\"IPv4\", flag=\"SYN\"}[1m])) by (pod) - sum(rate(hubble_tcp_flags_total{family=\"IPv4\", flag=\"SYN-ACK\"}[1m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Missing SYN-ACK", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.2 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing TCPv4 SYN-ACKs", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 35, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fin", + "yaxis": 1 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_tcp_flags_total{family=\"IPv6\"}[1m])) by (pod, flag)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{flag}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "TCPv6", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 0.2 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Missing TCPv6 SYN-ACKs alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 63, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "fin", + "yaxis": 1 + }, + { + "alias": "FIN", + "yaxis": 2 + }, + { + "alias": "RST", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_tcp_flags_total{family=\"IPv6\", flag=\"SYN\"}[1m])) by (pod) - sum(rate(hubble_tcp_flags_total{family=\"IPv6\", flag=\"SYN-ACK\"}[1m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Missing SYN-ACK", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.2 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing TCPv6 SYN-ACKs", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 31, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_icmp_total{family=\"IPv4\"}[1m])) by (pod, type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMPv4", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 0.1 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Missing ICMPv4 Echo-Reply alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 64, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_icmp_total{family=\"IPv4\", type=\"EchoRequest\"}[1m])) by (pod) - sum(rate(hubble_icmp_total{family=\"IPv4\", type=\"EchoReply\"}[1m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Missing ICMP Echo-Reply", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.1 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing ICMPv4 Echo-Reply", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 37 + }, + "id": 36, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_icmp_total{family=\"IPv6\"}[1m])) by (pod, type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMPv6", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 37 + }, + "id": 65, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_icmp_total{family=\"IPv6\", type=\"EchoRequest\"}[1m])) by (pod) - sum(rate(hubble_icmp_total{family=\"IPv6\", type=\"EchoReply\"}[1m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Missing ICMP Echo-Reply", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing ICMPv6 Echo-Reply", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 42 + }, + "id": 42, + "panels": [], + "title": "Network Policy", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 43, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_drop_total{reason=\"POLICY_DENIED\"}[1m])) by (pod, reason)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{reason}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Denies by Reason", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 4, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 61, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_drop_total{reason=\"POLICY_DENIED\"}[1m])) by (pod, protocol)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{protocol}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Denied Packets by Protocol", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 55, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum(rate(hubble_drop_total{reason=\"POLICY_DENIED\"}[1m])) by (pod, source))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{source}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Top 10 Source Pods with Denied Packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 54, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum(rate(hubble_drop_total{reason=\"POLICY_DENIED\"}[1m])) by (pod, destination))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{destination}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Top 10 Destination Pods with Denied Packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "pps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 47, + "panels": [], + "title": "HTTP", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 45, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_http_requests_total[1m])) by (pod, method)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP Requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "reqps", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 53 + }, + "id": 49, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_http_responses_total[1m])) by (pod, status)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP responses", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 51, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.5, rate(hubble_http_request_duration_seconds_bucket[1m]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP Request/Response Latency (p50)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 58, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "histogram_quantile(0.99, rate(hubble_http_request_duration_seconds_bucket[1m]))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP Request/Response Latency (p99)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 64 + }, + "id": 53, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": true, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_http_requests_total[5m])) by (pod, protocol)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{protocol}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP Protocol Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 69 + }, + "id": 6, + "panels": [], + "title": "DNS", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 70 + }, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_queries_total[1m])) by (pod, qtypes)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{qtypes}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS Requests", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 70 + }, + "id": 4, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_responses_total{rcode=\"No Error\"}[1m])) by (pod, qtypes)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{qtypes}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS responses", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "conditions": [ + { + "evaluator": { + "params": [ + 0.5 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "DNS Request/Response Symmetry alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 70 + }, + "id": 66, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_queries_total[1m])) by (pod, qtypes) - sum(rate(hubble_dns_responses_total[1m])) by (pod, qtypes)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{qtypes}}", + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.5 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Missing DNS Responses", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 75 + }, + "id": 40, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_response_types_total[1m])) by (pod, type)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS Response Record Type", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 75 + }, + "id": 57, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_responses_total{rcode=\"No Error\"}[1m])) by (pod,ips_returned)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ips_returned}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS Response IPs Returned", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 80 + }, + "id": 28, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(hubble_dns_responses_total{rcode!=\"No Error\"}[1m])) by (pod, qtypes, rcode)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{rcode}} ({{qtypes}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "DNS Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 4, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 80 + }, + "id": 56, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10,sum(rate(hubble_dns_responses_total{rcode!=\"No Error\"}[1m])) by (pod, destination))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{destination}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pods with DNS errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 4, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fill": 1, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 85 + }, + "id": 20, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": {}, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "topk(10, sum(rate(hubble_dns_queries_total[10m])*60) by (query, qtypes))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{query}} ({{qtypes}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Top 10 DNS Queries per minute", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "30s", + "schemaVersion": 18, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": {}, + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Hubble Metrics and Monitoring", + "uid": "5HftnJAWz", + "version": 24 +} diff --git a/docs/changelogs/v0.37.10.md b/docs/changelogs/v0.37.10.md new file mode 100644 index 00000000..18f0dd8b --- /dev/null +++ b/docs/changelogs/v0.37.10.md @@ -0,0 +1,16 @@ + + +## Features and Improvements + +* **[virtual-machine] Improve check for resizing job**: Improved storage resize logic to only expand persistent volume claims when storage is being increased, preventing unintended storage reduction operations. Added validation to accurately compare current and desired storage sizes before triggering resize operations ([**@kvaps**](https://github.com/kvaps) in #1688, #1702). + +## Fixes + +* **[dashboard] Fix CustomFormsOverride schema to nest properties under spec.properties**: Fixed the logic for generating CustomFormsOverride schema to properly nest properties under `spec.properties` instead of directly under `properties`, ensuring correct form schema generation in the dashboard ([**@kvaps**](https://github.com/kvaps) in #1692, #1699). + +--- + +**Full Changelog**: [v0.37.9...v0.37.10](https://github.com/cozystack/cozystack/compare/v0.37.9...v0.37.10) + diff --git a/docs/changelogs/v0.38.5.md b/docs/changelogs/v0.38.5.md new file mode 100644 index 00000000..0cae8b2a --- /dev/null +++ b/docs/changelogs/v0.38.5.md @@ -0,0 +1,18 @@ + + +## Features and Improvements + +* **[virtual-machine,vm-instance] Add nodeAffinity for Windows VMs based on scheduling config**: Added nodeAffinity configuration to virtual-machine and vm-instance charts to support dedicated nodes for Windows VMs. When `dedicatedNodesForWindowsVMs` is enabled in the `cozystack-scheduling` ConfigMap, Windows VMs are scheduled on nodes with label `scheduling.cozystack.io/vm-windows=true`, while non-Windows VMs prefer nodes without this label ([**@kvaps**](https://github.com/kvaps) in #1693, #1744). +* **[cilium] Enable automatic pod rollout on configmap updates**: Cilium and Cilium operator pods now automatically restart when the cilium-config ConfigMap is updated, ensuring configuration changes are applied immediately without manual intervention ([**@kvaps**](https://github.com/kvaps) in #1728, #1745). +* **Update SeaweedFS v4.02**: Updated SeaweedFS to version 4.02 with improved S3 daemon performance and fixes. This update includes better S3 compatibility and performance improvements ([**@kvaps**](https://github.com/kvaps) in #1725, #1732). + +## Fixes + +* **[apps] Refactor apiserver to use typed objects and fix UnstructuredList GVK**: Refactored the apiserver REST handlers to use typed objects (`appsv1alpha1.Application`) instead of `unstructured.Unstructured`, eliminating the need for runtime conversions and simplifying the codebase. Additionally, fixed an issue where `UnstructuredList` objects were using the first registered kind from `typeToGVK` instead of the kind from the object's field when multiple kinds are registered with the same Go type. This fix includes the upstream fix from kubernetes/kubernetes#135537 ([**@kvaps**](https://github.com/kvaps) in #1679, #1709). + +--- + +**Full Changelog**: [v0.38.4...v0.38.5](https://github.com/cozystack/cozystack/compare/v0.38.4...v0.38.5) + diff --git a/docs/changelogs/v0.38.6.md b/docs/changelogs/v0.38.6.md new file mode 100644 index 00000000..9c39b66d --- /dev/null +++ b/docs/changelogs/v0.38.6.md @@ -0,0 +1,12 @@ + + +## Development, Testing, and CI/CD + +* **[kubernetes] Add lb tests for tenant k8s**: Added load balancer tests for tenant Kubernetes clusters, improving test coverage and ensuring proper load balancer functionality in tenant environments ([**@IvanHunters**](https://github.com/IvanHunters) in #1783, #1792). + +--- + +**Full Changelog**: [v0.38.5...v0.38.6](https://github.com/cozystack/cozystack/compare/v0.38.5...v0.38.6) + diff --git a/docs/changelogs/v0.38.7.md b/docs/changelogs/v0.38.7.md new file mode 100644 index 00000000..3edfd94c --- /dev/null +++ b/docs/changelogs/v0.38.7.md @@ -0,0 +1,13 @@ + + +## Fixes + +* **[kubevirt-operator] Fix typo in VMNotRunningFor10Minutes alert**: Fixed typo in VM alert name, ensuring proper alert triggering and monitoring for virtual machines that are not running for extended periods ([**@lexfrei**](https://github.com/lexfrei) in #1770). +* **[kubevirt-operator] Revert incorrect case change in VM alerts**: Reverted incorrect case change in VM alert names to maintain consistency with alert naming conventions ([**@lexfrei**](https://github.com/lexfrei) in #1804, #1805). + +--- + +**Full Changelog**: [v0.38.6...v0.38.7](https://github.com/cozystack/cozystack/compare/v0.38.6...v0.38.7) + diff --git a/docs/changelogs/v0.38.8.md b/docs/changelogs/v0.38.8.md new file mode 100644 index 00000000..0dbfe7b8 --- /dev/null +++ b/docs/changelogs/v0.38.8.md @@ -0,0 +1,12 @@ + + +## Improvements + +* **[multus] Remove memory limit**: Removed memory limit for Multus daemonset due to unpredictable memory consumption spikes during startup after node reboots (reported up to 3Gi). This temporary change prevents out-of-memory issues while the root cause is addressed in future releases ([**@nbykov0**](https://github.com/nbykov0) in #1834). + +--- + +**Full Changelog**: [v0.38.7...v0.38.8](https://github.com/cozystack/cozystack/compare/v0.38.7...v0.38.8) + diff --git a/docs/changelogs/v0.39.2.md b/docs/changelogs/v0.39.2.md new file mode 100644 index 00000000..dacb094f --- /dev/null +++ b/docs/changelogs/v0.39.2.md @@ -0,0 +1,19 @@ + + +## Features and Improvements + +* **[vm] Always expose VMs with a service**: Virtual machines are now always exposed with at least a ClusterIP service, ensuring they have in-cluster DNS names and can be accessed from other pods even without public IP addresses ([**@lllamnyp**](https://github.com/lllamnyp) in #1738, #1751). +* **[tenant] Allow egress to parent ingress pods**: Updated tenant network policies to allow egress traffic to parent cluster ingress pods, enabling proper communication patterns between tenant namespaces and parent cluster ingress controllers ([**@lexfrei**](https://github.com/lexfrei) in #1765, #1776). +* **[system] Add resource requests and limits to etcd-defrag**: Added resource requests and limits to etcd-defrag job to ensure proper resource allocation and prevent resource contention during etcd maintenance operations ([**@matthieu-robin**](https://github.com/matthieu-robin) in #1785, #1786). +* **[tenant] Run cleanup job from system namespace**: Moved tenant cleanup job to run from system namespace, improving security and resource isolation for tenant cleanup operations ([**@lllamnyp**](https://github.com/lllamnyp) in #1774, #1777). + +## Fixes + +* **[kubevirt-operator] Fix typo in VMNotRunningFor10Minutes alert**: Fixed typo in VM alert name, ensuring proper alert triggering and monitoring for virtual machines that are not running for extended periods ([**@lexfrei**](https://github.com/lexfrei) in #1770, #1775). + +--- + +**Full Changelog**: [v0.39.1...v0.39.2](https://github.com/cozystack/cozystack/compare/v0.39.1...v0.39.2) + diff --git a/docs/changelogs/v0.39.3.md b/docs/changelogs/v0.39.3.md new file mode 100644 index 00000000..f493795b --- /dev/null +++ b/docs/changelogs/v0.39.3.md @@ -0,0 +1,36 @@ + + +## Features and Improvements + +* **[seaweedfs] Traffic locality**: Upgraded SeaweedFS to v4.05 with traffic locality capabilities, new admin component with web-based UI, worker component for distributed operations, and enhanced S3 monitoring with Grafana dashboards. Improves S3 service performance by routing requests to nearest available volume servers ([**@nbykov0**](https://github.com/nbykov0) in #1748, #1830). +* **[kube-ovn] Update to v1.14.25**: Updated Kube-OVN to version 1.14.25 with improved stability and new features ([**@kvaps**](https://github.com/kvaps) in #1819, #1837). +* **[linstor] Build linstor-server with custom patches**: Added custom patches to linstor-server build process, enabling platform-specific optimizations and fixes ([**@kvaps**](https://github.com/kvaps) in #1726, #1818). +* **[api, lineage] Tolerate all taints**: Updated API and lineage webhook to tolerate all taints, ensuring controllers can run on any node regardless of taint configuration ([**@nbykov0**](https://github.com/nbykov0) in #1781, #1827). +* **[ingress] Add topology anti-affinities**: Added topology anti-affinity rules to ingress controller deployment for better pod distribution across nodes ([**@kvaps**](https://github.com/kvaps) in commit 25f31022). + +## Fixes + +* **[linstor] fix: prevent DRBD device race condition in updateDiscGran**: Fixed race condition in DRBD device management during granularity updates, preventing potential data corruption or device conflicts ([**@kvaps**](https://github.com/kvaps) in #1829, #1836). +* **fix(linstor): prevent orphaned DRBD devices during toggle-disk retry**: Fixed issue where retry logic during disk toggle operations could leave orphaned DRBD devices, now properly cleans up devices during retry attempts ([**@kvaps**](https://github.com/kvaps) in #1823, #1825). +* **[kubernetes] Fix endpoints for cilium-gateway**: Fixed endpoint configuration for cilium-gateway, ensuring proper service discovery and connectivity ([**@kvaps**](https://github.com/kvaps) in #1729, #1808). +* **[kubevirt-operator] Revert incorrect case change in VM alerts**: Reverted incorrect case change in VM alert names to maintain consistency with alert naming conventions ([**@lexfrei**](https://github.com/lexfrei) in #1804, #1806). + +## System Configuration + +* **[kubeovn] Package from external repo**: Extracted Kube-OVN packaging from main repository to external repository, improving modularity ([**@lllamnyp**](https://github.com/lllamnyp) in #1535). + +## Development, Testing, and CI/CD + +* **[testing] Add aliases and autocomplete**: Added shell aliases and autocomplete support for testing commands, improving developer experience ([**@lllamnyp**](https://github.com/lllamnyp) in #1803, #1809). + +## Dependencies + +* **[seaweedfs] Traffic locality**: Upgraded SeaweedFS to v4.05 with traffic locality capabilities ([**@nbykov0**](https://github.com/nbykov0) in #1748, #1830). +* **[kube-ovn] Update to v1.14.25**: Updated Kube-OVN to version 1.14.25 ([**@kvaps**](https://github.com/kvaps) in #1819, #1837). + +--- + +**Full Changelog**: [v0.39.2...v0.39.3](https://github.com/cozystack/cozystack/compare/v0.39.2...v0.39.3) + diff --git a/docs/changelogs/v0.39.4.md b/docs/changelogs/v0.39.4.md new file mode 100644 index 00000000..36d9f016 --- /dev/null +++ b/docs/changelogs/v0.39.4.md @@ -0,0 +1,12 @@ + + +## Features and Improvements + +* **[paas-full] Add multus dependencies similar to other CNIs**: Added Multus as a dependency in the paas-full package, consistent with how other CNIs are included. This ensures proper dependency management and simplifies the installation process for environments using Multus networking ([**@nbykov0**](https://github.com/nbykov0) in #1835). + +--- + +**Full Changelog**: [v0.39.3...v0.39.4](https://github.com/cozystack/cozystack/compare/v0.39.3...v0.39.4) + diff --git a/docs/changelogs/v0.39.5.md b/docs/changelogs/v0.39.5.md new file mode 100644 index 00000000..de352b1c --- /dev/null +++ b/docs/changelogs/v0.39.5.md @@ -0,0 +1,11 @@ + + +## Fixes + +* **[linstor] Update piraeus-server patches with critical fixes**: Backported critical patches to piraeus-server that address storage stability issues and improve DRBD resource handling. These patches fix edge cases in device management and ensure more reliable storage operations ([**@kvaps**](https://github.com/kvaps) in #1850, #1853). + +--- + +**Full Changelog**: [v0.39.4...v0.39.5](https://github.com/cozystack/cozystack/compare/v0.39.4...v0.39.5) diff --git a/docs/changelogs/v0.40.0.md b/docs/changelogs/v0.40.0.md new file mode 100644 index 00000000..caaa08f6 --- /dev/null +++ b/docs/changelogs/v0.40.0.md @@ -0,0 +1,206 @@ +# Cozystack v0.40 — "Enhanced Storage & Platform Architecture" + +This release introduces LINSTOR scheduler for optimal pod placement, SeaweedFS traffic locality, a new valuesFrom-based configuration mechanism, auto-diskful for LINSTOR, automated version management systems, and numerous improvements across the platform. + +## Feature Highlights + +### LINSTOR Scheduler for Optimal Pod Placement + +Cozystack now includes a custom Kubernetes scheduler extender that works alongside the default kube-scheduler to optimize pod placement on nodes with LINSTOR storage. When a pod requests LINSTOR-backed storage, the scheduler communicates with the LINSTOR controller to find nodes that have local replicas of the requested volumes, prioritizing placement on nodes with existing data to minimize network traffic and improve I/O performance. + +The scheduler includes an admission webhook that automatically routes pods using LINSTOR CSI volumes to the custom scheduler, ensuring seamless integration without manual configuration. This feature significantly improves performance for workloads using LINSTOR storage by reducing network latency and improving data locality. + +Learn more about LINSTOR in the [documentation](https://cozystack.io/docs/operations/storage/linstor/). + +### SeaweedFS Traffic Locality + +SeaweedFS has been upgraded to version 4.05 with new traffic locality capabilities that optimize S3 service traffic distribution. The update includes a new admin component with a web-based UI and authentication support, as well as a worker component for distributed operations. These enhancements improve S3 service performance and provide better visibility through enhanced Grafana dashboard panels for buckets, API calls, costs, and performance metrics. + +The traffic locality feature ensures that S3 requests are routed to the nearest available volume servers, reducing latency and improving overall performance for distributed storage operations. TLS certificate support for admin and worker components adds an extra layer of security for management operations. + +### ValuesFrom Configuration Mechanism + +Cozystack now uses FluxCD's valuesFrom mechanism to replace Helm lookup functions for configuration propagation. This architectural improvement provides cleaner config propagation and eliminates the need for force reconcile controllers. Configuration from ConfigMaps (cozystack, cozystack-branding, cozystack-scheduling) and namespace service references (etcd, host, ingress, monitoring, seaweedfs) is now centrally managed through a `cozystack-values` Secret in each namespace. + +This change simplifies Helm chart templates by replacing complex lookup functions with direct value references, improves configuration consistency, and reduces the reconciliation overhead. All HelmReleases now automatically receive cluster and namespace configuration through the valuesFrom mechanism, making configuration management more transparent and maintainable. + +### Auto-diskful for LINSTOR + +The LINSTOR integration now includes automatic diskful functionality that converts diskless nodes to diskful when they hold DRBD resources in Primary state for an extended period (30 minutes). This feature addresses scenarios where workloads are scheduled on nodes without local storage replicas by automatically creating local disk replicas when needed, improving I/O performance for long-running workloads. + +When enabled with cleanup options, the system can automatically remove disk replicas that are no longer needed, preventing storage waste from temporary replicas. This intelligent storage management reduces network traffic for frequently accessed data while maintaining efficient storage utilization. + +### Automated Version Management Systems + +Cozystack now includes automated version management systems for PostgreSQL, Kubernetes, MariaDB, and Redis applications. These systems automatically track upstream versions and provide mechanisms for automated version updates, ensuring that platform users always have access to the latest stable versions while maintaining compatibility with existing deployments. + +The version management systems integrate with the Cozystack API and dashboard, providing administrators with visibility into available versions and update paths. This infrastructure sets the foundation for future automated upgrade workflows and version compatibility management. + +--- + +## Major Features and Improvements + +### Storage + +* **[linstor] Add linstor-scheduler package**: Added LINSTOR scheduler extender for optimal pod placement on nodes with LINSTOR storage. Includes admission webhook that automatically routes pods using LINSTOR CSI volumes to the custom scheduler, ensuring pods are placed on nodes with local replicas to minimize network traffic and improve I/O performance ([**@kvaps**](https://github.com/kvaps) in #1824). +* **[linstor] Enable auto-diskful for diskless nodes**: Enabled DRBD auto-diskful functionality to automatically convert diskless nodes to diskful when they hold volumes in Primary state for more than 30 minutes. Improves I/O performance for long-running workloads by creating local replicas and includes automatic cleanup options to prevent storage waste ([**@kvaps**](https://github.com/kvaps) in #1826). +* **[linstor] Build linstor-server with custom patches**: Added custom patches to linstor-server build process, enabling platform-specific optimizations and fixes ([**@kvaps**](https://github.com/kvaps) in #1726). +* **[seaweedfs] Traffic locality**: Upgraded SeaweedFS to v4.05 with traffic locality capabilities, new admin component with web-based UI, worker component for distributed operations, and enhanced S3 monitoring with Grafana dashboards. Improves S3 service performance by routing requests to nearest available volume servers ([**@nbykov0**](https://github.com/nbykov0) in #1748). +* **[linstor] fix: prevent DRBD device race condition in updateDiscGran**: Fixed race condition in DRBD device management during granularity updates, preventing potential data corruption or device conflicts ([**@kvaps**](https://github.com/kvaps) in #1829). +* **fix(linstor): prevent orphaned DRBD devices during toggle-disk retry**: Fixed issue where retry logic during disk toggle operations could leave orphaned DRBD devices, now properly cleans up devices during retry attempts ([**@kvaps**](https://github.com/kvaps) in #1823). + +### Platform Architecture + +* **[platform] Replace Helm lookup with valuesFrom mechanism**: Replaced Helm lookup functions with FluxCD valuesFrom mechanism for configuration propagation. Configuration from ConfigMaps and namespace references is now managed through `cozystack-values` Secret, simplifying templates and eliminating force reconcile controllers ([**@kvaps**](https://github.com/kvaps) in #1787). +* **[platform] refactor: split cozystack-resource-definitions into separate packages**: Refactored cozystack-resource-definitions into separate packages for better organization and maintainability, improving code structure and reducing coupling between components ([**@kvaps**](https://github.com/kvaps) in #1778). +* **[platform] Separate assets server into dedicated deployment**: Separated assets server from main platform deployment, improving scalability and allowing independent scaling of asset delivery infrastructure ([**@kvaps**](https://github.com/kvaps) in #1705). +* **[core] Extract Talos package from installer**: Extracted Talos package configuration from installer into a separate package, improving modularity and enabling independent updates ([**@kvaps**](https://github.com/kvaps) in #1724). +* **[registry] Add application labels and update filtering mechanism**: Added application labels to registry resources and improved filtering mechanism for better resource discovery and organization ([**@kvaps**](https://github.com/kvaps) in #1707). +* **fix(registry): implement field selector filtering for label-based resources**: Implemented field selector filtering for label-based resources in the registry, improving query performance and resource lookup efficiency ([**@kvaps**](https://github.com/kvaps) in #1845). +* **[platform] Add alphabetical sorting to registry resource lists**: Added alphabetical sorting to registry resource lists in the API and dashboard, improving user experience when browsing available applications ([**@lexfrei**](https://github.com/lexfrei) in #1764). + +### Version Management + +* **[postgres] Add version management system with automated version updates**: Introduced version management system for PostgreSQL with automated version tracking and update mechanisms ([**@kvaps**](https://github.com/kvaps) in #1671). +* **[kubernetes] Add version management system with automated version updates**: Added version management system for Kubernetes tenant clusters with automated version tracking and update capabilities ([**@kvaps**](https://github.com/kvaps) in #1672). +* **[mariadb] Add version management system with automated version updates**: Implemented version management system for MariaDB with automated version tracking and update mechanisms ([**@kvaps**](https://github.com/kvaps) in #1680). +* **[redis] Add version management system with automated version updates**: Added version management system for Redis with automated version tracking and update capabilities ([**@kvaps**](https://github.com/kvaps) in #1681). + +### Networking + +* **[kube-ovn] Update to v1.14.25**: Updated Kube-OVN to version 1.14.25 with improved stability and new features ([**@kvaps**](https://github.com/kvaps) in #1819). +* **[kubeovn] Package from external repo**: Extracted Kube-OVN packaging from main repository to external repository, improving modularity ([**@lllamnyp**](https://github.com/lllamnyp) in #1535). +* **[cilium] Update Cilium to v1.18.5**: Updated Cilium to version 1.18.5 with latest features and bug fixes ([**@lexfrei**](https://github.com/lexfrei) in #1769). +* **[system/cilium] Enable topology-aware routing for services**: Enabled topology-aware routing for Cilium services, improving traffic distribution and reducing latency by routing traffic to endpoints in the same zone when possible ([**@nbykov0**](https://github.com/nbykov0) in #1734). +* **[cilium] Enable automatic pod rollout on configmap updates**: Cilium and Cilium operator pods now automatically restart when the cilium-config ConfigMap is updated, ensuring configuration changes are applied immediately ([**@kvaps**](https://github.com/kvaps) in #1728). +* **[kubernetes] Fix endpoints for cilium-gateway**: Fixed endpoint configuration for cilium-gateway, ensuring proper service discovery and connectivity ([**@kvaps**](https://github.com/kvaps) in #1729). +* **[multus] Increase memory limit**: Increased memory limits for Multus components to handle larger network configurations and reduce out-of-memory issues ([**@nbykov0**](https://github.com/nbykov0) in #1773). +* **[main][paas-full] Add multus dependencies similar to other CNIs**: Added Multus as a dependency in the paas-full package, consistent with how other CNIs are included ([**@nbykov0**](https://github.com/nbykov0) in #1842). + +### Virtual Machines + +* **[vm] Always expose VMs with a service**: Virtual machines are now always exposed with at least a ClusterIP service, ensuring they have in-cluster DNS names and can be accessed from other pods even without public IP addresses ([**@lllamnyp**](https://github.com/lllamnyp) in #1738). +* **[virtual-machine] Improve check for resizing job**: Improved storage resize logic to only expand persistent volume claims when storage is being increased, preventing unintended storage reduction operations ([**@kvaps**](https://github.com/kvaps) in #1688). +* **[virtual-machine,vm-instance] Add nodeAffinity for Windows VMs based on scheduling config**: Added nodeAffinity configuration to virtual-machine and vm-instance charts to support dedicated nodes for Windows VMs ([**@kvaps**](https://github.com/kvaps) in #1693). + +### Monitoring + +* **[monitoring] Add SLACK_SEVERITY_FILTER field and VMAgent for tenant monitoring**: Introduced SLACK_SEVERITY_FILTER environment variable in Alerta deployment to enable filtering of alert severities for Slack notifications. Added VMAgent resource template for scraping metrics within tenant namespaces, improving monitoring granularity ([**@IvanHunters**](https://github.com/IvanHunters) in #1712). +* **[monitoring] Improve tenant metrics collection**: Improved tenant metrics collection mechanisms for better observability and monitoring coverage ([**@IvanHunters**](https://github.com/IvanHunters) in #1684). + +### System Configuration + +* **[api, lineage] Tolerate all taints**: Updated API and lineage webhook to tolerate all taints, ensuring controllers can run on any node regardless of taint configuration ([**@nbykov0**](https://github.com/nbykov0) in #1781). +* **[system] Add resource requests and limits to etcd-defrag**: Added resource requests and limits to etcd-defrag job to ensure proper resource allocation and prevent resource contention ([**@matthieu-robin**](https://github.com/matthieu-robin) in #1785). +* **[system:coredns] update coredns app labels to match Talos coredns labels**: Updated coredns app labels to match Talos coredns labels, ensuring consistency across the platform ([**@nbykov0**](https://github.com/nbykov0) in #1675). +* **[system:monitoring-agents] rename coredns metrics service**: Renamed coredns metrics service to avoid interference with coredns service used for name resolution in tenant k8s clusters ([**@nbykov0**](https://github.com/nbykov0) in #1676). + +### Tenants and Namespaces + +* **[tenant] Allow egress to parent ingress pods**: Updated tenant network policies to allow egress traffic to parent cluster ingress pods, enabling proper communication patterns ([**@lexfrei**](https://github.com/lexfrei) in #1765). +* **[tenant] Run cleanup job from system namespace**: Moved tenant cleanup job to run from system namespace, improving security and resource isolation ([**@lllamnyp**](https://github.com/lllamnyp) in #1774). + +### FluxCD + +* **[fluxcd] Add flux-aio module and migration**: Added FluxCD all-in-one module with migration support, simplifying FluxCD installation and management ([**@kvaps**](https://github.com/kvaps) in #1698). +* **[fluxcd] Enable source-watcher**: Enabled source-watcher in FluxCD configuration for improved GitOps synchronization and faster update detection ([**@kvaps**](https://github.com/kvaps) in #1706). + +### Applications + +* **[dashboard] Fix CustomFormsOverride schema to nest properties under spec.properties**: Fixed CustomFormsOverride schema generation to properly nest properties under `spec.properties` instead of directly under `properties`, ensuring correct form schema generation ([**@kvaps**](https://github.com/kvaps) in #1692). +* **[apps] Refactor apiserver to use typed objects and fix UnstructuredList GVK**: Refactored apiserver REST handlers to use typed objects instead of unstructured.Unstructured, eliminating runtime conversions. Fixed UnstructuredList GVK issue where objects were using the first registered kind instead of the correct kind ([**@kvaps**](https://github.com/kvaps) in #1679). +* **[keycloak] Make kubernetes client public**: Made Kubernetes client public in Keycloak configuration, enabling broader access patterns for Kubernetes integrations ([**@lllamnyp**](https://github.com/lllamnyp) in #1802). + +## Improvements + +* **[granular kubernetes application extensions dependencies]**: Improved dependency management for Kubernetes application extensions with more granular control over dependencies ([**@nbykov0**](https://github.com/nbykov0) in #1683). +* **[core:installer] Address buildx warnings**: Fixed Dockerfile syntax warnings from buildx, ensuring clean builds without warnings ([**@nbykov0**](https://github.com/nbykov0) in #1682). +* **[linstor] Update piraeus-operator v2.10.2**: Updated LINSTOR CSI to version 2.10.2 with improved stability and bug fixes ([**@kvaps**](https://github.com/kvaps) in #1689). +* **Update SeaweedFS v4.02**: Updated SeaweedFS to version 4.02 with improved S3 daemon performance and fixes ([**@kvaps**](https://github.com/kvaps) in #1725). +* **[installer,dx] Rename cozypkg to cozyhr**: Renamed cozypkg tool to cozyhr for better branding and consistency ([**@kvaps**](https://github.com/kvaps) in #1763). + +## Fixes + +* **fix(platform): fix migrations for v0.40 release**: Fixed platform migrations for v0.40 release, ensuring smooth upgrades from previous versions ([**@kvaps**](https://github.com/kvaps) in #1846). +* **[platform] fix migration for removing fluxcd-operator**: Fixed migration logic for removing fluxcd-operator, ensuring clean removal without leaving orphaned resources ([**@kvaps**](https://github.com/kvaps) in commit 4a83d2c7). +* **[kubevirt-operator] Fix typo in VMNotRunningFor10Minutes alert**: Fixed typo in VM alert name, ensuring proper alert triggering and monitoring ([**@kvaps**](https://github.com/kvaps) in #1770). +* **[kubevirt-operator] Revert incorrect case change in VM alerts**: Reverted incorrect case change in VM alert names to maintain consistency ([**@lexfrei**](https://github.com/lexfrei) in #1804). +* **[cozystack-controller] Fix: move crds to definitions**: Fixed CRD placement by moving them to definitions directory, ensuring proper resource organization ([**@kvaps**](https://github.com/kvaps) in #1759). + +## Dependencies + +* **Update SeaweedFS v4.02**: Updated SeaweedFS to version 4.02 ([**@kvaps**](https://github.com/kvaps) in #1725). +* **[seaweedfs] Traffic locality**: Upgraded SeaweedFS to v4.05 with traffic locality capabilities ([**@nbykov0**](https://github.com/nbykov0) in #1748). +* **[linstor] Update piraeus-operator v2.10.2**: Updated piraeus-operator to version 2.10.2 ([**@kvaps**](https://github.com/kvaps) in #1689). +* **[kube-ovn] Update to v1.14.25**: Updated Kube-OVN to version 1.14.25 ([**@kvaps**](https://github.com/kvaps) in #1819). +* **[cilium] Update Cilium to v1.18.5**: Updated Cilium to version 1.18.5 ([**@lexfrei**](https://github.com/lexfrei) in #1769). +* **Update go modules**: Updated Go modules to latest versions ([**@kvaps**](https://github.com/kvaps) in #1736). + +## Development, Testing, and CI/CD + +* **[ci] Fix auto-release workflow**: Fixed auto-release workflow to ensure correct release publishing and tagging ([**@kvaps**](https://github.com/kvaps) in commit 526af294). +* **fix(ci): ensure correct latest release after backport publishing**: Fixed CI workflow to correctly identify and tag the latest release after backport publishing ([**@kvaps**](https://github.com/kvaps) in #1800). +* **[workflows] Add auto patch release workflow**: Added automated patch release workflow for streamlined release management ([**@kvaps**](https://github.com/kvaps) in #1754). +* **[workflow] Add GitHub Action to update release notes from changelogs**: Added GitHub Action to automatically update release notes from changelog files ([**@kvaps**](https://github.com/kvaps) in #1752). +* **[ci] Improve backport workflow with merge_commits skip and conflict resolution**: Improved backport workflow with better merge commit handling and conflict resolution ([**@kvaps**](https://github.com/kvaps) in #1694). +* **[testing] Add aliases and autocomplete**: Added shell aliases and autocomplete support for testing commands, improving developer experience ([**@lllamnyp**](https://github.com/lllamnyp) in #1803). +* **[kubernetes] Add lb tests for tenant k8s**: Added load balancer tests for tenant Kubernetes clusters, improving test coverage ([**@IvanHunters**](https://github.com/IvanHunters) in #1783). +* **[agents] Add instructions for working with unresolved code review comments**: Added documentation and instructions for working with unresolved code review comments in agent workflows ([**@kvaps**](https://github.com/kvaps) in #1710). +* **feat(ci): add /retest command to rerun tests from Prepare environment**: Added `/retest` command to rerun tests from Prepare environment workflow ([**@kvaps**](https://github.com/kvaps) in commit 30c1041e). +* **fix(ci): remove GITHUB_TOKEN extraheader to trigger workflows**: Removed GITHUB_TOKEN extraheader to properly trigger workflows ([**@kvaps**](https://github.com/kvaps) in commit 68a639b3). +* **Fix: Add missing components to `distro-full` bundle**: Fixed missing components in distro-full bundle, ensuring all required components are included ([**@LoneExile**](https://github.com/LoneExile) in #1620). +* **Update Flux Operator (v0.33.0)**: Updated Flux Operator to version 0.33.0 ([**@kingdonb**](https://github.com/kingdonb) in #1649). +* **Add changelogs for v0.38.3 and v.0.38.4**: Added missing changelogs for v0.38.3 and v0.38.4 releases ([**@androndo**](https://github.com/androndo) in #1743). +* **Add changelogs to v.0.39.1**: Added changelog for v0.39.1 release ([**@androndo**](https://github.com/androndo) in #1750). +* **Add Cloupard to ADOPTERS.md**: Added Cloupard to the adopters list ([**@SerjioTT**](https://github.com/SerjioTT) in #1733). + +## Documentation + +* **[website] docs: expand monitoring and alerting documentation**: Expanded monitoring and alerting documentation with comprehensive guides, examples, and troubleshooting information ([**@IvanHunters**](https://github.com/IvanHunters) in [cozystack/website#388](https://github.com/cozystack/website/pull/388)). +* **[website] fix auto-generation of documentation**: Fixed automatic documentation generation process, ensuring all documentation is properly generated and formatted ([**@IvanHunters**](https://github.com/IvanHunters) in [cozystack/website#391](https://github.com/cozystack/website/pull/391)). +* **[website] secure boot**: Added documentation for Secure Boot support in Talos Linux ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#387](https://github.com/cozystack/website/pull/387)). + +## Tools + +* **[talm] feat(helpers): add bond interface discovery helpers**: Added bond interface discovery helpers to talm for easier network configuration ([**@kvaps**](https://github.com/kvaps) in [cozystack/talm#94](https://github.com/cozystack/talm/pull/94)). +* **[talm] feat(talosconfig): add certificate regeneration from secrets.yaml**: Added certificate regeneration functionality to talm talosconfig command, allowing certificates to be regenerated from secrets.yaml ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@1319dde). +* **[talm] fix(init): make name optional for -u flag**: Made name parameter optional for init command with -u flag, improving flexibility ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@da29320). +* **[talm] fix(wrapper): copy NoOptDefVal when remapping -f to -F flag**: Fixed wrapper to properly copy NoOptDefVal when remapping flags, ensuring correct default value handling ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@f6a6f1d). +* **[talm] fix(root): detect project root with secrets.encrypted.yaml**: Fixed root detection to properly identify project root when secrets.encrypted.yaml is present ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@cf56780). +* **[talm] Fix interfaces helper for Talos v1.12**: Fixed interfaces helper to work correctly with Talos v1.12 ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@34984ae). +* **[talm] Fix typo on README.md**: Fixed typo in README documentation ([**@diegolakatos**](https://github.com/diegolakatos) in [cozystack/talm#92](https://github.com/cozystack/talm/pull/92)). +* **[talm] fix(template): return error for invalid YAML in template output**: Fixed template command to return proper error for invalid YAML output ([**@kvaps**](https://github.com/kvaps) in [cozystack/talm#93](https://github.com/cozystack/talm/pull/93)). +* **[talm] feat(cozystack): enable allocateNodeCIDRs by default**: Enabled allocateNodeCIDRs by default in talm cozystack preset ([**@lexfrei**](https://github.com/lexfrei) in [cozystack/talm#91](https://github.com/cozystack/talm/pull/91)). +* **[boot-to-talos] feat(network): add VLAN interface support via netlink**: Added VLAN interface support via netlink in boot-to-talos for advanced network configuration ([**@kvaps**](https://github.com/kvaps) in cozystack/boot-to-talos@02874d7). +* **[boot-to-talos] feat(network): add bond interface support via netlink**: Added bond interface support via netlink in boot-to-talos for network bonding configurations ([**@kvaps**](https://github.com/kvaps) in cozystack/boot-to-talos@067822d). +* **[boot-to-talos] Draft EFI Support**: Added draft EFI support in boot-to-talos for UEFI boot scenarios ([**@kvaps**](https://github.com/kvaps) in cozystack/boot-to-talos@e194bc8). +* **[boot-to-talos] Change default install image size from 2GB to 3GB**: Changed default install image size from 2GB to 3GB to accommodate larger installations ([**@kvaps**](https://github.com/kvaps) in cozystack/boot-to-talos@3bfb035). +* **[cozyhr] feat(values): add valuesFrom support for HelmRelease**: Added valuesFrom support for HelmRelease in cozyhr tool, enabling better configuration management ([**@kvaps**](https://github.com/kvaps) in cozystack/cozyhr@7dff0c8). +* **[cozyhr] Rename cozypkg to cozyhr**: Renamed cozypkg tool to cozyhr for better branding ([**@kvaps**](https://github.com/kvaps) in cozystack/cozyhr@1029461). + +--- + +## Contributors + +We'd like to thank all contributors who made this release possible: + +* [**@IvanHunters**](https://github.com/IvanHunters) +* [**@kvaps**](https://github.com/kvaps) +* [**@lexfrei**](https://github.com/lexfrei) +* [**@lllamnyp**](https://github.com/lllamnyp) +* [**@nbykov0**](https://github.com/nbykov0) +* [**@LoneExile**](https://github.com/LoneExile) +* [**@kingdonb**](https://github.com/kingdonb) +* [**@androndo**](https://github.com/androndo) +* [**@SerjioTT**](https://github.com/SerjioTT) +* [**@matthieu-robin**](https://github.com/matthieu-robin) +* [**@diegolakatos**](https://github.com/diegolakatos) + +--- + +**Full Changelog**: [v0.39.0...v0.40.0](https://github.com/cozystack/cozystack/compare/v0.39.0...v0.40.0) + + + diff --git a/docs/changelogs/v0.40.1.md b/docs/changelogs/v0.40.1.md new file mode 100644 index 00000000..ee718b47 --- /dev/null +++ b/docs/changelogs/v0.40.1.md @@ -0,0 +1,11 @@ + + +## Fixes + +* **[linstor] Update piraeus-server patches with critical fixes**: Backported critical patches to piraeus-server that address storage stability issues and improve DRBD resource handling. These patches fix edge cases in device management and ensure more reliable storage operations ([**@kvaps**](https://github.com/kvaps) in #1850, #1852). + +--- + +**Full Changelog**: [v0.40.0...v0.40.1](https://github.com/cozystack/cozystack/compare/v0.40.0...v0.40.1) diff --git a/docs/changelogs/v0.40.2.md b/docs/changelogs/v0.40.2.md new file mode 100644 index 00000000..5c686b92 --- /dev/null +++ b/docs/changelogs/v0.40.2.md @@ -0,0 +1,15 @@ + + +## Improvements + +* **[linstor] Refactor node-level RWX validation**: Refactored the node-level ReadWriteMany (RWX) validation logic in LINSTOR CSI. The validation has been moved to the CSI driver level with a custom linstor-csi image build, providing more reliable RWX volume handling and clearer error messages when RWX requirements cannot be satisfied ([**@kvaps**](https://github.com/kvaps) in #1856, #1857). + +## Fixes + +* **[linstor] Remove node-level RWX validation**: Removed the problematic node-level RWX validation that was causing issues with volume provisioning. The validation logic has been refactored and moved to a more appropriate location in the LINSTOR CSI driver ([**@kvaps**](https://github.com/kvaps) in #1851). + +--- + +**Full Changelog**: [v0.40.1...v0.40.2](https://github.com/cozystack/cozystack/compare/v0.40.1...v0.40.2) diff --git a/docs/changelogs/v0.40.3.md b/docs/changelogs/v0.40.3.md new file mode 100644 index 00000000..a62a70bc --- /dev/null +++ b/docs/changelogs/v0.40.3.md @@ -0,0 +1,15 @@ + + +## Fixes + +* **[apiserver] Fix Watch resourceVersion and bookmark handling**: Fixed issues with Watch API handling of resourceVersion and bookmarks, ensuring proper event streaming and state synchronization for API clients ([**@kvaps**](https://github.com/kvaps) in #1860). + +## Dependencies + +* **[cilium] Update Cilium to v1.18.6**: Updated Cilium CNI to v1.18.6 with security fixes and performance improvements ([**@sircthulhu**](https://github.com/sircthulhu) in #1868, #1870). + +--- + +**Full Changelog**: [v0.40.2...v0.40.3](https://github.com/cozystack/cozystack/compare/v0.40.2...v0.40.3) diff --git a/docs/changelogs/v0.40.4.md b/docs/changelogs/v0.40.4.md new file mode 100644 index 00000000..ec175486 --- /dev/null +++ b/docs/changelogs/v0.40.4.md @@ -0,0 +1,23 @@ + + +## Improvements + +* **[kubernetes] Increase default apiServer resourcesPreset to large**: Increased the default resource preset for kube-apiserver to `large` to ensure more reliable operation under higher workloads and prevent resource constraints ([**@kvaps**](https://github.com/kvaps) in #1875, #1882). + +* **[kubernetes] Increase kube-apiserver startup probe threshold**: Increased the startup probe threshold for kube-apiserver to allow more time for the API server to become ready, especially in scenarios with slow storage or high load ([**@kvaps**](https://github.com/kvaps) in #1876, #1883). + +* **[etcd] Increase probe thresholds for better recovery**: Increased etcd probe thresholds to provide more time for recovery operations, improving cluster resilience during network issues or temporary slowdowns ([**@kvaps**](https://github.com/kvaps) in #1874, #1878). + +## Fixes + +* **[dashboard] Fix view of loadbalancer IP in services window**: Fixed an issue where load balancer IP addresses were not displayed correctly in the services window of the dashboard ([**@IvanHunters**](https://github.com/IvanHunters) in #1884, #1887). + +## Dependencies + +* **Update Talos Linux v1.11.6**: Updated Talos Linux to v1.11.6 with latest security patches and improvements ([**@kvaps**](https://github.com/kvaps) in #1879). + +--- + +**Full Changelog**: [v0.40.3...v0.40.4](https://github.com/cozystack/cozystack/compare/v0.40.3...v0.40.4) diff --git a/docs/changelogs/v0.41.0.md b/docs/changelogs/v0.41.0.md new file mode 100644 index 00000000..3084e493 --- /dev/null +++ b/docs/changelogs/v0.41.0.md @@ -0,0 +1,63 @@ + + +# Cozystack v0.41.0 — "MongoDB" + +This release introduces MongoDB as a new managed application, expanding Cozystack's database offerings alongside existing PostgreSQL, MySQL, and Redis services. The release also includes storage improvements, Kubernetes stability enhancements, and updated documentation. + +## Feature Highlights + +### MongoDB Managed Application + +Cozystack now includes MongoDB as a fully managed database service. Users can deploy production-ready MongoDB instances directly from the application catalog with minimal configuration. + +Key capabilities: +- **Replica Set deployment**: Automatic configuration of MongoDB replica sets for high availability +- **Persistent storage**: Integration with Cozystack storage backends for reliable data persistence +- **Resource management**: Configurable CPU, memory, and storage resources +- **Monitoring integration**: Built-in metrics export for platform monitoring + +Deploy MongoDB through the Cozystack dashboard or using the standard application deployment workflow ([**@lexfrei**](https://github.com/lexfrei) in #1822, #1881). + +## Improvements + +* **[linstor] Update piraeus-server patches with critical fixes**: Backported critical patches to piraeus-server that address storage stability issues and improve DRBD resource handling. These patches fix edge cases in device management and ensure more reliable storage operations ([**@kvaps**](https://github.com/kvaps) in #1850, #1852). + +* **[linstor] Refactor node-level RWX validation**: Refactored the node-level ReadWriteMany (RWX) validation logic in LINSTOR CSI. The validation has been moved to the CSI driver level with a custom linstor-csi image build, providing more reliable RWX volume handling and clearer error messages when RWX requirements cannot be satisfied ([**@kvaps**](https://github.com/kvaps) in #1856, #1857). + +* **[kubernetes] Increase default apiServer resourcesPreset to large**: Increased the default resource preset for kube-apiserver to `large` to ensure more reliable operation under higher workloads and prevent resource constraints ([**@kvaps**](https://github.com/kvaps) in #1875, #1882). + +* **[kubernetes] Increase kube-apiserver startup probe threshold**: Increased the startup probe threshold for kube-apiserver to allow more time for the API server to become ready, especially in scenarios with slow storage or high load ([**@kvaps**](https://github.com/kvaps) in #1876, #1883). + +* **[etcd] Increase probe thresholds for better recovery**: Increased etcd probe thresholds to provide more time for recovery operations, improving cluster resilience during network issues or temporary slowdowns ([**@kvaps**](https://github.com/kvaps) in #1874, #1878). + +## Fixes + +* **[linstor] Remove node-level RWX validation**: Removed the problematic node-level RWX validation that was causing issues with volume provisioning. The validation logic has been refactored and moved to a more appropriate location in the LINSTOR CSI driver ([**@kvaps**](https://github.com/kvaps) in #1851). + +* **[apiserver] Fix Watch resourceVersion and bookmark handling**: Fixed issues with Watch API handling of resourceVersion and bookmarks, ensuring proper event streaming and state synchronization for API clients ([**@kvaps**](https://github.com/kvaps) in #1860). + +* **[dashboard] Fix view of loadbalancer IP in services window**: Fixed an issue where load balancer IP addresses were not displayed correctly in the services window of the dashboard ([**@IvanHunters**](https://github.com/IvanHunters) in #1884, #1887). + +## Dependencies + +* **[cilium] Update cilium to v1.18.6**: Updated Cilium CNI to v1.18.6 with security fixes and performance improvements ([**@sircthulhu**](https://github.com/sircthulhu) in #1868, #1870). + +* **Update Talos Linux v1.11.6**: Updated Talos Linux to v1.11.6 with latest security patches and improvements ([**@kvaps**](https://github.com/kvaps) in #1879). + +## Documentation + +* **[website] Add documentation for creating and managing cloned virtual machines**: Added comprehensive guide for VM cloning operations ([**@sircthulhu**](https://github.com/sircthulhu) in [cozystack/website#401](https://github.com/cozystack/website/pull/401)). + +* **[website] Simplify NFS driver setup instructions**: Improved NFS driver setup documentation with clearer instructions ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#399](https://github.com/cozystack/website/pull/399)). + +* **[website] Update Talos installation docs for Hetzner and Servers.com**: Updated installation documentation with improved instructions for Hetzner and Servers.com environments ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#395](https://github.com/cozystack/website/pull/395)). + +* **[website] Add Hetzner RobotLB documentation**: Added documentation for configuring public IP with Hetzner RobotLB ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#394](https://github.com/cozystack/website/pull/394)). + +* **[website] Add Hidora organization support details**: Added Hidora to the support page with organization details ([**@matthieu-robin**](https://github.com/matthieu-robin) in [cozystack/website#397](https://github.com/cozystack/website/pull/397), [cozystack/website#398](https://github.com/cozystack/website/pull/398)). + +--- + +**Full Changelog**: [v0.40.0...v0.41.0](https://github.com/cozystack/cozystack/compare/v0.40.0...v0.41.0) diff --git a/docs/changelogs/v0.41.1.md b/docs/changelogs/v0.41.1.md new file mode 100644 index 00000000..d084d644 --- /dev/null +++ b/docs/changelogs/v0.41.1.md @@ -0,0 +1,11 @@ + + +## Improvements + +* **[kubernetes] Add enum validation for IngressNginx exposeMethod**: Added enum validation for the `exposeMethod` field in IngressNginx configuration, preventing invalid values and improving user experience with clear valid options ([**@sircthulhu**](https://github.com/sircthulhu) in #1895, #1897). + +--- + +**Full Changelog**: [v0.41.0...v0.41.1](https://github.com/cozystack/cozystack/compare/v0.41.0...v0.41.1) diff --git a/docs/changelogs/v0.41.2.md b/docs/changelogs/v0.41.2.md new file mode 100644 index 00000000..8b3a8261 --- /dev/null +++ b/docs/changelogs/v0.41.2.md @@ -0,0 +1,13 @@ + + +## Improvements + +* **[monitoring-agents] Set minReplicas to 1 for VPA for VMAgent**: Configured VPA (Vertical Pod Autoscaler) to maintain at least 1 replica for VMAgent, ensuring monitoring availability during scaling operations ([**@sircthulhu**](https://github.com/sircthulhu) in #1894, #1905). + +* **[mongodb] Remove user-configurable images from MongoDB chart**: Removed user-configurable image options from the MongoDB chart to simplify configuration and ensure consistency with tested image versions ([**@kvaps**](https://github.com/kvaps) in #1901, #1904). + +--- + +**Full Changelog**: [v0.41.1...v0.41.2](https://github.com/cozystack/cozystack/compare/v0.41.1...v0.41.2) diff --git a/docs/changelogs/v0.41.3.md b/docs/changelogs/v0.41.3.md new file mode 100644 index 00000000..6d04dad3 --- /dev/null +++ b/docs/changelogs/v0.41.3.md @@ -0,0 +1,15 @@ + + +## Improvements + +* **[kubernetes] Show Service and Ingress resources for Kubernetes app in dashboard**: Added visibility of Service and Ingress resources for Kubernetes applications in the dashboard, improving resource management and monitoring capabilities ([**@sircthulhu**](https://github.com/sircthulhu) in #1912, #1915). + +## Fixes + +* **[dashboard] Fix filtering on Pods tab for Service**: Fixed an issue where pod filtering was not working correctly on the Pods tab when viewing Services in the dashboard ([**@sircthulhu**](https://github.com/sircthulhu) in #1909, #1914). + +--- + +**Full Changelog**: [v0.41.2...v0.41.3](https://github.com/cozystack/cozystack/compare/v0.41.2...v0.41.3) diff --git a/docs/changelogs/v1.0.0-alpha.1.md b/docs/changelogs/v1.0.0-alpha.1.md new file mode 100644 index 00000000..4411b35f --- /dev/null +++ b/docs/changelogs/v1.0.0-alpha.1.md @@ -0,0 +1,134 @@ +# Cozystack v1.0.0-alpha.1 — "Package-Based Architecture" + +This alpha release introduces a fundamental architectural shift from HelmRelease bundles to Package-based deployment managed by the new cozystack-operator. It includes a comprehensive backup system with Velero integration, significant API changes that rename the core CRD, Flux sharding for improved tenant workload distribution, enhanced monitoring capabilities, and various improvements to virtual machines, tenants, and the build workflow. + +> **⚠️ Alpha Release Warning**: This is a pre-release version intended for testing and early adoption. Breaking changes may occur before the stable v1.0.0 release. + +## Breaking Changes + +### API Rename: CozystackResourceDefinition → ApplicationDefinition + +The `CozystackResourceDefinition` CRD has been renamed to `ApplicationDefinition` for better clarity and consistency. This change affects: +- All Go types and controller files +- CRD Helm chart renamed from `cozystack-resource-definition-crd` to `application-definition-crd` +- All cozyrds YAML manifests updated to use `kind: ApplicationDefinition` + +A migration (v24) is included to handle the transition automatically. + +### Package-Based Deployment + +The platform now uses Package resources managed by cozystack-operator instead of HelmRelease bundles. Key changes: +- Restructured values.yaml with full configuration support (networking, publishing, authentication, scheduling, branding, resources) +- Added values-isp-full.yaml and values-isp-hosted.yaml for bundle variants +- Package resources replace old HelmRelease templates +- PackageSources moved from sources/ to templates/sources/ +- Migration script `hack/migrate-to-version-1.0.sh` provided for converting ConfigMaps to Package resources + +--- + +## Major Features and Improvements + +### Cozystack Operator + +A new operator has been introduced to manage Package and PackageSource resources, providing declarative package management for the platform: + +* **[cozystack-operator] Introduce API objects: packages and packagesources**: Added new CRDs for declarative package management, defining the API for Package and PackageSource resources ([**@kvaps**](https://github.com/kvaps) in #1740). +* **[cozystack-operator] Introduce Cozystack-operator core logic**: Implemented core reconciliation logic for the operator, handling Package and PackageSource lifecycle management ([**@kvaps**](https://github.com/kvaps) in #1741). +* **[cozystack-operator] Add Package and PackageSource reconcilers**: Added controllers for Package and PackageSource resources with full reconciliation support ([**@kvaps**](https://github.com/kvaps) in #1755). +* **[cozystack-operator] Add deployment files**: Added Kubernetes deployment manifests for running cozystack-operator in the cluster ([**@kvaps**](https://github.com/kvaps) in #1761). +* **[platform] Add PackageSources for cozystack-operator**: Added PackageSource definitions for cozystack-operator integration ([**@kvaps**](https://github.com/kvaps) in #1760). +* **[cozypkg] Add tool for managing Package and PackageSources**: Added CLI tool for managing Package and PackageSource resources ([**@kvaps**](https://github.com/kvaps) in #1756). + +### Backup System + +Comprehensive backup functionality has been added with Velero integration for managing application backups: + +* **[backups] Implement core backup Plan controller**: Core controller for managing backup schedules and plans, providing the foundation for backup orchestration ([**@lllamnyp**](https://github.com/lllamnyp) in #1640). +* **[backups] Build and deploy backup controller**: Deployment infrastructure for the backup controller, including container image builds and Kubernetes manifests ([**@lllamnyp**](https://github.com/lllamnyp) in #1685). +* **[backups] Scaffold a backup strategy API group**: Added API group for backup strategies, enabling pluggable backup implementations ([**@lllamnyp**](https://github.com/lllamnyp) in #1687). +* **[backups] Add indices to core backup resources**: Added indices to backup resources for improved query performance ([**@lllamnyp**](https://github.com/lllamnyp) in #1719). +* **[backups] Stub the Job backup strategy controller**: Added stub implementation for Job-based backup strategy ([**@lllamnyp**](https://github.com/lllamnyp) in #1720). +* **[backups] Implement Velero strategy controller**: Integration with Velero for backup operations, enabling enterprise-grade backup capabilities ([**@androndo**](https://github.com/androndo) in #1762). +* **[backups,dashboard] User-facing UI**: Dashboard interface for managing backups and backup jobs, providing visibility into backup status and history ([**@lllamnyp**](https://github.com/lllamnyp) in #1737). + +### Platform Architecture + +* **[platform] Migrate from HelmRelease bundles to Package-based deployment**: Replaced HelmRelease bundle system with Package resources managed by cozystack-operator. Includes restructured values.yaml with full configuration support and migration tooling ([**@kvaps**](https://github.com/kvaps) in #1816). +* **refactor(api): rename CozystackResourceDefinition to ApplicationDefinition**: Renamed CRD and all related types for better clarity and consistency. Updated all Go types, controllers, and 25+ YAML manifests ([**@kvaps**](https://github.com/kvaps) in #1864). +* **feat(flux): implement flux sharding for tenant HelmReleases**: Added Flux sharding support to distribute tenant HelmRelease reconciliation across multiple controllers, improving scalability in multi-tenant environments ([**@kvaps**](https://github.com/kvaps) in #1816). +* **refactor(installer): migrate installer to cozystack-operator**: Moved installer functionality to cozystack-operator for unified management ([**@kvaps**](https://github.com/kvaps) in #1816). +* **feat(api): add chartRef to ApplicationDefinition**: Added chartRef field to support ExternalArtifact references for flexible chart sourcing ([**@kvaps**](https://github.com/kvaps) in #1816). +* **feat(api): show only hash in version column for applications and modules**: Simplified version display in API responses for cleaner output ([**@kvaps**](https://github.com/kvaps) in #1816). + +### Virtual Machines + +* **[vm] Always expose VMs with a service**: Virtual machines are now always exposed with at least a ClusterIP service, ensuring they have in-cluster DNS names and can be accessed from other pods even without public IP addresses ([**@lllamnyp**](https://github.com/lllamnyp) in #1738, #1751). + +### Monitoring + +* **[monitoring] Add SLACK_SEVERITY_FILTER field and VMAgent for tenant monitoring**: Introduced the SLACK_SEVERITY_FILTER environment variable in the Alerta deployment to enable filtering of alert severities for Slack notifications based on the disabledSeverity configuration. Additionally, added a VMAgent resource template for scraping metrics within tenant namespaces, improving monitoring granularity and control ([**@IvanHunters**](https://github.com/IvanHunters) in #1712). + +### Tenants + +* **[tenant] Allow egress to parent ingress pods**: Updated tenant network policies to allow egress traffic to parent cluster ingress pods, enabling proper communication patterns between tenant namespaces and parent cluster ingress controllers ([**@lexfrei**](https://github.com/lexfrei) in #1765, #1776). +* **[tenant] Run cleanup job from system namespace**: Moved tenant cleanup job to run from system namespace, improving security and resource isolation for tenant cleanup operations ([**@lllamnyp**](https://github.com/lllamnyp) in #1774, #1777). + +### System + +* **[system] Add resource requests and limits to etcd-defrag**: Added resource requests and limits to etcd-defrag job to ensure proper resource allocation and prevent resource contention during etcd maintenance operations ([**@matthieu-robin**](https://github.com/matthieu-robin) in #1785, #1786). + +### Development and Build + +* **feat(cozypkg): add cross-platform build targets with version injection**: Added cross-platform build targets (linux/amd64, linux/arm64, darwin/amd64, darwin/arm64) for cozypkg/cozyhr tool with automatic version injection from git tags ([**@kvaps**](https://github.com/kvaps) in #1862). +* **refactor: move scripts to hack directory**: Reorganized scripts to standard hack/ location following Kubernetes project conventions ([**@kvaps**](https://github.com/kvaps) in #1863). + +## Fixes + +* **fix(talos): skip rebuilding assets if files already exist**: Improved Talos package build process to avoid redundant asset rebuilds when files are already present, reducing build time ([**@kvaps**](https://github.com/kvaps)). +* **[kubevirt-operator] Fix typo in VMNotRunningFor10Minutes alert**: Fixed typo in VM alert name, ensuring proper alert triggering and monitoring for virtual machines that are not running for extended periods ([**@lexfrei**](https://github.com/lexfrei) in #1770, #1775). +* **[backups] Fix malformed glob and split in template**: Fixed malformed glob pattern and split operation in backup template processing ([**@lllamnyp**](https://github.com/lllamnyp) in #1708). + +## Documentation + +* **[website] docs(storage): simplify NFS driver setup instructions**: Simplified NFS driver setup documentation with clearer instructions ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#399](https://github.com/cozystack/website/pull/399)). +* **[website] Add Hidora organization support details**: Added Hidora to the support page with organization details ([**@matthieu-robin**](https://github.com/matthieu-robin) in [cozystack/website#397](https://github.com/cozystack/website/pull/397)). +* **[website] Update LinkedIn link for Hidora organization**: Updated LinkedIn link for Hidora organization on the support page ([**@matthieu-robin**](https://github.com/matthieu-robin) in [cozystack/website#398](https://github.com/cozystack/website/pull/398)). + +--- + +## Migration Guide + +### From v0.38.x / v0.39.x to v1.0.0-alpha.1 + +1. **Backup your cluster** before upgrading +2. Run the migration script: `hack/migrate-to-version-1.0.sh` +3. The migration will: + - Convert ConfigMaps to Package resources + - Rename CozystackResourceDefinition to ApplicationDefinition + - Update HelmRelease references to use Package-based deployment + +### Known Issues + +- This is an alpha release; some features may be incomplete or change before stable release +- Migration script should be tested in a non-production environment first + +--- + +## Contributors + +We'd like to thank all contributors who made this release possible: + +* [**@androndo**](https://github.com/androndo) +* [**@IvanHunters**](https://github.com/IvanHunters) +* [**@kvaps**](https://github.com/kvaps) +* [**@lexfrei**](https://github.com/lexfrei) +* [**@lllamnyp**](https://github.com/lllamnyp) +* [**@matthieu-robin**](https://github.com/matthieu-robin) + +--- + +**Full Changelog**: [v0.38.0...v1.0.0-alpha.1](https://github.com/cozystack/cozystack/compare/v0.38.0...v1.0.0-alpha.1) + + diff --git a/docs/changelogs/v1.0.0-alpha.2.md b/docs/changelogs/v1.0.0-alpha.2.md new file mode 100644 index 00000000..14bd89a2 --- /dev/null +++ b/docs/changelogs/v1.0.0-alpha.2.md @@ -0,0 +1,71 @@ + + +> **⚠️ Alpha Release Warning**: This is a pre-release version intended for testing and early adoption. Breaking changes may occur before the stable v1.0.0 release. + +## Major Features and Improvements + +### New Applications + +* **[apps] Add MongoDB managed application**: Added MongoDB as a new managed application, providing a fully managed MongoDB database with automatic scaling, backups, and high availability support ([**@lexfrei**](https://github.com/lexfrei) in #1822). + +### Networking + +* **[kilo] Introduce kilo**: Added Kilo WireGuard mesh networking support. Kilo provides secure WireGuard-based VPN mesh for connecting Kubernetes nodes across different networks and regions ([**@kvaps**](https://github.com/kvaps) in #1691). + +* **[local-ccm] Add local-ccm package**: Added local cloud controller manager package for managing load balancer services in local/bare-metal environments without a cloud provider ([**@kvaps**](https://github.com/kvaps) in #1831). + +### Platform + +* **[platform] Add flux-plunger controller**: Added flux-plunger controller to automatically fix stuck HelmRelease errors by cleaning up failed resources and retrying reconciliation ([**@kvaps**](https://github.com/kvaps) in #1843). + +* **[platform] Split telemetry between operator and controller**: Separated telemetry collection between cozystack-operator and cozystack-controller for better metrics isolation and monitoring capabilities ([**@kvaps**](https://github.com/kvaps) in #1869). + +* **[platform] Remove cozystack.io/ui label**: Cleaned up deprecated `cozystack.io/ui` labels from platform components ([**@kvaps**](https://github.com/kvaps) in #1872). + +## Improvements + +* **[kubernetes] Increase default apiServer resourcesPreset to large**: Increased the default resource preset for kube-apiserver to `large` to ensure more reliable operation under higher workloads ([**@kvaps**](https://github.com/kvaps) in #1875). + +* **[kubernetes] Increase kube-apiserver startup probe threshold**: Increased the startup probe threshold for kube-apiserver to allow more time for the API server to become ready ([**@kvaps**](https://github.com/kvaps) in #1876). + +* **[etcd] Increase probe thresholds for better recovery**: Increased etcd probe thresholds to provide more time for recovery operations, improving cluster resilience ([**@kvaps**](https://github.com/kvaps) in #1874). + +## Fixes + +* **[apiserver] Fix Watch resourceVersion and bookmark handling**: Fixed issues with Watch API handling of resourceVersion and bookmarks, ensuring proper event streaming and state synchronization ([**@kvaps**](https://github.com/kvaps) in #1860). + +* **[dashboard] Fix view of loadbalancer IP in services window**: Fixed an issue where load balancer IP addresses were not displayed correctly in the services window of the dashboard ([**@IvanHunters**](https://github.com/IvanHunters) in #1884). + +## Dependencies + +* **[cilium] Update cilium to v1.18.6**: Updated Cilium CNI to v1.18.6 with security fixes and performance improvements ([**@sircthulhu**](https://github.com/sircthulhu) in #1868). + +* **Update Talos Linux v1.12.1**: Updated Talos Linux to v1.12.1 with latest features, security patches and improvements ([**@kvaps**](https://github.com/kvaps) in #1877). + +## Documentation + +* **[website] Add documentation for creating and managing cloned virtual machines**: Added comprehensive guide for VM cloning operations ([**@sircthulhu**](https://github.com/sircthulhu) in [cozystack/website#401](https://github.com/cozystack/website/pull/401)). + +* **[website] Simplify NFS driver setup instructions**: Improved NFS driver setup documentation with clearer instructions ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#399](https://github.com/cozystack/website/pull/399)). + +* **[website] Update Talos installation docs for Hetzner and Servers.com**: Updated installation documentation with improved instructions for Hetzner and Servers.com environments ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#395](https://github.com/cozystack/website/pull/395)). + +* **[website] Add Hetzner RobotLB documentation**: Added documentation for configuring public IP with Hetzner RobotLB ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#394](https://github.com/cozystack/website/pull/394)). + +* **[website] Add Hidora organization support details**: Added Hidora to the support page with organization details ([**@matthieu-robin**](https://github.com/matthieu-robin) in [cozystack/website#397](https://github.com/cozystack/website/pull/397), [cozystack/website#398](https://github.com/cozystack/website/pull/398)). + +--- + +## Contributors + +* [**@IvanHunters**](https://github.com/IvanHunters) +* [**@kvaps**](https://github.com/kvaps) +* [**@lexfrei**](https://github.com/lexfrei) +* [**@matthieu-robin**](https://github.com/matthieu-robin) +* [**@sircthulhu**](https://github.com/sircthulhu) + +--- + +**Full Changelog**: [v1.0.0-alpha.1...v1.0.0-alpha.2](https://github.com/cozystack/cozystack/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) diff --git a/docs/hubble-observability.md b/docs/hubble-observability.md new file mode 100644 index 00000000..33597eec --- /dev/null +++ b/docs/hubble-observability.md @@ -0,0 +1,99 @@ +# Enabling Hubble for Network Observability + +Hubble is a network and security observability platform built on top of Cilium. It provides deep visibility into the communication and behavior of services in your Kubernetes cluster. + +## Prerequisites + +- Cozystack platform running with Cilium as the CNI +- Monitoring hub enabled for Grafana access + +## Configuration + +Hubble is disabled by default in Cozystack. To enable it, update the Cilium configuration. + +### Enable Hubble + +Edit the Cilium values in your platform configuration to enable Hubble: + +```yaml +cilium: + hubble: + enabled: true + relay: + enabled: true + ui: + enabled: true + metrics: + enabled: + - dns + - drop + - tcp + - flow + - port-distribution + - icmp + - httpV2:exemplars=true;labelsContext=source_ip,source_namespace,source_workload,destination_ip,destination_namespace,destination_workload,traffic_direction +``` + +### Components + +When Hubble is enabled, the following components become available: + +- **Hubble Relay**: Aggregates flow data from all Cilium agents +- **Hubble UI**: Web-based interface for exploring network flows +- **Hubble Metrics**: Prometheus metrics for network observability + +## Grafana Dashboards + +Once Hubble is enabled and the monitoring hub is deployed, the following dashboards become available in Grafana under the `hubble` folder: + +| Dashboard | Description | +|-----------|-------------| +| **Overview** | General Hubble metrics including processing statistics | +| **DNS Namespace** | DNS query and response metrics by namespace | +| **L7 HTTP Metrics** | HTTP layer 7 metrics by workload | +| **Network Overview** | Network flow overview by namespace | + +### Accessing Dashboards + +1. Navigate to Grafana via the monitoring hub +2. Browse to the `hubble` folder in the dashboard browser +3. Select a dashboard to view network observability data + +## Metrics Available + +Hubble exposes various metrics that can be queried in Grafana: + +- `hubble_flows_processed_total`: Total number of flows processed +- `hubble_dns_queries_total`: DNS queries by type +- `hubble_dns_responses_total`: DNS responses by status +- `hubble_drop_total`: Dropped packets by reason +- `hubble_tcp_flags_total`: TCP connections by flag +- `hubble_http_requests_total`: HTTP requests by method and status + +## Troubleshooting + +### Verify Hubble Status + +Check if Hubble is running: + +```bash +kubectl get pods -n cozy-cilium -l k8s-app=hubble-relay +kubectl get pods -n cozy-cilium -l k8s-app=hubble-ui +``` + +### Check Metrics Endpoint + +Verify Hubble metrics are being scraped: + +```bash +kubectl port-forward -n cozy-cilium svc/hubble-metrics 9965:9965 +curl http://localhost:9965/metrics +``` + +### Verify ServiceMonitor + +Ensure the ServiceMonitor is created for Prometheus scraping: + +```bash +kubectl get servicemonitor -n cozy-cilium +``` diff --git a/go.mod b/go.mod index 6ad144f7..9944df16 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,6 @@ require ( github.com/spf13/cobra v1.9.1 github.com/vmware-tanzu/velero v1.17.1 go.uber.org/zap v1.27.0 - gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.34.1 k8s.io/apiextensions-apiserver v0.34.1 k8s.io/apimachinery v0.34.2 diff --git a/go.sum b/go.sum index fe868468..d2cbc779 100644 --- a/go.sum +++ b/go.sum @@ -297,8 +297,6 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/scripts/common-envs.mk b/hack/common-envs.mk similarity index 100% rename from scripts/common-envs.mk rename to hack/common-envs.mk diff --git a/hack/cozyreport.sh b/hack/cozyreport.sh index 3174ed50..28fddfe9 100755 --- a/hack/cozyreport.sh +++ b/hack/cozyreport.sh @@ -56,6 +56,26 @@ kubectl get hr -A --no-headers | awk '$4 != "True"' | \ kubectl describe hr -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1 done +echo "Collecting packages..." +kubectl get packages -A > $REPORT_DIR/kubernetes/packages.txt 2>&1 +kubectl get packages -A --no-headers | awk '$4 != "True"' | \ + while read NAMESPACE NAME _; do + DIR=$REPORT_DIR/kubernetes/packages/$NAMESPACE/$NAME + mkdir -p $DIR + kubectl get package -n $NAMESPACE $NAME -o yaml > $DIR/package.yaml 2>&1 + kubectl describe package -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1 + done + +echo "Collecting packagesources..." +kubectl get packagesources -A > $REPORT_DIR/kubernetes/packagesources.txt 2>&1 +kubectl get packagesources -A --no-headers | awk '$4 != "True"' | \ + while read NAMESPACE NAME _; do + DIR=$REPORT_DIR/kubernetes/packagesources/$NAMESPACE/$NAME + mkdir -p $DIR + kubectl get packagesource -n $NAMESPACE $NAME -o yaml > $DIR/packagesource.yaml 2>&1 + kubectl describe packagesource -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1 + done + echo "Collecting pods..." kubectl get pod -A -o wide > $REPORT_DIR/kubernetes/pods.txt 2>&1 kubectl get pod -A --no-headers | awk '$4 !~ /Running|Succeeded|Completed/' | diff --git a/hack/e2e-apps/mongodb.bats b/hack/e2e-apps/mongodb.bats new file mode 100644 index 00000000..794baf63 --- /dev/null +++ b/hack/e2e-apps/mongodb.bats @@ -0,0 +1,39 @@ +#!/usr/bin/env bats + +@test "Create DB MongoDB" { + name='test' + kubectl apply -f - <&2 + if [ ! -f _out/assets/cozystack-crds.yaml ]; then + echo "Missing: _out/assets/cozystack-crds.yaml" >&2 + exit 1 + fi + if [ ! -f _out/assets/cozystack-operator.yaml ]; then + echo "Missing: _out/assets/cozystack-operator.yaml" >&2 exit 1 fi } @test "Install Cozystack" { - # Create namespace & configmap required by installer + # Create namespace kubectl create namespace cozy-system --dry-run=client -o yaml | kubectl apply -f - - kubectl create configmap cozystack -n cozy-system \ - --from-literal=bundle-name=paas-full \ - --from-literal=ipv4-pod-cidr=10.244.0.0/16 \ - --from-literal=ipv4-pod-gateway=10.244.0.1 \ - --from-literal=ipv4-svc-cidr=10.96.0.0/16 \ - --from-literal=ipv4-join-cidr=100.64.0.0/16 \ - --from-literal=root-host=example.org \ - --from-literal=api-server-endpoint=https://192.168.123.10:6443 \ - --dry-run=client -o yaml | kubectl apply -f - - # Apply installer manifests from file - kubectl apply -f _out/assets/cozystack-installer.yaml + # Apply installer manifests (CRDs + operator) + kubectl apply -f _out/assets/cozystack-crds.yaml + kubectl apply -f _out/assets/cozystack-operator.yaml - # Wait for the installer deployment to become available - kubectl wait deployment/cozystack -n cozy-system --timeout=1m --for=condition=Available + # Wait for the operator deployment to become available + kubectl wait deployment/cozystack-operator -n cozy-system --timeout=1m --for=condition=Available + + # Create platform Package with isp-full variant + kubectl apply -f - </dev/null | wc -l) -gt 10 ]; do sleep 1; done' sleep 5 - kubectl get hr -A -l cozystack.io/system-app=true | awk 'NR>1 {print "kubectl wait --timeout=15m --for=condition=ready -n "$1" hr/"$2" &"} END {print "wait"}' | sh -ex + kubectl get hr -A | awk 'NR>1 {print "kubectl wait --timeout=15m --for=condition=ready -n "$1" hr/"$2" &"} END {print "wait"}' | sh -ex # Fail the test if any HelmRelease is not Ready if kubectl get hr -A | grep -v " True " | grep -v NAME; then @@ -142,7 +159,7 @@ EOF # Expose Cozystack services through ingress - kubectl patch configmap/cozystack -n cozy-system --type merge -p '{"data":{"expose-services":"api,dashboard,cdi-uploadproxy,vm-exportproxy,keycloak"}}' + kubectl patch package cozystack.cozystack-platform --type merge -p '{"spec":{"components":{"platform":{"values":{"publishing":{"exposedServices":["api","dashboard","cdi-uploadproxy","vm-exportproxy","keycloak"]}}}}}}' # NGINX ingress controller timeout 60 sh -ec 'until kubectl get deploy root-ingress-controller -n tenant-root >/dev/null 2>&1; do sleep 1; done' @@ -169,7 +186,7 @@ EOF } @test "Keycloak OIDC stack is healthy" { - kubectl patch configmap/cozystack -n cozy-system --type merge -p '{"data":{"oidc-enabled":"true"}}' + kubectl patch package cozystack.cozystack-platform --type merge -p '{"spec":{"components":{"platform":{"values":{"authentication":{"oidc":{"enabled":true}}}}}}}' timeout 120 sh -ec 'until kubectl get hr -n cozy-keycloak keycloak keycloak-configure keycloak-operator >/dev/null 2>&1; do sleep 1; done' kubectl wait hr/keycloak hr/keycloak-configure hr/keycloak-operator -n cozy-keycloak --timeout=10m --for=condition=ready diff --git a/hack/e2e-prepare-cluster.bats b/hack/e2e-prepare-cluster.bats index 650ca643..df90b91a 100644 --- a/hack/e2e-prepare-cluster.bats +++ b/hack/e2e-prepare-cluster.bats @@ -136,25 +136,28 @@ machine: mirrors: docker.io: endpoints: - - https://dockerio.nexus.aenix.org - cr.fluentbit.io: - endpoints: - - https://fluentbit.nexus.aenix.org - docker-registry3.mariadb.com: - endpoints: - - https://mariadb.nexus.aenix.org - gcr.io: - endpoints: - - https://gcr.nexus.aenix.org - ghcr.io: - endpoints: - - https://ghcr.nexus.aenix.org - quay.io: - endpoints: - - https://quay.nexus.aenix.org - registry.k8s.io: - endpoints: - - https://k8s.nexus.aenix.org + - https://mirror.gcr.io + #docker.io: + # endpoints: + # - https://dockerio.nexus.aenix.org + #cr.fluentbit.io: + # endpoints: + # - https://fluentbit.nexus.aenix.org + #docker-registry3.mariadb.com: + # endpoints: + # - https://mariadb.nexus.aenix.org + #gcr.io: + # endpoints: + # - https://gcr.nexus.aenix.org + #ghcr.io: + # endpoints: + # - https://ghcr.nexus.aenix.org + #quay.io: + # endpoints: + # - https://quay.nexus.aenix.org + #registry.k8s.io: + # endpoints: + # - https://k8s.nexus.aenix.org files: - content: | [plugins] @@ -236,7 +239,10 @@ EOF timeout 10 sh -ec 'until talosctl bootstrap -n 192.168.123.11 -e 192.168.123.11; do sleep 1; done' # Wait until etcd is healthy - timeout 180 sh -ec 'until talosctl etcd members -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 >/dev/null 2>&1; do sleep 1; done' + if ! timeout 180 sh -ec 'until talosctl etcd members -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 >/dev/null 2>&1; do sleep 1; done'; then + talosctl dmesg -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 || true + exit 1 + fi timeout 60 sh -ec 'while talosctl etcd members -n 192.168.123.11,192.168.123.12,192.168.123.13 -e 192.168.123.10 2>&1 | grep -q "rpc error"; do sleep 1; done' # Retrieve kubeconfig diff --git a/hack/migrate-to-version-1.0.sh b/hack/migrate-to-version-1.0.sh new file mode 100755 index 00000000..743aaf30 --- /dev/null +++ b/hack/migrate-to-version-1.0.sh @@ -0,0 +1,179 @@ +#!/bin/bash +# Migration script from Cozystack ConfigMaps to Package-based configuration +# This script converts cozystack, cozystack-branding, and cozystack-scheduling +# ConfigMaps into a Package resource with the new values structure. + +set -e + +NAMESPACE="cozy-system" + +echo "=============================" +echo " Cozystack Migration to v1.0 " +echo "=============================" +echo "" +echo "This script will convert existing ConfigMaps to a Package resource." +echo "" + +# Check if kubectl is available +if ! command -v kubectl &> /dev/null; then + echo "Error: kubectl is not installed or not in PATH" + exit 1 +fi + +# Check if jq is available +if ! command -v jq &> /dev/null; then + echo "Error: jq is not installed or not in PATH" + exit 1 +fi + +# Check if we can access the cluster +if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then + echo "Error: Cannot access namespace $NAMESPACE" + exit 1 +fi + +# Read ConfigMap cozystack +echo "Reading ConfigMap cozystack..." +COZYSTACK_CM=$(kubectl get configmap -n "$NAMESPACE" cozystack -o json 2>/dev/null || echo "{}") + +# Read ConfigMap cozystack-branding +echo "Reading ConfigMap cozystack-branding..." +BRANDING_CM=$(kubectl get configmap -n "$NAMESPACE" cozystack-branding -o json 2>/dev/null || echo "{}") + +# Read ConfigMap cozystack-scheduling +echo "Reading ConfigMap cozystack-scheduling..." +SCHEDULING_CM=$(kubectl get configmap -n "$NAMESPACE" cozystack-scheduling -o json 2>/dev/null || echo "{}") + +# Extract values from cozystack ConfigMap +CLUSTER_DOMAIN=$(echo "$COZYSTACK_CM" | jq -r '.data["cluster-domain"] // "cozy.local"') +ROOT_HOST=$(echo "$COZYSTACK_CM" | jq -r '.data["root-host"] // "example.org"') +API_SERVER_ENDPOINT=$(echo "$COZYSTACK_CM" | jq -r '.data["api-server-endpoint"] // ""') +OIDC_ENABLED=$(echo "$COZYSTACK_CM" | jq -r '.data["oidc-enabled"] // "false"') +KEYCLOAK_REDIRECTS=$(echo "$COZYSTACK_CM" | jq -r '.data["extra-keycloak-redirect-uri-for-dashboard"] // ""' ) +TELEMETRY_ENABLED=$(echo "$COZYSTACK_CM" | jq -r '.data["telemetry-enabled"] // "true"') +BUNDLE_NAME=$(echo "$COZYSTACK_CM" | jq -r '.data["bundle-name"] // "paas-full"') + +# Network configuration +POD_CIDR=$(echo "$COZYSTACK_CM" | jq -r '.data["ipv4-pod-cidr"] // "10.244.0.0/16"') +POD_GATEWAY=$(echo "$COZYSTACK_CM" | jq -r '.data["ipv4-pod-gateway"] // "10.244.0.1"') +SVC_CIDR=$(echo "$COZYSTACK_CM" | jq -r '.data["ipv4-svc-cidr"] // "10.96.0.0/16"') +JOIN_CIDR=$(echo "$COZYSTACK_CM" | jq -r '.data["ipv4-join-cidr"] // "100.64.0.0/16"') + +EXTERNAL_IPS=$(echo "$COZYSTACK_CM" | jq -r '.data["expose-external-ips"] // ""') +if [ -z "$EXTERNAL_IPS" ]; then + EXTERNAL_IPS="[]" +else + EXTERNAL_IPS=$(echo "$EXTERNAL_IPS" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - "$0}') +fi + +# Determine bundle type +case "$BUNDLE_NAME" in + paas-full|distro-full) + SYSTEM_ENABLED="true" + SYSTEM_TYPE="full" + ;; + paas-hosted|distro-hosted) + SYSTEM_ENABLED="false" + SYSTEM_TYPE="hosted" + ;; + *) + SYSTEM_ENABLED="false" + SYSTEM_TYPE="hosted" + ;; +esac + +# Update bundle naming +BUNDLE_NAME=$(echo "$BUNDLE_NAME" | sed 's/paas/isp/') + +# Extract branding if available +BRANDING=$(echo "$BRANDING_CM" | jq -r '.data // {} | to_entries[] | "\(.key): \"\(.value)\""') +if [ -z "$BRANDING" ]; then + BRANDING="{}" +else + BRANDING=$(echo "$BRANDING" | awk 'BEGIN{print}{print " " $0}') +fi + +# Extract scheduling if available +SCHEDULING_CONSTRAINTS=$(echo "$SCHEDULING_CM" | jq -r '.data.["globalAppTopologySpreadConstraints"] // ""') +if [ -z "$SCHEDULING_CONSTRAINTS" ]; then + SCHEDULING_CONSTRAINTS='""' +else + SCHEDULING_CONSTRAINTS=$(echo "$SCHEDULING_CONSTRAINTS" | awk 'BEGIN{print}{print " " $0}') +fi + +echo "" +echo "Extracted configuration:" +echo " Cluster Domain: $CLUSTER_DOMAIN" +echo " Root Host: $ROOT_HOST" +echo " API Server Endpoint: $API_SERVER_ENDPOINT" +echo " OIDC Enabled: $OIDC_ENABLED" +echo " Bundle Name: $BUNDLE_NAME" +echo " System Enabled: $SYSTEM_ENABLED" +echo " System Type: $SYSTEM_TYPE" +echo "" + +# Generate Package YAML +PACKAGE_YAML=$(cat <"$OUT" < 0 { + if hrCopy.Labels == nil { + hrCopy.Labels = make(map[string]string) + } + for key, value := range appDef.Spec.Release.Labels { + if hrCopy.Labels[key] != value { + logger.V(4).Info("Updating HelmRelease label", "name", hr.Name, "namespace", hr.Namespace, "label", key, "value", value) + hrCopy.Labels[key] = value + updated = true + } + } + } + + if updated { + logger.V(4).Info("Updating HelmRelease", "name", hr.Name, "namespace", hr.Namespace) + if err := r.Update(ctx, hrCopy); err != nil { + return fmt.Errorf("failed to update HelmRelease: %w", err) + } + } + + return nil +} diff --git a/internal/controller/cozystackresourcedefinition_helmreconciler.go b/internal/controller/cozystackresourcedefinition_helmreconciler.go deleted file mode 100644 index 1ee4a2b7..00000000 --- a/internal/controller/cozystackresourcedefinition_helmreconciler.go +++ /dev/null @@ -1,201 +0,0 @@ -package controller - -import ( - "context" - "fmt" - - cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" - helmv2 "github.com/fluxcd/helm-controller/api/v2" - - "k8s.io/apimachinery/pkg/runtime" - - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -// +kubebuilder:rbac:groups=cozystack.io,resources=cozystackresourcedefinitions,verbs=get;list;watch -// +kubebuilder:rbac:groups=helm.toolkit.fluxcd.io,resources=helmreleases,verbs=get;list;watch;update;patch - -// CozystackResourceDefinitionHelmReconciler reconciles CozystackResourceDefinitions -// and updates related HelmReleases when a CozyRD changes. -// This controller does NOT watch HelmReleases to avoid mutual reconciliation storms -// with Flux's helm-controller. -type CozystackResourceDefinitionHelmReconciler struct { - client.Client - Scheme *runtime.Scheme -} - -func (r *CozystackResourceDefinitionHelmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := log.FromContext(ctx) - - // Get the CozystackResourceDefinition that triggered this reconciliation - crd := &cozyv1alpha1.CozystackResourceDefinition{} - if err := r.Get(ctx, req.NamespacedName, crd); err != nil { - logger.Error(err, "failed to get CozystackResourceDefinition", "name", req.Name) - return ctrl.Result{}, client.IgnoreNotFound(err) - } - - // Update HelmReleases related to this specific CozyRD - if err := r.updateHelmReleasesForCRD(ctx, crd); err != nil { - logger.Error(err, "failed to update HelmReleases for CRD", "crd", crd.Name) - return ctrl.Result{}, err - } - - return ctrl.Result{}, nil -} - -func (r *CozystackResourceDefinitionHelmReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - Named("cozystackresourcedefinition-helm-reconciler"). - For(&cozyv1alpha1.CozystackResourceDefinition{}). - Complete(r) -} - -// updateHelmReleasesForCRD updates all HelmReleases that match the application labels from CozystackResourceDefinition -func (r *CozystackResourceDefinitionHelmReconciler) updateHelmReleasesForCRD(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) error { - logger := log.FromContext(ctx) - - // Use application labels to find HelmReleases - // Labels: apps.cozystack.io/application.kind and apps.cozystack.io/application.group - applicationKind := crd.Spec.Application.Kind - - // Validate that applicationKind is non-empty - if applicationKind == "" { - logger.V(4).Info("Skipping HelmRelease update: Application.Kind is empty", "crd", crd.Name) - return nil - } - - applicationGroup := "apps.cozystack.io" // All applications use this group - - // Build label selector for HelmReleases - // Only reconcile HelmReleases with cozystack.io/ui=true label - labelSelector := client.MatchingLabels{ - "apps.cozystack.io/application.kind": applicationKind, - "apps.cozystack.io/application.group": applicationGroup, - "cozystack.io/ui": "true", - } - - // List all HelmReleases with matching labels - hrList := &helmv2.HelmReleaseList{} - if err := r.List(ctx, hrList, labelSelector); err != nil { - logger.Error(err, "failed to list HelmReleases", "kind", applicationKind, "group", applicationGroup) - return err - } - - logger.V(4).Info("Found HelmReleases to update", "crd", crd.Name, "kind", applicationKind, "count", len(hrList.Items)) - - // Update each HelmRelease - for i := range hrList.Items { - hr := &hrList.Items[i] - if err := r.updateHelmReleaseChart(ctx, hr, crd); err != nil { - logger.Error(err, "failed to update HelmRelease", "name", hr.Name, "namespace", hr.Namespace) - continue - } - } - - return nil -} - -// expectedValuesFrom returns the expected valuesFrom configuration for HelmReleases -func expectedValuesFrom() []helmv2.ValuesReference { - return []helmv2.ValuesReference{ - { - Kind: "Secret", - Name: "cozystack-values", - }, - } -} - -// valuesFromEqual compares two ValuesReference slices -func valuesFromEqual(a, b []helmv2.ValuesReference) bool { - if len(a) != len(b) { - return false - } - for i := range a { - if a[i].Kind != b[i].Kind || - a[i].Name != b[i].Name || - a[i].ValuesKey != b[i].ValuesKey || - a[i].TargetPath != b[i].TargetPath || - a[i].Optional != b[i].Optional { - return false - } - } - return true -} - -// updateHelmReleaseChart updates the chart and valuesFrom in HelmRelease based on CozystackResourceDefinition -func (r *CozystackResourceDefinitionHelmReconciler) updateHelmReleaseChart(ctx context.Context, hr *helmv2.HelmRelease, crd *cozyv1alpha1.CozystackResourceDefinition) error { - logger := log.FromContext(ctx) - hrCopy := hr.DeepCopy() - updated := false - - // Validate Chart configuration exists - if crd.Spec.Release.Chart.Name == "" { - logger.V(4).Info("Skipping HelmRelease chart update: Chart.Name is empty", "crd", crd.Name) - return nil - } - - // Validate SourceRef fields - if crd.Spec.Release.Chart.SourceRef.Kind == "" || - crd.Spec.Release.Chart.SourceRef.Name == "" || - crd.Spec.Release.Chart.SourceRef.Namespace == "" { - logger.Error(fmt.Errorf("invalid SourceRef in CRD"), "Skipping HelmRelease chart update: SourceRef fields are incomplete", - "crd", crd.Name, - "kind", crd.Spec.Release.Chart.SourceRef.Kind, - "name", crd.Spec.Release.Chart.SourceRef.Name, - "namespace", crd.Spec.Release.Chart.SourceRef.Namespace) - return nil - } - - // Get version and reconcileStrategy from CRD or use defaults - version := ">= 0.0.0-0" - reconcileStrategy := "Revision" - // TODO: Add Version and ReconcileStrategy fields to CozystackResourceDefinitionChart if needed - - // Build expected SourceRef - expectedSourceRef := helmv2.CrossNamespaceObjectReference{ - Kind: crd.Spec.Release.Chart.SourceRef.Kind, - Name: crd.Spec.Release.Chart.SourceRef.Name, - Namespace: crd.Spec.Release.Chart.SourceRef.Namespace, - } - - if hrCopy.Spec.Chart == nil { - // Need to create Chart spec - hrCopy.Spec.Chart = &helmv2.HelmChartTemplate{ - Spec: helmv2.HelmChartTemplateSpec{ - Chart: crd.Spec.Release.Chart.Name, - Version: version, - ReconcileStrategy: reconcileStrategy, - SourceRef: expectedSourceRef, - }, - } - updated = true - } else { - // Update existing Chart spec - if hrCopy.Spec.Chart.Spec.Chart != crd.Spec.Release.Chart.Name || - hrCopy.Spec.Chart.Spec.SourceRef != expectedSourceRef { - hrCopy.Spec.Chart.Spec.Chart = crd.Spec.Release.Chart.Name - hrCopy.Spec.Chart.Spec.SourceRef = expectedSourceRef - updated = true - } - } - - // Check and update valuesFrom configuration - expected := expectedValuesFrom() - if !valuesFromEqual(hrCopy.Spec.ValuesFrom, expected) { - logger.V(4).Info("Updating HelmRelease valuesFrom", "name", hr.Name, "namespace", hr.Namespace) - hrCopy.Spec.ValuesFrom = expected - updated = true - } - - if updated { - logger.V(4).Info("Updating HelmRelease chart", "name", hr.Name, "namespace", hr.Namespace) - if err := r.Update(ctx, hrCopy); err != nil { - return fmt.Errorf("failed to update HelmRelease: %w", err) - } - } - - return nil -} - diff --git a/internal/controller/dashboard/breadcrumb.go b/internal/controller/dashboard/breadcrumb.go index 5122f605..aadcacac 100644 --- a/internal/controller/dashboard/breadcrumb.go +++ b/internal/controller/dashboard/breadcrumb.go @@ -14,7 +14,7 @@ import ( ) // ensureBreadcrumb creates or updates a Breadcrumb resource for the given CRD -func (m *Manager) ensureBreadcrumb(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) error { +func (m *Manager) ensureBreadcrumb(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) error { group, version, kind := pickGVK(crd) lowerKind := strings.ToLower(kind) diff --git a/internal/controller/dashboard/customcolumns.go b/internal/controller/dashboard/customcolumns.go index 6c23d68b..19a5a16a 100644 --- a/internal/controller/dashboard/customcolumns.go +++ b/internal/controller/dashboard/customcolumns.go @@ -21,7 +21,7 @@ import ( // // metadata.name: stock-namespace-.. // spec.id: stock-namespace-/// -func (m *Manager) ensureCustomColumnsOverride(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) (controllerutil.OperationResult, error) { +func (m *Manager) ensureCustomColumnsOverride(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) (controllerutil.OperationResult, error) { g, v, kind := pickGVK(crd) plural := pickPlural(kind, crd) // Details page segment uses lowercase kind, mirroring your example @@ -34,9 +34,6 @@ func (m *Manager) ensureCustomColumnsOverride(ctx context.Context, crd *cozyv1al obj.SetName(name) href := fmt.Sprintf("/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/%s/{reqsJsonPath[0]['.metadata.name']['-']}", detailsSegment) - if g == "apps.cozystack.io" && kind == "Tenant" && plural == "tenants" { - href = "/openapi-ui/{2}/{reqsJsonPath[0]['.status.namespace']['-']}/api-table/core.cozystack.io/v1alpha1/tenantmodules" - } desired := map[string]any{ "spec": map[string]any{ diff --git a/internal/controller/dashboard/customformsoverride.go b/internal/controller/dashboard/customformsoverride.go index 2b0daa08..60bc82fc 100644 --- a/internal/controller/dashboard/customformsoverride.go +++ b/internal/controller/dashboard/customformsoverride.go @@ -15,7 +15,7 @@ import ( ) // ensureCustomFormsOverride creates or updates a CustomFormsOverride resource for the given CRD -func (m *Manager) ensureCustomFormsOverride(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) error { +func (m *Manager) ensureCustomFormsOverride(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) error { g, v, kind := pickGVK(crd) plural := pickPlural(kind, crd) diff --git a/internal/controller/dashboard/customformsprefill.go b/internal/controller/dashboard/customformsprefill.go index d2761873..35d22ff1 100644 --- a/internal/controller/dashboard/customformsprefill.go +++ b/internal/controller/dashboard/customformsprefill.go @@ -16,7 +16,7 @@ import ( ) // ensureCustomFormsPrefill creates or updates a CustomFormsPrefill resource for the given CRD -func (m *Manager) ensureCustomFormsPrefill(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) (reconcile.Result, error) { +func (m *Manager) ensureCustomFormsPrefill(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) (reconcile.Result, error) { logger := log.FromContext(ctx) app := crd.Spec.Application diff --git a/internal/controller/dashboard/factory.go b/internal/controller/dashboard/factory.go index 53d771d0..e55aedc7 100644 --- a/internal/controller/dashboard/factory.go +++ b/internal/controller/dashboard/factory.go @@ -15,7 +15,7 @@ import ( ) // ensureFactory creates or updates a Factory resource for the given CRD -func (m *Manager) ensureFactory(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) error { +func (m *Manager) ensureFactory(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) error { g, v, kind := pickGVK(crd) plural := pickPlural(kind, crd) @@ -174,6 +174,31 @@ func detailsTab(kind, endpoint, schemaJSON string, keysOrder [][]string) map[str }), ) } + if kind == "Tenant" { + leftColStack = append(leftColStack, antdFlexVertical("tenant-external-ip-count", 4, []any{ + antdText("tenant-external-ip-count-label", true, "External IPs count", nil), + parsedText("tenant-external-ip-count-value", `{reqsJsonPath[0]['.status.externalIPsCount']['0']}`, nil), + })) + rightColStack = append(rightColStack, + antdFlexVertical("resource-quotas-block", 4, []any{ + antdText("resource-quotas-label", true, "Resource Quotas", map[string]any{ + "fontSize": float64(20), + "marginBottom": float64(12), + }), + map[string]any{ + "type": "EnrichedTable", + "data": map[string]any{ + "id": "resource-quotas-table", + "baseprefix": "/openapi-ui", + "clusterNamePartOfUrl": "{2}", + "customizationId": "factory-resource-quotas", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{reqsJsonPath[0]['.status.namespace']}/resourcequotas", + "pathToItems": []any{`items`}, + }, + }, + }), + ) + } return map[string]any{ "key": "details", @@ -557,7 +582,7 @@ type factoryFlags struct { // factoryFeatureFlags tries several conventional locations so you can evolve the API // without breaking the controller. Defaults are false (hidden). -func factoryFeatureFlags(crd *cozyv1alpha1.CozystackResourceDefinition) factoryFlags { +func factoryFeatureFlags(crd *cozyv1alpha1.ApplicationDefinition) factoryFlags { var f factoryFlags f.Workloads = true diff --git a/internal/controller/dashboard/helpers.go b/internal/controller/dashboard/helpers.go index a0023a05..2a35bbff 100644 --- a/internal/controller/dashboard/helpers.go +++ b/internal/controller/dashboard/helpers.go @@ -23,7 +23,7 @@ type fieldInfo struct { // pickGVK tries to read group/version/kind from the CRD. We prefer the "application" section, // falling back to other likely fields if your schema differs. -func pickGVK(crd *cozyv1alpha1.CozystackResourceDefinition) (group, version, kind string) { +func pickGVK(crd *cozyv1alpha1.ApplicationDefinition) (group, version, kind string) { // Best guess based on your examples: if crd.Spec.Application.Kind != "" { kind = crd.Spec.Application.Kind @@ -41,7 +41,7 @@ func pickGVK(crd *cozyv1alpha1.CozystackResourceDefinition) (group, version, kin } // pickPlural prefers a field on the CRD if you have it; otherwise do a simple lowercase + "s". -func pickPlural(kind string, crd *cozyv1alpha1.CozystackResourceDefinition) string { +func pickPlural(kind string, crd *cozyv1alpha1.ApplicationDefinition) string { // If you have crd.Spec.Application.Plural, prefer it. Example: if crd.Spec.Application.Plural != "" { return crd.Spec.Application.Plural diff --git a/internal/controller/dashboard/manager.go b/internal/controller/dashboard/manager.go index 12e50fbc..23897586 100644 --- a/internal/controller/dashboard/manager.go +++ b/internal/controller/dashboard/manager.go @@ -41,7 +41,7 @@ func AddToScheme(s *runtime.Scheme) error { } // Manager owns logic for creating/updating dashboard resources derived from CRDs. -// It’s easy to extend: add new ensure* methods and wire them into EnsureForCRD. +// It’s easy to extend: add new ensure* methods and wire them into EnsureForAppDef. type Manager struct { client.Client Scheme *runtime.Scheme @@ -56,7 +56,7 @@ func NewManager(c client.Client, scheme *runtime.Scheme) *Manager { func (m *Manager) SetupWithManager(mgr ctrl.Manager) error { if err := ctrl.NewControllerManagedBy(mgr). Named("dashboard-reconciler"). - For(&cozyv1alpha1.CozystackResourceDefinition{}). + For(&cozyv1alpha1.ApplicationDefinition{}). Complete(m); err != nil { return err } @@ -72,7 +72,7 @@ func (m *Manager) SetupWithManager(mgr ctrl.Manager) error { func (m *Manager) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { l := log.FromContext(ctx) - crd := &cozyv1alpha1.CozystackResourceDefinition{} + crd := &cozyv1alpha1.ApplicationDefinition{} err := m.Get(ctx, types.NamespacedName{Name: req.Name}, crd) if err != nil { @@ -85,10 +85,10 @@ func (m *Manager) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, return ctrl.Result{}, err } - return m.EnsureForCRD(ctx, crd) + return m.EnsureForAppDef(ctx, crd) } -// EnsureForCRD is the single entry-point used by the controller. +// EnsureForAppDef is the single entry-point used by the controller. // Add more ensure* calls here as you implement support for other resources: // // - ensureBreadcrumb (implemented) @@ -99,7 +99,7 @@ func (m *Manager) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, // - ensureMarketplacePanel (implemented) // - ensureSidebar (implemented) // - ensureTableUriMapping (implemented) -func (m *Manager) EnsureForCRD(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) (reconcile.Result, error) { +func (m *Manager) EnsureForAppDef(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) (reconcile.Result, error) { // Early return if crd.Spec.Dashboard is nil to prevent oscillation if crd.Spec.Dashboard == nil { return reconcile.Result{}, nil @@ -148,7 +148,7 @@ func (m *Manager) InitializeStaticResources(ctx context.Context) error { } // addDashboardLabels adds standard dashboard management labels to a resource -func (m *Manager) addDashboardLabels(obj client.Object, crd *cozyv1alpha1.CozystackResourceDefinition, resourceType string) { +func (m *Manager) addDashboardLabels(obj client.Object, crd *cozyv1alpha1.ApplicationDefinition, resourceType string) { labels := obj.GetLabels() if labels == nil { labels = make(map[string]string) @@ -197,7 +197,7 @@ func (m *Manager) getStaticResourceSelector() client.MatchingLabels { // CleanupOrphanedResources removes dashboard resources that are no longer needed // This should be called after cache warming to ensure all current resources are known func (m *Manager) CleanupOrphanedResources(ctx context.Context) error { - var crdList cozyv1alpha1.CozystackResourceDefinitionList + var crdList cozyv1alpha1.ApplicationDefinitionList if err := m.List(ctx, &crdList, &client.ListOptions{}); err != nil { return err } @@ -228,7 +228,7 @@ func (m *Manager) CleanupOrphanedResources(ctx context.Context) error { } // buildExpectedResourceSet creates a map of expected resource names by type -func (m *Manager) buildExpectedResourceSet(crds []cozyv1alpha1.CozystackResourceDefinition) map[string]map[string]bool { +func (m *Manager) buildExpectedResourceSet(crds []cozyv1alpha1.ApplicationDefinition) map[string]map[string]bool { expected := make(map[string]map[string]bool) // Initialize maps for each resource type diff --git a/internal/controller/dashboard/marketplacepanel.go b/internal/controller/dashboard/marketplacepanel.go index 82a8f336..6bfce752 100644 --- a/internal/controller/dashboard/marketplacepanel.go +++ b/internal/controller/dashboard/marketplacepanel.go @@ -16,7 +16,7 @@ import ( ) // ensureMarketplacePanel creates or updates a MarketplacePanel resource for the given CRD -func (m *Manager) ensureMarketplacePanel(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) (reconcile.Result, error) { +func (m *Manager) ensureMarketplacePanel(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) (reconcile.Result, error) { logger := log.FromContext(ctx) mp := &dashv1alpha1.MarketplacePanel{} diff --git a/internal/controller/dashboard/sidebar.go b/internal/controller/dashboard/sidebar.go index c6f9d3ba..a6ade387 100644 --- a/internal/controller/dashboard/sidebar.go +++ b/internal/controller/dashboard/sidebar.go @@ -28,12 +28,12 @@ import ( // - Categories are ordered strictly as: // Marketplace, IaaS, PaaS, NaaS, , Resources, Backups, Administration // - Items within each category: sort by Weight (desc), then Label (A→Z). -func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) error { +func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) error { // Build the full menu once. // 1) Fetch all CRDs - var all []cozyv1alpha1.CozystackResourceDefinition - var crdList cozyv1alpha1.CozystackResourceDefinitionList + var all []cozyv1alpha1.ApplicationDefinition + var crdList cozyv1alpha1.ApplicationDefinitionList if err := m.List(ctx, &crdList, &client.ListOptions{}); err != nil { return err } @@ -111,6 +111,8 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Cozystack keysAndTags["services"] = []any{"service-sidebar"} keysAndTags["secrets"] = []any{"secret-sidebar"} keysAndTags["ingresses"] = []any{"ingress-sidebar"} + // Add sidebar for v1/services type loadbalancer + keysAndTags["loadbalancer-services"] = []any{"external-ips-sidebar"} // Add sidebar for backups.cozystack.io Plan resource keysAndTags["plans"] = []any{"plan-sidebar"} @@ -210,6 +212,11 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Cozystack "label": "Modules", "link": "/openapi-ui/{clusterName}/{namespace}/api-table/core.cozystack.io/v1alpha1/tenantmodules", }, + map[string]any{ + "key": "loadbalancer-services", + "label": "External IPs", + "link": "/openapi-ui/{clusterName}/{namespace}/factory/external-ips", + }, map[string]any{ "key": "tenants", "label": "Tenants", @@ -236,6 +243,7 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Cozystack "stock-project-factory-plan-details", "stock-project-factory-backupjob-details", "stock-project-factory-backup-details", + "stock-project-factory-external-ips", "stock-project-api-form", "stock-project-api-table", "stock-project-builtin-form", @@ -263,7 +271,7 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Cozystack // upsertMultipleSidebars creates/updates several Sidebar resources with the same menu spec. func (m *Manager) upsertMultipleSidebars( ctx context.Context, - crd *cozyv1alpha1.CozystackResourceDefinition, + crd *cozyv1alpha1.ApplicationDefinition, ids []string, keysAndTags map[string]any, menuItems []any, @@ -370,7 +378,7 @@ func orderCategoryLabels[T any](cats map[string][]T) []string { } // safeCategory returns spec.dashboard.category or "Resources" if not set. -func safeCategory(def *cozyv1alpha1.CozystackResourceDefinition) string { +func safeCategory(def *cozyv1alpha1.ApplicationDefinition) string { if def == nil || def.Spec.Dashboard == nil { return "Resources" } diff --git a/internal/controller/dashboard/static_refactored.go b/internal/controller/dashboard/static_refactored.go index 4c290c49..b2ace34b 100644 --- a/internal/controller/dashboard/static_refactored.go +++ b/internal/controller/dashboard/static_refactored.go @@ -134,7 +134,7 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid createCustomColumnsOverride("factory-details-v1.services", []any{ createCustomColumnWithSpecificColor("Name", "Service", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-service-details/{reqsJsonPath[0]['.metadata.name']['-']}"), createStringColumn("ClusterIP", ".spec.clusterIP"), - createStringColumn("LoadbalancerIP", ".spec.loadBalancerIP"), + createStringColumn("LoadbalancerIP", ".status.loadBalancer.ingress[0].ip"), createTimestampColumn("Created", ".metadata.creationTimestamp"), }), @@ -189,6 +189,14 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid createStringColumn("Values", "_flatMapData_Value"), }), + // Factory resource quotas + createCustomColumnsOverride("factory-resource-quotas", []any{ + createFlatMapColumn("Data", ".spec.hard"), + createStringColumn("Resource", "_flatMapData_Key"), + createStringColumn("Hard", "_flatMapData_Value"), + createStringColumn("Used", ".status.used[_flatMapData_Key]"), + }), + // Factory ingress details rules createCustomColumnsOverride("factory-kube-ingress-details-rules", []any{ createStringColumn("Host", ".host"), @@ -1144,7 +1152,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { "clusterNamePartOfUrl": "{2}", "customizationId": "factory-node-details-/v1/pods", "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/pods", - "labelsSelectorFull": map[string]any{ + "labelSelectorFull": map[string]any{ "pathToLabels": ".spec.selector", "reqIndex": 0, }, @@ -1885,6 +1893,46 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { } backupSpec := createUnifiedFactory(backupConfig, backupTabs, []any{"/api/clusters/{2}/k8s/apis/backups.cozystack.io/v1alpha1/namespaces/{3}/backups/{6}"}) + // External IPs factory (filtered services) + externalIPsTabs := []any{ + map[string]any{ + "key": "services", + "label": "Services", + "children": []any{ + map[string]any{ + "type": "EnrichedTable", + "data": map[string]any{ + "id": "external-ips-table", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services", + "clusterNamePartOfUrl": "{2}", + "baseprefix": "/openapi-ui", + "customizationId": "factory-details-v1.services", + "pathToItems": []any{"items"}, + "fieldSelector": map[string]any{ + "spec.type": "LoadBalancer", + }, + }, + }, + }, + }, + } + externalIPsSpec := map[string]any{ + "key": "external-ips", + "sidebarTags": []any{"external-ips-sidebar"}, + "withScrollableMainContentCard": true, + "urlsToFetch": []any{}, + "data": []any{ + map[string]any{ + "type": "antdTabs", + "data": map[string]any{ + "id": "tabs-root", + "defaultActiveKey": "services", + "items": externalIPsTabs, + }, + }, + }, + } + return []*dashboardv1alpha1.Factory{ createFactory("marketplace", marketplaceSpec), createFactory("namespace-details", namespaceSpec), @@ -1897,6 +1945,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { createFactory("plan-details", planSpec), createFactory("backupjob-details", backupJobSpec), createFactory("backup-details", backupSpec), + createFactory("external-ips", externalIPsSpec), } } diff --git a/internal/controller/dashboard/tableurimapping.go b/internal/controller/dashboard/tableurimapping.go index 6e8a395d..e9a4849c 100644 --- a/internal/controller/dashboard/tableurimapping.go +++ b/internal/controller/dashboard/tableurimapping.go @@ -7,7 +7,7 @@ import ( ) // ensureTableUriMapping creates or updates a TableUriMapping resource for the given CRD -func (m *Manager) ensureTableUriMapping(ctx context.Context, crd *cozyv1alpha1.CozystackResourceDefinition) error { +func (m *Manager) ensureTableUriMapping(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) error { // Links are fully managed by the CustomColumnsOverride. return nil } diff --git a/internal/controller/dashboard/ui_helpers.go b/internal/controller/dashboard/ui_helpers.go index fb29a608..6c7e3000 100644 --- a/internal/controller/dashboard/ui_helpers.go +++ b/internal/controller/dashboard/ui_helpers.go @@ -102,6 +102,22 @@ func antdFlex(id string, gap float64, children []any) map[string]any { } } +func antdFlexSpaceBetween(id string, children []any) map[string]any { + if id == "" { + id = generateContainerID("auto", "flex") + } + + return map[string]any{ + "type": "antdFlex", + "data": map[string]any{ + "id": id, + "align": "center", + "justify": "space-between", + }, + "children": children, + } +} + func antdFlexVertical(id string, gap float64, children []any) map[string]any { // Auto-generate ID if not provided if id == "" { diff --git a/internal/controller/dashboard/unified_helpers.go b/internal/controller/dashboard/unified_helpers.go index b25d5b65..d5edf207 100644 --- a/internal/controller/dashboard/unified_helpers.go +++ b/internal/controller/dashboard/unified_helpers.go @@ -237,9 +237,16 @@ func createUnifiedFactory(config UnifiedResourceConfig, tabs []any, urlsToFetch "lineHeight": "24px", }) - header := antdFlex(generateContainerID("header", "row"), float64(6), []any{ - badge, - nameText, + header := antdFlexSpaceBetween(generateContainerID("header", "row"), []any{ + antdFlex(generateContainerID("header", "title-text"), float64(6), []any{ + badge, + nameText, + }), + antdLink(generateLinkID("header", "edit"), + "Edit", + fmt.Sprintf("/openapi-ui/{2}/{3}/forms/apis/{reqsJsonPath[0]['.apiVersion']['-']}/%s/{reqsJsonPath[0]['.metadata.name']['-']}", + config.Plural), + ), }) // Add marginBottom style to header diff --git a/internal/controller/fluxplunger/flux_plunger.go b/internal/controller/fluxplunger/flux_plunger.go new file mode 100644 index 00000000..44886a2c --- /dev/null +++ b/internal/controller/fluxplunger/flux_plunger.go @@ -0,0 +1,333 @@ +package fluxplunger + +import ( + "context" + "fmt" + "sort" + "strconv" + "strings" + + helmv2 "github.com/fluxcd/helm-controller/api/v2" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" +) + +const ( + annotationLastProcessedVersion = "flux-plunger.cozystack.io/last-processed-version" + errorMessageNoDeployedReleases = "has no deployed releases" + fieldManager = "flux-client-side-apply" +) + +// FluxPlunger watches HelmRelease resources and fixes "has no deployed releases" errors +type FluxPlunger struct { + client.Client +} + +// +kubebuilder:rbac:groups=helm.toolkit.fluxcd.io,resources=helmreleases,verbs=get;list;watch;update;patch +// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;delete + +// Reconcile handles HelmRelease resources with "has no deployed releases" error +func (r *FluxPlunger) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + logger := log.FromContext(ctx) + + // Get the HelmRelease + hr := &helmv2.HelmRelease{} + if err := r.Get(ctx, req.NamespacedName, hr); err != nil { + return ctrl.Result{}, client.IgnoreNotFound(err) + } + + // Check if HelmRelease is suspended + if hr.Spec.Suspend { + logger.Info("HelmRelease is suspended, checking if we need to unsuspend") + + // Get the list of Helm release secrets + secrets, err := r.listHelmReleaseSecrets(ctx, hr.Namespace, hr.Name) + if err != nil { + logger.Error(err, "Failed to list Helm release secrets") + return ctrl.Result{}, err + } + + // If no secrets, treat latest version as 0 + latestVersion := 0 + if len(secrets) > 0 { + latestSecret := getLatestSecret(secrets) + latestVersion = extractVersionNumber(latestSecret.Name) + } else { + logger.Info("No Helm release secrets found while suspended, treating as version 0") + } + + // Check if version is previous to just processed (latestVersion+1 == processedVersion) + // This is the ONLY condition when we unsuspend + shouldUnsuspend := false + if hr.Annotations != nil { + if processedVersionStr, exists := hr.Annotations[annotationLastProcessedVersion]; exists { + processedVersion, err := strconv.Atoi(processedVersionStr) + if err == nil && latestVersion+1 == processedVersion { + shouldUnsuspend = true + } + } + } + + if shouldUnsuspend { + // Unsuspend the HelmRelease + logger.Info("Secret was already deleted in previous run, removing suspend", "latest", latestVersion, "processed", latestVersion+1) + if err := r.unsuspendHelmRelease(ctx, hr); err != nil { + logger.Info("Could not unsuspend HelmRelease, will retry on next reconcile", "error", err.Error()) + return ctrl.Result{}, nil + } + return ctrl.Result{}, nil + } + + // If not previous to processed, skip all actions + logger.Info("HelmRelease is suspended by external process, skipping", "latest", latestVersion) + return ctrl.Result{}, nil + } + + // Check if HelmRelease has the specific error + if !hasNoDeployedReleasesError(hr) { + logger.V(1).Info("HelmRelease does not have 'has no deployed releases' error, skipping") + return ctrl.Result{}, nil + } + + logger.Info("Detected HelmRelease with 'has no deployed releases' error") + + // Get the list of Helm release secrets + secrets, err := r.listHelmReleaseSecrets(ctx, hr.Namespace, hr.Name) + if err != nil { + logger.Error(err, "Failed to list Helm release secrets") + return ctrl.Result{}, err + } + + if len(secrets) == 0 { + logger.Info("No Helm release secrets found, skipping") + return ctrl.Result{}, nil + } + + // Find the latest version + latestSecret := getLatestSecret(secrets) + latestVersion := extractVersionNumber(latestSecret.Name) + + logger.Info("Found latest Helm release version", "version", latestVersion, "secret", latestSecret.Name) + + // Check if we just processed the next version (current + 1 == processed) + if hr.Annotations != nil { + if processedVersionStr, exists := hr.Annotations[annotationLastProcessedVersion]; exists { + processedVersion, err := strconv.Atoi(processedVersionStr) + if err == nil { + if latestVersion+1 == processedVersion { + logger.Info("Already processed, secret was deleted previously", "latest", latestVersion, "processed", processedVersion) + return ctrl.Result{}, nil + } + } else { + // Failed to parse annotation, treat as if annotation doesn't exist + logger.Info("Failed to parse annotation, will process", "annotation", processedVersionStr, "error", err) + } + } + } + + // Suspend the HelmRelease + logger.Info("Suspending HelmRelease") + if err := r.suspendHelmRelease(ctx, hr); err != nil { + // Optimistic lock conflicts are normal - FluxCD also updates HelmRelease + // Don't return error, just log and let controller-runtime requeue on next update + logger.Info("Could not suspend HelmRelease, will retry on next reconcile", "error", err.Error()) + return ctrl.Result{}, nil + } + + // Delete the latest secret + logger.Info("Deleting latest Helm release secret", "secret", latestSecret.Name) + if err := r.Delete(ctx, &latestSecret); err != nil { + logger.Error(err, "Failed to delete Helm release secret") + return ctrl.Result{}, err + } + + // Update annotation with processed version + logger.Info("Updating annotation with processed version", "version", latestVersion) + if err := r.updateProcessedVersionAnnotation(ctx, hr, latestVersion); err != nil { + logger.Info("Could not update annotation, will retry on next reconcile", "error", err.Error()) + return ctrl.Result{}, nil + } + + // Unsuspend the HelmRelease + logger.Info("Unsuspending HelmRelease") + if err := r.unsuspendHelmRelease(ctx, hr); err != nil { + logger.Info("Could not unsuspend HelmRelease, will retry on next reconcile", "error", err.Error()) + return ctrl.Result{}, nil + } + + logger.Info("Successfully processed HelmRelease", "version", latestVersion) + return ctrl.Result{}, nil +} + +// hasNoDeployedReleasesError checks if the HelmRelease has the specific error +func hasNoDeployedReleasesError(hr *helmv2.HelmRelease) bool { + for _, condition := range hr.Status.Conditions { + if condition.Type == "Ready" && condition.Status == metav1.ConditionFalse { + if strings.Contains(condition.Message, errorMessageNoDeployedReleases) { + return true + } + } + } + return false +} + +// listHelmReleaseSecrets lists all Helm release secrets for a specific release +func (r *FluxPlunger) listHelmReleaseSecrets(ctx context.Context, namespace, releaseName string) ([]corev1.Secret, error) { + secretList := &corev1.SecretList{} + listOpts := []client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabels{ + "name": releaseName, + "owner": "helm", + }, + } + + if err := r.List(ctx, secretList, listOpts...); err != nil { + return nil, fmt.Errorf("failed to list secrets: %w", err) + } + + // Filter only helm.sh/release.v1 secrets + filtered := []corev1.Secret{} + for _, secret := range secretList.Items { + if secret.Type == "helm.sh/release.v1" { + filtered = append(filtered, secret) + } + } + + return filtered, nil +} + +// getLatestSecret returns the secret with the highest version number +func getLatestSecret(secrets []corev1.Secret) corev1.Secret { + if len(secrets) == 1 { + return secrets[0] + } + + sort.Slice(secrets, func(i, j int) bool { + vi := extractVersionNumber(secrets[i].Name) + vj := extractVersionNumber(secrets[j].Name) + return vi > vj + }) + + return secrets[0] +} + +// extractVersionFromSecretName extracts version string from secret name +// e.g., "sh.helm.release.v1.cozystack-resource-definitions.v10" -> "v10" +func extractVersionFromSecretName(secretName string) string { + parts := strings.Split(secretName, ".") + if len(parts) > 0 { + return parts[len(parts)-1] + } + return "" +} + +// extractVersionNumber extracts numeric version from secret name +// e.g., "sh.helm.release.v1.cozystack-resource-definitions.v10" -> 10 +func extractVersionNumber(secretName string) int { + version := extractVersionFromSecretName(secretName) + // Remove 'v' prefix if present + version = strings.TrimPrefix(version, "v") + num, err := strconv.Atoi(version) + if err != nil { + return 0 + } + return num +} + +// suspendHelmRelease sets suspend to true on the HelmRelease +func (r *FluxPlunger) suspendHelmRelease(ctx context.Context, hr *helmv2.HelmRelease) error { + // Re-fetch the HelmRelease to get the latest state + key := types.NamespacedName{Namespace: hr.Namespace, Name: hr.Name} + latestHR := &helmv2.HelmRelease{} + if err := r.Get(ctx, key, latestHR); err != nil { + return fmt.Errorf("failed to get latest HelmRelease: %w", err) + } + + // If already suspended, nothing to do + if latestHR.Spec.Suspend { + return nil + } + + patch := client.MergeFromWithOptions(latestHR.DeepCopy(), client.MergeFromWithOptimisticLock{}) + latestHR.Spec.Suspend = true + + return r.Patch(ctx, latestHR, patch, client.FieldOwner(fieldManager)) +} + +// unsuspendHelmRelease sets suspend to false on the HelmRelease +func (r *FluxPlunger) unsuspendHelmRelease(ctx context.Context, hr *helmv2.HelmRelease) error { + // Re-fetch the HelmRelease to get the latest state + key := types.NamespacedName{Namespace: hr.Namespace, Name: hr.Name} + latestHR := &helmv2.HelmRelease{} + if err := r.Get(ctx, key, latestHR); err != nil { + return fmt.Errorf("failed to get latest HelmRelease: %w", err) + } + + // If already unsuspended, nothing to do + if !latestHR.Spec.Suspend { + return nil + } + + patch := client.MergeFromWithOptions(latestHR.DeepCopy(), client.MergeFromWithOptimisticLock{}) + latestHR.Spec.Suspend = false + + return r.Patch(ctx, latestHR, patch, client.FieldOwner(fieldManager)) +} + +// updateProcessedVersionAnnotation updates the annotation with the processed version +func (r *FluxPlunger) updateProcessedVersionAnnotation(ctx context.Context, hr *helmv2.HelmRelease, version int) error { + // Re-fetch the HelmRelease to get the latest state + key := types.NamespacedName{Namespace: hr.Namespace, Name: hr.Name} + latestHR := &helmv2.HelmRelease{} + if err := r.Get(ctx, key, latestHR); err != nil { + return fmt.Errorf("failed to get latest HelmRelease: %w", err) + } + + patch := client.MergeFromWithOptions(latestHR.DeepCopy(), client.MergeFromWithOptimisticLock{}) + + if latestHR.Annotations == nil { + latestHR.Annotations = make(map[string]string) + } + latestHR.Annotations[annotationLastProcessedVersion] = strconv.Itoa(version) + + return r.Patch(ctx, latestHR, patch, client.FieldOwner(fieldManager)) +} + +// SetupWithManager sets up the controller with the Manager +func (r *FluxPlunger) SetupWithManager(mgr ctrl.Manager) error { + // Watch HelmReleases that either: + // 1. Have the specific error, OR + // 2. Are suspended with our annotation (to handle crash recovery) + pred := predicate.NewPredicateFuncs(func(obj client.Object) bool { + hr, ok := obj.(*helmv2.HelmRelease) + if !ok { + return false + } + + // Always process if has error + if hasNoDeployedReleasesError(hr) { + return true + } + + // Also process suspended HelmReleases with our annotation (crash recovery) + if hr.Spec.Suspend && hr.Annotations != nil { + if _, exists := hr.Annotations[annotationLastProcessedVersion]; exists { + return true + } + } + + return false + }) + + return ctrl.NewControllerManagedBy(mgr). + Named("fluxplunger"). + For(&helmv2.HelmRelease{}). + WithEventFilter(pred). + Complete(r) +} diff --git a/internal/controller/workloadmonitor_controller.go b/internal/controller/workloadmonitor_controller.go index d4d86b97..a684df9b 100644 --- a/internal/controller/workloadmonitor_controller.go +++ b/internal/controller/workloadmonitor_controller.go @@ -467,5 +467,8 @@ func (r *WorkloadMonitorReconciler) getWorkloadMetadata(obj client.Object) map[s if instanceType, ok := annotations["kubevirt.io/cluster-instancetype-name"]; ok { labels["workloads.cozystack.io/kubevirt-vmi-instance-type"] = instanceType } + if instanceProfile, ok := annotations["kubevirt.io/cluster-instanceprofile-name"]; ok { + labels["workloads.cozystack.io/kubevirt-vmi-instance-profile"] = instanceProfile + } return labels } diff --git a/internal/fluxinstall/install.go b/internal/fluxinstall/install.go index aa834404..2097ecfb 100644 --- a/internal/fluxinstall/install.go +++ b/internal/fluxinstall/install.go @@ -56,26 +56,31 @@ func Install(ctx context.Context, k8sClient client.Client, writeEmbeddedManifest return fmt.Errorf("failed to extract embedded manifests: %w", err) } - // Find the manifest file (should be fluxcd.yaml from cozypkg) - manifestPath := filepath.Join(manifestsDir, "fluxcd.yaml") - if _, err := os.Stat(manifestPath); err != nil { - // Try to find any YAML file if fluxcd.yaml doesn't exist - entries, err := os.ReadDir(manifestsDir) - if err != nil { - return fmt.Errorf("failed to read manifests directory: %w", err) - } - for _, entry := range entries { - if strings.HasSuffix(entry.Name(), ".yaml") { - manifestPath = filepath.Join(manifestsDir, entry.Name()) - break - } + // Find all YAML manifest files + entries, err := os.ReadDir(manifestsDir) + if err != nil { + return fmt.Errorf("failed to read manifests directory: %w", err) + } + + var manifestFiles []string + for _, entry := range entries { + if strings.HasSuffix(entry.Name(), ".yaml") { + manifestFiles = append(manifestFiles, filepath.Join(manifestsDir, entry.Name())) } } - // Parse and apply manifests - objects, err := parseManifests(manifestPath) - if err != nil { - return fmt.Errorf("failed to parse manifests: %w", err) + if len(manifestFiles) == 0 { + return fmt.Errorf("no YAML manifest files found in directory") + } + + // Parse all manifest files + var objects []*unstructured.Unstructured + for _, manifestPath := range manifestFiles { + objs, err := parseManifests(manifestPath) + if err != nil { + return fmt.Errorf("failed to parse manifests from %s: %w", manifestPath, err) + } + objects = append(objects, objs...) } if len(objects) == 0 { @@ -96,7 +101,7 @@ func Install(ctx context.Context, k8sClient client.Client, writeEmbeddedManifest logger.Info("Installing Flux components", "namespace", namespace) // Apply manifests using server-side apply - logger.Info("Applying Flux manifests", "count", len(objects), "manifest", manifestPath, "namespace", namespace) + logger.Info("Applying Flux manifests", "count", len(objects), "files", len(manifestFiles), "namespace", namespace) if err := applyManifests(ctx, k8sClient, objects); err != nil { return fmt.Errorf("failed to apply manifests: %w", err) } @@ -251,11 +256,17 @@ func injectKubernetesServiceEnv(objects []*unstructured.Unstructured) error { continue } - // Navigate to spec.template.spec.containers + // Navigate to spec.template.spec spec, found, err := unstructured.NestedMap(obj.Object, "spec", "template", "spec") if !found { continue } + + // Skip pods that don't use hostNetwork - they should use normal Kubernetes DNS + hostNetwork, _, _ := unstructured.NestedBool(spec, "hostNetwork") + if !hostNetwork { + continue + } if err != nil { if firstErr == nil { firstErr = fmt.Errorf("failed to get spec for %s/%s: %w", kind, obj.GetName(), err) diff --git a/internal/fluxinstall/manifests/fluxcd-service.yaml b/internal/fluxinstall/manifests/fluxcd-service.yaml new file mode 100644 index 00000000..87feaec4 --- /dev/null +++ b/internal/fluxinstall/manifests/fluxcd-service.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: flux + app.kubernetes.io/part-of: flux + name: flux + namespace: cozy-fluxcd +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http-sc + selector: + app.kubernetes.io/name: flux + type: ClusterIP diff --git a/internal/fluxinstall/manifests/fluxcd-tenants.yaml b/internal/fluxinstall/manifests/fluxcd-tenants.yaml new file mode 100644 index 00000000..077cf34c --- /dev/null +++ b/internal/fluxinstall/manifests/fluxcd-tenants.yaml @@ -0,0 +1,102 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: flux-tenants + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.7.3 + sharding.fluxcd.io/role: shard + name: flux-tenants + namespace: cozy-fluxcd +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: flux-tenants + strategy: + type: Recreate + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + prometheus.io/scrape: "true" + labels: + app.kubernetes.io/name: flux-tenants + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/os + operator: In + values: + - linux + containers: + - args: + - --watch-all-namespaces + - --log-level=info + - --log-encoding=json + - --enable-leader-election=false + - --metrics-addr=:9795 + - --health-addr=:9796 + - --watch-label-selector=sharding.fluxcd.io/key=tenants + - --concurrent=5 + - --requeue-dependency=30s + - --feature-gates=ExternalArtifact=true + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: GOMEMLIMIT + valueFrom: + resourceFieldRef: + resource: limits.memory + - name: TUF_ROOT + value: /tmp/.sigstore + image: "ghcr.io/fluxcd/helm-controller:v1.4.3" + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: helm-controller + ports: + - containerPort: 9795 + name: http-prom + protocol: TCP + - containerPort: 9796 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + resources: + limits: + memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /tmp + name: tmp + priorityClassName: system-cluster-critical + securityContext: + fsGroup: 1337 + serviceAccountName: flux + terminationGracePeriodSeconds: 60 + volumes: + - emptyDir: {} + name: tmp diff --git a/internal/fluxinstall/manifests/fluxcd.yaml b/internal/fluxinstall/manifests/fluxcd.yaml index 237db089..803f52bb 100644 --- a/internal/fluxinstall/manifests/fluxcd.yaml +++ b/internal/fluxinstall/manifests/fluxcd.yaml @@ -11871,7 +11871,7 @@ spec: - --health-addr=:9693 - --storage-addr=:9691 - --storage-path=/data - - --storage-adv-addr=source-watcher.$(RUNTIME_NAMESPACE).svc + - --storage-adv-addr=flux.$(RUNTIME_NAMESPACE).svc - --events-addr=http://localhost:9690 env: - name: SOURCE_CONTROLLER_LOCALHOST @@ -11940,10 +11940,12 @@ spec: tolerations: - key: node.kubernetes.io/not-ready operator: Exists - - effect: NoExecute - key: node.kubernetes.io/unreachable + - key: node.kubernetes.io/unreachable + operator: Exists + - key: node.cilium.io/agent-not-ready + operator: Exists + - key: node.cloudprovider.kubernetes.io/uninitialized operator: Exists - tolerationSeconds: 300 volumes: - emptyDir: {} name: data diff --git a/internal/lineagecontrollerwebhook/config.go b/internal/lineagecontrollerwebhook/config.go index 7204ab66..ce4b6898 100644 --- a/internal/lineagecontrollerwebhook/config.go +++ b/internal/lineagecontrollerwebhook/config.go @@ -14,14 +14,14 @@ type appRef struct { } type runtimeConfig struct { - appCRDMap map[appRef]*cozyv1alpha1.CozystackResourceDefinition + appCRDMap map[appRef]*cozyv1alpha1.ApplicationDefinition } func (l *LineageControllerWebhook) initConfig() { l.initOnce.Do(func() { if l.config.Load() == nil { l.config.Store(&runtimeConfig{ - appCRDMap: make(map[appRef]*cozyv1alpha1.CozystackResourceDefinition), + appCRDMap: make(map[appRef]*cozyv1alpha1.ApplicationDefinition), }) } }) diff --git a/internal/lineagecontrollerwebhook/controller.go b/internal/lineagecontrollerwebhook/controller.go index 092d16e7..42bdb396 100644 --- a/internal/lineagecontrollerwebhook/controller.go +++ b/internal/lineagecontrollerwebhook/controller.go @@ -8,23 +8,23 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" ) -// +kubebuilder:rbac:groups=cozystack.io,resources=cozystackresourcedefinitions,verbs=list;watch;get +// +kubebuilder:rbac:groups=cozystack.io,resources=applicationdefinitions,verbs=list;watch;get func (c *LineageControllerWebhook) SetupWithManagerAsController(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&cozyv1alpha1.CozystackResourceDefinition{}). + For(&cozyv1alpha1.ApplicationDefinition{}). Complete(c) } func (c *LineageControllerWebhook) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { l := log.FromContext(ctx) - crds := &cozyv1alpha1.CozystackResourceDefinitionList{} + crds := &cozyv1alpha1.ApplicationDefinitionList{} if err := c.List(ctx, crds); err != nil { - l.Error(err, "failed reading CozystackResourceDefinitions") + l.Error(err, "failed reading ApplicationDefinitions") return ctrl.Result{}, err } cfg := &runtimeConfig{ - appCRDMap: make(map[appRef]*cozyv1alpha1.CozystackResourceDefinition), + appCRDMap: make(map[appRef]*cozyv1alpha1.ApplicationDefinition), } for _, crd := range crds.Items { appRef := appRef{ diff --git a/internal/lineagecontrollerwebhook/matcher.go b/internal/lineagecontrollerwebhook/matcher.go index 7c756a49..6e7bd318 100644 --- a/internal/lineagecontrollerwebhook/matcher.go +++ b/internal/lineagecontrollerwebhook/matcher.go @@ -42,7 +42,7 @@ func matchName(ctx context.Context, name string, templateContext map[string]stri return false } -func matchResourceToSelector(ctx context.Context, name string, templateContext, l map[string]string, s *cozyv1alpha1.CozystackResourceDefinitionResourceSelector) bool { +func matchResourceToSelector(ctx context.Context, name string, templateContext, l map[string]string, s *cozyv1alpha1.ApplicationDefinitionResourceSelector) bool { sel, err := metav1.LabelSelectorAsSelector(&s.LabelSelector) if err != nil { log.FromContext(ctx).Error(err, "failed to convert label selector to selector") @@ -53,7 +53,7 @@ func matchResourceToSelector(ctx context.Context, name string, templateContext, return labelMatches && nameMatches } -func matchResourceToSelectorArray(ctx context.Context, name string, templateContext, l map[string]string, ss []*cozyv1alpha1.CozystackResourceDefinitionResourceSelector) bool { +func matchResourceToSelectorArray(ctx context.Context, name string, templateContext, l map[string]string, ss []*cozyv1alpha1.ApplicationDefinitionResourceSelector) bool { for _, s := range ss { if matchResourceToSelector(ctx, name, templateContext, l, s) { return true @@ -62,7 +62,7 @@ func matchResourceToSelectorArray(ctx context.Context, name string, templateCont return false } -func matchResourceToExcludeInclude(ctx context.Context, name string, templateContext, l map[string]string, resources *cozyv1alpha1.CozystackResourceDefinitionResources) bool { +func matchResourceToExcludeInclude(ctx context.Context, name string, templateContext, l map[string]string, resources *cozyv1alpha1.ApplicationDefinitionResources) bool { if resources == nil { return false } diff --git a/internal/lineagecontrollerwebhook/webhook.go b/internal/lineagecontrollerwebhook/webhook.go index 0841c891..299cbaee 100644 --- a/internal/lineagecontrollerwebhook/webhook.go +++ b/internal/lineagecontrollerwebhook/webhook.go @@ -33,8 +33,8 @@ const ( ManagerNameKey = "apps.cozystack.io/application.name" ) -// getResourceSelectors returns the appropriate CozystackResourceDefinitionResources for a given GroupKind -func (h *LineageControllerWebhook) getResourceSelectors(gk schema.GroupKind, crd *cozyv1alpha1.CozystackResourceDefinition) *cozyv1alpha1.CozystackResourceDefinitionResources { +// getResourceSelectors returns the appropriate ApplicationDefinitionResources for a given GroupKind +func (h *LineageControllerWebhook) getResourceSelectors(gk schema.GroupKind, crd *cozyv1alpha1.ApplicationDefinition) *cozyv1alpha1.ApplicationDefinitionResources { switch { case gk.Group == "" && gk.Kind == "Secret": return &crd.Spec.Secrets diff --git a/internal/operator/package_reconciler.go b/internal/operator/package_reconciler.go index 07237fe5..79d78a87 100644 --- a/internal/operator/package_reconciler.go +++ b/internal/operator/package_reconciler.go @@ -211,11 +211,13 @@ func (r *PackageReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct Namespace: "cozy-system", }, Install: &helmv2.Install{ + Timeout: &metav1.Duration{Duration: 10 * 60 * 1000000000}, // 10m Remediation: &helmv2.InstallRemediation{ Retries: -1, }, }, Upgrade: &helmv2.Upgrade{ + Timeout: &metav1.Duration{Duration: 10 * 60 * 1000000000}, // 10m Remediation: &helmv2.UpgradeRemediation{ Retries: -1, }, diff --git a/internal/shared/crdmem/memory.go b/internal/shared/crdmem/memory.go index fbfbeeea..f0446627 100644 --- a/internal/shared/crdmem/memory.go +++ b/internal/shared/crdmem/memory.go @@ -11,13 +11,13 @@ import ( type Memory struct { mu sync.RWMutex - data map[string]cozyv1alpha1.CozystackResourceDefinition + data map[string]cozyv1alpha1.ApplicationDefinition primed bool primeOnce sync.Once } func New() *Memory { - return &Memory{data: make(map[string]cozyv1alpha1.CozystackResourceDefinition)} + return &Memory{data: make(map[string]cozyv1alpha1.ApplicationDefinition)} } var ( @@ -30,7 +30,7 @@ func Global() *Memory { return global } -func (m *Memory) Upsert(obj *cozyv1alpha1.CozystackResourceDefinition) { +func (m *Memory) Upsert(obj *cozyv1alpha1.ApplicationDefinition) { if obj == nil { return } @@ -45,10 +45,10 @@ func (m *Memory) Delete(name string) { m.mu.Unlock() } -func (m *Memory) Snapshot() []cozyv1alpha1.CozystackResourceDefinition { +func (m *Memory) Snapshot() []cozyv1alpha1.ApplicationDefinition { m.mu.RLock() defer m.mu.RUnlock() - out := make([]cozyv1alpha1.CozystackResourceDefinition, 0, len(m.data)) + out := make([]cozyv1alpha1.ApplicationDefinition, 0, len(m.data)) for _, v := range m.data { out = append(out, v) } @@ -72,7 +72,7 @@ func (m *Memory) EnsurePrimingWithManager(mgr ctrl.Manager) error { if ok := mgr.GetCache().WaitForCacheSync(ctx); !ok { return nil } - var list cozyv1alpha1.CozystackResourceDefinitionList + var list cozyv1alpha1.ApplicationDefinitionList if err := mgr.GetClient().List(ctx, &list); err == nil { for i := range list.Items { m.Upsert(&list.Items[i]) @@ -87,11 +87,11 @@ func (m *Memory) EnsurePrimingWithManager(mgr ctrl.Manager) error { return errOut } -func (m *Memory) ListFromCacheOrAPI(ctx context.Context, c client.Client) ([]cozyv1alpha1.CozystackResourceDefinition, error) { +func (m *Memory) ListFromCacheOrAPI(ctx context.Context, c client.Client) ([]cozyv1alpha1.ApplicationDefinition, error) { if m.IsPrimed() { return m.Snapshot(), nil } - var list cozyv1alpha1.CozystackResourceDefinitionList + var list cozyv1alpha1.ApplicationDefinitionList if err := c.List(ctx, &list); err != nil { return nil, err } diff --git a/internal/telemetry/collector.go b/internal/telemetry/collector.go index 04d05d3a..f4bb8dd8 100644 --- a/internal/telemetry/collector.go +++ b/internal/telemetry/collector.go @@ -9,35 +9,34 @@ import ( "time" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/discovery" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + helmv2 "github.com/fluxcd/helm-controller/api/v2" + cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" ) -// Collector handles telemetry data collection and sending +const ( + // ApplicationKindLabel is the label used to identify application kind on HelmReleases + ApplicationKindLabel = "apps.cozystack.io/application.kind" +) + +// Collector handles telemetry data collection for cozystack-controller type Collector struct { - client client.Client - discoveryClient discovery.DiscoveryInterface - config *Config - ticker *time.Ticker - stopCh chan struct{} + client client.Client + config *Config + ticker *time.Ticker + stopCh chan struct{} } -// NewCollector creates a new telemetry collector -func NewCollector(client client.Client, config *Config, kubeConfig *rest.Config) (*Collector, error) { - discoveryClient, err := discovery.NewDiscoveryClientForConfig(kubeConfig) - if err != nil { - return nil, fmt.Errorf("failed to create discovery client: %w", err) - } +// NewCollector creates a new telemetry collector for cozystack-controller +func NewCollector(c client.Client, config *Config, _ *rest.Config) (*Collector, error) { return &Collector{ - client: client, - discoveryClient: discoveryClient, - config: config, + client: c, + config: config, }, nil } @@ -67,46 +66,9 @@ func (c *Collector) Start(ctx context.Context) error { // NeedLeaderElection implements manager.LeaderElectionRunnable func (c *Collector) NeedLeaderElection() bool { - // Only run telemetry collector on the leader return true } -// Stop halts telemetry collection -func (c *Collector) Stop() { - close(c.stopCh) -} - -// getSizeGroup returns the exponential size group for PVC -func getSizeGroup(size resource.Quantity) string { - gb := size.Value() / (1024 * 1024 * 1024) - switch { - case gb <= 1: - return "1Gi" - case gb <= 5: - return "5Gi" - case gb <= 10: - return "10Gi" - case gb <= 25: - return "25Gi" - case gb <= 50: - return "50Gi" - case gb <= 100: - return "100Gi" - case gb <= 250: - return "250Gi" - case gb <= 500: - return "500Gi" - case gb <= 1024: - return "1Ti" - case gb <= 2048: - return "2Ti" - case gb <= 5120: - return "5Ti" - default: - return "10Ti" - } -} - // collect gathers and sends telemetry data func (c *Collector) collect(ctx context.Context) { logger := log.FromContext(ctx).V(1) @@ -120,151 +82,54 @@ func (c *Collector) collect(ctx context.Context) { clusterID := string(kubeSystemNS.UID) - var cozystackCM corev1.ConfigMap - if err := c.client.Get(ctx, types.NamespacedName{Namespace: "cozy-system", Name: "cozystack"}, &cozystackCM); err != nil { - logger.Info(fmt.Sprintf("Failed to get cozystack configmap in cozy-system namespace: %v", err)) + // Get all ApplicationDefinitions to know which kinds exist + var appDefList cozyv1alpha1.ApplicationDefinitionList + if err := c.client.List(ctx, &appDefList); err != nil { + logger.Info(fmt.Sprintf("Failed to list ApplicationDefinitions: %v", err)) return } - oidcEnabled := cozystackCM.Data["oidc-enabled"] - bundle := cozystackCM.Data["bundle-name"] - bundleEnable := cozystackCM.Data["bundle-enable"] - bundleDisable := cozystackCM.Data["bundle-disable"] + // Build a map of all known application kinds (initialized with 0) + appKindCounts := make(map[string]int) + for _, appDef := range appDefList.Items { + kind := appDef.Spec.Application.Kind + if kind != "" { + appKindCounts[kind] = 0 + } + } - // Get Kubernetes version from nodes - var nodeList corev1.NodeList - if err := c.client.List(ctx, &nodeList); err != nil { - logger.Info(fmt.Sprintf("Failed to list nodes: %v", err)) + // Get all HelmReleases with apps.cozystack.io/application.kind label in one request + var hrList helmv2.HelmReleaseList + if err := c.client.List(ctx, &hrList, client.HasLabels{ApplicationKindLabel}); err != nil { + logger.Info(fmt.Sprintf("Failed to list HelmReleases: %v", err)) return } + // Count HelmReleases by application kind + for _, hr := range hrList.Items { + kind := hr.Labels[ApplicationKindLabel] + if kind != "" { + appKindCounts[kind]++ + } + } + // Create metrics buffer var metrics strings.Builder - // Add Cozystack info metric - if len(nodeList.Items) > 0 { - k8sVersion, _ := c.discoveryClient.ServerVersion() + // Write application count metrics + for kind, count := range appKindCounts { metrics.WriteString(fmt.Sprintf( - "cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bunde_enable=\"%s\",bunde_disable=\"%s\"} 1\n", - c.config.CozystackVersion, - k8sVersion, - oidcEnabled, - bundle, - bundleEnable, - bundleDisable, - )) - } - - // Collect node metrics - nodeOSCount := make(map[string]int) - for _, node := range nodeList.Items { - key := fmt.Sprintf("%s (%s)", node.Status.NodeInfo.OperatingSystem, node.Status.NodeInfo.OSImage) - nodeOSCount[key] = nodeOSCount[key] + 1 - } - - for osKey, count := range nodeOSCount { - metrics.WriteString(fmt.Sprintf( - "cozy_nodes_count{os=\"%s\",kernel=\"%s\"} %d\n", - osKey, - nodeList.Items[0].Status.NodeInfo.KernelVersion, + "cozy_application_count{kind=\"%s\"} %d\n", + kind, count, )) } - // Collect LoadBalancer services metrics - var serviceList corev1.ServiceList - if err := c.client.List(ctx, &serviceList); err != nil { - logger.Info(fmt.Sprintf("Failed to list Services: %v", err)) - } else { - lbCount := 0 - for _, svc := range serviceList.Items { - if svc.Spec.Type == corev1.ServiceTypeLoadBalancer { - lbCount++ - } + // Send metrics only if there's something to send + if metrics.Len() > 0 { + if err := c.sendMetrics(clusterID, metrics.String()); err != nil { + logger.Info(fmt.Sprintf("Failed to send metrics: %v", err)) } - metrics.WriteString(fmt.Sprintf("cozy_loadbalancers_count %d\n", lbCount)) - } - - // Count tenant namespaces - var nsList corev1.NamespaceList - if err := c.client.List(ctx, &nsList); err != nil { - logger.Info(fmt.Sprintf("Failed to list Namespaces: %v", err)) - } else { - tenantCount := 0 - for _, ns := range nsList.Items { - if strings.HasPrefix(ns.Name, "tenant-") { - tenantCount++ - } - } - metrics.WriteString(fmt.Sprintf("cozy_tenants_count %d\n", tenantCount)) - } - - // Collect PV metrics grouped by driver and size - var pvList corev1.PersistentVolumeList - if err := c.client.List(ctx, &pvList); err != nil { - logger.Info(fmt.Sprintf("Failed to list PVs: %v", err)) - } else { - // Map to store counts by size and driver - pvMetrics := make(map[string]map[string]int) - - for _, pv := range pvList.Items { - if capacity, ok := pv.Spec.Capacity[corev1.ResourceStorage]; ok { - sizeGroup := getSizeGroup(capacity) - - // Get the CSI driver name - driver := "unknown" - if pv.Spec.CSI != nil { - driver = pv.Spec.CSI.Driver - } else if pv.Spec.HostPath != nil { - driver = "hostpath" - } else if pv.Spec.NFS != nil { - driver = "nfs" - } - - // Initialize nested map if needed - if _, exists := pvMetrics[sizeGroup]; !exists { - pvMetrics[sizeGroup] = make(map[string]int) - } - - // Increment count for this size/driver combination - pvMetrics[sizeGroup][driver]++ - } - } - - // Write metrics - for size, drivers := range pvMetrics { - for driver, count := range drivers { - metrics.WriteString(fmt.Sprintf( - "cozy_pvs_count{driver=\"%s\",size=\"%s\"} %d\n", - driver, - size, - count, - )) - } - } - } - - // Collect workload metrics - var monitorList cozyv1alpha1.WorkloadMonitorList - if err := c.client.List(ctx, &monitorList); err != nil { - logger.Info(fmt.Sprintf("Failed to list WorkloadMonitors: %v", err)) - return - } - - for _, monitor := range monitorList.Items { - metrics.WriteString(fmt.Sprintf( - "cozy_workloads_count{uid=\"%s\",kind=\"%s\",type=\"%s\",version=\"%s\"} %d\n", - monitor.UID, - monitor.Spec.Kind, - monitor.Spec.Type, - monitor.Spec.Version, - monitor.Status.ObservedReplicas, - )) - } - - // Send metrics - if err := c.sendMetrics(clusterID, metrics.String()); err != nil { - logger.Info(fmt.Sprintf("Failed to send metrics: %v", err)) } } diff --git a/internal/telemetry/config.go b/internal/telemetry/config.go index b4c9b4d1..d2d3dcc0 100644 --- a/internal/telemetry/config.go +++ b/internal/telemetry/config.go @@ -12,16 +12,13 @@ type Config struct { Endpoint string // Interval between telemetry data collection Interval time.Duration - // CozystackVersion represents the current version of Cozystack - CozystackVersion string } // DefaultConfig returns default telemetry configuration func DefaultConfig() *Config { return &Config{ - Disabled: false, - Endpoint: "https://telemetry.cozystack.io", - Interval: 15 * time.Minute, - CozystackVersion: "unknown", + Disabled: false, + Endpoint: "https://telemetry.cozystack.io", + Interval: 15 * time.Minute, } } diff --git a/internal/telemetry/operator_collector.go b/internal/telemetry/operator_collector.go new file mode 100644 index 00000000..8b4ec302 --- /dev/null +++ b/internal/telemetry/operator_collector.go @@ -0,0 +1,282 @@ +package telemetry + +import ( + "bytes" + "context" + "fmt" + "net/http" + "strings" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" + "github.com/cozystack/cozystack/pkg/version" +) + +// OperatorCollector handles telemetry data collection for cozystack-operator +type OperatorCollector struct { + reader client.Reader + discoveryClient discovery.DiscoveryInterface + config *Config + ticker *time.Ticker + stopCh chan struct{} +} + +// NewOperatorCollector creates a new telemetry collector for cozystack-operator +func NewOperatorCollector(r client.Reader, config *Config, kubeConfig *rest.Config) (*OperatorCollector, error) { + discoveryClient, err := discovery.NewDiscoveryClientForConfig(kubeConfig) + if err != nil { + return nil, fmt.Errorf("failed to create discovery client: %w", err) + } + return &OperatorCollector{ + reader: r, + discoveryClient: discoveryClient, + config: config, + }, nil +} + +// Start implements manager.Runnable +func (c *OperatorCollector) Start(ctx context.Context) error { + if c.config.Disabled { + return nil + } + + c.ticker = time.NewTicker(c.config.Interval) + c.stopCh = make(chan struct{}) + + // Initial collection + c.collect(ctx) + + for { + select { + case <-ctx.Done(): + c.ticker.Stop() + close(c.stopCh) + return nil + case <-c.ticker.C: + c.collect(ctx) + } + } +} + +// NeedLeaderElection implements manager.LeaderElectionRunnable +func (c *OperatorCollector) NeedLeaderElection() bool { + return true +} + +// getSizeGroup returns the exponential size group for PVC +func getSizeGroup(size resource.Quantity) string { + gb := size.Value() / (1024 * 1024 * 1024) + switch { + case gb <= 1: + return "1Gi" + case gb <= 5: + return "5Gi" + case gb <= 10: + return "10Gi" + case gb <= 25: + return "25Gi" + case gb <= 50: + return "50Gi" + case gb <= 100: + return "100Gi" + case gb <= 250: + return "250Gi" + case gb <= 500: + return "500Gi" + case gb <= 1024: + return "1Ti" + case gb <= 2048: + return "2Ti" + case gb <= 5120: + return "5Ti" + default: + return "10Ti" + } +} + +// collect gathers and sends telemetry data +func (c *OperatorCollector) collect(ctx context.Context) { + logger := log.FromContext(ctx).V(1) + + // Get cluster ID from kube-system namespace + var kubeSystemNS corev1.Namespace + if err := c.reader.Get(ctx, types.NamespacedName{Name: "kube-system"}, &kubeSystemNS); err != nil { + logger.Info(fmt.Sprintf("Failed to get kube-system namespace: %v", err)) + return + } + + clusterID := string(kubeSystemNS.UID) + + // Get Kubernetes version + k8sVersion, err := c.discoveryClient.ServerVersion() + if err != nil { + logger.Info(fmt.Sprintf("Failed to get Kubernetes version: %v", err)) + return + } + + // Get nodes + var nodeList corev1.NodeList + if err := c.reader.List(ctx, &nodeList); err != nil { + logger.Info(fmt.Sprintf("Failed to list nodes: %v", err)) + return + } + + // Create metrics buffer + var metrics strings.Builder + + // Add cluster info metric + metrics.WriteString(fmt.Sprintf( + "cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\"} 1\n", + version.Version, + k8sVersion.GitVersion, + )) + + // Collect node metrics grouped by OS and kernel + nodeOSCount := make(map[string]map[string]int) // os -> kernel -> count + for _, node := range nodeList.Items { + osKey := fmt.Sprintf("%s (%s)", node.Status.NodeInfo.OperatingSystem, node.Status.NodeInfo.OSImage) + kernelKey := node.Status.NodeInfo.KernelVersion + + if _, exists := nodeOSCount[osKey]; !exists { + nodeOSCount[osKey] = make(map[string]int) + } + nodeOSCount[osKey][kernelKey]++ + } + + for osKey, kernels := range nodeOSCount { + for kernel, count := range kernels { + metrics.WriteString(fmt.Sprintf( + "cozy_nodes_count{os=\"%s\",kernel=\"%s\"} %d\n", + osKey, + kernel, + count, + )) + } + } + + // Collect cluster capacity metrics (cpu, memory, gpu) + capacityTotals := make(map[string]int64) + for _, node := range nodeList.Items { + for resourceName, quantity := range node.Status.Capacity { + name := string(resourceName) + if name == "cpu" || name == "memory" || strings.HasPrefix(name, "nvidia.com/") { + capacityTotals[name] += quantity.Value() + } + } + } + + for resourceName, total := range capacityTotals { + metrics.WriteString(fmt.Sprintf( + "cozy_cluster_capacity{resource=\"%s\"} %d\n", + resourceName, + total, + )) + } + + // Collect LoadBalancer services metrics + var serviceList corev1.ServiceList + if err := c.reader.List(ctx, &serviceList); err != nil { + logger.Info(fmt.Sprintf("Failed to list Services: %v", err)) + } else { + lbCount := 0 + for _, svc := range serviceList.Items { + if svc.Spec.Type == corev1.ServiceTypeLoadBalancer { + lbCount++ + } + } + metrics.WriteString(fmt.Sprintf("cozy_loadbalancers_count %d\n", lbCount)) + } + + // Collect PV metrics grouped by driver and size + var pvList corev1.PersistentVolumeList + if err := c.reader.List(ctx, &pvList); err != nil { + logger.Info(fmt.Sprintf("Failed to list PVs: %v", err)) + } else { + pvMetrics := make(map[string]map[string]int) // size -> driver -> count + + for _, pv := range pvList.Items { + if capacity, ok := pv.Spec.Capacity[corev1.ResourceStorage]; ok { + sizeGroup := getSizeGroup(capacity) + + driver := "unknown" + if pv.Spec.CSI != nil { + driver = pv.Spec.CSI.Driver + } else if pv.Spec.HostPath != nil { + driver = "hostpath" + } else if pv.Spec.NFS != nil { + driver = "nfs" + } + + if _, exists := pvMetrics[sizeGroup]; !exists { + pvMetrics[sizeGroup] = make(map[string]int) + } + pvMetrics[sizeGroup][driver]++ + } + } + + for size, drivers := range pvMetrics { + for driver, count := range drivers { + metrics.WriteString(fmt.Sprintf( + "cozy_pvs_count{driver=\"%s\",size=\"%s\"} %d\n", + driver, + size, + count, + )) + } + } + } + + // Collect installed packages + var packageList cozyv1alpha1.PackageList + if err := c.reader.List(ctx, &packageList); err != nil { + logger.Info(fmt.Sprintf("Failed to list Packages: %v", err)) + } else { + for _, pkg := range packageList.Items { + variant := pkg.Spec.Variant + if variant == "" { + variant = "default" + } + metrics.WriteString(fmt.Sprintf( + "cozy_package_info{name=\"%s\",variant=\"%s\"} 1\n", + pkg.Name, + variant, + )) + } + } + + // Send metrics + if err := c.sendMetrics(clusterID, metrics.String()); err != nil { + logger.Info(fmt.Sprintf("Failed to send metrics: %v", err)) + } +} + +// sendMetrics sends collected metrics to the configured endpoint +func (c *OperatorCollector) sendMetrics(clusterID, metrics string) error { + req, err := http.NewRequest("POST", c.config.Endpoint, bytes.NewBufferString(metrics)) + if err != nil { + return fmt.Errorf("failed to create request: %w", err) + } + + req.Header.Set("Content-Type", "text/plain") + req.Header.Set("X-Cluster-ID", clusterID) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } + + return nil +} diff --git a/packages/apps/Makefile b/packages/apps/Makefile index b3917f20..50502f2b 100644 --- a/packages/apps/Makefile +++ b/packages/apps/Makefile @@ -1,7 +1,7 @@ OUT=../../_out/repos/apps CHARTS := $(shell find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}') -include ../../scripts/common-envs.mk +include ../../hack/common-envs.mk repo: rm -rf "$(OUT)" diff --git a/packages/apps/bucket/Makefile b/packages/apps/bucket/Makefile index d448d0c0..27cd199b 100644 --- a/packages/apps/bucket/Makefile +++ b/packages/apps/bucket/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/bucket/templates/helmrelease.yaml b/packages/apps/bucket/templates/helmrelease.yaml index 5d242f84..704470a8 100644 --- a/packages/apps/bucket/templates/helmrelease.yaml +++ b/packages/apps/bucket/templates/helmrelease.yaml @@ -2,16 +2,13 @@ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: {{ .Release.Name }}-system + labels: + sharding.fluxcd.io/key: tenants spec: - chart: - spec: - chart: cozy-bucket - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-bucket-application-default-bucket-system + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/apps/clickhouse/Makefile b/packages/apps/clickhouse/Makefile index 44ac851f..2c77add9 100644 --- a/packages/apps/clickhouse/Makefile +++ b/packages/apps/clickhouse/Makefile @@ -1,7 +1,7 @@ CLICKHOUSE_BACKUP_TAG = $(shell awk '$$0 ~ /^version:/ {print $$2}' Chart.yaml) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/ferretdb/Makefile b/packages/apps/ferretdb/Makefile index bd52fb05..40b7423f 100644 --- a/packages/apps/ferretdb/Makefile +++ b/packages/apps/ferretdb/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/foundationdb/Makefile b/packages/apps/foundationdb/Makefile index b885e4b1..76c84980 100644 --- a/packages/apps/foundationdb/Makefile +++ b/packages/apps/foundationdb/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md \ No newline at end of file diff --git a/packages/apps/http-cache/Makefile b/packages/apps/http-cache/Makefile index 3237f634..2cc11f87 100644 --- a/packages/apps/http-cache/Makefile +++ b/packages/apps/http-cache/Makefile @@ -1,7 +1,7 @@ NGINX_CACHE_TAG = $(shell awk '$$1 == "version:" {print $$2}' Chart.yaml) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk image: image-nginx diff --git a/packages/apps/http-cache/images/nginx-cache.tag b/packages/apps/http-cache/images/nginx-cache.tag index 185dcc66..ee4d8890 100644 --- a/packages/apps/http-cache/images/nginx-cache.tag +++ b/packages/apps/http-cache/images/nginx-cache.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:e0a07082bb6fc6aeaae2315f335386f1705a646c72f9e0af512aebbca5cb2b15 +ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:9e34fd50393b418d9516aadb488067a3a63675b045811beb1c0afc9c61e149e8 diff --git a/packages/apps/kafka/Makefile b/packages/apps/kafka/Makefile index 0d71076e..2cffdfa7 100644 --- a/packages/apps/kafka/Makefile +++ b/packages/apps/kafka/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk PRESET_ENUM := ["nano","micro","small","medium","large","xlarge","2xlarge"] generate: diff --git a/packages/apps/kubernetes/Makefile b/packages/apps/kubernetes/Makefile index ae6dd757..e6ed7c6f 100644 --- a/packages/apps/kubernetes/Makefile +++ b/packages/apps/kubernetes/Makefile @@ -1,8 +1,8 @@ KUBERNETES_VERSION = v1.33 KUBERNETES_PKG_TAG = $(shell awk '$$1 == "version:" {print $$2}' Chart.yaml) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md index 8bff49aa..b2fe102f 100644 --- a/packages/apps/kubernetes/README.md +++ b/packages/apps/kubernetes/README.md @@ -145,31 +145,31 @@ See the reference for components utilized in this service: ### Kubernetes Control Plane Configuration -| Name | Description | Type | Value | -| --------------------------------------------------- | ------------------------------------------------ | ---------- | -------- | -| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` | -| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` | -| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` | -| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` | -| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `medium` | -| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` | -| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` | -| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | -| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` | -| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` | -| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | -| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` | -| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` | -| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` | -| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | +| Name | Description | Type | Value | +| --------------------------------------------------- | ------------------------------------------------ | ---------- | ------- | +| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` | +| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` | +| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` | +| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` | +| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `large` | +| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` | +| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` | +| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | +| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` | +| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` | +| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | +| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` | +| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` | +| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` | +| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | ## Parameter examples and reference diff --git a/packages/apps/kubernetes/images/cluster-autoscaler.tag b/packages/apps/kubernetes/images/cluster-autoscaler.tag index d5ab33d1..03a5ad61 100644 --- a/packages/apps/kubernetes/images/cluster-autoscaler.tag +++ b/packages/apps/kubernetes/images/cluster-autoscaler.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/cluster-autoscaler:0.0.0@sha256:2d39989846c3579dd020b9f6c77e6e314cc81aa344eaac0f6d633e723c17196d +ghcr.io/cozystack/cozystack/cluster-autoscaler:0.0.0@sha256:6f2b1d6b0b2bdc66f1cbb30c59393369cbf070cb8f5fec748f176952273483cc diff --git a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag index 8120dd48..ca661f3a 100644 --- a/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag +++ b/packages/apps/kubernetes/images/kubevirt-cloud-provider.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.0.0@sha256:5335c044313b69ee13b30ca4941687e509005e55f4ae25723861edbf2fbd6dd2 +ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.0.0@sha256:dee69d15fa8616aa6a1e5a67fc76370e7698a7f58b25e30650eb39c9fb826de8 diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag index 80d3d2e6..02f8f103 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:d5c836ba33cf5dbed7e6f866784f668f80ffe69179e7c75847b680111984eefb +ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:726d9287e8caaea94eaf24c4f44734e3fbf4f8aa032b66b81848ebf95297cffe diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk.tag b/packages/apps/kubernetes/images/ubuntu-container-disk.tag index a35d1278..930a3fd2 100644 --- a/packages/apps/kubernetes/images/ubuntu-container-disk.tag +++ b/packages/apps/kubernetes/images/ubuntu-container-disk.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.33@sha256:a09724a7f95283f9130b3da2a89d81c4c6051c6edf0392a81b6fc90f404b76b6 +ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.33@sha256:71a74ca30f75967bae309be2758f19aa3d37c60b19426b9b622ff1c33a80362f diff --git a/packages/apps/kubernetes/templates/cloud-config.yaml b/packages/apps/kubernetes/templates/cloud-config.yaml index b1399b11..a4b7f2c9 100644 --- a/packages/apps/kubernetes/templates/cloud-config.yaml +++ b/packages/apps/kubernetes/templates/cloud-config.yaml @@ -10,3 +10,8 @@ data: enableEPSController: true selectorless: true namespace: {{ .Release.Namespace }} + infraLabels: + apps.cozystack.io/application.group: apps.cozystack.io + apps.cozystack.io/application.kind: Kubernetes + apps.cozystack.io/application.name: {{ .Release.Name | trimPrefix "kubernetes-" }} + internal.cozystack.io/tenantresource: "true" diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index 6acfb107..3d9c854a 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -292,6 +292,12 @@ metadata: {{- end }} spec: clusterName: {{ $.Release.Name }} + replicas: 2 + strategy: + rollingUpdate: + maxSurge: {{ $group.maxReplicas }} + maxUnavailable: 1 + type: RollingUpdate selector: matchLabels: cluster.x-k8s.io/cluster-name: {{ $.Release.Name }} @@ -326,6 +332,7 @@ metadata: namespace: {{ $.Release.Namespace }} spec: clusterName: {{ $.Release.Name }} + maxUnhealthy: 0 nodeStartupTimeout: 10m selector: matchLabels: diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml index 73954e12..be07a8b9 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml @@ -6,17 +6,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: cert-manager-crds - chart: - spec: - chart: cozy-cert-manager-crds - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-cert-manager-crds + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml index e0caf4cb..991ed70f 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml @@ -6,17 +6,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: cert-manager - chart: - spec: - chart: cozy-cert-manager - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-cert-manager + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml index c356dc79..64027e94 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -20,17 +20,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: cilium - chart: - spec: - chart: cozy-cilium - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-cilium + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/coredns.yaml b/packages/apps/kubernetes/templates/helmreleases/coredns.yaml index 37a09a0b..bdb6c682 100644 --- a/packages/apps/kubernetes/templates/helmreleases/coredns.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/coredns.yaml @@ -11,17 +11,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: coredns - chart: - spec: - chart: cozy-coredns - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-coredns + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/csi.yaml b/packages/apps/kubernetes/templates/helmreleases/csi.yaml index 3ecbf1eb..dd2c69a6 100644 --- a/packages/apps/kubernetes/templates/helmreleases/csi.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/csi.yaml @@ -5,18 +5,14 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: interval: 5m releaseName: csi - chart: - spec: - chart: cozy-kubevirt-csi-node - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-kubevirt-csi-node + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml index 7518601b..76499dfe 100644 --- a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml @@ -6,17 +6,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: fluxcd-operator - chart: - spec: - chart: cozy-fluxcd-operator - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-fluxcd-operator + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig @@ -53,18 +49,14 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: interval: 5m releaseName: fluxcd - chart: - spec: - chart: cozy-fluxcd - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-fluxcd + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml index 48a20c5a..2bcc8d4d 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml @@ -6,17 +6,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: gateway-api-crds - chart: - spec: - chart: cozy-gateway-api-crds - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-gateway-api-crds + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml index fbee1724..5ef48912 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml @@ -6,17 +6,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: gpu-operator - chart: - spec: - chart: cozy-gpu-operator - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-gpu-operator + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml index f80dd7ae..5cafff90 100644 --- a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml @@ -4,9 +4,12 @@ ingress-nginx: controller: kind: DaemonSet {{- if eq .Values.addons.ingressNginx.exposeMethod "Proxied" }} - hostNetwork: true service: - enabled: false + enabled: true + type: NodePort + nodePorts: + http: 30000 + https: 30001 {{- end }} {{- if not .Values.addons.certManager.enabled }} admissionWebhooks: @@ -25,17 +28,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: ingress-nginx - chart: - spec: - chart: cozy-ingress-nginx - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-ingress-nginx + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml b/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml index 394e6bb4..3cc81a14 100644 --- a/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml @@ -5,17 +5,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: metrics-server - chart: - spec: - chart: cozy-metrics-server - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-metrics-server + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml index 73c3a368..ff54b6e2 100644 --- a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml @@ -7,17 +7,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: cozy-monitoring-agents - chart: - spec: - chart: cozy-monitoring-agents - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-monitoring-agents + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml index 63972126..600a7994 100644 --- a/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml @@ -5,17 +5,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: prometheus-operator-crds - chart: - spec: - chart: cozy-prometheus-operator-crds - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-prometheus-operator-crds + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/velero.yaml b/packages/apps/kubernetes/templates/helmreleases/velero.yaml index 0c918da6..ad236d53 100644 --- a/packages/apps/kubernetes/templates/helmreleases/velero.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/velero.yaml @@ -6,17 +6,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: velero - chart: - spec: - chart: cozy-velero - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-velero + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml index 71bdc9ee..a3b7a9b4 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml @@ -6,18 +6,14 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: interval: 5m releaseName: vertical-pod-autoscaler-crds - chart: - spec: - chart: cozy-vertical-pod-autoscaler-crds - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-vertical-pod-autoscaler-crds + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml index 8a62288d..178df3e3 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml @@ -32,17 +32,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: vertical-pod-autoscaler - chart: - spec: - chart: cozy-vertical-pod-autoscaler - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-vertical-pod-autoscaler + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml index dbb4d8dc..99744277 100644 --- a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml @@ -6,17 +6,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: cozy-victoria-metrics-operator - chart: - spec: - chart: cozy-victoria-metrics-operator - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-victoria-metrics-operator + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml b/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml index 83fa32d1..025f01b7 100644 --- a/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml @@ -5,17 +5,13 @@ metadata: labels: cozystack.io/repository: system cozystack.io/target-cluster-name: {{ .Release.Name }} + sharding.fluxcd.io/key: tenants spec: releaseName: vsnap-crd - chart: - spec: - chart: cozy-vsnap-crd - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes-volumesnapshot-crd + namespace: cozy-system kubeConfig: secretRef: name: {{ .Release.Name }}-admin-kubeconfig diff --git a/packages/apps/kubernetes/templates/ingress.yaml b/packages/apps/kubernetes/templates/ingress.yaml index 7993dba8..4adb7458 100644 --- a/packages/apps/kubernetes/templates/ingress.yaml +++ b/packages/apps/kubernetes/templates/ingress.yaml @@ -14,6 +14,11 @@ metadata: } nginx.ingress.kubernetes.io/ssl-passthrough: "true" nginx.ingress.kubernetes.io/ssl-redirect: "false" + labels: + apps.cozystack.io/application.group: apps.cozystack.io + apps.cozystack.io/application.kind: Kubernetes + apps.cozystack.io/application.name: {{ .Release.Name | trimPrefix "kubernetes-" }} + internal.cozystack.io/tenantresource: "true" spec: ingressClassName: "{{ $ingress }}" rules: @@ -41,16 +46,21 @@ apiVersion: v1 kind: Service metadata: name: {{ .Release.Name }}-ingress-nginx + labels: + apps.cozystack.io/application.group: apps.cozystack.io + apps.cozystack.io/application.kind: Kubernetes + apps.cozystack.io/application.name: {{ .Release.Name | trimPrefix "kubernetes-" }} + internal.cozystack.io/tenantresource: "true" spec: ports: - appProtocol: http name: http port: 80 - targetPort: 80 + targetPort: 30000 - appProtocol: https name: https port: 443 - targetPort: 443 + targetPort: 30001 selector: cluster.x-k8s.io/cluster-name: {{ .Release.Name }} node-role.kubernetes.io/ingress-nginx: "" diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json index 9ec0c416..1f6c9361 100644 --- a/packages/apps/kubernetes/values.schema.json +++ b/packages/apps/kubernetes/values.schema.json @@ -150,7 +150,11 @@ "exposeMethod": { "description": "Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.", "type": "string", - "default": "Proxied" + "default": "Proxied", + "enum": [ + "Proxied", + "LoadBalancer" + ] }, "hosts": { "description": "Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.", @@ -287,7 +291,7 @@ "resourcesPreset": { "description": "Preset if `resources` omitted.", "type": "string", - "default": "medium", + "default": "large", "enum": [ "nano", "micro", diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index 567d2e02..7f15752f 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -76,9 +76,13 @@ host: "" ## @typedef {struct} GatewayAPIAddon - Gateway API addon. ## @field {bool} enabled - Enable Gateway API. +## @enum {string} IngressNginxExposeMethod - Method to expose the controller +## @value Proxied +## @value LoadBalancer + ## @typedef {struct} IngressNginxAddon - Ingress-NGINX controller. ## @field {bool} enabled - Enable the controller (requires nodes labeled `ingress-nginx`). -## @field {string} exposeMethod - Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`. +## @field {IngressNginxExposeMethod} exposeMethod - Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`. ## @field {[]string} hosts - Domains routed to this tenant cluster when `exposeMethod` is `Proxied`. ## @field {object} valuesOverride - Custom Helm values overrides. @@ -153,7 +157,7 @@ addons: ## @typedef {struct} APIServer - API Server configuration. ## @field {Resources} resources - CPU and memory resources for API Server. -## @field {ResourcesPreset} resourcesPreset="medium" - Preset if `resources` omitted. +## @field {ResourcesPreset} resourcesPreset="large" - Preset if `resources` omitted. ## @typedef {struct} ControllerManager - Controller Manager configuration. ## @field {Resources} resources - CPU and memory resources for Controller Manager. @@ -182,7 +186,7 @@ controlPlane: replicas: 2 apiServer: resources: {} - resourcesPreset: "medium" + resourcesPreset: "large" controllerManager: resources: {} resourcesPreset: "micro" diff --git a/packages/apps/mongodb/.helmignore b/packages/apps/mongodb/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/apps/mongodb/.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/packages/apps/mongodb/Chart.yaml b/packages/apps/mongodb/Chart.yaml new file mode 100644 index 00000000..ffa97e9c --- /dev/null +++ b/packages/apps/mongodb/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: mongodb +description: Managed MongoDB service +icon: /logos/mongodb.svg +type: application +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process +appVersion: "8.0" diff --git a/packages/apps/mongodb/Makefile b/packages/apps/mongodb/Makefile new file mode 100644 index 00000000..9440c3fd --- /dev/null +++ b/packages/apps/mongodb/Makefile @@ -0,0 +1,11 @@ +include ../../../hack/package.mk + +.PHONY: generate update + +generate: + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md + ../../../hack/update-crd.sh + +update: + hack/update-versions.sh + make generate diff --git a/packages/apps/mongodb/README.md b/packages/apps/mongodb/README.md new file mode 100644 index 00000000..82127c59 --- /dev/null +++ b/packages/apps/mongodb/README.md @@ -0,0 +1,110 @@ +# Managed MongoDB Service + +MongoDB is a popular document-oriented NoSQL database known for its flexibility and scalability. +The Managed MongoDB Service provides a self-healing replicated cluster managed by the Percona Operator for MongoDB. + +## Deployment Details + +This managed service is controlled by the Percona Operator for MongoDB, ensuring efficient management and seamless operation. + +- Docs: +- Github: + +## Deployment Modes + +### Replica Set Mode (default) + +By default, MongoDB deploys as a replica set with the specified number of replicas. +This mode is suitable for most use cases requiring high availability. + +### Sharded Cluster Mode + +Enable `sharding: true` for horizontal scaling across multiple shards. +Each shard is a replica set, and mongos routers handle query routing. + +## Notes + +### External Access + +When `external: true` is enabled: +- **Replica Set mode**: Traffic is load-balanced across all replica set members. This works well for read operations, but write operations require connecting to the primary. MongoDB drivers handle primary discovery automatically using the replica set connection string. +- **Sharded mode**: Traffic is routed through mongos routers, which handle both reads and writes correctly. + +### Credentials + +On first install, the credentials secret will be empty until the Percona operator initializes the cluster. +Run `helm upgrade` after MongoDB is ready to populate the credentials secret with the actual password. + +## Parameters + +### Common parameters + +| Name | Description | Type | Value | +| ------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- | +| `replicas` | Number of MongoDB replicas in replica set. | `int` | `3` | +| `resources` | Explicit CPU and memory configuration for each MongoDB replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | +| `resources.cpu` | CPU available to each replica. | `quantity` | `""` | +| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` | +| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | +| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` | +| `storageClass` | StorageClass used to store the data. | `string` | `""` | +| `external` | Enable external access from outside the cluster. | `bool` | `false` | +| `version` | MongoDB major version to deploy. | `string` | `v8` | + + +### Sharding configuration + +| Name | Description | Type | Value | +| ----------------------------------- | ------------------------------------------------------------------ | ---------- | ------- | +| `sharding` | Enable sharded cluster mode. When disabled, deploys a replica set. | `bool` | `false` | +| `shardingConfig` | Configuration for sharded cluster mode. | `object` | `{}` | +| `shardingConfig.configServers` | Number of config server replicas. | `int` | `3` | +| `shardingConfig.configServerSize` | PVC size for config servers. | `quantity` | `3Gi` | +| `shardingConfig.mongos` | Number of mongos router replicas. | `int` | `2` | +| `shardingConfig.shards` | List of shard configurations. | `[]object` | `[...]` | +| `shardingConfig.shards[i].name` | Shard name. | `string` | `""` | +| `shardingConfig.shards[i].replicas` | Number of replicas in this shard. | `int` | `0` | +| `shardingConfig.shards[i].size` | PVC size for this shard. | `quantity` | `""` | + + +### Users configuration + +| Name | Description | Type | Value | +| ---------------------- | -------------------------------------------------- | ------------------- | ----- | +| `users` | Users configuration map. | `map[string]object` | `{}` | +| `users[name].password` | Password for the user (auto-generated if omitted). | `string` | `""` | + + +### Databases configuration + +| Name | Description | Type | Value | +| -------------------------------- | ---------------------------------------------------------- | ------------------- | ----- | +| `databases` | Databases configuration map. | `map[string]object` | `{}` | +| `databases[name].roles` | Roles assigned to users. | `object` | `{}` | +| `databases[name].roles.admin` | List of users with admin privileges (readWrite + dbAdmin). | `[]string` | `[]` | +| `databases[name].roles.readonly` | List of users with read-only privileges. | `[]string` | `[]` | + + +### Backup parameters + +| Name | Description | Type | Value | +| ------------------------ | ------------------------------------------------------ | -------- | ----------------------------------- | +| `backup` | Backup configuration. | `object` | `{}` | +| `backup.enabled` | Enable regular backups. | `bool` | `false` | +| `backup.schedule` | Cron schedule for automated backups. | `string` | `0 2 * * *` | +| `backup.retentionPolicy` | Retention policy (e.g. "30d"). | `string` | `30d` | +| `backup.destinationPath` | Destination path for backups (e.g. s3://bucket/path/). | `string` | `s3://bucket/path/to/folder/` | +| `backup.endpointURL` | S3 endpoint URL for uploads. | `string` | `http://minio-gateway-service:9000` | +| `backup.s3AccessKey` | Access key for S3 authentication. | `string` | `""` | +| `backup.s3SecretKey` | Secret key for S3 authentication. | `string` | `""` | + + +### Bootstrap (recovery) parameters + +| Name | Description | Type | Value | +| ------------------------ | --------------------------------------------------------- | -------- | ------- | +| `bootstrap` | Bootstrap configuration. | `object` | `{}` | +| `bootstrap.enabled` | Whether to restore from a backup. | `bool` | `false` | +| `bootstrap.recoveryTime` | Timestamp for point-in-time recovery; empty means latest. | `string` | `""` | +| `bootstrap.backupName` | Name of backup to restore from. | `string` | `""` | + diff --git a/packages/apps/mongodb/charts/cozy-lib b/packages/apps/mongodb/charts/cozy-lib new file mode 120000 index 00000000..e1813509 --- /dev/null +++ b/packages/apps/mongodb/charts/cozy-lib @@ -0,0 +1 @@ +../../../library/cozy-lib \ No newline at end of file diff --git a/packages/apps/mongodb/files/versions.yaml b/packages/apps/mongodb/files/versions.yaml new file mode 100644 index 00000000..ee1333c5 --- /dev/null +++ b/packages/apps/mongodb/files/versions.yaml @@ -0,0 +1,5 @@ +# MongoDB version mapping (major version -> Percona image tag) +# Auto-generated by hack/update-versions.sh - do not edit manually +"v8": "8.0.17-6" +"v7": "7.0.28-15" +"v6": "6.0.25-20" diff --git a/packages/apps/mongodb/hack/update-versions.sh b/packages/apps/mongodb/hack/update-versions.sh new file mode 100755 index 00000000..832eaf76 --- /dev/null +++ b/packages/apps/mongodb/hack/update-versions.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MONGODB_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +VALUES_FILE="${MONGODB_DIR}/values.yaml" +VERSIONS_FILE="${MONGODB_DIR}/files/versions.yaml" + +# Supported major versions (newest first) +SUPPORTED_MAJOR_VERSIONS="8 7 6" + +echo "Supported major versions: $SUPPORTED_MAJOR_VERSIONS" + +# Check if skopeo is installed +if ! command -v skopeo &> /dev/null; then + echo "Error: skopeo is not installed. Please install skopeo and try again." >&2 + exit 1 +fi + +# Check if jq is installed +if ! command -v jq &> /dev/null; then + echo "Error: jq is not installed. Please install jq and try again." >&2 + exit 1 +fi + +# Get available image tags from Percona registry +echo "Fetching available image tags from registry..." +AVAILABLE_TAGS=$(skopeo list-tags docker://percona/percona-server-mongodb | jq -r '.Tags[]' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+-[0-9]+$' | sort -V) + +if [ -z "$AVAILABLE_TAGS" ]; then + echo "Error: Could not fetch available image tags" >&2 + exit 1 +fi + +# Build versions map: major version -> latest tag +declare -A VERSION_MAP +MAJOR_VERSIONS=() + +for major_version in $SUPPORTED_MAJOR_VERSIONS; do + # Find all tags that match this major version + matching_tags=$(echo "$AVAILABLE_TAGS" | grep "^${major_version}\\.") + + if [ -n "$matching_tags" ]; then + # Get the latest tag for this major version + latest_tag=$(echo "$matching_tags" | tail -n1) + VERSION_MAP["v${major_version}"]="${latest_tag}" + MAJOR_VERSIONS+=("v${major_version}") + echo "Found version: v${major_version} -> ${latest_tag}" + fi +done + +if [ ${#MAJOR_VERSIONS[@]} -eq 0 ]; then + echo "Error: No matching versions found" >&2 + exit 1 +fi + +echo "Major versions to add: ${MAJOR_VERSIONS[*]}" + +# Create/update versions.yaml file +echo "Updating $VERSIONS_FILE..." +{ + echo "# MongoDB version mapping (major version -> Percona image tag)" + echo "# Auto-generated by hack/update-versions.sh - do not edit manually" + for major_ver in "${MAJOR_VERSIONS[@]}"; do + echo "\"${major_ver}\": \"${VERSION_MAP[$major_ver]}\"" + done +} > "$VERSIONS_FILE" + +echo "Successfully updated $VERSIONS_FILE" + +# Update values.yaml - enum with major versions only +TEMP_FILE=$(mktemp) +trap 'rm -f "$TEMP_FILE" "${TEMP_FILE}.tmp"' EXIT + +# Build new version section +NEW_VERSION_SECTION="## @enum {string} Version" +for major_ver in "${MAJOR_VERSIONS[@]}"; do + NEW_VERSION_SECTION="${NEW_VERSION_SECTION} +## @value $major_ver" +done +NEW_VERSION_SECTION="${NEW_VERSION_SECTION} + +## @param {Version} version - MongoDB major version to deploy. +version: ${MAJOR_VERSIONS[0]}" + +# Check if version section already exists +if grep -q "^## @enum {string} Version" "$VALUES_FILE"; then + # Version section exists, update it using awk + echo "Updating existing version section in $VALUES_FILE..." + + # Use awk to replace the section from "## @enum {string} Version" to "version: " (inclusive) + awk -v new_section="$NEW_VERSION_SECTION" ' + /^## @enum {string} Version/ { + in_section = 1 + print new_section + next + } + in_section && /^version: / { + in_section = 0 + next + } + in_section { + next + } + { print } + ' "$VALUES_FILE" > "$TEMP_FILE.tmp" + mv "$TEMP_FILE.tmp" "$VALUES_FILE" +else + # Version section doesn't exist, insert it before Sharding section + echo "Inserting new version section in $VALUES_FILE..." + + awk -v new_section="$NEW_VERSION_SECTION" ' + /^## @section Sharding configuration/ { + print new_section + print "" + } + { print } + ' "$VALUES_FILE" > "$TEMP_FILE.tmp" + mv "$TEMP_FILE.tmp" "$VALUES_FILE" +fi + +echo "Successfully updated $VALUES_FILE with major versions: ${MAJOR_VERSIONS[*]}" diff --git a/packages/apps/mongodb/logos/mongodb.svg b/packages/apps/mongodb/logos/mongodb.svg new file mode 100644 index 00000000..3c76d2d6 --- /dev/null +++ b/packages/apps/mongodb/logos/mongodb.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/apps/mongodb/templates/.gitkeep b/packages/apps/mongodb/templates/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/packages/apps/mongodb/templates/_versions.tpl b/packages/apps/mongodb/templates/_versions.tpl new file mode 100644 index 00000000..6afc6457 --- /dev/null +++ b/packages/apps/mongodb/templates/_versions.tpl @@ -0,0 +1,12 @@ +{{/* +MongoDB version mapping +*/}} +{{- define "mongodb.versionMap" -}} +{{- $versions := .Files.Get "files/versions.yaml" | fromYaml -}} +{{- $version := .Values.version -}} +{{- if hasKey $versions $version -}} +{{- index $versions $version -}} +{{- else -}} +{{- fail (printf "Unsupported MongoDB version: %s. Supported versions: %s" $version (keys $versions | sortAlpha | join ", ")) -}} +{{- end -}} +{{- end -}} diff --git a/packages/apps/mongodb/templates/backup-secret.yaml b/packages/apps/mongodb/templates/backup-secret.yaml new file mode 100644 index 00000000..f7b2ba01 --- /dev/null +++ b/packages/apps/mongodb/templates/backup-secret.yaml @@ -0,0 +1,11 @@ +{{- if or .Values.backup.enabled .Values.bootstrap.enabled }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-s3-creds +type: Opaque +stringData: + AWS_ACCESS_KEY_ID: {{ required "backup.s3AccessKey is required when backup or bootstrap is enabled" .Values.backup.s3AccessKey | quote }} + AWS_SECRET_ACCESS_KEY: {{ required "backup.s3SecretKey is required when backup or bootstrap is enabled" .Values.backup.s3SecretKey | quote }} +{{- end }} diff --git a/packages/apps/mongodb/templates/credentials.yaml b/packages/apps/mongodb/templates/credentials.yaml new file mode 100644 index 00000000..561f7672 --- /dev/null +++ b/packages/apps/mongodb/templates/credentials.yaml @@ -0,0 +1,34 @@ +{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} +{{- $operatorSecret := lookup "v1" "Secret" .Release.Namespace (printf "internal-%s-users" .Release.Name) }} +{{- $password := "" }} +{{- if and $operatorSecret (hasKey $operatorSecret.data "MONGODB_DATABASE_ADMIN_PASSWORD") }} +{{- $password = index $operatorSecret.data "MONGODB_DATABASE_ADMIN_PASSWORD" | b64dec }} +{{- end }} +--- +# Dashboard credentials - lookup from operator-created secret +# Operator creates secret named "internal--users" with system user passwords +# Note: On first install, password/uri will be empty until operator creates the secret. +# Run 'helm upgrade' after MongoDB is ready to populate credentials. +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-credentials +type: Opaque +stringData: + username: databaseAdmin + password: {{ $password | quote }} + {{- if .Values.sharding }} + host: {{ .Release.Name }}-mongos.{{ .Release.Namespace }}.svc.{{ $clusterDomain }} + {{- else }} + host: {{ .Release.Name }}-rs0.{{ .Release.Namespace }}.svc.{{ $clusterDomain }} + {{- end }} + port: "27017" + {{- if $password }} + {{- if .Values.sharding }} + uri: mongodb://databaseAdmin:{{ $password | urlquery }}@{{ .Release.Name }}-mongos.{{ .Release.Namespace }}.svc.{{ $clusterDomain }}:27017/admin + {{- else }} + uri: mongodb://databaseAdmin:{{ $password | urlquery }}@{{ .Release.Name }}-rs0.{{ .Release.Namespace }}.svc.{{ $clusterDomain }}:27017/admin?replicaSet=rs0 + {{- end }} + {{- else }} + uri: "" + {{- end }} diff --git a/packages/apps/mongodb/templates/dashboard-resourcemap.yaml b/packages/apps/mongodb/templates/dashboard-resourcemap.yaml new file mode 100644 index 00000000..33a6a4ef --- /dev/null +++ b/packages/apps/mongodb/templates/dashboard-resourcemap.yaml @@ -0,0 +1,39 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Release.Name }}-dashboard-resources +rules: +- apiGroups: + - "" + resources: + - services + resourceNames: + - {{ .Release.Name }}-rs0 + - {{ .Release.Name }}-mongos + - {{ .Release.Name }}-external + verbs: ["get", "list", "watch"] +- apiGroups: + - "" + resources: + - secrets + resourceNames: + - {{ .Release.Name }}-credentials + verbs: ["get", "list", "watch"] +- apiGroups: + - cozystack.io + resources: + - workloadmonitors + resourceNames: + - {{ .Release.Name }} + verbs: ["get", "list", "watch"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Release.Name }}-dashboard-resources +subjects: +{{ include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "use" .Release.Namespace) }} +roleRef: + kind: Role + name: {{ .Release.Name }}-dashboard-resources + apiGroup: rbac.authorization.k8s.io diff --git a/packages/apps/mongodb/templates/external-svc.yaml b/packages/apps/mongodb/templates/external-svc.yaml new file mode 100644 index 00000000..22324514 --- /dev/null +++ b/packages/apps/mongodb/templates/external-svc.yaml @@ -0,0 +1,24 @@ +{{- if .Values.external }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-external +spec: + type: LoadBalancer + externalTrafficPolicy: Local + {{- if (include "cozy-lib.network.disableLoadBalancerNodePorts" $ | fromYaml) }} + allocateLoadBalancerNodePorts: false + {{- end }} + ports: + - name: mongodb + port: 27017 + selector: + app.kubernetes.io/name: percona-server-mongodb + app.kubernetes.io/instance: {{ .Release.Name }} + {{- if .Values.sharding }} + app.kubernetes.io/component: mongos + {{- else }} + app.kubernetes.io/component: mongod + app.kubernetes.io/replset: rs0 + {{- end }} +{{- end }} diff --git a/packages/apps/mongodb/templates/mongodb.yaml b/packages/apps/mongodb/templates/mongodb.yaml new file mode 100644 index 00000000..67969758 --- /dev/null +++ b/packages/apps/mongodb/templates/mongodb.yaml @@ -0,0 +1,189 @@ +{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} +--- +apiVersion: psmdb.percona.com/v1 +kind: PerconaServerMongoDB +metadata: + name: {{ .Release.Name }} +spec: + crVersion: 1.21.1 + clusterServiceDNSSuffix: svc.{{ $clusterDomain }} + pause: false + unmanaged: false + image: percona/percona-server-mongodb:{{ include "mongodb.versionMap" $ }} + imagePullPolicy: IfNotPresent + + {{- if lt (int .Values.replicas) 3 }} + unsafeFlags: + replsetSize: true + {{- end }} + + updateStrategy: SmartUpdate + upgradeOptions: + apply: disabled + + pmm: + enabled: false + image: percona/pmm-client:2.44.1 + serverHost: "" + + sharding: + enabled: {{ .Values.sharding | default false }} + balancer: + enabled: true + {{- if .Values.sharding }} + configsvrReplSet: + size: {{ .Values.shardingConfig.configServers }} + resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 8 }} + volumeSpec: + persistentVolumeClaim: + {{- with .Values.storageClass }} + storageClassName: {{ . }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.shardingConfig.configServerSize }} + affinity: + antiAffinityTopologyKey: kubernetes.io/hostname + podDisruptionBudget: + maxUnavailable: 1 + mongos: + size: {{ .Values.shardingConfig.mongos }} + resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 8 }} + affinity: + antiAffinityTopologyKey: kubernetes.io/hostname + podDisruptionBudget: + maxUnavailable: 1 + expose: + exposeType: ClusterIP + {{- end }} + + replsets: + {{- if .Values.sharding }} + {{- range .Values.shardingConfig.shards }} + - name: {{ .name }} + size: {{ .replicas }} + resources: {{- include "cozy-lib.resources.defaultingSanitize" (list $.Values.resourcesPreset $.Values.resources $) | nindent 8 }} + volumeSpec: + persistentVolumeClaim: + {{- with $.Values.storageClass }} + storageClassName: {{ . }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .size }} + affinity: + antiAffinityTopologyKey: kubernetes.io/hostname + podDisruptionBudget: + maxUnavailable: 1 + {{- end }} + {{- else }} + - name: rs0 + size: {{ .Values.replicas }} + resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 8 }} + volumeSpec: + persistentVolumeClaim: + {{- with .Values.storageClass }} + storageClassName: {{ . }} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.size }} + affinity: + antiAffinityTopologyKey: kubernetes.io/hostname + podDisruptionBudget: + maxUnavailable: 1 + expose: + enabled: false + {{- end }} + + {{- if .Values.users }} + {{- /* Build a map of username -> list of roles from databases config */}} + {{- $userRoles := dict }} + {{- range $dbname, $db := .Values.databases }} + {{- range $user := $db.roles.admin }} + {{- $roles := index $userRoles $user | default list }} + {{- $roles = append $roles (dict "name" "readWrite" "db" $dbname) }} + {{- $roles = append $roles (dict "name" "dbAdmin" "db" $dbname) }} + {{- $_ := set $userRoles $user $roles }} + {{- end }} + {{- range $user := $db.roles.readonly }} + {{- $roles := index $userRoles $user | default list }} + {{- $roles = append $roles (dict "name" "read" "db" $dbname) }} + {{- $_ := set $userRoles $user $roles }} + {{- end }} + {{- end }} + users: + {{- range $username, $user := .Values.users }} + {{- $roles := index $userRoles $username }} + {{- if not $roles }} + {{- fail (printf "user '%s' is not assigned to any database role in databases.*.roles" $username) }} + {{- end }} + - name: {{ $username }} + db: admin + passwordSecretRef: + name: {{ $.Release.Name }}-user-{{ $username }} + key: password + roles: + {{- range $roles }} + - name: {{ .name }} + db: {{ .db }} + {{- end }} + {{- end }} + {{- end }} + + backup: + enabled: {{ .Values.backup.enabled | default false }} + image: percona/percona-backup-mongodb:2.11.0 + {{- if .Values.backup.enabled }} + storages: + s3-storage: + type: s3 + s3: + bucket: {{ .Values.backup.destinationPath | trimPrefix "s3://" | regexFind "^[^/]+" }} + prefix: {{ .Values.backup.destinationPath | trimPrefix "s3://" | splitList "/" | rest | join "/" }} + endpointUrl: {{ .Values.backup.endpointURL }} + credentialsSecret: {{ .Release.Name }}-s3-creds + insecureSkipTLSVerify: false + forcePathStyle: true + tasks: + - name: daily-backup + enabled: true + schedule: {{ .Values.backup.schedule | quote }} + keep: {{ .Values.backup.retentionPolicy | trimSuffix "d" | int }} + storageName: s3-storage + type: logical + compressionType: gzip + pitr: + enabled: true + {{- end }} +--- +# WorkloadMonitor tracks data-bearing mongod pods only (not config servers or mongos routers) +# The selector filters by component=mongod, so we only count shard replicas +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: {{ .Release.Name }} +spec: + {{- if .Values.sharding }} + {{- $totalReplicas := 0 }} + {{- range .Values.shardingConfig.shards }} + {{- $totalReplicas = add $totalReplicas .replicas }} + {{- end }} + replicas: {{ $totalReplicas }} + {{- else }} + replicas: {{ .Values.replicas }} + {{- end }} + minReplicas: 1 + kind: mongodb + type: mongodb + selector: + app.kubernetes.io/name: percona-server-mongodb + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: mongod + version: {{ .Chart.Version }} diff --git a/packages/apps/mongodb/templates/restore.yaml b/packages/apps/mongodb/templates/restore.yaml new file mode 100644 index 00000000..56e2150b --- /dev/null +++ b/packages/apps/mongodb/templates/restore.yaml @@ -0,0 +1,37 @@ +{{- if .Values.bootstrap.enabled }} +{{- if not .Values.bootstrap.backupName }} +{{- fail "bootstrap.backupName is required when bootstrap.enabled is true" }} +{{- end }} +{{- if not .Values.backup.destinationPath }} +{{- fail "backup.destinationPath is required when bootstrap.enabled is true" }} +{{- end }} +{{- if not .Values.backup.endpointURL }} +{{- fail "backup.endpointURL is required when bootstrap.enabled is true" }} +{{- end }} +{{- if not .Values.backup.s3AccessKey }} +{{- fail "backup.s3AccessKey is required when bootstrap.enabled is true" }} +{{- end }} +{{- if not .Values.backup.s3SecretKey }} +{{- fail "backup.s3SecretKey is required when bootstrap.enabled is true" }} +{{- end }} +--- +apiVersion: psmdb.percona.com/v1 +kind: PerconaServerMongoDBRestore +metadata: + name: {{ .Release.Name }}-restore +spec: + clusterName: {{ .Release.Name }} + {{- if .Values.bootstrap.recoveryTime }} + pitr: + type: date + date: {{ .Values.bootstrap.recoveryTime | quote }} + {{- end }} + backupSource: + type: logical + destination: {{ .Values.backup.destinationPath | trimSuffix "/" }}/{{ .Values.bootstrap.backupName }} + s3: + credentialsSecret: {{ .Release.Name }}-s3-creds + endpointUrl: {{ .Values.backup.endpointURL }} + insecureSkipTLSVerify: false + forcePathStyle: true +{{- end }} diff --git a/packages/apps/mongodb/templates/user-secrets.yaml b/packages/apps/mongodb/templates/user-secrets.yaml new file mode 100644 index 00000000..8212e95f --- /dev/null +++ b/packages/apps/mongodb/templates/user-secrets.yaml @@ -0,0 +1,17 @@ +{{- range $username, $user := .Values.users }} +{{- $existingSecret := lookup "v1" "Secret" $.Release.Namespace (printf "%s-user-%s" $.Release.Name $username) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $.Release.Name }}-user-{{ $username }} +type: Opaque +stringData: + {{- if $user.password }} + password: {{ $user.password | quote }} + {{- else if and $existingSecret (hasKey $existingSecret.data "password") }} + password: {{ index $existingSecret.data "password" | b64dec | quote }} + {{- else }} + password: {{ randAlphaNum 16 | quote }} + {{- end }} +{{- end }} diff --git a/packages/apps/mongodb/tests/backup-secret_test.yaml b/packages/apps/mongodb/tests/backup-secret_test.yaml new file mode 100644 index 00000000..f3eca410 --- /dev/null +++ b/packages/apps/mongodb/tests/backup-secret_test.yaml @@ -0,0 +1,112 @@ +suite: backup secret tests + +templates: + - templates/backup-secret.yaml + +tests: + # Not rendered when both backup and bootstrap disabled + - it: does not render when backup and bootstrap disabled + release: + name: test-mongodb + namespace: tenant-test + set: + backup: + enabled: false + bootstrap: + enabled: false + asserts: + - hasDocuments: + count: 0 + + # Rendered when backup enabled + - it: renders when backup enabled + release: + name: test-mongodb + namespace: tenant-test + set: + backup: + enabled: true + s3AccessKey: "AKIAIOSFODNN7EXAMPLE" + s3SecretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Secret + + # Rendered when bootstrap enabled (for restore) + - it: renders when bootstrap enabled + release: + name: test-mongodb + namespace: tenant-test + set: + backup: + enabled: false + s3AccessKey: "AKIAIOSFODNN7EXAMPLE" + s3SecretKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" + bootstrap: + enabled: true + asserts: + - hasDocuments: + count: 1 + + # Secret name + - it: uses correct secret name + release: + name: mydb + namespace: tenant-test + set: + backup: + enabled: true + s3AccessKey: "accesskey" + s3SecretKey: "secretkey" + asserts: + - equal: + path: metadata.name + value: mydb-s3-creds + + # Contains AWS credentials + - it: contains AWS credentials + release: + name: test-mongodb + namespace: tenant-test + set: + backup: + enabled: true + s3AccessKey: "MYACCESSKEY" + s3SecretKey: "MYSECRETKEY" + asserts: + - equal: + path: stringData.AWS_ACCESS_KEY_ID + value: "MYACCESSKEY" + - equal: + path: stringData.AWS_SECRET_ACCESS_KEY + value: "MYSECRETKEY" + + # Fails without s3AccessKey + - it: fails when s3AccessKey missing + release: + name: test-mongodb + namespace: tenant-test + set: + backup: + enabled: true + s3AccessKey: "" + s3SecretKey: "secretkey" + asserts: + - failedTemplate: + errorMessage: "backup.s3AccessKey is required when backup or bootstrap is enabled" + + # Fails without s3SecretKey + - it: fails when s3SecretKey missing + release: + name: test-mongodb + namespace: tenant-test + set: + backup: + enabled: true + s3AccessKey: "accesskey" + s3SecretKey: "" + asserts: + - failedTemplate: + errorMessage: "backup.s3SecretKey is required when backup or bootstrap is enabled" diff --git a/packages/apps/mongodb/tests/credentials_test.yaml b/packages/apps/mongodb/tests/credentials_test.yaml new file mode 100644 index 00000000..b06924ef --- /dev/null +++ b/packages/apps/mongodb/tests/credentials_test.yaml @@ -0,0 +1,132 @@ +suite: credentials tests + +templates: + - templates/credentials.yaml + +tests: + # Basic rendering + - it: always renders a Secret + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Secret + - equal: + path: metadata.name + value: test-mongodb-credentials + - equal: + path: type + value: Opaque + + # Username is always databaseAdmin + - it: sets username to databaseAdmin + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: stringData.username + value: databaseAdmin + + # Port is always 27017 + - it: sets port to 27017 + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: stringData.port + value: "27017" + + # Host for replica set mode + - it: uses rs0 service for replica set mode + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: false + asserts: + - equal: + path: stringData.host + value: test-mongodb-rs0.tenant-test.svc.cozy.local + + # Host for sharded mode + - it: uses mongos service for sharded mode + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: true + asserts: + - equal: + path: stringData.host + value: test-mongodb-mongos.tenant-test.svc.cozy.local + + # Custom cluster domain + - it: uses custom cluster domain + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: custom.domain + sharding: false + asserts: + - equal: + path: stringData.host + value: test-mongodb-rs0.tenant-test.svc.custom.domain + + # Default cluster domain when not set + - it: defaults to cozy.local when cluster domain not set + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: {} + sharding: false + asserts: + - equal: + path: stringData.host + value: test-mongodb-rs0.tenant-test.svc.cozy.local + + # Password empty without operator secret (lookup returns nil in tests) + - it: has empty password on first install + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: stringData.password + value: "" + + # URI empty without password + - it: has empty uri when password not available + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: stringData.uri + value: "" diff --git a/packages/apps/mongodb/tests/dashboard-resourcemap_test.yaml b/packages/apps/mongodb/tests/dashboard-resourcemap_test.yaml new file mode 100644 index 00000000..8cc1a0a7 --- /dev/null +++ b/packages/apps/mongodb/tests/dashboard-resourcemap_test.yaml @@ -0,0 +1,106 @@ +suite: dashboard resourcemap tests + +templates: + - templates/dashboard-resourcemap.yaml + +tests: + # Always renders Role and RoleBinding + - it: renders Role and RoleBinding + release: + name: test-mongodb + namespace: tenant-test + asserts: + - hasDocuments: + count: 2 + - isKind: + of: Role + documentIndex: 0 + - isKind: + of: RoleBinding + documentIndex: 1 + + # Role naming + - it: uses correct Role name + release: + name: mydb + namespace: tenant-test + asserts: + - equal: + path: metadata.name + value: mydb-dashboard-resources + documentIndex: 0 + + # RoleBinding naming + - it: uses correct RoleBinding name + release: + name: mydb + namespace: tenant-test + asserts: + - equal: + path: metadata.name + value: mydb-dashboard-resources + documentIndex: 1 + + # Role grants access to services + - it: grants access to MongoDB services + release: + name: test-mongodb + namespace: tenant-test + asserts: + - contains: + path: rules[0].resourceNames + content: test-mongodb-rs0 + documentIndex: 0 + - contains: + path: rules[0].resourceNames + content: test-mongodb-mongos + documentIndex: 0 + - contains: + path: rules[0].resourceNames + content: test-mongodb-external + documentIndex: 0 + + # Role grants access to credentials secret + - it: grants access to credentials secret + release: + name: test-mongodb + namespace: tenant-test + asserts: + - contains: + path: rules[1].resourceNames + content: test-mongodb-credentials + documentIndex: 0 + + # Role grants access to workloadmonitor + - it: grants access to WorkloadMonitor + release: + name: test-mongodb + namespace: tenant-test + asserts: + - contains: + path: rules[2].resourceNames + content: test-mongodb + documentIndex: 0 + - equal: + path: rules[2].apiGroups[0] + value: cozystack.io + documentIndex: 0 + + # RoleBinding references correct Role + - it: RoleBinding references correct Role + release: + name: test-mongodb + namespace: tenant-test + asserts: + - equal: + path: roleRef.kind + value: Role + documentIndex: 1 + - equal: + path: roleRef.name + value: test-mongodb-dashboard-resources + documentIndex: 1 + - equal: + path: roleRef.apiGroup + value: rbac.authorization.k8s.io + documentIndex: 1 diff --git a/packages/apps/mongodb/tests/external-svc_test.yaml b/packages/apps/mongodb/tests/external-svc_test.yaml new file mode 100644 index 00000000..ed3bf597 --- /dev/null +++ b/packages/apps/mongodb/tests/external-svc_test.yaml @@ -0,0 +1,154 @@ +suite: external service tests + +templates: + - templates/external-svc.yaml + +tests: + ################### + # Rendering # + ################### + + - it: does not render when external is false + release: + name: test-mongodb + namespace: tenant-test + set: + external: false + asserts: + - hasDocuments: + count: 0 + + - it: renders LoadBalancer service when external is true + release: + name: test-mongodb + namespace: tenant-test + set: + external: true + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Service + + ################### + # Service config # + ################### + + - it: uses correct service name + release: + name: mydb + namespace: tenant-test + set: + external: true + asserts: + - equal: + path: metadata.name + value: mydb-external + + - it: sets LoadBalancer type + release: + name: test-mongodb + namespace: tenant-test + set: + external: true + asserts: + - equal: + path: spec.type + value: LoadBalancer + + - it: sets externalTrafficPolicy to Local + release: + name: test-mongodb + namespace: tenant-test + set: + external: true + asserts: + - equal: + path: spec.externalTrafficPolicy + value: Local + + - it: exposes MongoDB port 27017 + release: + name: test-mongodb + namespace: tenant-test + set: + external: true + asserts: + - equal: + path: spec.ports[0].name + value: mongodb + - equal: + path: spec.ports[0].port + value: 27017 + + ########################### + # Common selector labels # + ########################### + + - it: sets app.kubernetes.io/name selector + release: + name: test-mongodb + namespace: tenant-test + set: + external: true + asserts: + - equal: + path: spec.selector["app.kubernetes.io/name"] + value: percona-server-mongodb + + - it: sets app.kubernetes.io/instance selector + release: + name: mydb + namespace: tenant-test + set: + external: true + asserts: + - equal: + path: spec.selector["app.kubernetes.io/instance"] + value: mydb + + ########################### + # Replica set mode # + ########################### + + - it: selects mongod for replica set mode + release: + name: test-mongodb + namespace: tenant-test + set: + external: true + sharding: false + asserts: + - equal: + path: spec.selector["app.kubernetes.io/component"] + value: mongod + - equal: + path: spec.selector["app.kubernetes.io/replset"] + value: rs0 + + ########################### + # Sharded mode # + ########################### + + - it: selects mongos for sharded mode + release: + name: test-mongodb + namespace: tenant-test + set: + external: true + sharding: true + asserts: + - equal: + path: spec.selector["app.kubernetes.io/component"] + value: mongos + + - it: does not set replset selector for sharded mode + release: + name: test-mongodb + namespace: tenant-test + set: + external: true + sharding: true + asserts: + - notExists: + path: spec.selector["app.kubernetes.io/replset"] diff --git a/packages/apps/mongodb/tests/mongodb_test.yaml b/packages/apps/mongodb/tests/mongodb_test.yaml new file mode 100644 index 00000000..4154ca25 --- /dev/null +++ b/packages/apps/mongodb/tests/mongodb_test.yaml @@ -0,0 +1,731 @@ +suite: mongodb CR tests + +templates: + - templates/mongodb.yaml + +tests: + ################### + # Basic rendering # + ################### + + - it: renders PerconaServerMongoDB and WorkloadMonitor + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - hasDocuments: + count: 2 + - isKind: + of: PerconaServerMongoDB + documentIndex: 0 + - isKind: + of: WorkloadMonitor + documentIndex: 1 + + - it: sets correct CR name + release: + name: my-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: metadata.name + value: my-mongodb + documentIndex: 0 + + ################## + # CR Version # + ################## + + - it: sets crVersion to 1.21.1 + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: spec.crVersion + value: "1.21.1" + documentIndex: 0 + + ##################### + # Cluster DNS # + ##################### + + - it: sets clusterServiceDNSSuffix from cluster config + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: custom.local + asserts: + - equal: + path: spec.clusterServiceDNSSuffix + value: svc.custom.local + documentIndex: 0 + + - it: defaults clusterServiceDNSSuffix to cozy.local + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: {} + asserts: + - equal: + path: spec.clusterServiceDNSSuffix + value: svc.cozy.local + documentIndex: 0 + + ################## + # Unsafe flags # + ################## + + - it: enables unsafeFlags when replicas is 1 + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + replicas: 1 + asserts: + - equal: + path: spec.unsafeFlags.replsetSize + value: true + documentIndex: 0 + + - it: enables unsafeFlags when replicas is 2 + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + replicas: 2 + asserts: + - equal: + path: spec.unsafeFlags.replsetSize + value: true + documentIndex: 0 + + - it: does not set unsafeFlags when replicas is 3 + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + replicas: 3 + asserts: + - notExists: + path: spec.unsafeFlags + documentIndex: 0 + + - it: does not set unsafeFlags when replicas is 5 + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + replicas: 5 + asserts: + - notExists: + path: spec.unsafeFlags + documentIndex: 0 + + ########################### + # Replica Set Mode # + ########################### + + - it: configures replica set rs0 in non-sharded mode + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: false + replicas: 3 + asserts: + - equal: + path: spec.sharding.enabled + value: false + documentIndex: 0 + - equal: + path: spec.replsets[0].name + value: rs0 + documentIndex: 0 + - equal: + path: spec.replsets[0].size + value: 3 + documentIndex: 0 + + - it: sets storage size for replica set + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: false + size: 20Gi + asserts: + - equal: + path: spec.replsets[0].volumeSpec.persistentVolumeClaim.resources.requests.storage + value: 20Gi + documentIndex: 0 + + - it: sets storageClass when provided + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: false + storageClass: fast-ssd + asserts: + - equal: + path: spec.replsets[0].volumeSpec.persistentVolumeClaim.storageClassName + value: fast-ssd + documentIndex: 0 + + - it: does not set storageClass when empty + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: false + storageClass: "" + asserts: + - notExists: + path: spec.replsets[0].volumeSpec.persistentVolumeClaim.storageClassName + documentIndex: 0 + + ########################### + # Sharded Cluster Mode # + ########################### + + - it: enables sharding when configured + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: true + shardingConfig: + configServers: 3 + configServerSize: 3Gi + mongos: 2 + shards: + - name: rs0 + replicas: 3 + size: 10Gi + asserts: + - equal: + path: spec.sharding.enabled + value: true + documentIndex: 0 + - equal: + path: spec.sharding.balancer.enabled + value: true + documentIndex: 0 + + - it: configures config servers + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: true + shardingConfig: + configServers: 5 + configServerSize: 5Gi + mongos: 2 + shards: + - name: rs0 + replicas: 3 + size: 10Gi + asserts: + - equal: + path: spec.sharding.configsvrReplSet.size + value: 5 + documentIndex: 0 + - equal: + path: spec.sharding.configsvrReplSet.volumeSpec.persistentVolumeClaim.resources.requests.storage + value: 5Gi + documentIndex: 0 + + - it: configures mongos routers + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: true + shardingConfig: + configServers: 3 + configServerSize: 3Gi + mongos: 4 + shards: + - name: rs0 + replicas: 3 + size: 10Gi + asserts: + - equal: + path: spec.sharding.mongos.size + value: 4 + documentIndex: 0 + - equal: + path: spec.sharding.mongos.expose.exposeType + value: ClusterIP + documentIndex: 0 + + - it: configures multiple shards + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: true + shardingConfig: + configServers: 3 + configServerSize: 3Gi + mongos: 2 + shards: + - name: shard1 + replicas: 3 + size: 50Gi + - name: shard2 + replicas: 5 + size: 100Gi + asserts: + - equal: + path: spec.replsets[0].name + value: shard1 + documentIndex: 0 + - equal: + path: spec.replsets[0].size + value: 3 + documentIndex: 0 + - equal: + path: spec.replsets[0].volumeSpec.persistentVolumeClaim.resources.requests.storage + value: 50Gi + documentIndex: 0 + - equal: + path: spec.replsets[1].name + value: shard2 + documentIndex: 0 + - equal: + path: spec.replsets[1].size + value: 5 + documentIndex: 0 + - equal: + path: spec.replsets[1].volumeSpec.persistentVolumeClaim.resources.requests.storage + value: 100Gi + documentIndex: 0 + + ########################### + # Users configuration # + ########################### + + - it: does not include users section when no users defined + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + users: {} + databases: {} + asserts: + - notExists: + path: spec.users + documentIndex: 0 + + - it: configures users with admin role + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + users: + appuser: {} + databases: + appdb: + roles: + admin: + - appuser + asserts: + - exists: + path: spec.users + documentIndex: 0 + - equal: + path: spec.users[0].name + value: appuser + documentIndex: 0 + - equal: + path: spec.users[0].db + value: admin + documentIndex: 0 + - equal: + path: spec.users[0].passwordSecretRef.name + value: test-mongodb-user-appuser + documentIndex: 0 + - equal: + path: spec.users[0].passwordSecretRef.key + value: password + documentIndex: 0 + + - it: assigns readWrite and dbAdmin roles for admin users + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + users: + appuser: {} + databases: + mydb: + roles: + admin: + - appuser + asserts: + - equal: + path: spec.users[0].roles[0].name + value: readWrite + documentIndex: 0 + - equal: + path: spec.users[0].roles[0].db + value: mydb + documentIndex: 0 + - equal: + path: spec.users[0].roles[1].name + value: dbAdmin + documentIndex: 0 + - equal: + path: spec.users[0].roles[1].db + value: mydb + documentIndex: 0 + + - it: assigns read role for readonly users + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + users: + reader: {} + databases: + mydb: + roles: + readonly: + - reader + asserts: + - equal: + path: spec.users[0].roles[0].name + value: read + documentIndex: 0 + - equal: + path: spec.users[0].roles[0].db + value: mydb + documentIndex: 0 + + - it: fails when user is not assigned to any database role + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + users: + myuser: {} + databases: {} + asserts: + - failedTemplate: + errorMessage: "user 'myuser' is not assigned to any database role in databases.*.roles" + + ########################### + # Backup configuration # + ########################### + + - it: disables backup when not enabled + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + backup: + enabled: false + asserts: + - equal: + path: spec.backup.enabled + value: false + documentIndex: 0 + - notExists: + path: spec.backup.storages + documentIndex: 0 + + - it: configures backup when enabled + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + backup: + enabled: true + schedule: "0 3 * * *" + retentionPolicy: 14d + destinationPath: "s3://mybucket/backups/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backup.enabled + value: true + documentIndex: 0 + - equal: + path: spec.backup.storages.s3-storage.type + value: s3 + documentIndex: 0 + + - it: parses bucket from destinationPath + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + backup: + enabled: true + destinationPath: "s3://my-backup-bucket/mongodb/prod/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backup.storages.s3-storage.s3.bucket + value: my-backup-bucket + documentIndex: 0 + + - it: parses prefix from destinationPath + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + backup: + enabled: true + destinationPath: "s3://bucket/path/to/backups/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backup.storages.s3-storage.s3.prefix + value: path/to/backups/ + documentIndex: 0 + + - it: sets backup retention from retentionPolicy + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + backup: + enabled: true + retentionPolicy: 30d + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backup.tasks[0].keep + value: 30 + documentIndex: 0 + + - it: sets backup schedule + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + backup: + enabled: true + schedule: "0 4 * * *" + retentionPolicy: 7d + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backup.tasks[0].schedule + value: "0 4 * * *" + documentIndex: 0 + + - it: enables PITR when backup enabled + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + backup: + enabled: true + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backup.pitr.enabled + value: true + documentIndex: 0 + + - it: references s3-creds secret for backup + release: + name: mydb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + backup: + enabled: true + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backup.storages.s3-storage.s3.credentialsSecret + value: mydb-s3-creds + documentIndex: 0 + + ########################### + # WorkloadMonitor # + ########################### + + - it: creates WorkloadMonitor with correct metadata + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: metadata.name + value: test-mongodb + documentIndex: 1 + - equal: + path: spec.kind + value: mongodb + documentIndex: 1 + - equal: + path: spec.type + value: mongodb + documentIndex: 1 + + - it: sets replicas from values in non-sharded mode + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: false + replicas: 5 + asserts: + - equal: + path: spec.replicas + value: 5 + documentIndex: 1 + + - it: calculates total replicas in sharded mode + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + sharding: true + shardingConfig: + configServers: 3 + configServerSize: 3Gi + mongos: 2 + shards: + - name: rs0 + replicas: 3 + size: 10Gi + - name: rs1 + replicas: 5 + size: 10Gi + - name: rs2 + replicas: 2 + size: 10Gi + asserts: + - equal: + path: spec.replicas + value: 10 + documentIndex: 1 + + - it: sets minReplicas to 1 + release: + name: test-mongodb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: spec.minReplicas + value: 1 + documentIndex: 1 + + - it: sets correct selector labels + release: + name: mydb + namespace: tenant-test + set: + _cluster: + cluster-domain: cozy.local + asserts: + - equal: + path: spec.selector["app.kubernetes.io/name"] + value: percona-server-mongodb + documentIndex: 1 + - equal: + path: spec.selector["app.kubernetes.io/instance"] + value: mydb + documentIndex: 1 + - equal: + path: spec.selector["app.kubernetes.io/component"] + value: mongod + documentIndex: 1 + diff --git a/packages/apps/mongodb/tests/restore_test.yaml b/packages/apps/mongodb/tests/restore_test.yaml new file mode 100644 index 00000000..e591587b --- /dev/null +++ b/packages/apps/mongodb/tests/restore_test.yaml @@ -0,0 +1,349 @@ +suite: restore tests + +templates: + - templates/restore.yaml + +tests: + ##################### + # Rendering # + ##################### + + - it: does not render when bootstrap is disabled + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: renders PerconaServerMongoDBRestore CR when enabled + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "my-backup-2025-01-07" + backup: + destinationPath: "s3://bucket/backups/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - hasDocuments: + count: 1 + - isKind: + of: PerconaServerMongoDBRestore + + ##################### + # Validation # + ##################### + + - it: fails when backupName is missing + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - failedTemplate: + errorMessage: "bootstrap.backupName is required when bootstrap.enabled is true" + + - it: fails when destinationPath is missing + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "my-backup" + backup: + destinationPath: "" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - failedTemplate: + errorMessage: "backup.destinationPath is required when bootstrap.enabled is true" + + - it: fails when endpointURL is missing + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "my-backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - failedTemplate: + errorMessage: "backup.endpointURL is required when bootstrap.enabled is true" + + ##################### + # CR metadata # + ##################### + + - it: uses correct restore CR name + release: + name: mydb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup-2025" + backup: + destinationPath: "s3://bucket/backups/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: metadata.name + value: mydb-restore + + - it: references correct cluster name + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup-2025" + backup: + destinationPath: "s3://bucket/backups/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.clusterName + value: test-mongodb + + ##################### + # Backup source # + ##################### + + - it: sets backupSource type to logical + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup-2025" + backup: + destinationPath: "s3://bucket/backups/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backupSource.type + value: logical + + - it: constructs destination from destinationPath and backupName + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "daily-backup-2025-01-07" + backup: + destinationPath: "s3://mybucket/mongodb/prod/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backupSource.destination + value: s3://mybucket/mongodb/prod/daily-backup-2025-01-07 + + - it: trims trailing slash from destinationPath + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backupSource.destination + value: s3://bucket/path/backup + + ##################### + # S3 configuration # + ##################### + + - it: references s3-creds secret + release: + name: mydb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backupSource.s3.credentialsSecret + value: mydb-s3-creds + + - it: sets S3 endpoint URL + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "https://s3.amazonaws.com" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backupSource.s3.endpointUrl + value: "https://s3.amazonaws.com" + + - it: disables insecureSkipTLSVerify + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backupSource.s3.insecureSkipTLSVerify + value: false + + - it: enables forcePathStyle + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.backupSource.s3.forcePathStyle + value: true + + ##################### + # PITR # + ##################### + + - it: does not set pitr when recoveryTime not specified + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - notExists: + path: spec.pitr + + - it: configures PITR when recoveryTime is set + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "my-backup" + recoveryTime: "2025-01-07 14:30:00" + backup: + destinationPath: "s3://bucket/backups/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "secret" + asserts: + - equal: + path: spec.pitr.type + value: date + - equal: + path: spec.pitr.date + value: "2025-01-07 14:30:00" + + ##################### + # S3 credentials # + ##################### + + - it: fails when s3AccessKey is missing + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "" + s3SecretKey: "secret" + asserts: + - failedTemplate: + errorMessage: "backup.s3AccessKey is required when bootstrap.enabled is true" + + - it: fails when s3SecretKey is missing + release: + name: test-mongodb + namespace: tenant-test + set: + bootstrap: + enabled: true + backupName: "backup" + backup: + destinationPath: "s3://bucket/path/" + endpointURL: "http://minio:9000" + s3AccessKey: "access" + s3SecretKey: "" + asserts: + - failedTemplate: + errorMessage: "backup.s3SecretKey is required when bootstrap.enabled is true" diff --git a/packages/apps/mongodb/tests/user-secrets_test.yaml b/packages/apps/mongodb/tests/user-secrets_test.yaml new file mode 100644 index 00000000..6d9fb388 --- /dev/null +++ b/packages/apps/mongodb/tests/user-secrets_test.yaml @@ -0,0 +1,78 @@ +suite: user secrets tests + +templates: + - templates/user-secrets.yaml + +tests: + # No users configured + - it: does not render when no users defined + release: + name: test-mongodb + namespace: tenant-test + set: + users: {} + asserts: + - hasDocuments: + count: 0 + + # Single user + - it: creates secret for single user + release: + name: test-mongodb + namespace: tenant-test + set: + users: + myuser: {} + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Secret + - equal: + path: metadata.name + value: test-mongodb-user-myuser + - equal: + path: type + value: Opaque + - exists: + path: stringData.password + + # Multiple users + - it: creates separate secrets for multiple users + release: + name: test-mongodb + namespace: tenant-test + set: + users: + user1: {} + user2: {} + asserts: + - hasDocuments: + count: 2 + + # User with explicit password + - it: uses explicit password when provided + release: + name: test-mongodb + namespace: tenant-test + set: + users: + myuser: + password: "mysecretpassword" + asserts: + - equal: + path: stringData.password + value: "mysecretpassword" + + # Secret naming convention + - it: follows naming convention release-user-username + release: + name: prod-db + namespace: tenant-prod + set: + users: + admin: {} + asserts: + - equal: + path: metadata.name + value: prod-db-user-admin diff --git a/packages/apps/mongodb/values.schema.json b/packages/apps/mongodb/values.schema.json new file mode 100644 index 00000000..3a66d60d --- /dev/null +++ b/packages/apps/mongodb/values.schema.json @@ -0,0 +1,290 @@ +{ + "title": "Chart Values", + "type": "object", + "properties": { + "backup": { + "description": "Backup configuration.", + "type": "object", + "default": {}, + "required": [ + "enabled" + ], + "properties": { + "destinationPath": { + "description": "Destination path for backups (e.g. s3://bucket/path/).", + "type": "string", + "default": "s3://bucket/path/to/folder/" + }, + "enabled": { + "description": "Enable regular backups.", + "type": "boolean", + "default": false + }, + "endpointURL": { + "description": "S3 endpoint URL for uploads.", + "type": "string", + "default": "http://minio-gateway-service:9000" + }, + "retentionPolicy": { + "description": "Retention policy (e.g. \"30d\").", + "type": "string", + "default": "30d" + }, + "s3AccessKey": { + "description": "Access key for S3 authentication.", + "type": "string", + "default": "" + }, + "s3SecretKey": { + "description": "Secret key for S3 authentication.", + "type": "string", + "default": "" + }, + "schedule": { + "description": "Cron schedule for automated backups.", + "type": "string", + "default": "0 2 * * *" + } + } + }, + "bootstrap": { + "description": "Bootstrap configuration.", + "type": "object", + "default": {}, + "required": [ + "backupName", + "enabled" + ], + "properties": { + "backupName": { + "description": "Name of backup to restore from.", + "type": "string", + "default": "" + }, + "enabled": { + "description": "Whether to restore from a backup.", + "type": "boolean", + "default": false + }, + "recoveryTime": { + "description": "Timestamp for point-in-time recovery; empty means latest.", + "type": "string", + "default": "" + } + } + }, + "databases": { + "description": "Databases configuration map.", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "roles": { + "description": "Roles assigned to users.", + "type": "object", + "properties": { + "admin": { + "description": "List of users with admin privileges (readWrite + dbAdmin).", + "type": "array", + "items": { + "type": "string" + } + }, + "readonly": { + "description": "List of users with read-only privileges.", + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, + "replicas": { + "description": "Number of MongoDB replicas in replica set.", + "type": "integer", + "default": 3 + }, + "resources": { + "description": "Explicit CPU and memory configuration for each MongoDB replica. When omitted, the preset defined in `resourcesPreset` is applied.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "CPU available to each replica.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory (RAM) available to each replica.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "resourcesPreset": { + "description": "Default sizing preset used when `resources` is omitted.", + "type": "string", + "default": "small", + "enum": [ + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] + }, + "sharding": { + "description": "Enable sharded cluster mode. When disabled, deploys a replica set.", + "type": "boolean", + "default": false + }, + "shardingConfig": { + "description": "Configuration for sharded cluster mode.", + "type": "object", + "default": {}, + "required": [ + "configServerSize", + "configServers", + "mongos" + ], + "properties": { + "configServerSize": { + "description": "PVC size for config servers.", + "default": "3Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "configServers": { + "description": "Number of config server replicas.", + "type": "integer", + "default": 3 + }, + "mongos": { + "description": "Number of mongos router replicas.", + "type": "integer", + "default": 2 + }, + "shards": { + "description": "List of shard configurations.", + "type": "array", + "default": [ + { + "name": "rs0", + "replicas": 3, + "size": "10Gi" + } + ], + "items": { + "type": "object", + "required": [ + "name", + "replicas", + "size" + ], + "properties": { + "name": { + "description": "Shard name.", + "type": "string" + }, + "replicas": { + "description": "Number of replicas in this shard.", + "type": "integer" + }, + "size": { + "description": "PVC size for this shard.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + } + } + } + }, + "size": { + "description": "Persistent Volume Claim size available for application data.", + "default": "10Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "storageClass": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "" + }, + "users": { + "description": "Users configuration map.", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "password": { + "description": "Password for the user (auto-generated if omitted).", + "type": "string" + } + } + } + }, + "version": { + "description": "MongoDB major version to deploy.", + "type": "string", + "default": "v8", + "enum": [ + "v8", + "v7", + "v6" + ] + } + } +} \ No newline at end of file diff --git a/packages/apps/mongodb/values.yaml b/packages/apps/mongodb/values.yaml new file mode 100644 index 00000000..df8fbe37 --- /dev/null +++ b/packages/apps/mongodb/values.yaml @@ -0,0 +1,146 @@ +## +## @section Common parameters +## + +## @typedef {struct} Resources - Explicit CPU and memory configuration for each MongoDB replica. +## @field {quantity} [cpu] - CPU available to each replica. +## @field {quantity} [memory] - Memory (RAM) available to each replica. + +## @enum {string} ResourcesPreset - Default sizing preset. +## @value nano +## @value micro +## @value small +## @value medium +## @value large +## @value xlarge +## @value 2xlarge + +## @param {int} replicas - Number of MongoDB replicas in replica set. +replicas: 3 + +## @param {Resources} [resources] - Explicit CPU and memory configuration for each MongoDB replica. When omitted, the preset defined in `resourcesPreset` is applied. +resources: {} + +## @param {ResourcesPreset} resourcesPreset="small" - Default sizing preset used when `resources` is omitted. +resourcesPreset: "small" + +## @param {quantity} size - Persistent Volume Claim size available for application data. +size: 10Gi + +## @param {string} storageClass - StorageClass used to store the data. +storageClass: "" + +## @param {bool} external - Enable external access from outside the cluster. +external: false + +## +## @enum {string} Version +## @value v8 +## @value v7 +## @value v6 + +## @param {Version} version - MongoDB major version to deploy. +version: v8 + +## +## @section Sharding configuration +## + +## @param {bool} sharding - Enable sharded cluster mode. When disabled, deploys a replica set. +sharding: false + +## @typedef {struct} ShardingConfig - Sharded cluster configuration. +## @field {int} configServers - Number of config server replicas. +## @field {quantity} configServerSize - PVC size for config servers. +## @field {int} mongos - Number of mongos router replicas. +## @field {[]Shard} shards - List of shard configurations. + +## @typedef {struct} Shard - Individual shard configuration. +## @field {string} name - Shard name. +## @field {int} replicas - Number of replicas in this shard. +## @field {quantity} size - PVC size for this shard. + +## @param {ShardingConfig} shardingConfig - Configuration for sharded cluster mode. +shardingConfig: + configServers: 3 + configServerSize: 3Gi + mongos: 2 + shards: + - name: rs0 + replicas: 3 + size: 10Gi + +## +## @section Users configuration +## + +## @typedef {struct} User - User configuration. +## @field {string} [password] - Password for the user (auto-generated if omitted). + +## @param {map[string]User} users - Users configuration map. +users: {} +## Example: +## users: +## user1: +## password: strongpassword +## user2: {} + +## +## @section Databases configuration +## + +## @typedef {struct} DatabaseRoles - Role assignments for a database. +## @field {[]string} [admin] - List of users with admin privileges (readWrite + dbAdmin). +## @field {[]string} [readonly] - List of users with read-only privileges. + +## @typedef {struct} Database - Database configuration. +## @field {DatabaseRoles} [roles] - Roles assigned to users. + +## @param {map[string]Database} databases - Databases configuration map. +databases: {} +## Example: +## databases: +## myapp: +## roles: +## admin: +## - user1 +## readonly: +## - user2 + +## +## @section Backup parameters +## + +## @typedef {struct} Backup - Backup configuration. +## @field {bool} enabled - Enable regular backups. +## @field {string} [schedule] - Cron schedule for automated backups. +## @field {string} [retentionPolicy] - Retention policy (e.g. "30d"). +## @field {string} [destinationPath] - Destination path for backups (e.g. s3://bucket/path/). +## @field {string} [endpointURL] - S3 endpoint URL for uploads. +## @field {string} [s3AccessKey] - Access key for S3 authentication. +## @field {string} [s3SecretKey] - Secret key for S3 authentication. + +## @param {Backup} backup - Backup configuration. +backup: + enabled: false + schedule: "0 2 * * *" + retentionPolicy: 30d + destinationPath: "s3://bucket/path/to/folder/" + endpointURL: "http://minio-gateway-service:9000" + s3AccessKey: "" + s3SecretKey: "" + +## +## @section Bootstrap (recovery) parameters +## + +## @typedef {struct} Bootstrap - Bootstrap configuration for restoring a database cluster from a backup. +## @field {bool} enabled - Whether to restore from a backup. +## @field {string} [recoveryTime] - Timestamp for point-in-time recovery; empty means latest. +## @field {string} backupName - Name of backup to restore from. + +## @param {Bootstrap} bootstrap - Bootstrap configuration. +bootstrap: + enabled: false + recoveryTime: "" + backupName: "" diff --git a/packages/apps/mysql/Makefile b/packages/apps/mysql/Makefile index f4ea3f78..e8f02703 100644 --- a/packages/apps/mysql/Makefile +++ b/packages/apps/mysql/Makefile @@ -1,7 +1,7 @@ MARIADB_BACKUP_TAG = $(shell awk '$$1 == "version:" {print $$2}' Chart.yaml) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/mysql/images/mariadb-backup.tag b/packages/apps/mysql/images/mariadb-backup.tag index af6247da..1e381661 100644 --- a/packages/apps/mysql/images/mariadb-backup.tag +++ b/packages/apps/mysql/images/mariadb-backup.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/mariadb-backup:0.0.0@sha256:1c0beb1b23a109b0e13727b4c73d2c74830e11cede92858ab20101b66f45a858 +ghcr.io/cozystack/cozystack/mariadb-backup:0.0.0@sha256:0ddbbec0568dcb9fbc317cd9cc654e826dbe88ba3f184fa9b6b58aacb93b4570 diff --git a/packages/apps/nats/Makefile b/packages/apps/nats/Makefile index 8b1dce9d..d1cfda8e 100644 --- a/packages/apps/nats/Makefile +++ b/packages/apps/nats/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/nats/templates/nats.yaml b/packages/apps/nats/templates/nats.yaml index 3e858fd5..4f52ff11 100644 --- a/packages/apps/nats/templates/nats.yaml +++ b/packages/apps/nats/templates/nats.yaml @@ -33,16 +33,13 @@ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: {{ .Release.Name }}-system + labels: + sharding.fluxcd.io/key: tenants spec: - chart: - spec: - chart: cozy-nats - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-nats-application-default-nats-system + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/apps/postgres/Makefile b/packages/apps/postgres/Makefile index a2ba188f..aa9b0ccc 100644 --- a/packages/apps/postgres/Makefile +++ b/packages/apps/postgres/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/rabbitmq/Makefile b/packages/apps/rabbitmq/Makefile index 8b1dce9d..d1cfda8e 100644 --- a/packages/apps/rabbitmq/Makefile +++ b/packages/apps/rabbitmq/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/redis/Makefile b/packages/apps/redis/Makefile index a2ba188f..aa9b0ccc 100644 --- a/packages/apps/redis/Makefile +++ b/packages/apps/redis/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/tcp-balancer/Makefile b/packages/apps/tcp-balancer/Makefile index 8b1dce9d..d1cfda8e 100644 --- a/packages/apps/tcp-balancer/Makefile +++ b/packages/apps/tcp-balancer/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/tenant/Makefile b/packages/apps/tenant/Makefile index 8b1dce9d..d1cfda8e 100644 --- a/packages/apps/tenant/Makefile +++ b/packages/apps/tenant/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/tenant/README.md b/packages/apps/tenant/README.md index 222c98a5..99a973c7 100644 --- a/packages/apps/tenant/README.md +++ b/packages/apps/tenant/README.md @@ -76,6 +76,36 @@ tenant-u1 | `monitoring` | Deploy own Monitoring Stack. | `bool` | `false` | | `ingress` | Deploy own Ingress Controller. | `bool` | `false` | | `seaweedfs` | Deploy own SeaweedFS. | `bool` | `false` | -| `isolated` | Enforce tenant namespace with network policies (default: true). | `bool` | `true` | | `resourceQuotas` | Define resource quotas for the tenant. | `map[string]quantity` | `{}` | + +## Configuration + +### Resource Quotas + +The `resourceQuotas` parameter allows you to limit resources available to the tenant. Supported keys include: + +**Compute resources** (converted to `requests.X` and `limits.X`): +- `cpu` - Total CPU cores (e.g., `"4"` or `"500m"`) +- `memory` - Total memory (e.g., `"4Gi"` or `"512Mi"`) +- `ephemeral-storage` - Ephemeral storage limit (e.g., `"10Gi"`) +- `storage` - Total persistent storage (e.g., `"100Gi"`) + +**Object count quotas** (passed as-is): +- `pods` - Maximum number of pods +- `services` - Maximum number of services +- `services.loadbalancers` - Maximum number of LoadBalancer services +- `services.nodeports` - Maximum number of NodePort services +- `configmaps` - Maximum number of ConfigMaps +- `secrets` - Maximum number of Secrets +- `persistentvolumeclaims` - Maximum number of PVCs + +**Example:** +```yaml +resourceQuotas: + cpu: 4 + memory: 4Gi + storage: 10Gi + services.loadbalancers: "3" + pods: "50" +``` diff --git a/packages/apps/tenant/templates/cleanup-job.yaml b/packages/apps/tenant/templates/cleanup-job.yaml index 9b2f2c50..0f13daa4 100644 --- a/packages/apps/tenant/templates/cleanup-job.yaml +++ b/packages/apps/tenant/templates/cleanup-job.yaml @@ -74,12 +74,12 @@ spec: echo "Deleting Applications" kubectl delete helmreleases.helm.toolkit.fluxcd.io -n "$NAMESPACE" \ - -l 'cozystack.io/ui=true,internal.cozystack.io/tenantmodule!=true' \ + -l 'apps.cozystack.io/application.kind,internal.cozystack.io/tenantmodule!=true' \ --ignore-not-found=true --wait=true - + echo "Deleting Tenant Modules" kubectl delete helmreleases.helm.toolkit.fluxcd.io -n "$NAMESPACE" \ - -l 'cozystack.io/ui=true,internal.cozystack.io/tenantmodule=true' \ + -l 'apps.cozystack.io/application.kind,internal.cozystack.io/tenantmodule=true' \ --ignore-not-found=true --wait=true echo "Cleanup completed successfully" diff --git a/packages/apps/tenant/templates/etcd.yaml b/packages/apps/tenant/templates/etcd.yaml index e67ab597..97b39205 100644 --- a/packages/apps/tenant/templates/etcd.yaml +++ b/packages/apps/tenant/templates/etcd.yaml @@ -5,7 +5,7 @@ metadata: name: etcd namespace: {{ include "tenant.name" . }} labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} @@ -13,15 +13,10 @@ metadata: apps.cozystack.io/application.group: apps.cozystack.io apps.cozystack.io/application.name: etcd spec: - chart: - spec: - chart: etcd - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-etcd-application-default-etcd + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/apps/tenant/templates/info.yaml b/packages/apps/tenant/templates/info.yaml index efa01b87..520028c1 100644 --- a/packages/apps/tenant/templates/info.yaml +++ b/packages/apps/tenant/templates/info.yaml @@ -4,7 +4,7 @@ metadata: name: info namespace: {{ include "tenant.name" . }} labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} @@ -12,15 +12,10 @@ metadata: apps.cozystack.io/application.group: apps.cozystack.io apps.cozystack.io/application.name: info spec: - chart: - spec: - chart: info - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-info-application-default-info + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/apps/tenant/templates/ingress.yaml b/packages/apps/tenant/templates/ingress.yaml index 6e870043..1899a4da 100644 --- a/packages/apps/tenant/templates/ingress.yaml +++ b/packages/apps/tenant/templates/ingress.yaml @@ -5,7 +5,7 @@ metadata: name: ingress namespace: {{ include "tenant.name" . }} labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} @@ -13,15 +13,10 @@ metadata: apps.cozystack.io/application.group: apps.cozystack.io apps.cozystack.io/application.name: ingress spec: - chart: - spec: - chart: ingress - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-ingress-application-default-ingress + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/apps/tenant/templates/monitoring.yaml b/packages/apps/tenant/templates/monitoring.yaml index 625670e9..4d77faa6 100644 --- a/packages/apps/tenant/templates/monitoring.yaml +++ b/packages/apps/tenant/templates/monitoring.yaml @@ -5,7 +5,7 @@ metadata: name: monitoring namespace: {{ include "tenant.name" . }} labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} @@ -13,15 +13,10 @@ metadata: apps.cozystack.io/application.group: apps.cozystack.io apps.cozystack.io/application.name: monitoring spec: - chart: - spec: - chart: monitoring - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-monitoring-application-default-monitoring + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/apps/tenant/templates/networkpolicy.yaml b/packages/apps/tenant/templates/networkpolicy.yaml index 2c15a877..d9f87856 100644 --- a/packages/apps/tenant/templates/networkpolicy.yaml +++ b/packages/apps/tenant/templates/networkpolicy.yaml @@ -1,4 +1,3 @@ -{{- if .Values.isolated }} --- apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy @@ -220,4 +219,3 @@ spec: - toEndpoints: - matchLabels: cozystack.io/service: ingress -{{- end }} diff --git a/packages/apps/tenant/templates/seaweedfs.yaml b/packages/apps/tenant/templates/seaweedfs.yaml index ff0db1e4..e0002ec9 100644 --- a/packages/apps/tenant/templates/seaweedfs.yaml +++ b/packages/apps/tenant/templates/seaweedfs.yaml @@ -5,7 +5,7 @@ metadata: name: seaweedfs namespace: {{ include "tenant.name" . }} labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} @@ -13,15 +13,10 @@ metadata: apps.cozystack.io/application.group: apps.cozystack.io apps.cozystack.io/application.name: seaweedfs spec: - chart: - spec: - chart: seaweedfs - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-seaweedfs-application-default-seaweedfs + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/apps/tenant/values.schema.json b/packages/apps/tenant/values.schema.json index 7690e2b4..2c3d5f89 100644 --- a/packages/apps/tenant/values.schema.json +++ b/packages/apps/tenant/values.schema.json @@ -17,11 +17,6 @@ "type": "boolean", "default": false }, - "isolated": { - "description": "Enforce tenant namespace with network policies (default: true).", - "type": "boolean", - "default": true - }, "monitoring": { "description": "Deploy own Monitoring Stack.", "type": "boolean", diff --git a/packages/apps/tenant/values.yaml b/packages/apps/tenant/values.yaml index 4543bb6b..58bb451f 100644 --- a/packages/apps/tenant/values.yaml +++ b/packages/apps/tenant/values.yaml @@ -17,8 +17,5 @@ ingress: false ## @param {bool} seaweedfs - Deploy own SeaweedFS. seaweedfs: false -## @param {bool} isolated - Enforce tenant namespace with network policies (default: true). -isolated: true - ## @param {map[string]quantity} resourceQuotas - Define resource quotas for the tenant. resourceQuotas: {} diff --git a/packages/apps/virtual-machine/Makefile b/packages/apps/virtual-machine/Makefile index b70ac622..7c482228 100644 --- a/packages/apps/virtual-machine/Makefile +++ b/packages/apps/virtual-machine/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/virtual-machine/templates/vm-update-hook.yaml b/packages/apps/virtual-machine/templates/vm-update-hook.yaml index 1197c027..3c7d7d34 100644 --- a/packages/apps/virtual-machine/templates/vm-update-hook.yaml +++ b/packages/apps/virtual-machine/templates/vm-update-hook.yaml @@ -3,14 +3,17 @@ {{- $existingVM := lookup "kubevirt.io/v1" "VirtualMachine" $namespace $vmName -}} {{- $existingPVC := lookup "v1" "PersistentVolumeClaim" $namespace $vmName -}} +{{- $existingService := lookup "v1" "Service" $namespace $vmName -}} {{- $instanceType := .Values.instanceType | default "" -}} {{- $instanceProfile := .Values.instanceProfile | default "" -}} {{- $desiredStorage := .Values.systemDisk.storage | default "" -}} +{{- $desiredServiceType := ternary "LoadBalancer" "ClusterIP" .Values.external -}} {{- $needUpdateType := false -}} {{- $needUpdateProfile := false -}} {{- $needResizePVC := false -}} +{{- $needRecreateService := false -}} {{- if and $existingVM $instanceType -}} {{- if not (eq $existingVM.spec.instancetype.name $instanceType) -}} @@ -35,7 +38,14 @@ {{- end -}} {{- end -}} -{{- if or $needUpdateType $needUpdateProfile $needResizePVC }} +{{- if $existingService -}} + {{- $currentServiceType := $existingService.spec.type -}} + {{- if ne $currentServiceType $desiredServiceType -}} + {{- $needRecreateService = true -}} + {{- end -}} +{{- end -}} + +{{- if or $needUpdateType $needUpdateProfile $needResizePVC $needRecreateService }} apiVersion: batch/v1 kind: Job metadata: @@ -86,6 +96,11 @@ spec: --type merge \ -p '{"spec":{"resources":{"requests":{"storage":"{{ $desiredStorage }}"}}}}' {{- end }} + + {{- if $needRecreateService }} + echo "Removing Service..." + kubectl delete service --cascade=orphan -n {{ $namespace }} {{ $vmName }} + {{- end }} --- apiVersion: v1 kind: ServiceAccount @@ -111,6 +126,10 @@ rules: - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["patch", "get", "list", "watch"] + - apiGroups: [""] + resources: ["services"] + resourceNames: ["{{ $vmName }}"] + verbs: ["delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/packages/apps/vm-disk/Makefile b/packages/apps/vm-disk/Makefile index 8b1dce9d..d1cfda8e 100644 --- a/packages/apps/vm-disk/Makefile +++ b/packages/apps/vm-disk/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/vm-instance/Makefile b/packages/apps/vm-instance/Makefile index 105ca7db..3b6d471d 100644 --- a/packages/apps/vm-instance/Makefile +++ b/packages/apps/vm-instance/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/vpc/Makefile b/packages/apps/vpc/Makefile index 8807454f..ea4f5d1b 100644 --- a/packages/apps/vpc/Makefile +++ b/packages/apps/vpc/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json diff --git a/packages/apps/vpn/Makefile b/packages/apps/vpn/Makefile index 8b1dce9d..d1cfda8e 100644 --- a/packages/apps/vpn/Makefile +++ b/packages/apps/vpn/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/core/flux-aio/Makefile b/packages/core/flux-aio/Makefile index 2b3c1408..c5eb27f9 100644 --- a/packages/core/flux-aio/Makefile +++ b/packages/core/flux-aio/Makefile @@ -1,7 +1,7 @@ NAME=flux-aio NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk +include ../../../hack/common-envs.mk show: cozyhr show -n $(NAMESPACE) $(NAME) --plain @@ -12,23 +12,13 @@ apply: diff: cozyhr show -n $(NAMESPACE) $(NAME) --plain | kubectl diff -f- -update: update-old update-new +MANIFESTS_DIR=../../../internal/fluxinstall/manifests -# TODO: remove old manifest after migration to cozystack-operator -update-old: - timoni bundle build -f flux-aio.cue > templates/fluxcd.yaml - yq eval '(select(.kind == "Namespace") | .metadata.labels."pod-security.kubernetes.io/enforce") = "privileged"' -i templates/fluxcd.yaml - sed -i templates/fluxcd.yaml \ +update: + timoni bundle build -f flux-aio.cue > $(MANIFESTS_DIR)/fluxcd.yaml + yq eval '(select(.kind == "Namespace") | .metadata.labels."pod-security.kubernetes.io/enforce") = "privileged"' -i $(MANIFESTS_DIR)/fluxcd.yaml + sed -i $(MANIFESTS_DIR)/fluxcd.yaml \ -e '/timoni/d' \ -e 's|\.cluster\.local\.,||g' -e 's|\.cluster\.local\,||g' -e 's|\.cluster\.local\.||g' \ - -e '/value: .svc/a \ {{- include "cozy.kubernetes_envs" . | nindent 12 }}' \ - -e '/hostNetwork: true/i \ dnsPolicy: ClusterFirstWithHostNet' - -update-new: - timoni bundle build -f flux-aio.cue > ../../../internal/fluxinstall/manifests/fluxcd.yaml - yq eval '(select(.kind == "Namespace") | .metadata.labels."pod-security.kubernetes.io/enforce") = "privileged"' -i ../../../internal/fluxinstall/manifests/fluxcd.yaml - sed -i ../../../internal/fluxinstall/manifests/fluxcd.yaml \ - -e '/timoni/d' \ - -e 's|\.cluster\.local\.,||g' -e 's|\.cluster\.local\,||g' -e 's|\.cluster\.local\.||g' - # TODO: solve dns issue with hostNetwork for installing helmreleases in tenant k8s clusters - #-e '/hostNetwork: true/i \ dnsPolicy: ClusterFirstWithHostNet' + -e 's|--storage-adv-addr=source-watcher.$$(RUNTIME_NAMESPACE).svc|--storage-adv-addr=flux.$$(RUNTIME_NAMESPACE).svc|' + yq eval '.spec.template.spec.containers[0].image = "'"$$(yq eval 'select(.kind == "Deployment" and .metadata.name == "flux") | .spec.template.spec.containers[] | select(.name == "helm-controller").image' $(MANIFESTS_DIR)/fluxcd.yaml)"'"' -i $(MANIFESTS_DIR)/fluxcd-tenants.yaml diff --git a/packages/core/flux-aio/flux-aio.cue b/packages/core/flux-aio/flux-aio.cue index 8c067c3b..e47d20aa 100644 --- a/packages/core/flux-aio/flux-aio.cue +++ b/packages/core/flux-aio/flux-aio.cue @@ -10,6 +10,19 @@ bundle: { namespace: "cozy-fluxcd" values: { securityProfile: "privileged" + tolerations: [{ + operator: "Exists" + key: "node.kubernetes.io/not-ready" + }, { + operator: "Exists" + key: "node.kubernetes.io/unreachable" + }, { + operator: "Exists" + key: "node.cilium.io/agent-not-ready" + }, { + operator: "Exists" + key: "node.cloudprovider.kubernetes.io/uninitialized" + }] } } } diff --git a/packages/core/flux-aio/manifests b/packages/core/flux-aio/manifests new file mode 120000 index 00000000..f9bb5aad --- /dev/null +++ b/packages/core/flux-aio/manifests @@ -0,0 +1 @@ +../../../internal/fluxinstall/manifests \ No newline at end of file diff --git a/packages/core/flux-aio/templates/_helpers.tpl b/packages/core/flux-aio/templates/_helpers.tpl deleted file mode 100644 index e22979ba..00000000 --- a/packages/core/flux-aio/templates/_helpers.tpl +++ /dev/null @@ -1,13 +0,0 @@ -{{- define "cozy.kubernetes_envs" }} -{{- $cozyDeployment := lookup "apps/v1" "Deployment" "cozy-system" "cozystack" }} -{{- $cozyContainers := dig "spec" "template" "spec" "containers" dict $cozyDeployment }} -{{- range $cozyContainers }} -{{- if eq .name "cozystack" }} -{{- range .env }} -{{- if has .name (list "KUBERNETES_SERVICE_HOST" "KUBERNETES_SERVICE_PORT") }} -- {{ toJson . }} -{{- end }} -{{- end }} -{{- end }} -{{- end }} -{{- end }} diff --git a/packages/core/flux-aio/templates/fluxcd.yaml b/packages/core/flux-aio/templates/fluxcd.yaml deleted file mode 100644 index 71a354c6..00000000 --- a/packages/core/flux-aio/templates/fluxcd.yaml +++ /dev/null @@ -1,11957 +0,0 @@ ---- -# Instance: flux ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: alerts.notification.toolkit.fluxcd.io -spec: - group: notification.toolkit.fluxcd.io - names: - kind: Alert - listKind: AlertList - plural: alerts - singular: alert - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v1beta2 Alert is deprecated, upgrade to v1beta3 - name: v1beta2 - schema: - openAPIV3Schema: - description: Alert is the Schema for the alerts 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: AlertSpec defines an alerting rule for events involving a list of objects. - properties: - eventMetadata: - additionalProperties: - type: string - description: |- - EventMetadata is an optional field for adding metadata to events dispatched by the - controller. This can be used for enhancing the context of the event. If a field - would override one already present on the original event as generated by the emitter, - then the override doesn't happen, i.e. the original value is preserved, and an info - log is printed. - type: object - eventSeverity: - default: info - description: |- - EventSeverity specifies how to filter events based on severity. - If set to 'info' no events will be filtered. - enum: - - info - - error - type: string - eventSources: - description: |- - EventSources specifies how to filter events based - on the involved object kind, name and namespace. - items: - description: |- - CrossNamespaceObjectReference contains enough information to let you locate the - typed referenced object at cluster level - properties: - apiVersion: - description: API version of the referent - type: string - kind: - description: Kind of the referent - enum: - - Bucket - - GitRepository - - Kustomization - - HelmRelease - - HelmChart - - HelmRepository - - ImageRepository - - ImagePolicy - - ImageUpdateAutomation - - OCIRepository - type: string - 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. - MatchLabels requires the name to be set to `*`. - type: object - name: - description: |- - Name of the referent - If multiple resources are targeted `*` may be set. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace of the referent - maxLength: 253 - minLength: 1 - type: string - required: - - kind - - name - type: object - type: array - exclusionList: - description: |- - ExclusionList specifies a list of Golang regular expressions - to be used for excluding messages. - items: - type: string - type: array - inclusionList: - description: |- - InclusionList specifies a list of Golang regular expressions - to be used for including messages. - items: - type: string - type: array - providerRef: - description: ProviderRef specifies which Provider this Alert should use. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - summary: - description: Summary holds a short description of the impact and affected cluster. - maxLength: 255 - type: string - suspend: - description: |- - Suspend tells the controller to suspend subsequent - events handling for this Alert. - type: boolean - required: - - eventSources - - providerRef - type: object - status: - default: - observedGeneration: -1 - description: AlertStatus defines the observed state of the Alert. - properties: - conditions: - description: Conditions holds the conditions for the Alert. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta3 - schema: - openAPIV3Schema: - description: Alert is the Schema for the alerts 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: AlertSpec defines an alerting rule for events involving a list of objects. - properties: - eventMetadata: - additionalProperties: - type: string - description: |- - EventMetadata is an optional field for adding metadata to events dispatched by the - controller. This can be used for enhancing the context of the event. If a field - would override one already present on the original event as generated by the emitter, - then the override doesn't happen, i.e. the original value is preserved, and an info - log is printed. - type: object - eventSeverity: - default: info - description: |- - EventSeverity specifies how to filter events based on severity. - If set to 'info' no events will be filtered. - enum: - - info - - error - type: string - eventSources: - description: |- - EventSources specifies how to filter events based - on the involved object kind, name and namespace. - items: - description: |- - CrossNamespaceObjectReference contains enough information to let you locate the - typed referenced object at cluster level - properties: - apiVersion: - description: API version of the referent - type: string - kind: - description: Kind of the referent - enum: - - Bucket - - GitRepository - - Kustomization - - HelmRelease - - HelmChart - - HelmRepository - - ImageRepository - - ImagePolicy - - ImageUpdateAutomation - - OCIRepository - type: string - 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. - MatchLabels requires the name to be set to `*`. - type: object - name: - description: |- - Name of the referent - If multiple resources are targeted `*` may be set. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace of the referent - maxLength: 253 - minLength: 1 - type: string - required: - - kind - - name - type: object - type: array - exclusionList: - description: |- - ExclusionList specifies a list of Golang regular expressions - to be used for excluding messages. - items: - type: string - type: array - inclusionList: - description: |- - InclusionList specifies a list of Golang regular expressions - to be used for including messages. - items: - type: string - type: array - providerRef: - description: ProviderRef specifies which Provider this Alert should use. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - summary: - description: |- - Summary holds a short description of the impact and affected cluster. - Deprecated: Use EventMetadata instead. - maxLength: 255 - type: string - suspend: - description: |- - Suspend tells the controller to suspend subsequent - events handling for this Alert. - type: boolean - required: - - eventSources - - providerRef - type: object - type: object - served: true - storage: true - subresources: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: artifactgenerators.source.extensions.fluxcd.io -spec: - group: source.extensions.fluxcd.io - names: - kind: ArtifactGenerator - listKind: ArtifactGeneratorList - plural: artifactgenerators - shortNames: - - ag - singular: artifactgenerator - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: ArtifactGenerator is the Schema for the artifactgenerators 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: ArtifactGeneratorSpec defines the desired state of ArtifactGenerator. - properties: - artifacts: - description: OutputArtifacts is a list of output artifacts to be generated. - items: - description: |- - OutputArtifact defines the desired state of an ExternalArtifact - generated by the ArtifactGenerator. - properties: - copy: - description: |- - Copy defines a list of copy operations to perform from the sources to the generated artifact. - The copy operations are performed in the order they are listed with existing files - being overwritten by later copy operations. - items: - properties: - exclude: - description: |- - Exclude specifies a list of glob patterns to exclude - files and dirs matched by the 'From' field. - items: - type: string - maxItems: 100 - type: array - from: - description: |- - From specifies the source (by alias) and the glob pattern to match files. - The format is "@/". - maxLength: 1024 - pattern: ^@([a-z0-9]([a-z0-9_-]*[a-z0-9])?)/(.*)$ - type: string - strategy: - description: |- - Strategy specifies the copy strategy to use. - 'Overwrite' will overwrite existing files in the destination. - 'Merge' is for merging YAML files using Helm values merge strategy. - If not specified, defaults to 'Overwrite'. - enum: - - Overwrite - - Merge - type: string - to: - description: |- - To specifies the destination path within the artifact. - The format is "@artifact/path", the alias "artifact" - refers to the root path of the generated artifact. - maxLength: 1024 - pattern: ^@(artifact)/(.*)$ - type: string - required: - - from - - to - type: object - minItems: 1 - type: array - name: - description: Name is the name of the generated artifact. - maxLength: 253 - pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ - type: string - originRevision: - description: |- - OriginRevision is used to set the 'org.opencontainers.image.revision' - annotation on the generated artifact metadata. - If specified, it must point to an existing source alias in the format "@". - If the referenced source has an origin revision (e.g. a Git commit SHA), - it will be used to set the annotation on the generated artifact. - If the referenced source does not have an origin revision, the field is ignored. - maxLength: 64 - pattern: ^@([a-z0-9]([a-z0-9_-]*[a-z0-9])?)$ - type: string - revision: - description: |- - Revision is the revision of the generated artifact. - If specified, it must point to an existing source alias in the format "@". - If not specified, the revision is automatically set to the digest of the artifact content. - maxLength: 64 - pattern: ^@([a-z0-9]([a-z0-9_-]*[a-z0-9])?)$ - type: string - required: - - copy - - name - type: object - maxItems: 1000 - minItems: 1 - type: array - sources: - description: |- - Sources is a list of references to the Flux source-controller - resources that will be used to generate the artifact. - items: - description: SourceReference contains the reference to a Flux source-controller resource. - properties: - alias: - description: |- - Alias of the source within the ArtifactGenerator context. - The alias must be unique per ArtifactGenerator, and must consist - of lower case alphanumeric characters, underscores, and hyphens. - It must start and end with an alphanumeric character. - maxLength: 63 - pattern: ^[a-z0-9]([a-z0-9_-]*[a-z0-9])?$ - type: string - kind: - description: Kind of the source. - enum: - - Bucket - - GitRepository - - OCIRepository - type: string - name: - description: Name of the source. - maxLength: 253 - pattern: ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ - type: string - namespace: - description: |- - Namespace of the source. - If not provided, defaults to the same namespace as the ArtifactGenerator. - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - alias - - kind - - name - type: object - maxItems: 1000 - minItems: 1 - type: array - required: - - artifacts - - sources - type: object - status: - description: ArtifactGeneratorStatus defines the observed state of ArtifactGenerator. - properties: - conditions: - description: Conditions holds the conditions for the ArtifactGenerator. - 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 - inventory: - description: Inventory contains the list of generated ExternalArtifact references. - items: - description: |- - ExternalArtifactReference contains the reference to a - generated ExternalArtifact along with its digest. - properties: - digest: - description: Digest of the referent artifact. - type: string - filename: - description: Filename is the name of the artifact file. - type: string - name: - description: Name of the referent artifact. - type: string - namespace: - description: Namespace of the referent artifact. - type: string - required: - - digest - - filename - - name - - namespace - type: object - type: array - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedSourcesDigest: - description: |- - ObservedSourcesDigest is a hash representing the current state of - all the sources referenced by the ArtifactGenerator. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: buckets.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: Bucket - listKind: BucketList - plural: buckets - singular: bucket - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.endpoint - name: Endpoint - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - name: v1 - schema: - openAPIV3Schema: - description: Bucket is the Schema for the buckets 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: |- - BucketSpec specifies the required configuration to produce an Artifact for - an object storage bucket. - properties: - bucketName: - description: BucketName is the name of the object storage bucket. - type: string - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - bucket. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - This field is only supported for the `generic` provider. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - endpoint: - description: Endpoint is the object storage address the BucketName is located at. - type: string - ignore: - description: |- - Ignore overrides the set of excluded patterns in the .sourceignore format - (which is the same as .gitignore). If not provided, a default will be used, - consult the documentation for your version to find out what those are. - type: string - insecure: - description: Insecure allows connecting to a non-TLS HTTP Endpoint. - type: boolean - interval: - description: |- - Interval at which the Bucket Endpoint is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - prefix: - description: Prefix to use for server-side filtering of files in the Bucket. - type: string - provider: - default: generic - description: |- - Provider of the object storage bucket. - Defaults to 'generic', which expects an S3 (API) compatible object - storage. - enum: - - generic - - aws - - gcp - - azure - type: string - proxySecretRef: - description: |- - ProxySecretRef specifies the Secret containing the proxy configuration - to use while communicating with the Bucket server. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - region: - description: Region of the Endpoint where the BucketName is located in. - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing authentication credentials - for the Bucket. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate - the bucket. This field is only supported for the 'gcp' and 'aws' providers. - For more information about workload identity: - https://fluxcd.io/flux/components/source/buckets/#workload-identity - type: string - sts: - description: |- - STS specifies the required configuration to use a Security Token - Service for fetching temporary credentials to authenticate in a - Bucket provider. - - This field is only supported for the `aws` and `generic` providers. - properties: - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - STS endpoint. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - This field is only supported for the `ldap` provider. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - endpoint: - description: |- - Endpoint is the HTTP/S endpoint of the Security Token Service from - where temporary credentials will be fetched. - pattern: ^(http|https)://.*$ - type: string - provider: - description: Provider of the Security Token Service. - enum: - - aws - - ldap - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing authentication credentials - for the STS endpoint. This Secret must contain the fields `username` - and `password` and is supported only for the `ldap` provider. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - endpoint - - provider - type: object - suspend: - description: |- - Suspend tells the controller to suspend the reconciliation of this - Bucket. - type: boolean - timeout: - default: 60s - description: Timeout for fetch operations, defaults to 60s. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - required: - - bucketName - - endpoint - - interval - type: object - x-kubernetes-validations: - - message: STS configuration is only supported for the 'aws' and 'generic' Bucket providers - rule: self.provider == 'aws' || self.provider == 'generic' || !has(self.sts) - - message: '''aws'' is the only supported STS provider for the ''aws'' Bucket provider' - rule: self.provider != 'aws' || !has(self.sts) || self.sts.provider == 'aws' - - message: '''ldap'' is the only supported STS provider for the ''generic'' Bucket provider' - rule: self.provider != 'generic' || !has(self.sts) || self.sts.provider == 'ldap' - - message: spec.sts.secretRef is not required for the 'aws' STS provider - rule: '!has(self.sts) || self.sts.provider != ''aws'' || !has(self.sts.secretRef)' - - message: spec.sts.certSecretRef is not required for the 'aws' STS provider - rule: '!has(self.sts) || self.sts.provider != ''aws'' || !has(self.sts.certSecretRef)' - - message: ServiceAccountName is not supported for the 'generic' Bucket provider - rule: self.provider != 'generic' || !has(self.serviceAccountName) - - message: cannot set both .spec.secretRef and .spec.serviceAccountName - rule: '!has(self.secretRef) || !has(self.serviceAccountName)' - status: - default: - observedGeneration: -1 - description: BucketStatus records the observed state of a Bucket. - properties: - artifact: - description: Artifact represents the last successful Bucket reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the Bucket. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation of the Bucket object. - format: int64 - type: integer - observedIgnore: - description: |- - ObservedIgnore is the observed exclusion patterns used for constructing - the source artifact. - type: string - url: - description: |- - URL is the dynamic fetch link for the latest Artifact. - It is provided on a "best effort" basis, and using the precise - BucketStatus.Artifact data is recommended. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.endpoint - name: Endpoint - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v1beta2 Bucket is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: Bucket is the Schema for the buckets 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: |- - BucketSpec specifies the required configuration to produce an Artifact for - an object storage bucket. - properties: - accessFrom: - description: |- - AccessFrom specifies an Access Control List for allowing cross-namespace - references to this object. - NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 - properties: - namespaceSelectors: - description: |- - NamespaceSelectors is the list of namespace selectors to which this ACL applies. - Items in this list are evaluated using a logical OR operation. - items: - description: |- - NamespaceSelector selects the namespaces to which this ACL applies. - An empty map of MatchLabels matches all namespaces in a cluster. - properties: - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - type: array - required: - - namespaceSelectors - type: object - bucketName: - description: BucketName is the name of the object storage bucket. - type: string - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - bucket. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - This field is only supported for the `generic` provider. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - endpoint: - description: Endpoint is the object storage address the BucketName is located at. - type: string - ignore: - description: |- - Ignore overrides the set of excluded patterns in the .sourceignore format - (which is the same as .gitignore). If not provided, a default will be used, - consult the documentation for your version to find out what those are. - type: string - insecure: - description: Insecure allows connecting to a non-TLS HTTP Endpoint. - type: boolean - interval: - description: |- - Interval at which the Bucket Endpoint is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - prefix: - description: Prefix to use for server-side filtering of files in the Bucket. - type: string - provider: - default: generic - description: |- - Provider of the object storage bucket. - Defaults to 'generic', which expects an S3 (API) compatible object - storage. - enum: - - generic - - aws - - gcp - - azure - type: string - proxySecretRef: - description: |- - ProxySecretRef specifies the Secret containing the proxy configuration - to use while communicating with the Bucket server. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - region: - description: Region of the Endpoint where the BucketName is located in. - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing authentication credentials - for the Bucket. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - sts: - description: |- - STS specifies the required configuration to use a Security Token - Service for fetching temporary credentials to authenticate in a - Bucket provider. - - This field is only supported for the `aws` and `generic` providers. - properties: - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - STS endpoint. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - This field is only supported for the `ldap` provider. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - endpoint: - description: |- - Endpoint is the HTTP/S endpoint of the Security Token Service from - where temporary credentials will be fetched. - pattern: ^(http|https)://.*$ - type: string - provider: - description: Provider of the Security Token Service. - enum: - - aws - - ldap - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing authentication credentials - for the STS endpoint. This Secret must contain the fields `username` - and `password` and is supported only for the `ldap` provider. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - endpoint - - provider - type: object - suspend: - description: |- - Suspend tells the controller to suspend the reconciliation of this - Bucket. - type: boolean - timeout: - default: 60s - description: Timeout for fetch operations, defaults to 60s. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - required: - - bucketName - - endpoint - - interval - type: object - x-kubernetes-validations: - - message: STS configuration is only supported for the 'aws' and 'generic' Bucket providers - rule: self.provider == 'aws' || self.provider == 'generic' || !has(self.sts) - - message: '''aws'' is the only supported STS provider for the ''aws'' Bucket provider' - rule: self.provider != 'aws' || !has(self.sts) || self.sts.provider == 'aws' - - message: '''ldap'' is the only supported STS provider for the ''generic'' Bucket provider' - rule: self.provider != 'generic' || !has(self.sts) || self.sts.provider == 'ldap' - - message: spec.sts.secretRef is not required for the 'aws' STS provider - rule: '!has(self.sts) || self.sts.provider != ''aws'' || !has(self.sts.secretRef)' - - message: spec.sts.certSecretRef is not required for the 'aws' STS provider - rule: '!has(self.sts) || self.sts.provider != ''aws'' || !has(self.sts.certSecretRef)' - status: - default: - observedGeneration: -1 - description: BucketStatus records the observed state of a Bucket. - properties: - artifact: - description: Artifact represents the last successful Bucket reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the Bucket. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation of the Bucket object. - format: int64 - type: integer - observedIgnore: - description: |- - ObservedIgnore is the observed exclusion patterns used for constructing - the source artifact. - type: string - url: - description: |- - URL is the dynamic fetch link for the latest Artifact. - It is provided on a "best effort" basis, and using the precise - BucketStatus.Artifact data is recommended. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: externalartifacts.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: ExternalArtifact - listKind: ExternalArtifactList - plural: externalartifacts - singular: externalartifact - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .spec.sourceRef.name - name: Source - type: string - name: v1 - schema: - openAPIV3Schema: - description: ExternalArtifact is the Schema for the external artifacts 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: ExternalArtifactSpec defines the desired state of ExternalArtifact - properties: - sourceRef: - description: |- - SourceRef points to the Kubernetes custom resource for - which the artifact is generated. - properties: - apiVersion: - description: API version of the referent, if not specified the Kubernetes preferred version will be used. - type: string - kind: - description: Kind of the referent. - type: string - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, when not specified it acts as LocalObjectReference. - type: string - required: - - kind - - name - type: object - type: object - status: - description: ExternalArtifactStatus defines the observed state of ExternalArtifact - properties: - artifact: - description: Artifact represents the output of an ExternalArtifact reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the ExternalArtifact. - 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 - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: gitrepositories.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: GitRepository - listKind: GitRepositoryList - plural: gitrepositories - shortNames: - - gitrepo - singular: gitrepository - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - name: v1 - schema: - openAPIV3Schema: - description: GitRepository is the Schema for the gitrepositories 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: |- - GitRepositorySpec specifies the required configuration to produce an - Artifact for a Git repository. - properties: - ignore: - description: |- - Ignore overrides the set of excluded patterns in the .sourceignore format - (which is the same as .gitignore). If not provided, a default will be used, - consult the documentation for your version to find out what those are. - type: string - include: - description: |- - Include specifies a list of GitRepository resources which Artifacts - should be included in the Artifact produced for this GitRepository. - items: - description: |- - GitRepositoryInclude specifies a local reference to a GitRepository which - Artifact (sub-)contents must be included, and where they should be placed. - properties: - fromPath: - description: |- - FromPath specifies the path to copy contents from, defaults to the root - of the Artifact. - type: string - repository: - description: |- - GitRepositoryRef specifies the GitRepository which Artifact contents - must be included. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - toPath: - description: |- - ToPath specifies the path to copy contents to, defaults to the name of - the GitRepositoryRef. - type: string - required: - - repository - type: object - type: array - interval: - description: |- - Interval at which the GitRepository URL is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - provider: - description: |- - Provider used for authentication, can be 'azure', 'github', 'generic'. - When not specified, defaults to 'generic'. - enum: - - generic - - azure - - github - type: string - proxySecretRef: - description: |- - ProxySecretRef specifies the Secret containing the proxy configuration - to use while communicating with the Git server. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - recurseSubmodules: - description: |- - RecurseSubmodules enables the initialization of all submodules within - the GitRepository as cloned from the URL, using their default settings. - type: boolean - ref: - description: |- - Reference specifies the Git reference to resolve and monitor for - changes, defaults to the 'master' branch. - properties: - branch: - description: Branch to check out, defaults to 'master' if no other field is defined. - type: string - commit: - description: |- - Commit SHA to check out, takes precedence over all reference fields. - - This can be combined with Branch to shallow clone the branch, in which - the commit is expected to exist. - type: string - name: - description: |- - Name of the reference to check out; takes precedence over Branch, Tag and SemVer. - - It must be a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description - Examples: "refs/heads/main", "refs/tags/v0.1.0", "refs/pull/420/head", "refs/merge-requests/1/head" - type: string - semver: - description: SemVer tag expression to check out, takes precedence over Tag. - type: string - tag: - description: Tag to check out, takes precedence over Branch. - type: string - type: object - secretRef: - description: |- - SecretRef specifies the Secret containing authentication credentials for - the GitRepository. - For HTTPS repositories the Secret must contain 'username' and 'password' - fields for basic auth or 'bearerToken' field for token auth. - For SSH repositories the Secret must contain 'identity' - and 'known_hosts' fields. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the Kubernetes ServiceAccount used to - authenticate to the GitRepository. This field is only supported for 'azure' provider. - type: string - sparseCheckout: - description: |- - SparseCheckout specifies a list of directories to checkout when cloning - the repository. If specified, only these directories are included in the - Artifact produced for this GitRepository. - items: - type: string - type: array - suspend: - description: |- - Suspend tells the controller to suspend the reconciliation of this - GitRepository. - type: boolean - timeout: - default: 60s - description: Timeout for Git operations like cloning, defaults to 60s. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - url: - description: URL specifies the Git repository URL, it can be an HTTP/S or SSH address. - pattern: ^(http|https|ssh)://.*$ - type: string - verify: - description: |- - Verification specifies the configuration to verify the Git commit - signature(s). - properties: - mode: - default: HEAD - description: |- - Mode specifies which Git object(s) should be verified. - - The variants "head" and "HEAD" both imply the same thing, i.e. verify - the commit that the HEAD of the Git repository points to. The variant - "head" solely exists to ensure backwards compatibility. - enum: - - head - - HEAD - - Tag - - TagAndHEAD - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing the public keys of trusted Git - authors. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - secretRef - type: object - required: - - interval - - url - type: object - x-kubernetes-validations: - - message: serviceAccountName can only be set when provider is 'azure' - rule: '!has(self.serviceAccountName) || (has(self.provider) && self.provider == ''azure'')' - status: - default: - observedGeneration: -1 - description: GitRepositoryStatus records the observed state of a Git repository. - properties: - artifact: - description: Artifact represents the last successful GitRepository reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the GitRepository. - 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 - includedArtifacts: - description: |- - IncludedArtifacts contains a list of the last successfully included - Artifacts as instructed by GitRepositorySpec.Include. - items: - description: Artifact represents the output of a Source reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - type: array - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: |- - ObservedGeneration is the last observed generation of the GitRepository - object. - format: int64 - type: integer - observedIgnore: - description: |- - ObservedIgnore is the observed exclusion patterns used for constructing - the source artifact. - type: string - observedInclude: - description: |- - ObservedInclude is the observed list of GitRepository resources used to - produce the current Artifact. - items: - description: |- - GitRepositoryInclude specifies a local reference to a GitRepository which - Artifact (sub-)contents must be included, and where they should be placed. - properties: - fromPath: - description: |- - FromPath specifies the path to copy contents from, defaults to the root - of the Artifact. - type: string - repository: - description: |- - GitRepositoryRef specifies the GitRepository which Artifact contents - must be included. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - toPath: - description: |- - ToPath specifies the path to copy contents to, defaults to the name of - the GitRepositoryRef. - type: string - required: - - repository - type: object - type: array - observedRecurseSubmodules: - description: |- - ObservedRecurseSubmodules is the observed resource submodules - configuration used to produce the current Artifact. - type: boolean - observedSparseCheckout: - description: |- - ObservedSparseCheckout is the observed list of directories used to - produce the current Artifact. - items: - type: string - type: array - sourceVerificationMode: - description: |- - SourceVerificationMode is the last used verification mode indicating - which Git object(s) have been verified. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v1beta2 GitRepository is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: GitRepository is the Schema for the gitrepositories 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: |- - GitRepositorySpec specifies the required configuration to produce an - Artifact for a Git repository. - properties: - accessFrom: - description: |- - AccessFrom specifies an Access Control List for allowing cross-namespace - references to this object. - NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 - properties: - namespaceSelectors: - description: |- - NamespaceSelectors is the list of namespace selectors to which this ACL applies. - Items in this list are evaluated using a logical OR operation. - items: - description: |- - NamespaceSelector selects the namespaces to which this ACL applies. - An empty map of MatchLabels matches all namespaces in a cluster. - properties: - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - type: array - required: - - namespaceSelectors - type: object - gitImplementation: - default: go-git - description: |- - GitImplementation specifies which Git client library implementation to - use. Defaults to 'go-git', valid values are ('go-git', 'libgit2'). - Deprecated: gitImplementation is deprecated now that 'go-git' is the - only supported implementation. - enum: - - go-git - - libgit2 - type: string - ignore: - description: |- - Ignore overrides the set of excluded patterns in the .sourceignore format - (which is the same as .gitignore). If not provided, a default will be used, - consult the documentation for your version to find out what those are. - type: string - include: - description: |- - Include specifies a list of GitRepository resources which Artifacts - should be included in the Artifact produced for this GitRepository. - items: - description: |- - GitRepositoryInclude specifies a local reference to a GitRepository which - Artifact (sub-)contents must be included, and where they should be placed. - properties: - fromPath: - description: |- - FromPath specifies the path to copy contents from, defaults to the root - of the Artifact. - type: string - repository: - description: |- - GitRepositoryRef specifies the GitRepository which Artifact contents - must be included. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - toPath: - description: |- - ToPath specifies the path to copy contents to, defaults to the name of - the GitRepositoryRef. - type: string - required: - - repository - type: object - type: array - interval: - description: Interval at which to check the GitRepository for updates. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - recurseSubmodules: - description: |- - RecurseSubmodules enables the initialization of all submodules within - the GitRepository as cloned from the URL, using their default settings. - type: boolean - ref: - description: |- - Reference specifies the Git reference to resolve and monitor for - changes, defaults to the 'master' branch. - properties: - branch: - description: Branch to check out, defaults to 'master' if no other field is defined. - type: string - commit: - description: |- - Commit SHA to check out, takes precedence over all reference fields. - - This can be combined with Branch to shallow clone the branch, in which - the commit is expected to exist. - type: string - name: - description: |- - Name of the reference to check out; takes precedence over Branch, Tag and SemVer. - - It must be a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description - Examples: "refs/heads/main", "refs/tags/v0.1.0", "refs/pull/420/head", "refs/merge-requests/1/head" - type: string - semver: - description: SemVer tag expression to check out, takes precedence over Tag. - type: string - tag: - description: Tag to check out, takes precedence over Branch. - type: string - type: object - secretRef: - description: |- - SecretRef specifies the Secret containing authentication credentials for - the GitRepository. - For HTTPS repositories the Secret must contain 'username' and 'password' - fields for basic auth or 'bearerToken' field for token auth. - For SSH repositories the Secret must contain 'identity' - and 'known_hosts' fields. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - suspend: - description: |- - Suspend tells the controller to suspend the reconciliation of this - GitRepository. - type: boolean - timeout: - default: 60s - description: Timeout for Git operations like cloning, defaults to 60s. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - url: - description: URL specifies the Git repository URL, it can be an HTTP/S or SSH address. - pattern: ^(http|https|ssh)://.*$ - type: string - verify: - description: |- - Verification specifies the configuration to verify the Git commit - signature(s). - properties: - mode: - description: Mode specifies what Git object should be verified, currently ('head'). - enum: - - head - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing the public keys of trusted Git - authors. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - mode - - secretRef - type: object - required: - - interval - - url - type: object - status: - default: - observedGeneration: -1 - description: GitRepositoryStatus records the observed state of a Git repository. - properties: - artifact: - description: Artifact represents the last successful GitRepository reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the GitRepository. - 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 - contentConfigChecksum: - description: |- - ContentConfigChecksum is a checksum of all the configurations related to - the content of the source artifact: - - .spec.ignore - - .spec.recurseSubmodules - - .spec.included and the checksum of the included artifacts - observed in .status.observedGeneration version of the object. This can - be used to determine if the content of the included repository has - changed. - It has the format of `:`, for example: `sha256:`. - - Deprecated: Replaced with explicit fields for observed artifact content - config in the status. - type: string - includedArtifacts: - description: |- - IncludedArtifacts contains a list of the last successfully included - Artifacts as instructed by GitRepositorySpec.Include. - items: - description: Artifact represents the output of a Source reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - type: array - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: |- - ObservedGeneration is the last observed generation of the GitRepository - object. - format: int64 - type: integer - observedIgnore: - description: |- - ObservedIgnore is the observed exclusion patterns used for constructing - the source artifact. - type: string - observedInclude: - description: |- - ObservedInclude is the observed list of GitRepository resources used to - to produce the current Artifact. - items: - description: |- - GitRepositoryInclude specifies a local reference to a GitRepository which - Artifact (sub-)contents must be included, and where they should be placed. - properties: - fromPath: - description: |- - FromPath specifies the path to copy contents from, defaults to the root - of the Artifact. - type: string - repository: - description: |- - GitRepositoryRef specifies the GitRepository which Artifact contents - must be included. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - toPath: - description: |- - ToPath specifies the path to copy contents to, defaults to the name of - the GitRepositoryRef. - type: string - required: - - repository - type: object - type: array - observedRecurseSubmodules: - description: |- - ObservedRecurseSubmodules is the observed resource submodules - configuration used to produce the current Artifact. - type: boolean - url: - description: |- - URL is the dynamic fetch link for the latest Artifact. - It is provided on a "best effort" basis, and using the precise - GitRepositoryStatus.Artifact data is recommended. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: helmcharts.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: HelmChart - listKind: HelmChartList - plural: helmcharts - shortNames: - - hc - singular: helmchart - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.chart - name: Chart - type: string - - jsonPath: .spec.version - name: Version - type: string - - jsonPath: .spec.sourceRef.kind - name: Source Kind - type: string - - jsonPath: .spec.sourceRef.name - name: Source Name - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - name: v1 - schema: - openAPIV3Schema: - description: HelmChart is the Schema for the helmcharts 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: HelmChartSpec specifies the desired state of a Helm chart. - properties: - chart: - description: |- - Chart is the name or path the Helm chart is available at in the - SourceRef. - type: string - ignoreMissingValuesFiles: - description: |- - IgnoreMissingValuesFiles controls whether to silently ignore missing values - files rather than failing. - type: boolean - interval: - description: |- - Interval at which the HelmChart SourceRef is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - reconcileStrategy: - default: ChartVersion - description: |- - ReconcileStrategy determines what enables the creation of a new artifact. - Valid values are ('ChartVersion', 'Revision'). - See the documentation of the values for an explanation on their behavior. - Defaults to ChartVersion when omitted. - enum: - - ChartVersion - - Revision - type: string - sourceRef: - description: SourceRef is the reference to the Source the chart is available at. - properties: - apiVersion: - description: APIVersion of the referent. - type: string - kind: - description: |- - Kind of the referent, valid values are ('HelmRepository', 'GitRepository', - 'Bucket'). - enum: - - HelmRepository - - GitRepository - - Bucket - type: string - name: - description: Name of the referent. - type: string - required: - - kind - - name - type: object - suspend: - description: |- - Suspend tells the controller to suspend the reconciliation of this - source. - type: boolean - valuesFiles: - description: |- - ValuesFiles is an alternative list of values files to use as the chart - values (values.yaml is not included by default), expected to be a - relative path in the SourceRef. - Values files are merged in the order of this list with the last file - overriding the first. Ignored when omitted. - items: - type: string - type: array - verify: - description: |- - Verify contains the secret name containing the trusted public keys - used to verify the signature and specifies which provider to use to check - whether OCI image is authentic. - This field is only supported when using HelmRepository source with spec.type 'oci'. - Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. - properties: - matchOIDCIdentity: - description: |- - MatchOIDCIdentity specifies the identity matching criteria to use - while verifying an OCI artifact which was signed using Cosign keyless - signing. The artifact's identity is deemed to be verified if any of the - specified matchers match against the identity. - items: - description: |- - OIDCIdentityMatch specifies options for verifying the certificate identity, - i.e. the issuer and the subject of the certificate. - properties: - issuer: - description: |- - Issuer specifies the regex pattern to match against to verify - the OIDC issuer in the Fulcio certificate. The pattern must be a - valid Go regular expression. - type: string - subject: - description: |- - Subject specifies the regex pattern to match against to verify - the identity subject in the Fulcio certificate. The pattern must - be a valid Go regular expression. - type: string - required: - - issuer - - subject - type: object - type: array - provider: - default: cosign - description: Provider specifies the technology used to sign the OCI Artifact. - enum: - - cosign - - notation - type: string - secretRef: - description: |- - SecretRef specifies the Kubernetes Secret containing the - trusted public keys. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - provider - type: object - version: - default: '*' - description: |- - Version is the chart version semver expression, ignored for charts from - GitRepository and Bucket sources. Defaults to latest when omitted. - type: string - required: - - chart - - interval - - sourceRef - type: object - status: - default: - observedGeneration: -1 - description: HelmChartStatus records the observed state of the HelmChart. - properties: - artifact: - description: Artifact represents the output of the last successful reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the HelmChart. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedChartName: - description: |- - ObservedChartName is the last observed chart name as specified by the - resolved chart reference. - type: string - observedGeneration: - description: |- - ObservedGeneration is the last observed generation of the HelmChart - object. - format: int64 - type: integer - observedSourceArtifactRevision: - description: |- - ObservedSourceArtifactRevision is the last observed Artifact.Revision - of the HelmChartSpec.SourceRef. - type: string - observedValuesFiles: - description: |- - ObservedValuesFiles are the observed value files of the last successful - reconciliation. - It matches the chart in the last successfully reconciled artifact. - items: - type: string - type: array - url: - description: |- - URL is the dynamic fetch link for the latest Artifact. - It is provided on a "best effort" basis, and using the precise - BucketStatus.Artifact data is recommended. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.chart - name: Chart - type: string - - jsonPath: .spec.version - name: Version - type: string - - jsonPath: .spec.sourceRef.kind - name: Source Kind - type: string - - jsonPath: .spec.sourceRef.name - name: Source Name - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v1beta2 HelmChart is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: HelmChart is the Schema for the helmcharts 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: HelmChartSpec specifies the desired state of a Helm chart. - properties: - accessFrom: - description: |- - AccessFrom specifies an Access Control List for allowing cross-namespace - references to this object. - NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 - properties: - namespaceSelectors: - description: |- - NamespaceSelectors is the list of namespace selectors to which this ACL applies. - Items in this list are evaluated using a logical OR operation. - items: - description: |- - NamespaceSelector selects the namespaces to which this ACL applies. - An empty map of MatchLabels matches all namespaces in a cluster. - properties: - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - type: array - required: - - namespaceSelectors - type: object - chart: - description: |- - Chart is the name or path the Helm chart is available at in the - SourceRef. - type: string - ignoreMissingValuesFiles: - description: |- - IgnoreMissingValuesFiles controls whether to silently ignore missing values - files rather than failing. - type: boolean - interval: - description: |- - Interval at which the HelmChart SourceRef is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - reconcileStrategy: - default: ChartVersion - description: |- - ReconcileStrategy determines what enables the creation of a new artifact. - Valid values are ('ChartVersion', 'Revision'). - See the documentation of the values for an explanation on their behavior. - Defaults to ChartVersion when omitted. - enum: - - ChartVersion - - Revision - type: string - sourceRef: - description: SourceRef is the reference to the Source the chart is available at. - properties: - apiVersion: - description: APIVersion of the referent. - type: string - kind: - description: |- - Kind of the referent, valid values are ('HelmRepository', 'GitRepository', - 'Bucket'). - enum: - - HelmRepository - - GitRepository - - Bucket - type: string - name: - description: Name of the referent. - type: string - required: - - kind - - name - type: object - suspend: - description: |- - Suspend tells the controller to suspend the reconciliation of this - source. - type: boolean - valuesFile: - description: |- - ValuesFile is an alternative values file to use as the default chart - values, expected to be a relative path in the SourceRef. Deprecated in - favor of ValuesFiles, for backwards compatibility the file specified here - is merged before the ValuesFiles items. Ignored when omitted. - type: string - valuesFiles: - description: |- - ValuesFiles is an alternative list of values files to use as the chart - values (values.yaml is not included by default), expected to be a - relative path in the SourceRef. - Values files are merged in the order of this list with the last file - overriding the first. Ignored when omitted. - items: - type: string - type: array - verify: - description: |- - Verify contains the secret name containing the trusted public keys - used to verify the signature and specifies which provider to use to check - whether OCI image is authentic. - This field is only supported when using HelmRepository source with spec.type 'oci'. - Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. - properties: - matchOIDCIdentity: - description: |- - MatchOIDCIdentity specifies the identity matching criteria to use - while verifying an OCI artifact which was signed using Cosign keyless - signing. The artifact's identity is deemed to be verified if any of the - specified matchers match against the identity. - items: - description: |- - OIDCIdentityMatch specifies options for verifying the certificate identity, - i.e. the issuer and the subject of the certificate. - properties: - issuer: - description: |- - Issuer specifies the regex pattern to match against to verify - the OIDC issuer in the Fulcio certificate. The pattern must be a - valid Go regular expression. - type: string - subject: - description: |- - Subject specifies the regex pattern to match against to verify - the identity subject in the Fulcio certificate. The pattern must - be a valid Go regular expression. - type: string - required: - - issuer - - subject - type: object - type: array - provider: - default: cosign - description: Provider specifies the technology used to sign the OCI Artifact. - enum: - - cosign - - notation - type: string - secretRef: - description: |- - SecretRef specifies the Kubernetes Secret containing the - trusted public keys. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - provider - type: object - version: - default: '*' - description: |- - Version is the chart version semver expression, ignored for charts from - GitRepository and Bucket sources. Defaults to latest when omitted. - type: string - required: - - chart - - interval - - sourceRef - type: object - status: - default: - observedGeneration: -1 - description: HelmChartStatus records the observed state of the HelmChart. - properties: - artifact: - description: Artifact represents the output of the last successful reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the HelmChart. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedChartName: - description: |- - ObservedChartName is the last observed chart name as specified by the - resolved chart reference. - type: string - observedGeneration: - description: |- - ObservedGeneration is the last observed generation of the HelmChart - object. - format: int64 - type: integer - observedSourceArtifactRevision: - description: |- - ObservedSourceArtifactRevision is the last observed Artifact.Revision - of the HelmChartSpec.SourceRef. - type: string - observedValuesFiles: - description: |- - ObservedValuesFiles are the observed value files of the last successful - reconciliation. - It matches the chart in the last successfully reconciled artifact. - items: - type: string - type: array - url: - description: |- - URL is the dynamic fetch link for the latest Artifact. - It is provided on a "best effort" basis, and using the precise - BucketStatus.Artifact data is recommended. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: helmreleases.helm.toolkit.fluxcd.io -spec: - group: helm.toolkit.fluxcd.io - names: - kind: HelmRelease - listKind: HelmReleaseList - plural: helmreleases - shortNames: - - hr - singular: helmrelease - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - name: v2 - schema: - openAPIV3Schema: - description: HelmRelease is the Schema for the helmreleases 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: HelmReleaseSpec defines the desired state of a Helm release. - properties: - chart: - description: |- - Chart defines the template of the v1.HelmChart that should be created - for this HelmRelease. - properties: - metadata: - description: ObjectMeta holds the template for metadata like labels and annotations. - 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: https://kubernetes.io/docs/concepts/overview/working-with-objects/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. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - type: object - type: object - spec: - description: Spec holds the template for the v1.HelmChartSpec for this HelmRelease. - properties: - chart: - description: The name or path the Helm chart is available at in the SourceRef. - maxLength: 2048 - minLength: 1 - type: string - ignoreMissingValuesFiles: - description: IgnoreMissingValuesFiles controls whether to silently ignore missing values files rather than failing. - type: boolean - interval: - description: |- - Interval at which to check the v1.Source for updates. Defaults to - 'HelmReleaseSpec.Interval'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - reconcileStrategy: - default: ChartVersion - description: |- - Determines what enables the creation of a new artifact. Valid values are - ('ChartVersion', 'Revision'). - See the documentation of the values for an explanation on their behavior. - Defaults to ChartVersion when omitted. - enum: - - ChartVersion - - Revision - type: string - sourceRef: - description: The name and namespace of the v1.Source the chart is available at. - properties: - apiVersion: - description: APIVersion of the referent. - type: string - kind: - description: Kind of the referent. - enum: - - HelmRepository - - GitRepository - - Bucket - type: string - name: - description: Name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace of the referent. - maxLength: 63 - minLength: 1 - type: string - required: - - kind - - name - type: object - valuesFiles: - description: |- - Alternative list of values files to use as the chart values (values.yaml - is not included by default), expected to be a relative path in the SourceRef. - Values files are merged in the order of this list with the last file overriding - the first. Ignored when omitted. - items: - type: string - type: array - verify: - description: |- - Verify contains the secret name containing the trusted public keys - used to verify the signature and specifies which provider to use to check - whether OCI image is authentic. - This field is only supported for OCI sources. - Chart dependencies, which are not bundled in the umbrella chart artifact, - are not verified. - properties: - provider: - default: cosign - description: Provider specifies the technology used to sign the OCI Helm chart. - enum: - - cosign - - notation - type: string - secretRef: - description: |- - SecretRef specifies the Kubernetes Secret containing the - trusted public keys. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - provider - type: object - version: - default: '*' - description: |- - Version semver expression, ignored for charts from v1.GitRepository and - v1beta2.Bucket sources. Defaults to latest when omitted. - type: string - required: - - chart - - sourceRef - type: object - required: - - spec - type: object - chartRef: - description: |- - ChartRef holds a reference to a source controller resource containing the - Helm chart artifact. - properties: - apiVersion: - description: APIVersion of the referent. - type: string - kind: - description: Kind of the referent. - enum: - - OCIRepository - - HelmChart - - ExternalArtifact - type: string - name: - description: Name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace of the referent, defaults to the namespace of the Kubernetes - resource object that contains the reference. - maxLength: 63 - minLength: 1 - type: string - required: - - kind - - name - type: object - commonMetadata: - description: |- - CommonMetadata specifies the common labels and annotations that are - applied to all resources. Any existing label or annotation will be - overridden if its key matches a common one. - properties: - annotations: - additionalProperties: - type: string - description: Annotations to be added to the object's metadata. - type: object - labels: - additionalProperties: - type: string - description: Labels to be added to the object's metadata. - type: object - type: object - dependsOn: - description: |- - DependsOn may contain a DependencyReference slice with - references to HelmRelease resources that must be ready before this HelmRelease - can be reconciled. - items: - description: DependencyReference defines a HelmRelease dependency on another HelmRelease resource. - properties: - name: - description: Name of the referent. - type: string - namespace: - description: |- - Namespace of the referent, defaults to the namespace of the HelmRelease - resource object that contains the reference. - type: string - readyExpr: - description: |- - ReadyExpr is a CEL expression that can be used to assess the readiness - of a dependency. When specified, the built-in readiness check - is replaced by the logic defined in the CEL expression. - To make the CEL expression additive to the built-in readiness check, - the feature gate `AdditiveCELDependencyCheck` must be set to `true`. - type: string - required: - - name - type: object - type: array - driftDetection: - description: |- - DriftDetection holds the configuration for detecting and handling - differences between the manifest in the Helm storage and the resources - currently existing in the cluster. - properties: - ignore: - description: |- - Ignore contains a list of rules for specifying which changes to ignore - during diffing. - items: - description: |- - IgnoreRule defines a rule to selectively disregard specific changes during - the drift detection process. - properties: - paths: - description: |- - Paths is a list of JSON Pointer (RFC 6901) paths to be excluded from - consideration in a Kubernetes object. - items: - type: string - type: array - target: - description: |- - Target is a selector for specifying Kubernetes objects to which this - rule applies. - If Target is not set, the Paths will be ignored for all Kubernetes - objects within the manifest of the Helm release. - properties: - annotationSelector: - description: |- - AnnotationSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: |- - Group is the API group to select resources from. - Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: |- - Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: |- - LabelSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: |- - Version of the API Group to select resources from. - Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - paths - type: object - type: array - mode: - description: |- - Mode defines how differences should be handled between the Helm manifest - and the manifest currently applied to the cluster. - If not explicitly set, it defaults to DiffModeDisabled. - enum: - - enabled - - warn - - disabled - type: string - type: object - install: - description: Install holds the configuration for Helm install actions for this HelmRelease. - properties: - crds: - description: |- - CRDs upgrade CRDs from the Helm Chart's crds directory according - to the CRD upgrade policy provided here. Valid values are `Skip`, - `Create` or `CreateReplace`. Default is `Create` and if omitted - CRDs are installed but not updated. - - Skip: do neither install nor replace (update) any CRDs. - - Create: new CRDs are created, existing CRDs are neither updated nor deleted. - - CreateReplace: new CRDs are created, existing CRDs are updated (replaced) - but not deleted. - - By default, CRDs are applied (installed) during Helm install action. - With this option users can opt in to CRD replace existing CRDs on Helm - install actions, which is not (yet) natively supported by Helm. - https://helm.sh/docs/chart_best_practices/custom_resource_definitions. - enum: - - Skip - - Create - - CreateReplace - type: string - createNamespace: - description: |- - CreateNamespace tells the Helm install action to create the - HelmReleaseSpec.TargetNamespace if it does not exist yet. - On uninstall, the namespace will not be garbage collected. - type: boolean - disableHooks: - description: DisableHooks prevents hooks from running during the Helm install action. - type: boolean - disableOpenAPIValidation: - description: |- - DisableOpenAPIValidation prevents the Helm install action from validating - rendered templates against the Kubernetes OpenAPI Schema. - type: boolean - disableSchemaValidation: - description: |- - DisableSchemaValidation prevents the Helm install action from validating - the values against the JSON Schema. - type: boolean - disableTakeOwnership: - description: |- - DisableTakeOwnership disables taking ownership of existing resources - during the Helm install action. Defaults to false. - type: boolean - disableWait: - description: |- - DisableWait disables the waiting for resources to be ready after a Helm - install has been performed. - type: boolean - disableWaitForJobs: - description: |- - DisableWaitForJobs disables waiting for jobs to complete after a Helm - install has been performed. - type: boolean - remediation: - description: |- - Remediation holds the remediation configuration for when the Helm install - action for the HelmRelease fails. The default is to not perform any action. - properties: - ignoreTestFailures: - description: |- - IgnoreTestFailures tells the controller to skip remediation when the Helm - tests are run after an install action but fail. Defaults to - 'Test.IgnoreFailures'. - type: boolean - remediateLastFailure: - description: |- - RemediateLastFailure tells the controller to remediate the last failure, when - no retries remain. Defaults to 'false'. - type: boolean - retries: - description: |- - Retries is the number of retries that should be attempted on failures before - bailing. Remediation, using an uninstall, is performed between each attempt. - Defaults to '0', a negative integer equals to unlimited retries. - type: integer - type: object - replace: - description: |- - Replace tells the Helm install action to re-use the 'ReleaseName', but only - if that name is a deleted release which remains in the history. - type: boolean - skipCRDs: - description: |- - SkipCRDs tells the Helm install action to not install any CRDs. By default, - CRDs are installed if not already present. - - Deprecated use CRD policy (`crds`) attribute with value `Skip` instead. - type: boolean - strategy: - description: |- - Strategy defines the install strategy to use for this HelmRelease. - Defaults to 'RemediateOnFailure'. - properties: - name: - description: Name of the install strategy. - enum: - - RemediateOnFailure - - RetryOnFailure - type: string - retryInterval: - description: |- - RetryInterval is the interval at which to retry a failed install. - Can be used only when Name is set to RetryOnFailure. - Defaults to '5m'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - required: - - name - type: object - x-kubernetes-validations: - - message: .retryInterval cannot be set when .name is 'RemediateOnFailure' - rule: '!has(self.retryInterval) || self.name != ''RemediateOnFailure''' - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like - Jobs for hooks) during the performance of a Helm install action. Defaults to - 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - interval: - description: Interval at which to reconcile the Helm release. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - kubeConfig: - description: |- - KubeConfig for reconciling the HelmRelease on a remote cluster. - When used in combination with HelmReleaseSpec.ServiceAccountName, - forces the controller to act on behalf of that Service Account at the - target cluster. - If the --default-service-account flag is set, its value will be used as - a controller level fallback for when HelmReleaseSpec.ServiceAccountName - is empty. - properties: - configMapRef: - description: |- - ConfigMapRef holds an optional name of a ConfigMap that contains - the following keys: - - - `provider`: the provider to use. One of `aws`, `azure`, `gcp`, or - `generic`. Required. - - `cluster`: the fully qualified resource name of the Kubernetes - cluster in the cloud provider API. Not used by the `generic` - provider. Required when one of `address` or `ca.crt` is not set. - - `address`: the address of the Kubernetes API server. Required - for `generic`. For the other providers, if not specified, the - first address in the cluster resource will be used, and if - specified, it must match one of the addresses in the cluster - resource. - If audiences is not set, will be used as the audience for the - `generic` provider. - - `ca.crt`: the optional PEM-encoded CA certificate for the - Kubernetes API server. If not set, the controller will use the - CA certificate from the cluster resource. - - `audiences`: the optional audiences as a list of - line-break-separated strings for the Kubernetes ServiceAccount - token. Defaults to the `address` for the `generic` provider, or - to specific values for the other providers depending on the - provider. - - `serviceAccountName`: the optional name of the Kubernetes - ServiceAccount in the same namespace that should be used - for authentication. If not specified, the controller - ServiceAccount will be used. - - Mutually exclusive with SecretRef. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - secretRef: - description: |- - SecretRef holds an optional name of a secret that contains a key with - the kubeconfig file as the value. If no key is set, the key will default - to 'value'. Mutually exclusive with ConfigMapRef. - It is recommended that the kubeconfig is self-contained, and the secret - is regularly updated if credentials such as a cloud-access-token expire. - Cloud specific `cmd-path` auth helpers will not function without adding - binaries and credentials to the Pod that is responsible for reconciling - Kubernetes resources. Supported only for the generic provider. - properties: - key: - description: Key in the Secret, when not specified an implementation-specific default key is used. - type: string - name: - description: Name of the Secret. - type: string - required: - - name - type: object - type: object - x-kubernetes-validations: - - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified - rule: has(self.configMapRef) || has(self.secretRef) - - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified - rule: '!has(self.configMapRef) || !has(self.secretRef)' - maxHistory: - description: |- - MaxHistory is the number of revisions saved by Helm for this HelmRelease. - Use '0' for an unlimited number of revisions; defaults to '5'. - type: integer - persistentClient: - description: |- - PersistentClient tells the controller to use a persistent Kubernetes - client for this release. When enabled, the client will be reused for the - duration of the reconciliation, instead of being created and destroyed - for each (step of a) Helm action. - - This can improve performance, but may cause issues with some Helm charts - that for example do create Custom Resource Definitions during installation - outside Helm's CRD lifecycle hooks, which are then not observed to be - available by e.g. post-install hooks. - - If not set, it defaults to true. - type: boolean - postRenderers: - description: |- - PostRenderers holds an array of Helm PostRenderers, which will be applied in order - of their definition. - items: - description: PostRenderer contains a Helm PostRenderer specification. - properties: - kustomize: - description: Kustomization to apply as PostRenderer. - properties: - images: - description: |- - Images is a list of (image name, new name, new tag or digest) - for changing image names, tags or digests. This can also be achieved with a - patch, but this operator is simpler to specify. - items: - description: Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag. - properties: - digest: - description: |- - Digest is the value used to replace the original image tag. - If digest is present NewTag value is ignored. - type: string - name: - description: Name is a tag-less image name. - type: string - newName: - description: NewName is the value used to replace the original name. - type: string - newTag: - description: NewTag is the value used to replace the original tag. - type: string - required: - - name - type: object - type: array - patches: - description: |- - Strategic merge and JSON patches, defined as inline YAML objects, - capable of targeting objects based on kind, label and annotation selectors. - items: - description: |- - Patch contains an inline StrategicMerge or JSON6902 patch, and the target the patch should - be applied to. - properties: - patch: - description: |- - Patch contains an inline StrategicMerge patch or an inline JSON6902 patch with - an array of operation objects. - type: string - target: - description: Target points to the resources that the patch document should be applied to. - properties: - annotationSelector: - description: |- - AnnotationSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: |- - Group is the API group to select resources from. - Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: |- - Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: |- - LabelSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: |- - Version of the API Group to select resources from. - Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - type: object - type: array - type: object - type: object - type: array - releaseName: - description: |- - ReleaseName used for the Helm release. Defaults to a composition of - '[TargetNamespace-]Name'. - maxLength: 53 - minLength: 1 - type: string - rollback: - description: Rollback holds the configuration for Helm rollback actions for this HelmRelease. - properties: - cleanupOnFail: - description: |- - CleanupOnFail allows deletion of new resources created during the Helm - rollback action when it fails. - type: boolean - disableHooks: - description: DisableHooks prevents hooks from running during the Helm rollback action. - type: boolean - disableWait: - description: |- - DisableWait disables the waiting for resources to be ready after a Helm - rollback has been performed. - type: boolean - disableWaitForJobs: - description: |- - DisableWaitForJobs disables waiting for jobs to complete after a Helm - rollback has been performed. - type: boolean - force: - description: Force forces resource updates through a replacement strategy. - type: boolean - recreate: - description: Recreate performs pod restarts for the resource if applicable. - type: boolean - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like - Jobs for hooks) during the performance of a Helm rollback action. Defaults to - 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - serviceAccountName: - description: |- - The name of the Kubernetes service account to impersonate - when reconciling this HelmRelease. - maxLength: 253 - minLength: 1 - type: string - storageNamespace: - description: |- - StorageNamespace used for the Helm storage. - Defaults to the namespace of the HelmRelease. - maxLength: 63 - minLength: 1 - type: string - suspend: - description: |- - Suspend tells the controller to suspend reconciliation for this HelmRelease, - it does not apply to already started reconciliations. Defaults to false. - type: boolean - targetNamespace: - description: |- - TargetNamespace to target when performing operations for the HelmRelease. - Defaults to the namespace of the HelmRelease. - maxLength: 63 - minLength: 1 - type: string - test: - description: Test holds the configuration for Helm test actions for this HelmRelease. - properties: - enable: - description: |- - Enable enables Helm test actions for this HelmRelease after an Helm install - or upgrade action has been performed. - type: boolean - filters: - description: Filters is a list of tests to run or exclude from running. - items: - description: Filter holds the configuration for individual Helm test filters. - properties: - exclude: - description: Exclude specifies whether the named test should be excluded. - type: boolean - name: - description: Name is the name of the test. - maxLength: 253 - minLength: 1 - type: string - required: - - name - type: object - type: array - ignoreFailures: - description: |- - IgnoreFailures tells the controller to skip remediation when the Helm tests - are run but fail. Can be overwritten for tests run after install or upgrade - actions in 'Install.IgnoreTestFailures' and 'Upgrade.IgnoreTestFailures'. - type: boolean - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation during - the performance of a Helm test action. Defaults to 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like Jobs - for hooks) during the performance of a Helm action. Defaults to '5m0s'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - uninstall: - description: Uninstall holds the configuration for Helm uninstall actions for this HelmRelease. - properties: - deletionPropagation: - default: background - description: |- - DeletionPropagation specifies the deletion propagation policy when - a Helm uninstall is performed. - enum: - - background - - foreground - - orphan - type: string - disableHooks: - description: DisableHooks prevents hooks from running during the Helm rollback action. - type: boolean - disableWait: - description: |- - DisableWait disables waiting for all the resources to be deleted after - a Helm uninstall is performed. - type: boolean - keepHistory: - description: |- - KeepHistory tells Helm to remove all associated resources and mark the - release as deleted, but retain the release history. - type: boolean - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like - Jobs for hooks) during the performance of a Helm uninstall action. Defaults - to 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - upgrade: - description: Upgrade holds the configuration for Helm upgrade actions for this HelmRelease. - properties: - cleanupOnFail: - description: |- - CleanupOnFail allows deletion of new resources created during the Helm - upgrade action when it fails. - type: boolean - crds: - description: |- - CRDs upgrade CRDs from the Helm Chart's crds directory according - to the CRD upgrade policy provided here. Valid values are `Skip`, - `Create` or `CreateReplace`. Default is `Skip` and if omitted - CRDs are neither installed nor upgraded. - - Skip: do neither install nor replace (update) any CRDs. - - Create: new CRDs are created, existing CRDs are neither updated nor deleted. - - CreateReplace: new CRDs are created, existing CRDs are updated (replaced) - but not deleted. - - By default, CRDs are not applied during Helm upgrade action. With this - option users can opt-in to CRD upgrade, which is not (yet) natively supported by Helm. - https://helm.sh/docs/chart_best_practices/custom_resource_definitions. - enum: - - Skip - - Create - - CreateReplace - type: string - disableHooks: - description: DisableHooks prevents hooks from running during the Helm upgrade action. - type: boolean - disableOpenAPIValidation: - description: |- - DisableOpenAPIValidation prevents the Helm upgrade action from validating - rendered templates against the Kubernetes OpenAPI Schema. - type: boolean - disableSchemaValidation: - description: |- - DisableSchemaValidation prevents the Helm upgrade action from validating - the values against the JSON Schema. - type: boolean - disableTakeOwnership: - description: |- - DisableTakeOwnership disables taking ownership of existing resources - during the Helm upgrade action. Defaults to false. - type: boolean - disableWait: - description: |- - DisableWait disables the waiting for resources to be ready after a Helm - upgrade has been performed. - type: boolean - disableWaitForJobs: - description: |- - DisableWaitForJobs disables waiting for jobs to complete after a Helm - upgrade has been performed. - type: boolean - force: - description: Force forces resource updates through a replacement strategy. - type: boolean - preserveValues: - description: |- - PreserveValues will make Helm reuse the last release's values and merge in - overrides from 'Values'. Setting this flag makes the HelmRelease - non-declarative. - type: boolean - remediation: - description: |- - Remediation holds the remediation configuration for when the Helm upgrade - action for the HelmRelease fails. The default is to not perform any action. - properties: - ignoreTestFailures: - description: |- - IgnoreTestFailures tells the controller to skip remediation when the Helm - tests are run after an upgrade action but fail. - Defaults to 'Test.IgnoreFailures'. - type: boolean - remediateLastFailure: - description: |- - RemediateLastFailure tells the controller to remediate the last failure, when - no retries remain. Defaults to 'false' unless 'Retries' is greater than 0. - type: boolean - retries: - description: |- - Retries is the number of retries that should be attempted on failures before - bailing. Remediation, using 'Strategy', is performed between each attempt. - Defaults to '0', a negative integer equals to unlimited retries. - type: integer - strategy: - description: Strategy to use for failure remediation. Defaults to 'rollback'. - enum: - - rollback - - uninstall - type: string - type: object - strategy: - description: |- - Strategy defines the upgrade strategy to use for this HelmRelease. - Defaults to 'RemediateOnFailure'. - properties: - name: - description: Name of the upgrade strategy. - enum: - - RemediateOnFailure - - RetryOnFailure - type: string - retryInterval: - description: |- - RetryInterval is the interval at which to retry a failed upgrade. - Can be used only when Name is set to RetryOnFailure. - Defaults to '5m'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - required: - - name - type: object - x-kubernetes-validations: - - message: .retryInterval can only be set when .name is 'RetryOnFailure' - rule: '!has(self.retryInterval) || self.name == ''RetryOnFailure''' - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like - Jobs for hooks) during the performance of a Helm upgrade action. Defaults to - 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - values: - description: Values holds the values for this Helm release. - x-kubernetes-preserve-unknown-fields: true - valuesFrom: - description: |- - ValuesFrom holds references to resources containing Helm values for this HelmRelease, - and information about how they should be merged. - items: - description: |- - ValuesReference contains a reference to a resource containing Helm values, - and optionally the key they can be found at. - properties: - kind: - description: Kind of the values referent, valid values are ('Secret', 'ConfigMap'). - enum: - - Secret - - ConfigMap - type: string - name: - description: |- - Name of the values referent. Should reside in the same namespace as the - referring resource. - maxLength: 253 - minLength: 1 - type: string - optional: - description: |- - Optional marks this ValuesReference as optional. When set, a not found error - for the values reference is ignored, but any ValuesKey, TargetPath or - transient error will still result in a reconciliation failure. - type: boolean - targetPath: - description: |- - TargetPath is the YAML dot notation path the value should be merged at. When - set, the ValuesKey is expected to be a single flat value. Defaults to 'None', - which results in the values getting merged at the root. - maxLength: 250 - pattern: ^([a-zA-Z0-9_\-.\\\/]|\[[0-9]{1,5}\])+$ - type: string - valuesKey: - description: |- - ValuesKey is the data key where the values.yaml or a specific value can be - found at. Defaults to 'values.yaml'. - maxLength: 253 - pattern: ^[\-._a-zA-Z0-9]+$ - type: string - required: - - kind - - name - type: object - type: array - required: - - interval - type: object - x-kubernetes-validations: - - message: either chart or chartRef must be set - rule: (has(self.chart) && !has(self.chartRef)) || (!has(self.chart) && has(self.chartRef)) - status: - default: - observedGeneration: -1 - description: HelmReleaseStatus defines the observed state of a HelmRelease. - properties: - conditions: - description: Conditions holds the conditions for the HelmRelease. - 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 - failures: - description: |- - Failures is the reconciliation failure count against the latest desired - state. It is reset after a successful reconciliation. - format: int64 - type: integer - helmChart: - description: |- - HelmChart is the namespaced name of the HelmChart resource created by - the controller for the HelmRelease. - type: string - history: - description: |- - History holds the history of Helm releases performed for this HelmRelease - up to the last successfully completed release. - items: - description: |- - Snapshot captures a point-in-time copy of the status information for a Helm release, - as managed by the controller. - properties: - apiVersion: - description: |- - APIVersion is the API version of the Snapshot. - Provisional: when the calculation method of the Digest field is changed, - this field will be used to distinguish between the old and new methods. - type: string - appVersion: - description: AppVersion is the chart app version of the release object in storage. - type: string - chartName: - description: ChartName is the chart name of the release object in storage. - type: string - chartVersion: - description: |- - ChartVersion is the chart version of the release object in - storage. - type: string - configDigest: - description: |- - ConfigDigest is the checksum of the config (better known as - "values") of the release object in storage. - It has the format of `:`. - type: string - deleted: - description: Deleted is when the release was deleted. - format: date-time - type: string - digest: - description: |- - Digest is the checksum of the release object in storage. - It has the format of `:`. - type: string - firstDeployed: - description: FirstDeployed is when the release was first deployed. - format: date-time - type: string - lastDeployed: - description: LastDeployed is when the release was last deployed. - format: date-time - type: string - name: - description: Name is the name of the release. - type: string - namespace: - description: Namespace is the namespace the release is deployed to. - type: string - ociDigest: - description: OCIDigest is the digest of the OCI artifact associated with the release. - type: string - status: - description: Status is the current state of the release. - type: string - testHooks: - additionalProperties: - description: |- - TestHookStatus holds the status information for a test hook as observed - to be run by the controller. - properties: - lastCompleted: - description: LastCompleted is the time the test hook last completed. - format: date-time - type: string - lastStarted: - description: LastStarted is the time the test hook was last started. - format: date-time - type: string - phase: - description: Phase the test hook was observed to be in. - type: string - type: object - description: |- - TestHooks is the list of test hooks for the release as observed to be - run by the controller. - type: object - version: - description: Version is the version of the release object in storage. - type: integer - required: - - chartName - - chartVersion - - configDigest - - digest - - firstDeployed - - lastDeployed - - name - - namespace - - status - - version - type: object - type: array - installFailures: - description: |- - InstallFailures is the install failure count against the latest desired - state. It is reset after a successful reconciliation. - format: int64 - type: integer - lastAttemptedConfigDigest: - description: |- - LastAttemptedConfigDigest is the digest for the config (better known as - "values") of the last reconciliation attempt. - type: string - lastAttemptedGeneration: - description: |- - LastAttemptedGeneration is the last generation the controller attempted - to reconcile. - format: int64 - type: integer - lastAttemptedReleaseAction: - description: |- - LastAttemptedReleaseAction is the last release action performed for this - HelmRelease. It is used to determine the active retry or remediation - strategy. - enum: - - install - - upgrade - type: string - lastAttemptedReleaseActionDuration: - description: |- - LastAttemptedReleaseActionDuration is the duration of the last - release action performed for this HelmRelease. - type: string - lastAttemptedRevision: - description: |- - LastAttemptedRevision is the Source revision of the last reconciliation - attempt. For OCIRepository sources, the 12 first characters of the digest are - appended to the chart version e.g. "1.2.3+1234567890ab". - type: string - lastAttemptedRevisionDigest: - description: |- - LastAttemptedRevisionDigest is the digest of the last reconciliation attempt. - This is only set for OCIRepository sources. - type: string - lastAttemptedValuesChecksum: - description: |- - LastAttemptedValuesChecksum is the SHA1 checksum for the values of the last - reconciliation attempt. - - Deprecated: Use LastAttemptedConfigDigest instead. - type: string - lastHandledForceAt: - description: |- - LastHandledForceAt holds the value of the most recent - force request value, so a change of the annotation value - can be detected. - type: string - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - lastHandledResetAt: - description: |- - LastHandledResetAt holds the value of the most recent reset request - value, so a change of the annotation value can be detected. - type: string - lastReleaseRevision: - description: |- - LastReleaseRevision is the revision of the last successful Helm release. - - Deprecated: Use History instead. - type: integer - observedCommonMetadataDigest: - description: |- - ObservedCommonMetadataDigest is the digest for the common metadata of - the last successful reconciliation attempt. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - observedPostRenderersDigest: - description: |- - ObservedPostRenderersDigest is the digest for the post-renderers of - the last successful reconciliation attempt. - type: string - storageNamespace: - description: |- - StorageNamespace is the namespace of the Helm release storage for the - current release. - maxLength: 63 - minLength: 1 - type: string - upgradeFailures: - description: |- - UpgradeFailures is the upgrade failure count against the latest desired - state. It is reset after a successful reconciliation. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v2beta2 HelmRelease is deprecated, upgrade to v2 - name: v2beta2 - schema: - openAPIV3Schema: - description: HelmRelease is the Schema for the helmreleases 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: HelmReleaseSpec defines the desired state of a Helm release. - properties: - chart: - description: |- - Chart defines the template of the v1beta2.HelmChart that should be created - for this HelmRelease. - properties: - metadata: - description: ObjectMeta holds the template for metadata like labels and annotations. - 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: https://kubernetes.io/docs/concepts/overview/working-with-objects/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. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ - type: object - type: object - spec: - description: Spec holds the template for the v1beta2.HelmChartSpec for this HelmRelease. - properties: - chart: - description: The name or path the Helm chart is available at in the SourceRef. - maxLength: 2048 - minLength: 1 - type: string - ignoreMissingValuesFiles: - description: IgnoreMissingValuesFiles controls whether to silently ignore missing values files rather than failing. - type: boolean - interval: - description: |- - Interval at which to check the v1.Source for updates. Defaults to - 'HelmReleaseSpec.Interval'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - reconcileStrategy: - default: ChartVersion - description: |- - Determines what enables the creation of a new artifact. Valid values are - ('ChartVersion', 'Revision'). - See the documentation of the values for an explanation on their behavior. - Defaults to ChartVersion when omitted. - enum: - - ChartVersion - - Revision - type: string - sourceRef: - description: The name and namespace of the v1.Source the chart is available at. - properties: - apiVersion: - description: APIVersion of the referent. - type: string - kind: - description: Kind of the referent. - enum: - - HelmRepository - - GitRepository - - Bucket - type: string - name: - description: Name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace of the referent. - maxLength: 63 - minLength: 1 - type: string - required: - - kind - - name - type: object - valuesFile: - description: |- - Alternative values file to use as the default chart values, expected to - be a relative path in the SourceRef. Deprecated in favor of ValuesFiles, - for backwards compatibility the file defined here is merged before the - ValuesFiles items. Ignored when omitted. - type: string - valuesFiles: - description: |- - Alternative list of values files to use as the chart values (values.yaml - is not included by default), expected to be a relative path in the SourceRef. - Values files are merged in the order of this list with the last file overriding - the first. Ignored when omitted. - items: - type: string - type: array - verify: - description: |- - Verify contains the secret name containing the trusted public keys - used to verify the signature and specifies which provider to use to check - whether OCI image is authentic. - This field is only supported for OCI sources. - Chart dependencies, which are not bundled in the umbrella chart artifact, - are not verified. - properties: - provider: - default: cosign - description: Provider specifies the technology used to sign the OCI Helm chart. - enum: - - cosign - - notation - type: string - secretRef: - description: |- - SecretRef specifies the Kubernetes Secret containing the - trusted public keys. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - provider - type: object - version: - default: '*' - description: |- - Version semver expression, ignored for charts from v1beta2.GitRepository and - v1beta2.Bucket sources. Defaults to latest when omitted. - type: string - required: - - chart - - sourceRef - type: object - required: - - spec - type: object - chartRef: - description: |- - ChartRef holds a reference to a source controller resource containing the - Helm chart artifact. - - Note: this field is provisional to the v2 API, and not actively used - by v2beta2 HelmReleases. - properties: - apiVersion: - description: APIVersion of the referent. - type: string - kind: - description: Kind of the referent. - enum: - - OCIRepository - - HelmChart - type: string - name: - description: Name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace of the referent, defaults to the namespace of the Kubernetes - resource object that contains the reference. - maxLength: 63 - minLength: 1 - type: string - required: - - kind - - name - type: object - dependsOn: - description: |- - DependsOn may contain a meta.NamespacedObjectReference slice with - references to HelmRelease resources that must be ready before this HelmRelease - can be reconciled. - items: - description: |- - NamespacedObjectReference contains enough information to locate the referenced Kubernetes resource object in any - namespace. - properties: - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, when not specified it acts as LocalObjectReference. - type: string - required: - - name - type: object - type: array - driftDetection: - description: |- - DriftDetection holds the configuration for detecting and handling - differences between the manifest in the Helm storage and the resources - currently existing in the cluster. - properties: - ignore: - description: |- - Ignore contains a list of rules for specifying which changes to ignore - during diffing. - items: - description: |- - IgnoreRule defines a rule to selectively disregard specific changes during - the drift detection process. - properties: - paths: - description: |- - Paths is a list of JSON Pointer (RFC 6901) paths to be excluded from - consideration in a Kubernetes object. - items: - type: string - type: array - target: - description: |- - Target is a selector for specifying Kubernetes objects to which this - rule applies. - If Target is not set, the Paths will be ignored for all Kubernetes - objects within the manifest of the Helm release. - properties: - annotationSelector: - description: |- - AnnotationSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: |- - Group is the API group to select resources from. - Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: |- - Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: |- - LabelSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: |- - Version of the API Group to select resources from. - Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - paths - type: object - type: array - mode: - description: |- - Mode defines how differences should be handled between the Helm manifest - and the manifest currently applied to the cluster. - If not explicitly set, it defaults to DiffModeDisabled. - enum: - - enabled - - warn - - disabled - type: string - type: object - install: - description: Install holds the configuration for Helm install actions for this HelmRelease. - properties: - crds: - description: |- - CRDs upgrade CRDs from the Helm Chart's crds directory according - to the CRD upgrade policy provided here. Valid values are `Skip`, - `Create` or `CreateReplace`. Default is `Create` and if omitted - CRDs are installed but not updated. - - Skip: do neither install nor replace (update) any CRDs. - - Create: new CRDs are created, existing CRDs are neither updated nor deleted. - - CreateReplace: new CRDs are created, existing CRDs are updated (replaced) - but not deleted. - - By default, CRDs are applied (installed) during Helm install action. - With this option users can opt in to CRD replace existing CRDs on Helm - install actions, which is not (yet) natively supported by Helm. - https://helm.sh/docs/chart_best_practices/custom_resource_definitions. - enum: - - Skip - - Create - - CreateReplace - type: string - createNamespace: - description: |- - CreateNamespace tells the Helm install action to create the - HelmReleaseSpec.TargetNamespace if it does not exist yet. - On uninstall, the namespace will not be garbage collected. - type: boolean - disableHooks: - description: DisableHooks prevents hooks from running during the Helm install action. - type: boolean - disableOpenAPIValidation: - description: |- - DisableOpenAPIValidation prevents the Helm install action from validating - rendered templates against the Kubernetes OpenAPI Schema. - type: boolean - disableWait: - description: |- - DisableWait disables the waiting for resources to be ready after a Helm - install has been performed. - type: boolean - disableWaitForJobs: - description: |- - DisableWaitForJobs disables waiting for jobs to complete after a Helm - install has been performed. - type: boolean - remediation: - description: |- - Remediation holds the remediation configuration for when the Helm install - action for the HelmRelease fails. The default is to not perform any action. - properties: - ignoreTestFailures: - description: |- - IgnoreTestFailures tells the controller to skip remediation when the Helm - tests are run after an install action but fail. Defaults to - 'Test.IgnoreFailures'. - type: boolean - remediateLastFailure: - description: |- - RemediateLastFailure tells the controller to remediate the last failure, when - no retries remain. Defaults to 'false'. - type: boolean - retries: - description: |- - Retries is the number of retries that should be attempted on failures before - bailing. Remediation, using an uninstall, is performed between each attempt. - Defaults to '0', a negative integer equals to unlimited retries. - type: integer - type: object - replace: - description: |- - Replace tells the Helm install action to re-use the 'ReleaseName', but only - if that name is a deleted release which remains in the history. - type: boolean - skipCRDs: - description: |- - SkipCRDs tells the Helm install action to not install any CRDs. By default, - CRDs are installed if not already present. - - Deprecated use CRD policy (`crds`) attribute with value `Skip` instead. - type: boolean - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like - Jobs for hooks) during the performance of a Helm install action. Defaults to - 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - interval: - description: Interval at which to reconcile the Helm release. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - kubeConfig: - description: |- - KubeConfig for reconciling the HelmRelease on a remote cluster. - When used in combination with HelmReleaseSpec.ServiceAccountName, - forces the controller to act on behalf of that Service Account at the - target cluster. - If the --default-service-account flag is set, its value will be used as - a controller level fallback for when HelmReleaseSpec.ServiceAccountName - is empty. - properties: - configMapRef: - description: |- - ConfigMapRef holds an optional name of a ConfigMap that contains - the following keys: - - - `provider`: the provider to use. One of `aws`, `azure`, `gcp`, or - `generic`. Required. - - `cluster`: the fully qualified resource name of the Kubernetes - cluster in the cloud provider API. Not used by the `generic` - provider. Required when one of `address` or `ca.crt` is not set. - - `address`: the address of the Kubernetes API server. Required - for `generic`. For the other providers, if not specified, the - first address in the cluster resource will be used, and if - specified, it must match one of the addresses in the cluster - resource. - If audiences is not set, will be used as the audience for the - `generic` provider. - - `ca.crt`: the optional PEM-encoded CA certificate for the - Kubernetes API server. If not set, the controller will use the - CA certificate from the cluster resource. - - `audiences`: the optional audiences as a list of - line-break-separated strings for the Kubernetes ServiceAccount - token. Defaults to the `address` for the `generic` provider, or - to specific values for the other providers depending on the - provider. - - `serviceAccountName`: the optional name of the Kubernetes - ServiceAccount in the same namespace that should be used - for authentication. If not specified, the controller - ServiceAccount will be used. - - Mutually exclusive with SecretRef. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - secretRef: - description: |- - SecretRef holds an optional name of a secret that contains a key with - the kubeconfig file as the value. If no key is set, the key will default - to 'value'. Mutually exclusive with ConfigMapRef. - It is recommended that the kubeconfig is self-contained, and the secret - is regularly updated if credentials such as a cloud-access-token expire. - Cloud specific `cmd-path` auth helpers will not function without adding - binaries and credentials to the Pod that is responsible for reconciling - Kubernetes resources. Supported only for the generic provider. - properties: - key: - description: Key in the Secret, when not specified an implementation-specific default key is used. - type: string - name: - description: Name of the Secret. - type: string - required: - - name - type: object - type: object - x-kubernetes-validations: - - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified - rule: has(self.configMapRef) || has(self.secretRef) - - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified - rule: '!has(self.configMapRef) || !has(self.secretRef)' - maxHistory: - description: |- - MaxHistory is the number of revisions saved by Helm for this HelmRelease. - Use '0' for an unlimited number of revisions; defaults to '5'. - type: integer - persistentClient: - description: |- - PersistentClient tells the controller to use a persistent Kubernetes - client for this release. When enabled, the client will be reused for the - duration of the reconciliation, instead of being created and destroyed - for each (step of a) Helm action. - - This can improve performance, but may cause issues with some Helm charts - that for example do create Custom Resource Definitions during installation - outside Helm's CRD lifecycle hooks, which are then not observed to be - available by e.g. post-install hooks. - - If not set, it defaults to true. - type: boolean - postRenderers: - description: |- - PostRenderers holds an array of Helm PostRenderers, which will be applied in order - of their definition. - items: - description: PostRenderer contains a Helm PostRenderer specification. - properties: - kustomize: - description: Kustomization to apply as PostRenderer. - properties: - images: - description: |- - Images is a list of (image name, new name, new tag or digest) - for changing image names, tags or digests. This can also be achieved with a - patch, but this operator is simpler to specify. - items: - description: Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag. - properties: - digest: - description: |- - Digest is the value used to replace the original image tag. - If digest is present NewTag value is ignored. - type: string - name: - description: Name is a tag-less image name. - type: string - newName: - description: NewName is the value used to replace the original name. - type: string - newTag: - description: NewTag is the value used to replace the original tag. - type: string - required: - - name - type: object - type: array - patches: - description: |- - Strategic merge and JSON patches, defined as inline YAML objects, - capable of targeting objects based on kind, label and annotation selectors. - items: - description: |- - Patch contains an inline StrategicMerge or JSON6902 patch, and the target the patch should - be applied to. - properties: - patch: - description: |- - Patch contains an inline StrategicMerge patch or an inline JSON6902 patch with - an array of operation objects. - type: string - target: - description: Target points to the resources that the patch document should be applied to. - properties: - annotationSelector: - description: |- - AnnotationSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: |- - Group is the API group to select resources from. - Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: |- - Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: |- - LabelSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: |- - Version of the API Group to select resources from. - Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - type: object - type: array - patchesJson6902: - description: |- - JSON 6902 patches, defined as inline YAML objects. - - Deprecated: use Patches instead. - items: - description: JSON6902Patch contains a JSON6902 patch and the target the patch should be applied to. - properties: - patch: - description: Patch contains the JSON6902 patch document with an array of operation objects. - items: - description: |- - JSON6902 is a JSON6902 operation object. - https://datatracker.ietf.org/doc/html/rfc6902#section-4 - properties: - from: - description: |- - From contains a JSON-pointer value that references a location within the target document where the operation is - performed. The meaning of the value depends on the value of Op, and is NOT taken into account by all operations. - type: string - op: - description: |- - Op indicates the operation to perform. Its value MUST be one of "add", "remove", "replace", "move", "copy", or - "test". - https://datatracker.ietf.org/doc/html/rfc6902#section-4 - enum: - - test - - remove - - add - - replace - - move - - copy - type: string - path: - description: |- - Path contains the JSON-pointer value that references a location within the target document where the operation - is performed. The meaning of the value depends on the value of Op. - type: string - value: - description: |- - Value contains a valid JSON structure. The meaning of the value depends on the value of Op, and is NOT taken into - account by all operations. - x-kubernetes-preserve-unknown-fields: true - required: - - op - - path - type: object - type: array - target: - description: Target points to the resources that the patch document should be applied to. - properties: - annotationSelector: - description: |- - AnnotationSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: |- - Group is the API group to select resources from. - Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: |- - Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: |- - LabelSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: |- - Version of the API Group to select resources from. - Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - - target - type: object - type: array - patchesStrategicMerge: - description: |- - Strategic merge patches, defined as inline YAML objects. - - Deprecated: use Patches instead. - items: - x-kubernetes-preserve-unknown-fields: true - type: array - type: object - type: object - type: array - releaseName: - description: |- - ReleaseName used for the Helm release. Defaults to a composition of - '[TargetNamespace-]Name'. - maxLength: 53 - minLength: 1 - type: string - rollback: - description: Rollback holds the configuration for Helm rollback actions for this HelmRelease. - properties: - cleanupOnFail: - description: |- - CleanupOnFail allows deletion of new resources created during the Helm - rollback action when it fails. - type: boolean - disableHooks: - description: DisableHooks prevents hooks from running during the Helm rollback action. - type: boolean - disableWait: - description: |- - DisableWait disables the waiting for resources to be ready after a Helm - rollback has been performed. - type: boolean - disableWaitForJobs: - description: |- - DisableWaitForJobs disables waiting for jobs to complete after a Helm - rollback has been performed. - type: boolean - force: - description: Force forces resource updates through a replacement strategy. - type: boolean - recreate: - description: Recreate performs pod restarts for the resource if applicable. - type: boolean - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like - Jobs for hooks) during the performance of a Helm rollback action. Defaults to - 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - serviceAccountName: - description: |- - The name of the Kubernetes service account to impersonate - when reconciling this HelmRelease. - maxLength: 253 - minLength: 1 - type: string - storageNamespace: - description: |- - StorageNamespace used for the Helm storage. - Defaults to the namespace of the HelmRelease. - maxLength: 63 - minLength: 1 - type: string - suspend: - description: |- - Suspend tells the controller to suspend reconciliation for this HelmRelease, - it does not apply to already started reconciliations. Defaults to false. - type: boolean - targetNamespace: - description: |- - TargetNamespace to target when performing operations for the HelmRelease. - Defaults to the namespace of the HelmRelease. - maxLength: 63 - minLength: 1 - type: string - test: - description: Test holds the configuration for Helm test actions for this HelmRelease. - properties: - enable: - description: |- - Enable enables Helm test actions for this HelmRelease after an Helm install - or upgrade action has been performed. - type: boolean - filters: - description: Filters is a list of tests to run or exclude from running. - items: - description: Filter holds the configuration for individual Helm test filters. - properties: - exclude: - description: Exclude specifies whether the named test should be excluded. - type: boolean - name: - description: Name is the name of the test. - maxLength: 253 - minLength: 1 - type: string - required: - - name - type: object - type: array - ignoreFailures: - description: |- - IgnoreFailures tells the controller to skip remediation when the Helm tests - are run but fail. Can be overwritten for tests run after install or upgrade - actions in 'Install.IgnoreTestFailures' and 'Upgrade.IgnoreTestFailures'. - type: boolean - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation during - the performance of a Helm test action. Defaults to 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like Jobs - for hooks) during the performance of a Helm action. Defaults to '5m0s'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - uninstall: - description: Uninstall holds the configuration for Helm uninstall actions for this HelmRelease. - properties: - deletionPropagation: - default: background - description: |- - DeletionPropagation specifies the deletion propagation policy when - a Helm uninstall is performed. - enum: - - background - - foreground - - orphan - type: string - disableHooks: - description: DisableHooks prevents hooks from running during the Helm rollback action. - type: boolean - disableWait: - description: |- - DisableWait disables waiting for all the resources to be deleted after - a Helm uninstall is performed. - type: boolean - keepHistory: - description: |- - KeepHistory tells Helm to remove all associated resources and mark the - release as deleted, but retain the release history. - type: boolean - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like - Jobs for hooks) during the performance of a Helm uninstall action. Defaults - to 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - upgrade: - description: Upgrade holds the configuration for Helm upgrade actions for this HelmRelease. - properties: - cleanupOnFail: - description: |- - CleanupOnFail allows deletion of new resources created during the Helm - upgrade action when it fails. - type: boolean - crds: - description: |- - CRDs upgrade CRDs from the Helm Chart's crds directory according - to the CRD upgrade policy provided here. Valid values are `Skip`, - `Create` or `CreateReplace`. Default is `Skip` and if omitted - CRDs are neither installed nor upgraded. - - Skip: do neither install nor replace (update) any CRDs. - - Create: new CRDs are created, existing CRDs are neither updated nor deleted. - - CreateReplace: new CRDs are created, existing CRDs are updated (replaced) - but not deleted. - - By default, CRDs are not applied during Helm upgrade action. With this - option users can opt-in to CRD upgrade, which is not (yet) natively supported by Helm. - https://helm.sh/docs/chart_best_practices/custom_resource_definitions. - enum: - - Skip - - Create - - CreateReplace - type: string - disableHooks: - description: DisableHooks prevents hooks from running during the Helm upgrade action. - type: boolean - disableOpenAPIValidation: - description: |- - DisableOpenAPIValidation prevents the Helm upgrade action from validating - rendered templates against the Kubernetes OpenAPI Schema. - type: boolean - disableWait: - description: |- - DisableWait disables the waiting for resources to be ready after a Helm - upgrade has been performed. - type: boolean - disableWaitForJobs: - description: |- - DisableWaitForJobs disables waiting for jobs to complete after a Helm - upgrade has been performed. - type: boolean - force: - description: Force forces resource updates through a replacement strategy. - type: boolean - preserveValues: - description: |- - PreserveValues will make Helm reuse the last release's values and merge in - overrides from 'Values'. Setting this flag makes the HelmRelease - non-declarative. - type: boolean - remediation: - description: |- - Remediation holds the remediation configuration for when the Helm upgrade - action for the HelmRelease fails. The default is to not perform any action. - properties: - ignoreTestFailures: - description: |- - IgnoreTestFailures tells the controller to skip remediation when the Helm - tests are run after an upgrade action but fail. - Defaults to 'Test.IgnoreFailures'. - type: boolean - remediateLastFailure: - description: |- - RemediateLastFailure tells the controller to remediate the last failure, when - no retries remain. Defaults to 'false' unless 'Retries' is greater than 0. - type: boolean - retries: - description: |- - Retries is the number of retries that should be attempted on failures before - bailing. Remediation, using 'Strategy', is performed between each attempt. - Defaults to '0', a negative integer equals to unlimited retries. - type: integer - strategy: - description: Strategy to use for failure remediation. Defaults to 'rollback'. - enum: - - rollback - - uninstall - type: string - type: object - timeout: - description: |- - Timeout is the time to wait for any individual Kubernetes operation (like - Jobs for hooks) during the performance of a Helm upgrade action. Defaults to - 'HelmReleaseSpec.Timeout'. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - type: object - values: - description: Values holds the values for this Helm release. - x-kubernetes-preserve-unknown-fields: true - valuesFrom: - description: |- - ValuesFrom holds references to resources containing Helm values for this HelmRelease, - and information about how they should be merged. - items: - description: |- - ValuesReference contains a reference to a resource containing Helm values, - and optionally the key they can be found at. - properties: - kind: - description: Kind of the values referent, valid values are ('Secret', 'ConfigMap'). - enum: - - Secret - - ConfigMap - type: string - name: - description: |- - Name of the values referent. Should reside in the same namespace as the - referring resource. - maxLength: 253 - minLength: 1 - type: string - optional: - description: |- - Optional marks this ValuesReference as optional. When set, a not found error - for the values reference is ignored, but any ValuesKey, TargetPath or - transient error will still result in a reconciliation failure. - type: boolean - targetPath: - description: |- - TargetPath is the YAML dot notation path the value should be merged at. When - set, the ValuesKey is expected to be a single flat value. Defaults to 'None', - which results in the values getting merged at the root. - maxLength: 250 - pattern: ^([a-zA-Z0-9_\-.\\\/]|\[[0-9]{1,5}\])+$ - type: string - valuesKey: - description: |- - ValuesKey is the data key where the values.yaml or a specific value can be - found at. Defaults to 'values.yaml'. - maxLength: 253 - pattern: ^[\-._a-zA-Z0-9]+$ - type: string - required: - - kind - - name - type: object - type: array - required: - - interval - type: object - x-kubernetes-validations: - - message: either chart or chartRef must be set - rule: (has(self.chart) && !has(self.chartRef)) || (!has(self.chart) && has(self.chartRef)) - status: - default: - observedGeneration: -1 - description: HelmReleaseStatus defines the observed state of a HelmRelease. - properties: - conditions: - description: Conditions holds the conditions for the HelmRelease. - 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 - failures: - description: |- - Failures is the reconciliation failure count against the latest desired - state. It is reset after a successful reconciliation. - format: int64 - type: integer - helmChart: - description: |- - HelmChart is the namespaced name of the HelmChart resource created by - the controller for the HelmRelease. - type: string - history: - description: |- - History holds the history of Helm releases performed for this HelmRelease - up to the last successfully completed release. - items: - description: |- - Snapshot captures a point-in-time copy of the status information for a Helm release, - as managed by the controller. - properties: - apiVersion: - description: |- - APIVersion is the API version of the Snapshot. - Provisional: when the calculation method of the Digest field is changed, - this field will be used to distinguish between the old and new methods. - type: string - appVersion: - description: AppVersion is the chart app version of the release object in storage. - type: string - chartName: - description: ChartName is the chart name of the release object in storage. - type: string - chartVersion: - description: |- - ChartVersion is the chart version of the release object in - storage. - type: string - configDigest: - description: |- - ConfigDigest is the checksum of the config (better known as - "values") of the release object in storage. - It has the format of `:`. - type: string - deleted: - description: Deleted is when the release was deleted. - format: date-time - type: string - digest: - description: |- - Digest is the checksum of the release object in storage. - It has the format of `:`. - type: string - firstDeployed: - description: FirstDeployed is when the release was first deployed. - format: date-time - type: string - lastDeployed: - description: LastDeployed is when the release was last deployed. - format: date-time - type: string - name: - description: Name is the name of the release. - type: string - namespace: - description: Namespace is the namespace the release is deployed to. - type: string - ociDigest: - description: OCIDigest is the digest of the OCI artifact associated with the release. - type: string - status: - description: Status is the current state of the release. - type: string - testHooks: - additionalProperties: - description: |- - TestHookStatus holds the status information for a test hook as observed - to be run by the controller. - properties: - lastCompleted: - description: LastCompleted is the time the test hook last completed. - format: date-time - type: string - lastStarted: - description: LastStarted is the time the test hook was last started. - format: date-time - type: string - phase: - description: Phase the test hook was observed to be in. - type: string - type: object - description: |- - TestHooks is the list of test hooks for the release as observed to be - run by the controller. - type: object - version: - description: Version is the version of the release object in storage. - type: integer - required: - - chartName - - chartVersion - - configDigest - - digest - - firstDeployed - - lastDeployed - - name - - namespace - - status - - version - type: object - type: array - installFailures: - description: |- - InstallFailures is the install failure count against the latest desired - state. It is reset after a successful reconciliation. - format: int64 - type: integer - lastAppliedRevision: - description: |- - LastAppliedRevision is the revision of the last successfully applied - source. - - Deprecated: the revision can now be found in the History. - type: string - lastAttemptedConfigDigest: - description: |- - LastAttemptedConfigDigest is the digest for the config (better known as - "values") of the last reconciliation attempt. - type: string - lastAttemptedGeneration: - description: |- - LastAttemptedGeneration is the last generation the controller attempted - to reconcile. - format: int64 - type: integer - lastAttemptedReleaseAction: - description: |- - LastAttemptedReleaseAction is the last release action performed for this - HelmRelease. It is used to determine the active remediation strategy. - enum: - - install - - upgrade - type: string - lastAttemptedRevision: - description: |- - LastAttemptedRevision is the Source revision of the last reconciliation - attempt. For OCIRepository sources, the 12 first characters of the digest are - appended to the chart version e.g. "1.2.3+1234567890ab". - type: string - lastAttemptedRevisionDigest: - description: |- - LastAttemptedRevisionDigest is the digest of the last reconciliation attempt. - This is only set for OCIRepository sources. - type: string - lastAttemptedValuesChecksum: - description: |- - LastAttemptedValuesChecksum is the SHA1 checksum for the values of the last - reconciliation attempt. - - Deprecated: Use LastAttemptedConfigDigest instead. - type: string - lastHandledForceAt: - description: |- - LastHandledForceAt holds the value of the most recent force request - value, so a change of the annotation value can be detected. - type: string - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - lastHandledResetAt: - description: |- - LastHandledResetAt holds the value of the most recent reset request - value, so a change of the annotation value can be detected. - type: string - lastReleaseRevision: - description: |- - LastReleaseRevision is the revision of the last successful Helm release. - - Deprecated: Use History instead. - type: integer - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - observedPostRenderersDigest: - description: |- - ObservedPostRenderersDigest is the digest for the post-renderers of - the last successful reconciliation attempt. - type: string - storageNamespace: - description: |- - StorageNamespace is the namespace of the Helm release storage for the - current release. - maxLength: 63 - minLength: 1 - type: string - upgradeFailures: - description: |- - UpgradeFailures is the upgrade failure count against the latest desired - state. It is reset after a successful reconciliation. - format: int64 - type: integer - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: helmrepositories.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: HelmRepository - listKind: HelmRepositoryList - plural: helmrepositories - shortNames: - - helmrepo - singular: helmrepository - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - name: v1 - schema: - openAPIV3Schema: - description: HelmRepository is the Schema for the helmrepositories 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: |- - HelmRepositorySpec specifies the required configuration to produce an - Artifact for a Helm repository index YAML. - properties: - accessFrom: - description: |- - AccessFrom specifies an Access Control List for allowing cross-namespace - references to this object. - NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 - properties: - namespaceSelectors: - description: |- - NamespaceSelectors is the list of namespace selectors to which this ACL applies. - Items in this list are evaluated using a logical OR operation. - items: - description: |- - NamespaceSelector selects the namespaces to which this ACL applies. - An empty map of MatchLabels matches all namespaces in a cluster. - properties: - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - type: array - required: - - namespaceSelectors - type: object - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - registry. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - It takes precedence over the values specified in the Secret referred - to by `.spec.secretRef`. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - insecure: - description: |- - Insecure allows connecting to a non-TLS HTTP container registry. - This field is only taken into account if the .spec.type field is set to 'oci'. - type: boolean - interval: - description: |- - Interval at which the HelmRepository URL is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - passCredentials: - description: |- - PassCredentials allows the credentials from the SecretRef to be passed - on to a host that does not match the host as defined in URL. - This may be required if the host of the advertised chart URLs in the - index differ from the defined URL. - Enabling this should be done with caution, as it can potentially result - in credentials getting stolen in a MITM-attack. - type: boolean - provider: - default: generic - description: |- - Provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. - This field is optional, and only taken into account if the .spec.type field is set to 'oci'. - When not specified, defaults to 'generic'. - enum: - - generic - - aws - - azure - - gcp - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing authentication credentials - for the HelmRepository. - For HTTP/S basic auth the secret must contain 'username' and 'password' - fields. - Support for TLS auth using the 'certFile' and 'keyFile', and/or 'caFile' - keys is deprecated. Please use `.spec.certSecretRef` instead. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - suspend: - description: |- - Suspend tells the controller to suspend the reconciliation of this - HelmRepository. - type: boolean - timeout: - description: |- - Timeout is used for the index fetch operation for an HTTPS helm repository, - and for remote OCI Repository operations like pulling for an OCI helm - chart by the associated HelmChart. - Its default value is 60s. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - type: - description: |- - Type of the HelmRepository. - When this field is set to "oci", the URL field value must be prefixed with "oci://". - enum: - - default - - oci - type: string - url: - description: |- - URL of the Helm repository, a valid URL contains at least a protocol and - host. - pattern: ^(http|https|oci)://.*$ - type: string - required: - - url - type: object - status: - default: - observedGeneration: -1 - description: HelmRepositoryStatus records the observed state of the HelmRepository. - properties: - artifact: - description: Artifact represents the last successful HelmRepository reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the HelmRepository. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: |- - ObservedGeneration is the last observed generation of the HelmRepository - object. - format: int64 - type: integer - url: - description: |- - URL is the dynamic fetch link for the latest Artifact. - It is provided on a "best effort" basis, and using the precise - HelmRepositoryStatus.Artifact data is recommended. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v1beta2 HelmRepository is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: HelmRepository is the Schema for the helmrepositories 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: |- - HelmRepositorySpec specifies the required configuration to produce an - Artifact for a Helm repository index YAML. - properties: - accessFrom: - description: |- - AccessFrom specifies an Access Control List for allowing cross-namespace - references to this object. - NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 - properties: - namespaceSelectors: - description: |- - NamespaceSelectors is the list of namespace selectors to which this ACL applies. - Items in this list are evaluated using a logical OR operation. - items: - description: |- - NamespaceSelector selects the namespaces to which this ACL applies. - An empty map of MatchLabels matches all namespaces in a cluster. - properties: - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - type: array - required: - - namespaceSelectors - type: object - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - registry. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - It takes precedence over the values specified in the Secret referred - to by `.spec.secretRef`. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - insecure: - description: |- - Insecure allows connecting to a non-TLS HTTP container registry. - This field is only taken into account if the .spec.type field is set to 'oci'. - type: boolean - interval: - description: |- - Interval at which the HelmRepository URL is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - passCredentials: - description: |- - PassCredentials allows the credentials from the SecretRef to be passed - on to a host that does not match the host as defined in URL. - This may be required if the host of the advertised chart URLs in the - index differ from the defined URL. - Enabling this should be done with caution, as it can potentially result - in credentials getting stolen in a MITM-attack. - type: boolean - provider: - default: generic - description: |- - Provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. - This field is optional, and only taken into account if the .spec.type field is set to 'oci'. - When not specified, defaults to 'generic'. - enum: - - generic - - aws - - azure - - gcp - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing authentication credentials - for the HelmRepository. - For HTTP/S basic auth the secret must contain 'username' and 'password' - fields. - Support for TLS auth using the 'certFile' and 'keyFile', and/or 'caFile' - keys is deprecated. Please use `.spec.certSecretRef` instead. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - suspend: - description: |- - Suspend tells the controller to suspend the reconciliation of this - HelmRepository. - type: boolean - timeout: - description: |- - Timeout is used for the index fetch operation for an HTTPS helm repository, - and for remote OCI Repository operations like pulling for an OCI helm - chart by the associated HelmChart. - Its default value is 60s. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - type: - description: |- - Type of the HelmRepository. - When this field is set to "oci", the URL field value must be prefixed with "oci://". - enum: - - default - - oci - type: string - url: - description: |- - URL of the Helm repository, a valid URL contains at least a protocol and - host. - pattern: ^(http|https|oci)://.*$ - type: string - required: - - url - type: object - status: - default: - observedGeneration: -1 - description: HelmRepositoryStatus records the observed state of the HelmRepository. - properties: - artifact: - description: Artifact represents the last successful HelmRepository reconciliation. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the HelmRepository. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: |- - ObservedGeneration is the last observed generation of the HelmRepository - object. - format: int64 - type: integer - url: - description: |- - URL is the dynamic fetch link for the latest Artifact. - It is provided on a "best effort" basis, and using the precise - HelmRepositoryStatus.Artifact data is recommended. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: imagepolicies.image.toolkit.fluxcd.io -spec: - group: image.toolkit.fluxcd.io - names: - kind: ImagePolicy - listKind: ImagePolicyList - plural: imagepolicies - shortNames: - - imgpol - - imagepol - singular: imagepolicy - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.latestRef.name - name: Image - type: string - - jsonPath: .status.latestRef.tag - name: Tag - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: ImagePolicy is the Schema for the imagepolicies 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: |- - ImagePolicySpec defines the parameters for calculating the - ImagePolicy. - properties: - digestReflectionPolicy: - default: Never - description: |- - DigestReflectionPolicy governs the setting of the `.status.latestRef.digest` field. - - Never: The digest field will always be set to the empty string. - - IfNotPresent: The digest field will be set to the digest of the elected - latest image if the field is empty and the image did not change. - - Always: The digest field will always be set to the digest of the elected - latest image. - - Default: Never. - enum: - - Always - - IfNotPresent - - Never - type: string - filterTags: - description: |- - FilterTags enables filtering for only a subset of tags based on a set of - rules. If no rules are provided, all the tags from the repository will be - ordered and compared. - properties: - extract: - description: |- - Extract allows a capture group to be extracted from the specified regular - expression pattern, useful before tag evaluation. - type: string - pattern: - description: |- - Pattern specifies a regular expression pattern used to filter for image - tags. - type: string - type: object - imageRepositoryRef: - description: |- - ImageRepositoryRef points at the object specifying the image - being scanned - properties: - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, when not specified it acts as LocalObjectReference. - type: string - required: - - name - type: object - interval: - description: |- - Interval is the length of time to wait between - refreshing the digest of the latest tag when the - reflection policy is set to "Always". - - Defaults to 10m. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - policy: - description: |- - Policy gives the particulars of the policy to be followed in - selecting the most recent image - properties: - alphabetical: - description: Alphabetical set of rules to use for alphabetical ordering of the tags. - properties: - order: - default: asc - description: |- - Order specifies the sorting order of the tags. Given the letters of the - alphabet as tags, ascending order would select Z, and descending order - would select A. - enum: - - asc - - desc - type: string - type: object - numerical: - description: Numerical set of rules to use for numerical ordering of the tags. - properties: - order: - default: asc - description: |- - Order specifies the sorting order of the tags. Given the integer values - from 0 to 9 as tags, ascending order would select 9, and descending order - would select 0. - enum: - - asc - - desc - type: string - type: object - semver: - description: |- - SemVer gives a semantic version range to check against the tags - available. - properties: - range: - description: |- - Range gives a semver range for the image tag; the highest - version within the range that's a tag yields the latest image. - type: string - required: - - range - type: object - type: object - suspend: - description: |- - This flag tells the controller to suspend subsequent policy reconciliations. - It does not apply to already started reconciliations. Defaults to false. - type: boolean - required: - - imageRepositoryRef - - policy - type: object - x-kubernetes-validations: - - message: spec.interval is only accepted when spec.digestReflectionPolicy is set to 'Always' - rule: '!has(self.interval) || (has(self.digestReflectionPolicy) && self.digestReflectionPolicy == ''Always'')' - - message: spec.interval must be set when spec.digestReflectionPolicy is set to 'Always' - rule: has(self.interval) || !has(self.digestReflectionPolicy) || self.digestReflectionPolicy != 'Always' - status: - default: - observedGeneration: -1 - description: ImagePolicyStatus defines the observed state of ImagePolicy - properties: - conditions: - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - latestRef: - description: |- - LatestRef gives the first in the list of images scanned by - the image repository, when filtered and ordered according - to the policy. - properties: - digest: - description: Digest is the image's digest. - type: string - name: - description: Name is the bare image's name. - type: string - tag: - description: Tag is the image's tag. - type: string - required: - - name - - tag - type: object - observedGeneration: - format: int64 - type: integer - observedPreviousRef: - description: |- - ObservedPreviousRef is the observed previous LatestRef. It is used - to keep track of the previous and current images. - properties: - digest: - description: Digest is the image's digest. - type: string - name: - description: Name is the bare image's name. - type: string - tag: - description: Tag is the image's tag. - type: string - required: - - name - - tag - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .status.latestRef.name - name: Image - type: string - - jsonPath: .status.latestRef.tag - name: Tag - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - deprecated: true - deprecationWarning: v1beta2 ImagePolicy is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: ImagePolicy is the Schema for the imagepolicies 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: |- - ImagePolicySpec defines the parameters for calculating the - ImagePolicy. - properties: - digestReflectionPolicy: - default: Never - description: |- - DigestReflectionPolicy governs the setting of the `.status.latestRef.digest` field. - - Never: The digest field will always be set to the empty string. - - IfNotPresent: The digest field will be set to the digest of the elected - latest image if the field is empty and the image did not change. - - Always: The digest field will always be set to the digest of the elected - latest image. - - Default: Never. - enum: - - Always - - IfNotPresent - - Never - type: string - filterTags: - description: |- - FilterTags enables filtering for only a subset of tags based on a set of - rules. If no rules are provided, all the tags from the repository will be - ordered and compared. - properties: - extract: - description: |- - Extract allows a capture group to be extracted from the specified regular - expression pattern, useful before tag evaluation. - type: string - pattern: - description: |- - Pattern specifies a regular expression pattern used to filter for image - tags. - type: string - type: object - imageRepositoryRef: - description: |- - ImageRepositoryRef points at the object specifying the image - being scanned - properties: - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, when not specified it acts as LocalObjectReference. - type: string - required: - - name - type: object - interval: - description: |- - Interval is the length of time to wait between - refreshing the digest of the latest tag when the - reflection policy is set to "Always". - - Defaults to 10m. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - policy: - description: |- - Policy gives the particulars of the policy to be followed in - selecting the most recent image - properties: - alphabetical: - description: Alphabetical set of rules to use for alphabetical ordering of the tags. - properties: - order: - default: asc - description: |- - Order specifies the sorting order of the tags. Given the letters of the - alphabet as tags, ascending order would select Z, and descending order - would select A. - enum: - - asc - - desc - type: string - type: object - numerical: - description: Numerical set of rules to use for numerical ordering of the tags. - properties: - order: - default: asc - description: |- - Order specifies the sorting order of the tags. Given the integer values - from 0 to 9 as tags, ascending order would select 9, and descending order - would select 0. - enum: - - asc - - desc - type: string - type: object - semver: - description: |- - SemVer gives a semantic version range to check against the tags - available. - properties: - range: - description: |- - Range gives a semver range for the image tag; the highest - version within the range that's a tag yields the latest image. - type: string - required: - - range - type: object - type: object - suspend: - description: |- - This flag tells the controller to suspend subsequent policy reconciliations. - It does not apply to already started reconciliations. Defaults to false. - type: boolean - required: - - imageRepositoryRef - - policy - type: object - x-kubernetes-validations: - - message: spec.interval is only accepted when spec.digestReflectionPolicy is set to 'Always' - rule: '!has(self.interval) || (has(self.digestReflectionPolicy) && self.digestReflectionPolicy == ''Always'')' - - message: spec.interval must be set when spec.digestReflectionPolicy is set to 'Always' - rule: has(self.interval) || !has(self.digestReflectionPolicy) || self.digestReflectionPolicy != 'Always' - status: - default: - observedGeneration: -1 - description: ImagePolicyStatus defines the observed state of ImagePolicy - properties: - conditions: - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - latestRef: - description: |- - LatestRef gives the first in the list of images scanned by - the image repository, when filtered and ordered according - to the policy. - properties: - digest: - description: Digest is the image's digest. - type: string - name: - description: Name is the bare image's name. - type: string - tag: - description: Tag is the image's tag. - type: string - required: - - name - - tag - type: object - observedGeneration: - format: int64 - type: integer - observedPreviousRef: - description: |- - ObservedPreviousRef is the observed previous LatestRef. It is used - to keep track of the previous and current images. - properties: - digest: - description: Digest is the image's digest. - type: string - name: - description: Name is the bare image's name. - type: string - tag: - description: Tag is the image's tag. - type: string - required: - - name - - tag - type: object - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: imagerepositories.image.toolkit.fluxcd.io -spec: - group: image.toolkit.fluxcd.io - names: - kind: ImageRepository - listKind: ImageRepositoryList - plural: imagerepositories - shortNames: - - imgrepo - - imagerepo - singular: imagerepository - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.image - name: Image - type: string - - jsonPath: .status.lastScanResult.tagCount - name: Tags - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .status.lastScanResult.scanTime - name: Last scan - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: ImageRepository is the Schema for the imagerepositories 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: |- - ImageRepositorySpec defines the parameters for scanning an image - repository, e.g., `fluxcd/flux`. - properties: - accessFrom: - description: |- - AccessFrom defines an ACL for allowing cross-namespace references - to the ImageRepository object based on the caller's namespace labels. - properties: - namespaceSelectors: - description: |- - NamespaceSelectors is the list of namespace selectors to which this ACL applies. - Items in this list are evaluated using a logical OR operation. - items: - description: |- - NamespaceSelector selects the namespaces to which this ACL applies. - An empty map of MatchLabels matches all namespaces in a cluster. - properties: - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - type: array - required: - - namespaceSelectors - type: object - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - registry. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - Note: Support for the `caFile`, `certFile` and `keyFile` keys has - been deprecated. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - exclusionList: - default: - - ^.*\.sig$ - description: |- - ExclusionList is a list of regex strings used to exclude certain tags - from being stored in the database. - items: - type: string - maxItems: 25 - type: array - image: - description: Image is the name of the image repository - type: string - insecure: - description: Insecure allows connecting to a non-TLS HTTP container registry. - type: boolean - interval: - description: |- - Interval is the length of time to wait between - scans of the image repository. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - provider: - default: generic - description: |- - The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. - When not specified, defaults to 'generic'. - enum: - - generic - - aws - - azure - - gcp - type: string - proxySecretRef: - description: |- - ProxySecretRef specifies the Secret containing the proxy configuration - to use while communicating with the container registry. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - secretRef: - description: |- - SecretRef can be given the name of a secret containing - credentials to use for the image registry. The secret should be - created with `kubectl create secret docker-registry`, or the - equivalent. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate - the image pull if the service account has attached pull secrets. - maxLength: 253 - type: string - suspend: - description: |- - This flag tells the controller to suspend subsequent image scans. - It does not apply to already started scans. Defaults to false. - type: boolean - timeout: - description: |- - Timeout for image scanning. - Defaults to 'Interval' duration. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - required: - - image - - interval - type: object - status: - default: - observedGeneration: -1 - description: ImageRepositoryStatus defines the observed state of ImageRepository - properties: - canonicalImageName: - description: |- - CanonicalName is the name of the image repository with all the - implied bits made explicit; e.g., `docker.io/library/alpine` - rather than `alpine`. - type: string - conditions: - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - lastScanResult: - description: LastScanResult contains the number of fetched tags. - properties: - latestTags: - description: |- - LatestTags is a small sample of the tags found in the last scan. - It's the first 10 tags when sorting all the tags in descending - alphabetical order. - items: - type: string - type: array - revision: - description: Revision is a stable hash of the scanned tags. - type: string - scanTime: - description: ScanTime is the time when the last scan was performed. - format: date-time - type: string - tagCount: - description: TagCount is the number of tags found in the last scan. - type: integer - required: - - tagCount - type: object - observedExclusionList: - description: |- - ObservedExclusionList is a list of observed exclusion list. It reflects - the exclusion rules used for the observed scan result in - spec.lastScanResult. - items: - type: string - type: array - observedGeneration: - description: ObservedGeneration is the last reconciled generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.image - name: Image - type: string - - jsonPath: .status.lastScanResult.tagCount - name: Tags - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .status.lastScanResult.scanTime - name: Last scan - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - deprecated: true - deprecationWarning: v1beta2 ImageRepository is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: ImageRepository is the Schema for the imagerepositories 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: |- - ImageRepositorySpec defines the parameters for scanning an image - repository, e.g., `fluxcd/flux`. - properties: - accessFrom: - description: |- - AccessFrom defines an ACL for allowing cross-namespace references - to the ImageRepository object based on the caller's namespace labels. - properties: - namespaceSelectors: - description: |- - NamespaceSelectors is the list of namespace selectors to which this ACL applies. - Items in this list are evaluated using a logical OR operation. - items: - description: |- - NamespaceSelector selects the namespaces to which this ACL applies. - An empty map of MatchLabels matches all namespaces in a cluster. - properties: - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - type: array - required: - - namespaceSelectors - type: object - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - registry. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - Note: Support for the `caFile`, `certFile` and `keyFile` keys has - been deprecated. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - exclusionList: - default: - - ^.*\.sig$ - description: |- - ExclusionList is a list of regex strings used to exclude certain tags - from being stored in the database. - items: - type: string - maxItems: 25 - type: array - image: - description: Image is the name of the image repository - type: string - insecure: - description: Insecure allows connecting to a non-TLS HTTP container registry. - type: boolean - interval: - description: |- - Interval is the length of time to wait between - scans of the image repository. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - provider: - default: generic - description: |- - The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. - When not specified, defaults to 'generic'. - enum: - - generic - - aws - - azure - - gcp - type: string - proxySecretRef: - description: |- - ProxySecretRef specifies the Secret containing the proxy configuration - to use while communicating with the container registry. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - secretRef: - description: |- - SecretRef can be given the name of a secret containing - credentials to use for the image registry. The secret should be - created with `kubectl create secret docker-registry`, or the - equivalent. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate - the image pull if the service account has attached pull secrets. - maxLength: 253 - type: string - suspend: - description: |- - This flag tells the controller to suspend subsequent image scans. - It does not apply to already started scans. Defaults to false. - type: boolean - timeout: - description: |- - Timeout for image scanning. - Defaults to 'Interval' duration. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - required: - - image - - interval - type: object - status: - default: - observedGeneration: -1 - description: ImageRepositoryStatus defines the observed state of ImageRepository - properties: - canonicalImageName: - description: |- - CanonicalName is the name of the image repository with all the - implied bits made explicit; e.g., `docker.io/library/alpine` - rather than `alpine`. - type: string - conditions: - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - lastScanResult: - description: LastScanResult contains the number of fetched tags. - properties: - latestTags: - description: |- - LatestTags is a small sample of the tags found in the last scan. - It's the first 10 tags when sorting all the tags in descending - alphabetical order. - items: - type: string - type: array - revision: - description: Revision is a stable hash of the scanned tags. - type: string - scanTime: - description: ScanTime is the time when the last scan was performed. - format: date-time - type: string - tagCount: - description: TagCount is the number of tags found in the last scan. - type: integer - required: - - tagCount - type: object - observedExclusionList: - description: |- - ObservedExclusionList is a list of observed exclusion list. It reflects - the exclusion rules used for the observed scan result in - spec.lastScanResult. - items: - type: string - type: array - observedGeneration: - description: ObservedGeneration is the last reconciled generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: imageupdateautomations.image.toolkit.fluxcd.io -spec: - group: image.toolkit.fluxcd.io - names: - kind: ImageUpdateAutomation - listKind: ImageUpdateAutomationList - plural: imageupdateautomations - shortNames: - - iua - - imgupd - - imgauto - singular: imageupdateautomation - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .status.lastAutomationRunTime - name: Last run - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: ImageUpdateAutomation is the Schema for the imageupdateautomations 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: ImageUpdateAutomationSpec defines the desired state of ImageUpdateAutomation - properties: - git: - description: |- - GitSpec contains all the git-specific definitions. This is - technically optional, but in practice mandatory until there are - other kinds of source allowed. - properties: - checkout: - description: |- - Checkout gives the parameters for cloning the git repository, - ready to make changes. If not present, the `spec.ref` field from the - referenced `GitRepository` or its default will be used. - properties: - ref: - description: |- - Reference gives a branch, tag or commit to clone from the Git - repository. - properties: - branch: - description: Branch to check out, defaults to 'master' if no other field is defined. - type: string - commit: - description: |- - Commit SHA to check out, takes precedence over all reference fields. - - This can be combined with Branch to shallow clone the branch, in which - the commit is expected to exist. - type: string - name: - description: |- - Name of the reference to check out; takes precedence over Branch, Tag and SemVer. - - It must be a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description - Examples: "refs/heads/main", "refs/tags/v0.1.0", "refs/pull/420/head", "refs/merge-requests/1/head" - type: string - semver: - description: SemVer tag expression to check out, takes precedence over Tag. - type: string - tag: - description: Tag to check out, takes precedence over Branch. - type: string - type: object - required: - - ref - type: object - commit: - description: Commit specifies how to commit to the git repository. - properties: - author: - description: |- - Author gives the email and optionally the name to use as the - author of commits. - properties: - email: - description: Email gives the email to provide when making a commit. - type: string - name: - description: Name gives the name to provide when making a commit. - type: string - required: - - email - type: object - messageTemplate: - description: |- - MessageTemplate provides a template for the commit message, - into which will be interpolated the details of the change made. - Note: The `Updated` template field has been removed. Use `Changed` instead. - type: string - messageTemplateValues: - additionalProperties: - type: string - description: |- - MessageTemplateValues provides additional values to be available to the - templating rendering. - type: object - signingKey: - description: SigningKey provides the option to sign commits with a GPG key - properties: - secretRef: - description: |- - SecretRef holds the name to a secret that contains a 'git.asc' key - corresponding to the ASCII Armored file containing the GPG signing - keypair as the value. It must be in the same namespace as the - ImageUpdateAutomation. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - secretRef - type: object - required: - - author - type: object - push: - description: |- - Push specifies how and where to push commits made by the - automation. If missing, commits are pushed (back) to - `.spec.checkout.branch` or its default. - properties: - branch: - description: |- - Branch specifies that commits should be pushed to the branch - named. The branch is created using `.spec.checkout.branch` as the - starting point, if it doesn't already exist. - type: string - options: - additionalProperties: - type: string - description: |- - Options specifies the push options that are sent to the Git - server when performing a push operation. For details, see: - https://git-scm.com/docs/git-push#Documentation/git-push.txt---push-optionltoptiongt - type: object - refspec: - description: |- - Refspec specifies the Git Refspec to use for a push operation. - If both Branch and Refspec are provided, then the commit is pushed - to the branch and also using the specified refspec. - For more details about Git Refspecs, see: - https://git-scm.com/book/en/v2/Git-Internals-The-Refspec - type: string - type: object - required: - - commit - type: object - interval: - description: |- - Interval gives an lower bound for how often the automation - run should be attempted. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - policySelector: - description: |- - PolicySelector allows to filter applied policies based on labels. - By default includes all policies in 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - sourceRef: - description: |- - SourceRef refers to the resource giving access details - to a git repository. - properties: - apiVersion: - description: API version of the referent. - type: string - kind: - default: GitRepository - description: Kind of the referent. - enum: - - GitRepository - type: string - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference. - type: string - required: - - kind - - name - type: object - suspend: - description: |- - Suspend tells the controller to not run this automation, until - it is unset (or set to false). Defaults to false. - type: boolean - update: - default: - strategy: Setters - description: |- - Update gives the specification for how to update the files in - the repository. This can be left empty, to use the default - value. - properties: - path: - description: |- - Path to the directory containing the manifests to be updated. - Defaults to 'None', which translates to the root path - of the GitRepositoryRef. - type: string - strategy: - default: Setters - description: Strategy names the strategy to be used. - enum: - - Setters - type: string - type: object - required: - - interval - - sourceRef - type: object - status: - default: - observedGeneration: -1 - description: ImageUpdateAutomationStatus defines the observed state of ImageUpdateAutomation - properties: - conditions: - 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 - lastAutomationRunTime: - description: |- - LastAutomationRunTime records the last time the controller ran - this automation through to completion (even if no updates were - made). - format: date-time - type: string - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - lastPushCommit: - description: |- - LastPushCommit records the SHA1 of the last commit made by the - controller, for this automation object - type: string - lastPushTime: - description: LastPushTime records the time of the last pushed change. - format: date-time - type: string - observedGeneration: - format: int64 - type: integer - observedPolicies: - additionalProperties: - description: ImageRef represents an image reference. - properties: - digest: - description: Digest is the image's digest. - type: string - name: - description: Name is the bare image's name. - type: string - tag: - description: Tag is the image's tag. - type: string - required: - - name - - tag - type: object - description: |- - ObservedPolicies is the list of observed ImagePolicies that were - considered by the ImageUpdateAutomation update process. - type: object - observedSourceRevision: - description: |- - ObservedPolicies []ObservedPolicy `json:"observedPolicies,omitempty"` - ObservedSourceRevision is the last observed source revision. This can be - used to determine if the source has been updated since last observation. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .status.lastAutomationRunTime - name: Last run - priority: 1 - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - deprecated: true - deprecationWarning: v1beta2 ImageUpdateAutomation is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: ImageUpdateAutomation is the Schema for the imageupdateautomations 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: ImageUpdateAutomationSpec defines the desired state of ImageUpdateAutomation - properties: - git: - description: |- - GitSpec contains all the git-specific definitions. This is - technically optional, but in practice mandatory until there are - other kinds of source allowed. - properties: - checkout: - description: |- - Checkout gives the parameters for cloning the git repository, - ready to make changes. If not present, the `spec.ref` field from the - referenced `GitRepository` or its default will be used. - properties: - ref: - description: |- - Reference gives a branch, tag or commit to clone from the Git - repository. - properties: - branch: - description: Branch to check out, defaults to 'master' if no other field is defined. - type: string - commit: - description: |- - Commit SHA to check out, takes precedence over all reference fields. - - This can be combined with Branch to shallow clone the branch, in which - the commit is expected to exist. - type: string - name: - description: |- - Name of the reference to check out; takes precedence over Branch, Tag and SemVer. - - It must be a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description - Examples: "refs/heads/main", "refs/tags/v0.1.0", "refs/pull/420/head", "refs/merge-requests/1/head" - type: string - semver: - description: SemVer tag expression to check out, takes precedence over Tag. - type: string - tag: - description: Tag to check out, takes precedence over Branch. - type: string - type: object - required: - - ref - type: object - commit: - description: Commit specifies how to commit to the git repository. - properties: - author: - description: |- - Author gives the email and optionally the name to use as the - author of commits. - properties: - email: - description: Email gives the email to provide when making a commit. - type: string - name: - description: Name gives the name to provide when making a commit. - type: string - required: - - email - type: object - messageTemplate: - description: |- - MessageTemplate provides a template for the commit message, - into which will be interpolated the details of the change made. - Note: The `Updated` template field has been removed. Use `Changed` instead. - type: string - messageTemplateValues: - additionalProperties: - type: string - description: |- - MessageTemplateValues provides additional values to be available to the - templating rendering. - type: object - signingKey: - description: SigningKey provides the option to sign commits with a GPG key - properties: - secretRef: - description: |- - SecretRef holds the name to a secret that contains a 'git.asc' key - corresponding to the ASCII Armored file containing the GPG signing - keypair as the value. It must be in the same namespace as the - ImageUpdateAutomation. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - secretRef - type: object - required: - - author - type: object - push: - description: |- - Push specifies how and where to push commits made by the - automation. If missing, commits are pushed (back) to - `.spec.checkout.branch` or its default. - properties: - branch: - description: |- - Branch specifies that commits should be pushed to the branch - named. The branch is created using `.spec.checkout.branch` as the - starting point, if it doesn't already exist. - type: string - options: - additionalProperties: - type: string - description: |- - Options specifies the push options that are sent to the Git - server when performing a push operation. For details, see: - https://git-scm.com/docs/git-push#Documentation/git-push.txt---push-optionltoptiongt - type: object - refspec: - description: |- - Refspec specifies the Git Refspec to use for a push operation. - If both Branch and Refspec are provided, then the commit is pushed - to the branch and also using the specified refspec. - For more details about Git Refspecs, see: - https://git-scm.com/book/en/v2/Git-Internals-The-Refspec - type: string - type: object - required: - - commit - type: object - interval: - description: |- - Interval gives an lower bound for how often the automation - run should be attempted. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - policySelector: - description: |- - PolicySelector allows to filter applied policies based on labels. - By default includes all policies in 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 - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - 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 - sourceRef: - description: |- - SourceRef refers to the resource giving access details - to a git repository. - properties: - apiVersion: - description: API version of the referent. - type: string - kind: - default: GitRepository - description: Kind of the referent. - enum: - - GitRepository - type: string - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference. - type: string - required: - - kind - - name - type: object - suspend: - description: |- - Suspend tells the controller to not run this automation, until - it is unset (or set to false). Defaults to false. - type: boolean - update: - default: - strategy: Setters - description: |- - Update gives the specification for how to update the files in - the repository. This can be left empty, to use the default - value. - properties: - path: - description: |- - Path to the directory containing the manifests to be updated. - Defaults to 'None', which translates to the root path - of the GitRepositoryRef. - type: string - strategy: - default: Setters - description: Strategy names the strategy to be used. - enum: - - Setters - type: string - type: object - required: - - interval - - sourceRef - type: object - status: - default: - observedGeneration: -1 - description: ImageUpdateAutomationStatus defines the observed state of ImageUpdateAutomation - properties: - conditions: - 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 - lastAutomationRunTime: - description: |- - LastAutomationRunTime records the last time the controller ran - this automation through to completion (even if no updates were - made). - format: date-time - type: string - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - lastPushCommit: - description: |- - LastPushCommit records the SHA1 of the last commit made by the - controller, for this automation object - type: string - lastPushTime: - description: LastPushTime records the time of the last pushed change. - format: date-time - type: string - observedGeneration: - format: int64 - type: integer - observedPolicies: - additionalProperties: - description: ImageRef represents an image reference. - properties: - digest: - description: Digest is the image's digest. - type: string - name: - description: Name is the bare image's name. - type: string - tag: - description: Tag is the image's tag. - type: string - required: - - name - - tag - type: object - description: |- - ObservedPolicies is the list of observed ImagePolicies that were - considered by the ImageUpdateAutomation update process. - type: object - observedSourceRevision: - description: |- - ObservedPolicies []ObservedPolicy `json:"observedPolicies,omitempty"` - ObservedSourceRevision is the last observed source revision. This can be - used to determine if the source has been updated since last observation. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: kustomizations.kustomize.toolkit.fluxcd.io -spec: - group: kustomize.toolkit.fluxcd.io - names: - kind: Kustomization - listKind: KustomizationList - plural: kustomizations - shortNames: - - ks - singular: kustomization - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - name: v1 - schema: - openAPIV3Schema: - description: Kustomization is the Schema for the kustomizations 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: |- - KustomizationSpec defines the configuration to calculate the desired state - from a Source using Kustomize. - properties: - commonMetadata: - description: |- - CommonMetadata specifies the common labels and annotations that are - applied to all resources. Any existing label or annotation will be - overridden if its key matches a common one. - properties: - annotations: - additionalProperties: - type: string - description: Annotations to be added to the object's metadata. - type: object - labels: - additionalProperties: - type: string - description: Labels to be added to the object's metadata. - type: object - type: object - components: - description: Components specifies relative paths to kustomize Components. - items: - type: string - type: array - decryption: - description: Decrypt Kubernetes secrets before applying them on the cluster. - properties: - provider: - description: Provider is the name of the decryption engine. - enum: - - sops - type: string - secretRef: - description: |- - The secret name containing the private OpenPGP keys used for decryption. - A static credential for a cloud provider defined inside the Secret - takes priority to secret-less authentication with the ServiceAccountName - field. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the service account used to - authenticate with KMS services from cloud providers. If a - static credential for a given cloud provider is defined - inside the Secret referenced by SecretRef, that static - credential takes priority. - type: string - required: - - provider - type: object - deletionPolicy: - description: |- - DeletionPolicy can be used to control garbage collection when this - Kustomization is deleted. Valid values are ('MirrorPrune', 'Delete', - 'WaitForTermination', 'Orphan'). 'MirrorPrune' mirrors the Prune field - (orphan if false, delete if true). Defaults to 'MirrorPrune'. - enum: - - MirrorPrune - - Delete - - WaitForTermination - - Orphan - type: string - dependsOn: - description: |- - DependsOn may contain a DependencyReference slice - with references to Kustomization resources that must be ready before this - Kustomization can be reconciled. - items: - description: DependencyReference defines a Kustomization dependency on another Kustomization resource. - properties: - name: - description: Name of the referent. - type: string - namespace: - description: |- - Namespace of the referent, defaults to the namespace of the Kustomization - resource object that contains the reference. - type: string - readyExpr: - description: |- - ReadyExpr is a CEL expression that can be used to assess the readiness - of a dependency. When specified, the built-in readiness check - is replaced by the logic defined in the CEL expression. - To make the CEL expression additive to the built-in readiness check, - the feature gate `AdditiveCELDependencyCheck` must be set to `true`. - type: string - required: - - name - type: object - type: array - force: - default: false - description: |- - Force instructs the controller to recreate resources - when patching fails due to an immutable field change. - type: boolean - healthCheckExprs: - description: |- - HealthCheckExprs is a list of healthcheck expressions for evaluating the - health of custom resources using Common Expression Language (CEL). - The expressions are evaluated only when Wait or HealthChecks are specified. - items: - description: CustomHealthCheck defines the health check for custom resources. - properties: - apiVersion: - description: APIVersion of the custom resource under evaluation. - type: string - current: - description: |- - Current is the CEL expression that determines if the status - of the custom resource has reached the desired state. - type: string - failed: - description: |- - Failed is the CEL expression that determines if the status - of the custom resource has failed to reach the desired state. - type: string - inProgress: - description: |- - InProgress is the CEL expression that determines if the status - of the custom resource has not yet reached the desired state. - type: string - kind: - description: Kind of the custom resource under evaluation. - type: string - required: - - apiVersion - - current - - kind - type: object - type: array - healthChecks: - description: A list of resources to be included in the health assessment. - items: - description: |- - NamespacedObjectKindReference contains enough information to locate the typed referenced Kubernetes resource object - in any namespace. - properties: - apiVersion: - description: API version of the referent, if not specified the Kubernetes preferred version will be used. - type: string - kind: - description: Kind of the referent. - type: string - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, when not specified it acts as LocalObjectReference. - type: string - required: - - kind - - name - type: object - type: array - ignoreMissingComponents: - description: |- - IgnoreMissingComponents instructs the controller to ignore Components paths - not found in source by removing them from the generated kustomization.yaml - before running kustomize build. - type: boolean - images: - description: |- - Images is a list of (image name, new name, new tag or digest) - for changing image names, tags or digests. This can also be achieved with a - patch, but this operator is simpler to specify. - items: - description: Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag. - properties: - digest: - description: |- - Digest is the value used to replace the original image tag. - If digest is present NewTag value is ignored. - type: string - name: - description: Name is a tag-less image name. - type: string - newName: - description: NewName is the value used to replace the original name. - type: string - newTag: - description: NewTag is the value used to replace the original tag. - type: string - required: - - name - type: object - type: array - interval: - description: |- - The interval at which to reconcile the Kustomization. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - kubeConfig: - description: |- - The KubeConfig for reconciling the Kustomization on a remote cluster. - When used in combination with KustomizationSpec.ServiceAccountName, - forces the controller to act on behalf of that Service Account at the - target cluster. - If the --default-service-account flag is set, its value will be used as - a controller level fallback for when KustomizationSpec.ServiceAccountName - is empty. - properties: - configMapRef: - description: |- - ConfigMapRef holds an optional name of a ConfigMap that contains - the following keys: - - - `provider`: the provider to use. One of `aws`, `azure`, `gcp`, or - `generic`. Required. - - `cluster`: the fully qualified resource name of the Kubernetes - cluster in the cloud provider API. Not used by the `generic` - provider. Required when one of `address` or `ca.crt` is not set. - - `address`: the address of the Kubernetes API server. Required - for `generic`. For the other providers, if not specified, the - first address in the cluster resource will be used, and if - specified, it must match one of the addresses in the cluster - resource. - If audiences is not set, will be used as the audience for the - `generic` provider. - - `ca.crt`: the optional PEM-encoded CA certificate for the - Kubernetes API server. If not set, the controller will use the - CA certificate from the cluster resource. - - `audiences`: the optional audiences as a list of - line-break-separated strings for the Kubernetes ServiceAccount - token. Defaults to the `address` for the `generic` provider, or - to specific values for the other providers depending on the - provider. - - `serviceAccountName`: the optional name of the Kubernetes - ServiceAccount in the same namespace that should be used - for authentication. If not specified, the controller - ServiceAccount will be used. - - Mutually exclusive with SecretRef. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - secretRef: - description: |- - SecretRef holds an optional name of a secret that contains a key with - the kubeconfig file as the value. If no key is set, the key will default - to 'value'. Mutually exclusive with ConfigMapRef. - It is recommended that the kubeconfig is self-contained, and the secret - is regularly updated if credentials such as a cloud-access-token expire. - Cloud specific `cmd-path` auth helpers will not function without adding - binaries and credentials to the Pod that is responsible for reconciling - Kubernetes resources. Supported only for the generic provider. - properties: - key: - description: Key in the Secret, when not specified an implementation-specific default key is used. - type: string - name: - description: Name of the Secret. - type: string - required: - - name - type: object - type: object - x-kubernetes-validations: - - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified - rule: has(self.configMapRef) || has(self.secretRef) - - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified - rule: '!has(self.configMapRef) || !has(self.secretRef)' - namePrefix: - description: NamePrefix will prefix the names of all managed resources. - maxLength: 200 - minLength: 1 - type: string - nameSuffix: - description: NameSuffix will suffix the names of all managed resources. - maxLength: 200 - minLength: 1 - type: string - patches: - description: |- - Strategic merge and JSON patches, defined as inline YAML objects, - capable of targeting objects based on kind, label and annotation selectors. - items: - description: |- - Patch contains an inline StrategicMerge or JSON6902 patch, and the target the patch should - be applied to. - properties: - patch: - description: |- - Patch contains an inline StrategicMerge patch or an inline JSON6902 patch with - an array of operation objects. - type: string - target: - description: Target points to the resources that the patch document should be applied to. - properties: - annotationSelector: - description: |- - AnnotationSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: |- - Group is the API group to select resources from. - Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: |- - Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: |- - LabelSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: |- - Version of the API Group to select resources from. - Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - type: object - type: array - path: - description: |- - Path to the directory containing the kustomization.yaml file, or the - set of plain YAMLs a kustomization.yaml should be generated for. - Defaults to 'None', which translates to the root path of the SourceRef. - type: string - postBuild: - description: |- - PostBuild describes which actions to perform on the YAML manifest - generated by building the kustomize overlay. - properties: - substitute: - additionalProperties: - type: string - description: |- - Substitute holds a map of key/value pairs. - The variables defined in your YAML manifests that match any of the keys - defined in the map will be substituted with the set value. - Includes support for bash string replacement functions - e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}. - type: object - substituteFrom: - description: |- - SubstituteFrom holds references to ConfigMaps and Secrets containing - the variables and their values to be substituted in the YAML manifests. - The ConfigMap and the Secret data keys represent the var names, and they - must match the vars declared in the manifests for the substitution to - happen. - items: - description: |- - SubstituteReference contains a reference to a resource containing - the variables name and value. - properties: - kind: - description: Kind of the values referent, valid values are ('Secret', 'ConfigMap'). - enum: - - Secret - - ConfigMap - type: string - name: - description: |- - Name of the values referent. Should reside in the same namespace as the - referring resource. - maxLength: 253 - minLength: 1 - type: string - optional: - default: false - description: |- - Optional indicates whether the referenced resource must exist, or whether to - tolerate its absence. If true and the referenced resource is absent, proceed - as if the resource was present but empty, without any variables defined. - type: boolean - required: - - kind - - name - type: object - type: array - type: object - prune: - description: Prune enables garbage collection. - type: boolean - retryInterval: - description: |- - The interval at which to retry a previously failed reconciliation. - When not specified, the controller uses the KustomizationSpec.Interval - value to retry failures. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - serviceAccountName: - description: |- - The name of the Kubernetes service account to impersonate - when reconciling this Kustomization. - type: string - sourceRef: - description: Reference of the source where the kustomization file is. - properties: - apiVersion: - description: API version of the referent. - type: string - kind: - description: Kind of the referent. - enum: - - OCIRepository - - GitRepository - - Bucket - - ExternalArtifact - type: string - name: - description: Name of the referent. - type: string - namespace: - description: |- - Namespace of the referent, defaults to the namespace of the Kubernetes - resource object that contains the reference. - type: string - required: - - kind - - name - type: object - suspend: - description: |- - This flag tells the controller to suspend subsequent kustomize executions, - it does not apply to already started executions. Defaults to false. - type: boolean - targetNamespace: - description: |- - TargetNamespace sets or overrides the namespace in the - kustomization.yaml file. - maxLength: 63 - minLength: 1 - type: string - timeout: - description: |- - Timeout for validation, apply and health checking operations. - Defaults to 'Interval' duration. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - wait: - description: |- - Wait instructs the controller to check the health of all the reconciled - resources. When enabled, the HealthChecks are ignored. Defaults to false. - type: boolean - required: - - interval - - prune - - sourceRef - type: object - status: - default: - observedGeneration: -1 - description: KustomizationStatus defines the observed state of a kustomization. - properties: - conditions: - 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 - history: - description: |- - History contains a set of snapshots of the last reconciliation attempts - tracking the revision, the state and the duration of each attempt. - items: - description: |- - Snapshot represents a point-in-time record of a group of resources reconciliation, - including timing information, status, and a unique digest identifier. - properties: - digest: - description: Digest is the checksum in the format `:` of the resources in this snapshot. - type: string - firstReconciled: - description: FirstReconciled is the time when this revision was first reconciled to the cluster. - format: date-time - type: string - lastReconciled: - description: LastReconciled is the time when this revision was last reconciled to the cluster. - format: date-time - type: string - lastReconciledDuration: - description: LastReconciledDuration is time it took to reconcile the resources in this revision. - type: string - lastReconciledStatus: - description: LastReconciledStatus is the status of the last reconciliation. - type: string - metadata: - additionalProperties: - type: string - description: Metadata contains additional information about the snapshot. - type: object - totalReconciliations: - description: TotalReconciliations is the total number of reconciliations that have occurred for this snapshot. - format: int64 - type: integer - required: - - digest - - firstReconciled - - lastReconciled - - lastReconciledDuration - - lastReconciledStatus - - totalReconciliations - type: object - type: array - inventory: - description: |- - Inventory contains the list of Kubernetes resource object references that - have been successfully applied. - properties: - entries: - description: Entries of Kubernetes resource object references. - items: - description: ResourceRef contains the information necessary to locate a resource within a cluster. - properties: - id: - description: |- - ID is the string representation of the Kubernetes resource object's metadata, - in the format '___'. - type: string - v: - description: Version is the API version of the Kubernetes resource object's kind. - type: string - required: - - id - - v - type: object - type: array - required: - - entries - type: object - lastAppliedOriginRevision: - description: |- - The last successfully applied origin revision. - Equals the origin revision of the applied Artifact from the referenced Source. - Usually present on the Metadata of the applied Artifact and depends on the - Source type, e.g. for OCI it's the value associated with the key - "org.opencontainers.image.revision". - type: string - lastAppliedRevision: - description: |- - The last successfully applied revision. - Equals the Revision of the applied Artifact from the referenced Source. - type: string - lastAttemptedRevision: - description: LastAttemptedRevision is the revision of the last reconciliation attempt. - type: string - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last reconciled generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v1beta2 Kustomization is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: Kustomization is the Schema for the kustomizations 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: KustomizationSpec defines the configuration to calculate the desired state from a Source using Kustomize. - properties: - commonMetadata: - description: |- - CommonMetadata specifies the common labels and annotations that are applied to all resources. - Any existing label or annotation will be overridden if its key matches a common one. - properties: - annotations: - additionalProperties: - type: string - description: Annotations to be added to the object's metadata. - type: object - labels: - additionalProperties: - type: string - description: Labels to be added to the object's metadata. - type: object - type: object - components: - description: Components specifies relative paths to specifications of other Components. - items: - type: string - type: array - decryption: - description: Decrypt Kubernetes secrets before applying them on the cluster. - properties: - provider: - description: Provider is the name of the decryption engine. - enum: - - sops - type: string - secretRef: - description: The secret name containing the private OpenPGP keys used for decryption. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - provider - type: object - dependsOn: - description: |- - DependsOn may contain a meta.NamespacedObjectReference slice - with references to Kustomization resources that must be ready before this - Kustomization can be reconciled. - items: - description: |- - NamespacedObjectReference contains enough information to locate the referenced Kubernetes resource object in any - namespace. - properties: - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, when not specified it acts as LocalObjectReference. - type: string - required: - - name - type: object - type: array - force: - default: false - description: |- - Force instructs the controller to recreate resources - when patching fails due to an immutable field change. - type: boolean - healthChecks: - description: A list of resources to be included in the health assessment. - items: - description: |- - NamespacedObjectKindReference contains enough information to locate the typed referenced Kubernetes resource object - in any namespace. - properties: - apiVersion: - description: API version of the referent, if not specified the Kubernetes preferred version will be used. - type: string - kind: - description: Kind of the referent. - type: string - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, when not specified it acts as LocalObjectReference. - type: string - required: - - kind - - name - type: object - type: array - images: - description: |- - Images is a list of (image name, new name, new tag or digest) - for changing image names, tags or digests. This can also be achieved with a - patch, but this operator is simpler to specify. - items: - description: Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag. - properties: - digest: - description: |- - Digest is the value used to replace the original image tag. - If digest is present NewTag value is ignored. - type: string - name: - description: Name is a tag-less image name. - type: string - newName: - description: NewName is the value used to replace the original name. - type: string - newTag: - description: NewTag is the value used to replace the original tag. - type: string - required: - - name - type: object - type: array - interval: - description: The interval at which to reconcile the Kustomization. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - kubeConfig: - description: |- - The KubeConfig for reconciling the Kustomization on a remote cluster. - When used in combination with KustomizationSpec.ServiceAccountName, - forces the controller to act on behalf of that Service Account at the - target cluster. - If the --default-service-account flag is set, its value will be used as - a controller level fallback for when KustomizationSpec.ServiceAccountName - is empty. - properties: - configMapRef: - description: |- - ConfigMapRef holds an optional name of a ConfigMap that contains - the following keys: - - - `provider`: the provider to use. One of `aws`, `azure`, `gcp`, or - `generic`. Required. - - `cluster`: the fully qualified resource name of the Kubernetes - cluster in the cloud provider API. Not used by the `generic` - provider. Required when one of `address` or `ca.crt` is not set. - - `address`: the address of the Kubernetes API server. Required - for `generic`. For the other providers, if not specified, the - first address in the cluster resource will be used, and if - specified, it must match one of the addresses in the cluster - resource. - If audiences is not set, will be used as the audience for the - `generic` provider. - - `ca.crt`: the optional PEM-encoded CA certificate for the - Kubernetes API server. If not set, the controller will use the - CA certificate from the cluster resource. - - `audiences`: the optional audiences as a list of - line-break-separated strings for the Kubernetes ServiceAccount - token. Defaults to the `address` for the `generic` provider, or - to specific values for the other providers depending on the - provider. - - `serviceAccountName`: the optional name of the Kubernetes - ServiceAccount in the same namespace that should be used - for authentication. If not specified, the controller - ServiceAccount will be used. - - Mutually exclusive with SecretRef. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - secretRef: - description: |- - SecretRef holds an optional name of a secret that contains a key with - the kubeconfig file as the value. If no key is set, the key will default - to 'value'. Mutually exclusive with ConfigMapRef. - It is recommended that the kubeconfig is self-contained, and the secret - is regularly updated if credentials such as a cloud-access-token expire. - Cloud specific `cmd-path` auth helpers will not function without adding - binaries and credentials to the Pod that is responsible for reconciling - Kubernetes resources. Supported only for the generic provider. - properties: - key: - description: Key in the Secret, when not specified an implementation-specific default key is used. - type: string - name: - description: Name of the Secret. - type: string - required: - - name - type: object - type: object - x-kubernetes-validations: - - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified - rule: has(self.configMapRef) || has(self.secretRef) - - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified - rule: '!has(self.configMapRef) || !has(self.secretRef)' - patches: - description: |- - Strategic merge and JSON patches, defined as inline YAML objects, - capable of targeting objects based on kind, label and annotation selectors. - items: - description: |- - Patch contains an inline StrategicMerge or JSON6902 patch, and the target the patch should - be applied to. - properties: - patch: - description: |- - Patch contains an inline StrategicMerge patch or an inline JSON6902 patch with - an array of operation objects. - type: string - target: - description: Target points to the resources that the patch document should be applied to. - properties: - annotationSelector: - description: |- - AnnotationSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: |- - Group is the API group to select resources from. - Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: |- - Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: |- - LabelSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: |- - Version of the API Group to select resources from. - Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - type: object - type: array - patchesJson6902: - description: |- - JSON 6902 patches, defined as inline YAML objects. - Deprecated: Use Patches instead. - items: - description: JSON6902Patch contains a JSON6902 patch and the target the patch should be applied to. - properties: - patch: - description: Patch contains the JSON6902 patch document with an array of operation objects. - items: - description: |- - JSON6902 is a JSON6902 operation object. - https://datatracker.ietf.org/doc/html/rfc6902#section-4 - properties: - from: - description: |- - From contains a JSON-pointer value that references a location within the target document where the operation is - performed. The meaning of the value depends on the value of Op, and is NOT taken into account by all operations. - type: string - op: - description: |- - Op indicates the operation to perform. Its value MUST be one of "add", "remove", "replace", "move", "copy", or - "test". - https://datatracker.ietf.org/doc/html/rfc6902#section-4 - enum: - - test - - remove - - add - - replace - - move - - copy - type: string - path: - description: |- - Path contains the JSON-pointer value that references a location within the target document where the operation - is performed. The meaning of the value depends on the value of Op. - type: string - value: - description: |- - Value contains a valid JSON structure. The meaning of the value depends on the value of Op, and is NOT taken into - account by all operations. - x-kubernetes-preserve-unknown-fields: true - required: - - op - - path - type: object - type: array - target: - description: Target points to the resources that the patch document should be applied to. - properties: - annotationSelector: - description: |- - AnnotationSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: |- - Group is the API group to select resources from. - Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: |- - Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: |- - LabelSelector is a string that follows the label selection expression - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: |- - Version of the API Group to select resources from. - Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - - target - type: object - type: array - patchesStrategicMerge: - description: |- - Strategic merge patches, defined as inline YAML objects. - Deprecated: Use Patches instead. - items: - x-kubernetes-preserve-unknown-fields: true - type: array - path: - description: |- - Path to the directory containing the kustomization.yaml file, or the - set of plain YAMLs a kustomization.yaml should be generated for. - Defaults to 'None', which translates to the root path of the SourceRef. - type: string - postBuild: - description: |- - PostBuild describes which actions to perform on the YAML manifest - generated by building the kustomize overlay. - properties: - substitute: - additionalProperties: - type: string - description: |- - Substitute holds a map of key/value pairs. - The variables defined in your YAML manifests - that match any of the keys defined in the map - will be substituted with the set value. - Includes support for bash string replacement functions - e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}. - type: object - substituteFrom: - description: |- - SubstituteFrom holds references to ConfigMaps and Secrets containing - the variables and their values to be substituted in the YAML manifests. - The ConfigMap and the Secret data keys represent the var names and they - must match the vars declared in the manifests for the substitution to happen. - items: - description: |- - SubstituteReference contains a reference to a resource containing - the variables name and value. - properties: - kind: - description: Kind of the values referent, valid values are ('Secret', 'ConfigMap'). - enum: - - Secret - - ConfigMap - type: string - name: - description: |- - Name of the values referent. Should reside in the same namespace as the - referring resource. - maxLength: 253 - minLength: 1 - type: string - optional: - default: false - description: |- - Optional indicates whether the referenced resource must exist, or whether to - tolerate its absence. If true and the referenced resource is absent, proceed - as if the resource was present but empty, without any variables defined. - type: boolean - required: - - kind - - name - type: object - type: array - type: object - prune: - description: Prune enables garbage collection. - type: boolean - retryInterval: - description: |- - The interval at which to retry a previously failed reconciliation. - When not specified, the controller uses the KustomizationSpec.Interval - value to retry failures. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - serviceAccountName: - description: |- - The name of the Kubernetes service account to impersonate - when reconciling this Kustomization. - type: string - sourceRef: - description: Reference of the source where the kustomization file is. - properties: - apiVersion: - description: API version of the referent. - type: string - kind: - description: Kind of the referent. - enum: - - OCIRepository - - GitRepository - - Bucket - type: string - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference. - type: string - required: - - kind - - name - type: object - suspend: - description: |- - This flag tells the controller to suspend subsequent kustomize executions, - it does not apply to already started executions. Defaults to false. - type: boolean - targetNamespace: - description: |- - TargetNamespace sets or overrides the namespace in the - kustomization.yaml file. - maxLength: 63 - minLength: 1 - type: string - timeout: - description: |- - Timeout for validation, apply and health checking operations. - Defaults to 'Interval' duration. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - validation: - description: 'Deprecated: Not used in v1beta2.' - enum: - - none - - client - - server - type: string - wait: - description: |- - Wait instructs the controller to check the health of all the reconciled resources. - When enabled, the HealthChecks are ignored. Defaults to false. - type: boolean - required: - - interval - - prune - - sourceRef - type: object - status: - default: - observedGeneration: -1 - description: KustomizationStatus defines the observed state of a kustomization. - properties: - conditions: - 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 - inventory: - description: Inventory contains the list of Kubernetes resource object references that have been successfully applied. - properties: - entries: - description: Entries of Kubernetes resource object references. - items: - description: ResourceRef contains the information necessary to locate a resource within a cluster. - properties: - id: - description: |- - ID is the string representation of the Kubernetes resource object's metadata, - in the format '___'. - type: string - v: - description: Version is the API version of the Kubernetes resource object's kind. - type: string - required: - - id - - v - type: object - type: array - required: - - entries - type: object - lastAppliedRevision: - description: |- - The last successfully applied revision. - Equals the Revision of the applied Artifact from the referenced Source. - type: string - lastAttemptedRevision: - description: LastAttemptedRevision is the revision of the last reconciliation attempt. - type: string - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last reconciled generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: ocirepositories.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: OCIRepository - listKind: OCIRepositoryList - plural: ocirepositories - shortNames: - - ocirepo - singular: ocirepository - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: OCIRepository is the Schema for the ocirepositories 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: OCIRepositorySpec defines the desired state of OCIRepository - properties: - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - registry. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - ignore: - description: |- - Ignore overrides the set of excluded patterns in the .sourceignore format - (which is the same as .gitignore). If not provided, a default will be used, - consult the documentation for your version to find out what those are. - type: string - insecure: - description: Insecure allows connecting to a non-TLS HTTP container registry. - type: boolean - interval: - description: |- - Interval at which the OCIRepository URL is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - layerSelector: - description: |- - LayerSelector specifies which layer should be extracted from the OCI artifact. - When not specified, the first layer found in the artifact is selected. - properties: - mediaType: - description: |- - MediaType specifies the OCI media type of the layer - which should be extracted from the OCI Artifact. The - first layer matching this type is selected. - type: string - operation: - description: |- - Operation specifies how the selected layer should be processed. - By default, the layer compressed content is extracted to storage. - When the operation is set to 'copy', the layer compressed content - is persisted to storage as it is. - enum: - - extract - - copy - type: string - type: object - provider: - default: generic - description: |- - The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. - When not specified, defaults to 'generic'. - enum: - - generic - - aws - - azure - - gcp - type: string - proxySecretRef: - description: |- - ProxySecretRef specifies the Secret containing the proxy configuration - to use while communicating with the container registry. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - ref: - description: |- - The OCI reference to pull and monitor for changes, - defaults to the latest tag. - properties: - digest: - description: |- - Digest is the image digest to pull, takes precedence over SemVer. - The value should be in the format 'sha256:'. - type: string - semver: - description: |- - SemVer is the range of tags to pull selecting the latest within - the range, takes precedence over Tag. - type: string - semverFilter: - description: SemverFilter is a regex pattern to filter the tags within the SemVer range. - type: string - tag: - description: Tag is the image tag to pull, defaults to latest. - type: string - type: object - secretRef: - description: |- - SecretRef contains the secret name containing the registry login - credentials to resolve image metadata. - The secret must be of type kubernetes.io/dockerconfigjson. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate - the image pull if the service account has attached pull secrets. For more information: - https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account - type: string - suspend: - description: This flag tells the controller to suspend the reconciliation of this source. - type: boolean - timeout: - default: 60s - description: The timeout for remote OCI Repository operations like pulling, defaults to 60s. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - url: - description: |- - URL is a reference to an OCI artifact repository hosted - on a remote container registry. - pattern: ^oci://.*$ - type: string - verify: - description: |- - Verify contains the secret name containing the trusted public keys - used to verify the signature and specifies which provider to use to check - whether OCI image is authentic. - properties: - matchOIDCIdentity: - description: |- - MatchOIDCIdentity specifies the identity matching criteria to use - while verifying an OCI artifact which was signed using Cosign keyless - signing. The artifact's identity is deemed to be verified if any of the - specified matchers match against the identity. - items: - description: |- - OIDCIdentityMatch specifies options for verifying the certificate identity, - i.e. the issuer and the subject of the certificate. - properties: - issuer: - description: |- - Issuer specifies the regex pattern to match against to verify - the OIDC issuer in the Fulcio certificate. The pattern must be a - valid Go regular expression. - type: string - subject: - description: |- - Subject specifies the regex pattern to match against to verify - the identity subject in the Fulcio certificate. The pattern must - be a valid Go regular expression. - type: string - required: - - issuer - - subject - type: object - type: array - provider: - default: cosign - description: Provider specifies the technology used to sign the OCI Artifact. - enum: - - cosign - - notation - type: string - secretRef: - description: |- - SecretRef specifies the Kubernetes Secret containing the - trusted public keys. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - provider - type: object - required: - - interval - - url - type: object - status: - default: - observedGeneration: -1 - description: OCIRepositoryStatus defines the observed state of OCIRepository - properties: - artifact: - description: Artifact represents the output of the last successful OCI Repository sync. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the OCIRepository. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - observedIgnore: - description: |- - ObservedIgnore is the observed exclusion patterns used for constructing - the source artifact. - type: string - observedLayerSelector: - description: |- - ObservedLayerSelector is the observed layer selector used for constructing - the source artifact. - properties: - mediaType: - description: |- - MediaType specifies the OCI media type of the layer - which should be extracted from the OCI Artifact. The - first layer matching this type is selected. - type: string - operation: - description: |- - Operation specifies how the selected layer should be processed. - By default, the layer compressed content is extracted to storage. - When the operation is set to 'copy', the layer compressed content - is persisted to storage as it is. - enum: - - extract - - copy - type: string - type: object - url: - description: URL is the download link for the artifact output of the last OCI Repository sync. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - deprecated: true - deprecationWarning: v1beta2 OCIRepository is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: OCIRepository is the Schema for the ocirepositories 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: OCIRepositorySpec defines the desired state of OCIRepository - properties: - certSecretRef: - description: |- - CertSecretRef can be given the name of a Secret containing - either or both of - - - a PEM-encoded client certificate (`tls.crt`) and private - key (`tls.key`); - - a PEM-encoded CA certificate (`ca.crt`) - - and whichever are supplied, will be used for connecting to the - registry. The client cert and key are useful if you are - authenticating with a certificate; the CA cert is useful if - you are using a self-signed server certificate. The Secret must - be of type `Opaque` or `kubernetes.io/tls`. - - Note: Support for the `caFile`, `certFile` and `keyFile` keys have - been deprecated. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - ignore: - description: |- - Ignore overrides the set of excluded patterns in the .sourceignore format - (which is the same as .gitignore). If not provided, a default will be used, - consult the documentation for your version to find out what those are. - type: string - insecure: - description: Insecure allows connecting to a non-TLS HTTP container registry. - type: boolean - interval: - description: |- - Interval at which the OCIRepository URL is checked for updates. - This interval is approximate and may be subject to jitter to ensure - efficient use of resources. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - layerSelector: - description: |- - LayerSelector specifies which layer should be extracted from the OCI artifact. - When not specified, the first layer found in the artifact is selected. - properties: - mediaType: - description: |- - MediaType specifies the OCI media type of the layer - which should be extracted from the OCI Artifact. The - first layer matching this type is selected. - type: string - operation: - description: |- - Operation specifies how the selected layer should be processed. - By default, the layer compressed content is extracted to storage. - When the operation is set to 'copy', the layer compressed content - is persisted to storage as it is. - enum: - - extract - - copy - type: string - type: object - provider: - default: generic - description: |- - The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. - When not specified, defaults to 'generic'. - enum: - - generic - - aws - - azure - - gcp - type: string - proxySecretRef: - description: |- - ProxySecretRef specifies the Secret containing the proxy configuration - to use while communicating with the container registry. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - ref: - description: |- - The OCI reference to pull and monitor for changes, - defaults to the latest tag. - properties: - digest: - description: |- - Digest is the image digest to pull, takes precedence over SemVer. - The value should be in the format 'sha256:'. - type: string - semver: - description: |- - SemVer is the range of tags to pull selecting the latest within - the range, takes precedence over Tag. - type: string - semverFilter: - description: SemverFilter is a regex pattern to filter the tags within the SemVer range. - type: string - tag: - description: Tag is the image tag to pull, defaults to latest. - type: string - type: object - secretRef: - description: |- - SecretRef contains the secret name containing the registry login - credentials to resolve image metadata. - The secret must be of type kubernetes.io/dockerconfigjson. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate - the image pull if the service account has attached pull secrets. For more information: - https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account - type: string - suspend: - description: This flag tells the controller to suspend the reconciliation of this source. - type: boolean - timeout: - default: 60s - description: The timeout for remote OCI Repository operations like pulling, defaults to 60s. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - url: - description: |- - URL is a reference to an OCI artifact repository hosted - on a remote container registry. - pattern: ^oci://.*$ - type: string - verify: - description: |- - Verify contains the secret name containing the trusted public keys - used to verify the signature and specifies which provider to use to check - whether OCI image is authentic. - properties: - matchOIDCIdentity: - description: |- - MatchOIDCIdentity specifies the identity matching criteria to use - while verifying an OCI artifact which was signed using Cosign keyless - signing. The artifact's identity is deemed to be verified if any of the - specified matchers match against the identity. - items: - description: |- - OIDCIdentityMatch specifies options for verifying the certificate identity, - i.e. the issuer and the subject of the certificate. - properties: - issuer: - description: |- - Issuer specifies the regex pattern to match against to verify - the OIDC issuer in the Fulcio certificate. The pattern must be a - valid Go regular expression. - type: string - subject: - description: |- - Subject specifies the regex pattern to match against to verify - the identity subject in the Fulcio certificate. The pattern must - be a valid Go regular expression. - type: string - required: - - issuer - - subject - type: object - type: array - provider: - default: cosign - description: Provider specifies the technology used to sign the OCI Artifact. - enum: - - cosign - - notation - type: string - secretRef: - description: |- - SecretRef specifies the Kubernetes Secret containing the - trusted public keys. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - provider - type: object - required: - - interval - - url - type: object - status: - default: - observedGeneration: -1 - description: OCIRepositoryStatus defines the observed state of OCIRepository - properties: - artifact: - description: Artifact represents the output of the last successful OCI Repository sync. - properties: - digest: - description: Digest is the digest of the file in the form of ':'. - pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of the - Artifact. - format: date-time - type: string - metadata: - additionalProperties: - type: string - description: Metadata holds upstream information such as OCI annotations. - type: object - path: - description: |- - Path is the relative file path of the Artifact. It can be used to locate - the file in the root of the Artifact storage on the local file system of - the controller managing the Source. - type: string - revision: - description: |- - Revision is a human-readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. - type: string - size: - description: Size is the number of bytes in the file. - format: int64 - type: integer - url: - description: |- - URL is the HTTP address of the Artifact as exposed by the controller - managing the Source. It can be used to retrieve the Artifact for - consumption, e.g. by another controller applying the Artifact contents. - type: string - required: - - digest - - lastUpdateTime - - path - - revision - - url - type: object - conditions: - description: Conditions holds the conditions for the OCIRepository. - 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 - contentConfigChecksum: - description: |- - ContentConfigChecksum is a checksum of all the configurations related to - the content of the source artifact: - - .spec.ignore - - .spec.layerSelector - observed in .status.observedGeneration version of the object. This can - be used to determine if the content configuration has changed and the - artifact needs to be rebuilt. - It has the format of `:`, for example: `sha256:`. - - Deprecated: Replaced with explicit fields for observed artifact content - config in the status. - type: string - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - observedIgnore: - description: |- - ObservedIgnore is the observed exclusion patterns used for constructing - the source artifact. - type: string - observedLayerSelector: - description: |- - ObservedLayerSelector is the observed layer selector used for constructing - the source artifact. - properties: - mediaType: - description: |- - MediaType specifies the OCI media type of the layer - which should be extracted from the OCI Artifact. The - first layer matching this type is selected. - type: string - operation: - description: |- - Operation specifies how the selected layer should be processed. - By default, the layer compressed content is extracted to storage. - When the operation is set to 'copy', the layer compressed content - is persisted to storage as it is. - enum: - - extract - - copy - type: string - type: object - url: - description: URL is the download link for the artifact output of the last OCI Repository sync. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: providers.notification.toolkit.fluxcd.io -spec: - group: notification.toolkit.fluxcd.io - names: - kind: Provider - listKind: ProviderList - plural: providers - singular: provider - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v1beta2 Provider is deprecated, upgrade to v1beta3 - name: v1beta2 - schema: - openAPIV3Schema: - description: Provider is the Schema for the providers 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: ProviderSpec defines the desired state of the Provider. - properties: - address: - description: |- - Address specifies the endpoint, in a generic sense, to where alerts are sent. - What kind of endpoint depends on the specific Provider type being used. - For the generic Provider, for example, this is an HTTP/S address. - For other Provider types this could be a project ID or a namespace. - maxLength: 2048 - type: string - certSecretRef: - description: |- - CertSecretRef specifies the Secret containing - a PEM-encoded CA certificate (in the `ca.crt` key). - - Note: Support for the `caFile` key has - been deprecated. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - channel: - description: Channel specifies the destination channel where events should be posted. - maxLength: 2048 - type: string - interval: - description: Interval at which to reconcile the Provider with its Secret references. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - proxy: - description: Proxy the HTTP/S address of the proxy server. - maxLength: 2048 - pattern: ^(http|https)://.*$ - type: string - secretRef: - description: |- - SecretRef specifies the Secret containing the authentication - credentials for this Provider. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - suspend: - description: |- - Suspend tells the controller to suspend subsequent - events handling for this Provider. - type: boolean - timeout: - description: Timeout for sending alerts to the Provider. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - type: - description: Type specifies which Provider implementation to use. - enum: - - slack - - discord - - msteams - - rocket - - generic - - generic-hmac - - github - - gitlab - - gitea - - bitbucketserver - - bitbucket - - azuredevops - - googlechat - - googlepubsub - - webex - - sentry - - azureeventhub - - telegram - - lark - - matrix - - opsgenie - - alertmanager - - grafana - - githubdispatch - - pagerduty - - datadog - type: string - username: - description: Username specifies the name under which events are posted. - maxLength: 2048 - type: string - required: - - type - type: object - status: - default: - observedGeneration: -1 - description: ProviderStatus defines the observed state of the Provider. - properties: - conditions: - description: Conditions holds the conditions for the Provider. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last reconciled generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta3 - schema: - openAPIV3Schema: - description: Provider is the Schema for the providers 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: ProviderSpec defines the desired state of the Provider. - properties: - address: - description: |- - Address specifies the endpoint, in a generic sense, to where alerts are sent. - What kind of endpoint depends on the specific Provider type being used. - For the generic Provider, for example, this is an HTTP/S address. - For other Provider types this could be a project ID or a namespace. - maxLength: 2048 - type: string - certSecretRef: - description: |- - CertSecretRef specifies the Secret containing TLS certificates - for secure communication. - - Supported configurations: - - CA-only: Server authentication (provide ca.crt only) - - mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key) - - Client-only: Client authentication with system CA (provide tls.crt + tls.key only) - - Legacy keys "caFile", "certFile", "keyFile" are supported but deprecated. Use "ca.crt", "tls.crt", "tls.key" instead. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - channel: - description: Channel specifies the destination channel where events should be posted. - maxLength: 2048 - type: string - commitStatusExpr: - description: |- - CommitStatusExpr is a CEL expression that evaluates to a string value - that can be used to generate a custom commit status message for use - with eligible Provider types (github, gitlab, gitea, bitbucketserver, - bitbucket, azuredevops). Supported variables are: event, provider, - and alert. - type: string - interval: - description: |- - Interval at which to reconcile the Provider with its Secret references. - Deprecated and not used in v1beta3. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - proxy: - description: |- - Proxy the HTTP/S address of the proxy server. - Deprecated: Use ProxySecretRef instead. Will be removed in v1. - maxLength: 2048 - pattern: ^(http|https)://.*$ - type: string - proxySecretRef: - description: |- - ProxySecretRef specifies the Secret containing the proxy configuration - for this Provider. The Secret should contain an 'address' key with the - HTTP/S address of the proxy server. Optional 'username' and 'password' - keys can be provided for proxy authentication. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - secretRef: - description: |- - SecretRef specifies the Secret containing the authentication - credentials for this Provider. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - serviceAccountName: - description: |- - ServiceAccountName is the name of the Kubernetes ServiceAccount used to - authenticate with cloud provider services through workload identity. - This enables multi-tenant authentication without storing static credentials. - - Supported provider types: azureeventhub, azuredevops, googlepubsub - - When specified, the controller will: - 1. Create an OIDC token for the specified ServiceAccount - 2. Exchange it for cloud provider credentials via STS - 3. Use the obtained credentials for API authentication - - When unspecified, controller-level authentication is used (single-tenant). - - An error is thrown if static credentials are also defined in SecretRef. - This field requires the ObjectLevelWorkloadIdentity feature gate to be enabled. - type: string - suspend: - description: |- - Suspend tells the controller to suspend subsequent - events handling for this Provider. - type: boolean - timeout: - description: Timeout for sending alerts to the Provider. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ - type: string - type: - description: Type specifies which Provider implementation to use. - enum: - - slack - - discord - - msteams - - rocket - - generic - - generic-hmac - - github - - gitlab - - gitea - - bitbucketserver - - bitbucket - - azuredevops - - googlechat - - googlepubsub - - webex - - sentry - - azureeventhub - - telegram - - lark - - matrix - - opsgenie - - alertmanager - - grafana - - githubdispatch - - pagerduty - - datadog - - nats - - zulip - - otel - type: string - username: - description: Username specifies the name under which events are posted. - maxLength: 2048 - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: spec.commitStatusExpr is only supported for the 'github', 'gitlab', 'gitea', 'bitbucketserver', 'bitbucket', 'azuredevops' provider types - rule: self.type == 'github' || self.type == 'gitlab' || self.type == 'gitea' || self.type == 'bitbucketserver' || self.type == 'bitbucket' || self.type == 'azuredevops' || !has(self.commitStatusExpr) - type: object - served: true - storage: true - subresources: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: receivers.notification.toolkit.fluxcd.io -spec: - group: notification.toolkit.fluxcd.io - names: - kind: Receiver - listKind: ReceiverList - plural: receivers - singular: receiver - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - name: v1 - schema: - openAPIV3Schema: - description: Receiver is the Schema for the receivers 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: ReceiverSpec defines the desired state of the Receiver. - properties: - events: - description: |- - Events specifies the list of event types to handle, - e.g. 'push' for GitHub or 'Push Hook' for GitLab. - items: - type: string - type: array - interval: - default: 10m - description: Interval at which to reconcile the Receiver with its Secret references. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - resourceFilter: - description: |- - ResourceFilter is a CEL expression expected to return a boolean that is - evaluated for each resource referenced in the Resources field when a - webhook is received. If the expression returns false then the controller - will not request a reconciliation for the resource. - When the expression is specified the controller will parse it and mark - the object as terminally failed if the expression is invalid or does not - return a boolean. - type: string - resources: - description: A list of resources to be notified about changes. - items: - description: |- - CrossNamespaceObjectReference contains enough information to let you locate the - typed referenced object at cluster level - properties: - apiVersion: - description: API version of the referent - type: string - kind: - description: Kind of the referent - enum: - - Bucket - - GitRepository - - Kustomization - - HelmRelease - - HelmChart - - HelmRepository - - ImageRepository - - ImagePolicy - - ImageUpdateAutomation - - OCIRepository - type: string - 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. - MatchLabels requires the name to be set to `*`. - type: object - name: - description: |- - Name of the referent - If multiple resources are targeted `*` may be set. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace of the referent - maxLength: 253 - minLength: 1 - type: string - required: - - kind - - name - type: object - type: array - secretRef: - description: |- - SecretRef specifies the Secret containing the token used - to validate the payload authenticity. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - suspend: - description: |- - Suspend tells the controller to suspend subsequent - events handling for this receiver. - type: boolean - type: - description: |- - Type of webhook sender, used to determine - the validation procedure and payload deserialization. - enum: - - generic - - generic-hmac - - github - - gitlab - - bitbucket - - harbor - - dockerhub - - quay - - gcr - - nexus - - acr - - cdevents - type: string - required: - - resources - - secretRef - - type - type: object - status: - default: - observedGeneration: -1 - description: ReceiverStatus defines the observed state of the Receiver. - properties: - conditions: - description: Conditions holds the conditions for the Receiver. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation of the Receiver object. - format: int64 - type: integer - webhookPath: - description: |- - WebhookPath is the generated incoming webhook address in the format - of '/hook/sha256sum(token+name+namespace)'. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - deprecated: true - deprecationWarning: v1beta2 Receiver is deprecated, upgrade to v1 - name: v1beta2 - schema: - openAPIV3Schema: - description: Receiver is the Schema for the receivers 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: ReceiverSpec defines the desired state of the Receiver. - properties: - events: - description: |- - Events specifies the list of event types to handle, - e.g. 'push' for GitHub or 'Push Hook' for GitLab. - items: - type: string - type: array - interval: - description: Interval at which to reconcile the Receiver with its Secret references. - pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ - type: string - resources: - description: A list of resources to be notified about changes. - items: - description: |- - CrossNamespaceObjectReference contains enough information to let you locate the - typed referenced object at cluster level - properties: - apiVersion: - description: API version of the referent - type: string - kind: - description: Kind of the referent - enum: - - Bucket - - GitRepository - - Kustomization - - HelmRelease - - HelmChart - - HelmRepository - - ImageRepository - - ImagePolicy - - ImageUpdateAutomation - - OCIRepository - type: string - 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. - MatchLabels requires the name to be set to `*`. - type: object - name: - description: |- - Name of the referent - If multiple resources are targeted `*` may be set. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace of the referent - maxLength: 253 - minLength: 1 - type: string - required: - - kind - - name - type: object - type: array - secretRef: - description: |- - SecretRef specifies the Secret containing the token used - to validate the payload authenticity. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - suspend: - description: |- - Suspend tells the controller to suspend subsequent - events handling for this receiver. - type: boolean - type: - description: |- - Type of webhook sender, used to determine - the validation procedure and payload deserialization. - enum: - - generic - - generic-hmac - - github - - gitlab - - bitbucket - - harbor - - dockerhub - - quay - - gcr - - nexus - - acr - type: string - required: - - resources - - secretRef - - type - type: object - status: - default: - observedGeneration: -1 - description: ReceiverStatus defines the observed state of the Receiver. - properties: - conditions: - description: Conditions holds the conditions for the Receiver. - 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 - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation of the Receiver object. - format: int64 - type: integer - url: - description: |- - URL is the generated incoming webhook address in the format - of '/hook/sha256sum(token+name+namespace)'. - Deprecated: Replaced by WebhookPath. - type: string - webhookPath: - description: |- - WebhookPath is the generated incoming webhook address in the format - of '/hook/sha256sum(token+name+namespace)'. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} ---- -apiVersion: v1 -kind: Namespace -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - pod-security.kubernetes.io/enforce: privileged - name: cozy-fluxcd ---- -apiVersion: v1 -kind: ResourceQuota -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: flux - namespace: cozy-fluxcd -spec: - hard: - pods: "1000" - scopeSelector: - matchExpressions: - - operator: In - scopeName: PriorityClass - values: - - system-node-critical - - system-cluster-critical ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: flux - namespace: cozy-fluxcd ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - rbac.authorization.k8s.io/aggregate-to-admin: "true" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - rbac.authorization.k8s.io/aggregate-to-view: "true" - name: flux-view -rules: - - apiGroups: - - notification.toolkit.fluxcd.io - - source.toolkit.fluxcd.io - - helm.toolkit.fluxcd.io - - image.toolkit.fluxcd.io - - kustomize.toolkit.fluxcd.io - - source.extensions.fluxcd.io - resources: - - '*' - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: flux -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: flux - namespace: cozy-fluxcd ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - app.kubernetes.io/role: cluster-admin - labels: - app.kubernetes.io/name: flux - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v2.7.3 - name: flux - namespace: cozy-fluxcd -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: flux - strategy: - type: Recreate - template: - metadata: - annotations: - cluster-autoscaler.kubernetes.io/safe-to-evict: "true" - prometheus.io/scrape: "true" - labels: - app.kubernetes.io/name: flux - spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchExpressions: - - key: app.kubernetes.io/name - operator: In - values: - - flux - topologyKey: kubernetes.io/hostname - containers: - - args: - - --watch-all-namespaces - - --log-level=info - - --log-encoding=json - - --enable-leader-election=false - - --metrics-addr=:9791 - - --health-addr=:9792 - - --storage-addr=:9790 - - --storage-path=/data - - --storage-adv-addr=flux.$(RUNTIME_NAMESPACE).svc - - --concurrent=5 - - --requeue-dependency=30s - - --watch-label-selector=!sharding.fluxcd.io/key - - --helm-cache-max-size=10 - - --helm-cache-ttl=60m - - --helm-cache-purge-interval=5m - - --events-addr=http://localhost:9690 - env: - - name: SOURCE_CONTROLLER_LOCALHOST - value: localhost:9790 - - name: SOURCE_WATCHER_LOCALHOST - value: localhost:9691 - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: GOMEMLIMIT - valueFrom: - resourceFieldRef: - resource: limits.memory - - name: TUF_ROOT - value: /tmp/.sigstore - - name: NO_PROXY - value: .svc - {{- include "cozy.kubernetes_envs" . | nindent 12 }} - image: ghcr.io/fluxcd/source-controller:v1.7.3 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz-sc - name: source-controller - ports: - - containerPort: 9790 - name: http-sc - protocol: TCP - - containerPort: 9791 - name: http-prom-sc - protocol: TCP - - containerPort: 9792 - name: healthz-sc - protocol: TCP - readinessProbe: - httpGet: - path: / - port: http-sc - resources: - limits: - memory: 1Gi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /data - name: data - - mountPath: /tmp - name: tmp - - args: - - --watch-all-namespaces - - --log-level=info - - --log-encoding=json - - --enable-leader-election=false - - --metrics-addr=:9793 - - --health-addr=:9794 - - --watch-label-selector=!sharding.fluxcd.io/key - - --concurrent=5 - - --requeue-dependency=30s - - --events-addr=http://localhost:9690 - - --feature-gates=ExternalArtifact=true - env: - - name: SOURCE_CONTROLLER_LOCALHOST - value: localhost:9790 - - name: SOURCE_WATCHER_LOCALHOST - value: localhost:9691 - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: GOMEMLIMIT - valueFrom: - resourceFieldRef: - resource: limits.memory - - name: TUF_ROOT - value: /tmp/.sigstore - - name: NO_PROXY - value: .svc - {{- include "cozy.kubernetes_envs" . | nindent 12 }} - image: ghcr.io/fluxcd/kustomize-controller:v1.7.2 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz-kc - name: kustomize-controller - ports: - - containerPort: 9793 - name: http-prom-kc - protocol: TCP - - containerPort: 9794 - name: healthz-kc - protocol: TCP - readinessProbe: - httpGet: - path: /readyz - port: healthz-kc - resources: - limits: - memory: 1Gi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /tmp - name: tmp - - args: - - --watch-all-namespaces - - --log-level=info - - --log-encoding=json - - --enable-leader-election=false - - --metrics-addr=:9795 - - --health-addr=:9796 - - --watch-label-selector=!sharding.fluxcd.io/key - - --concurrent=5 - - --requeue-dependency=30s - - --events-addr=http://localhost:9690 - - --feature-gates=ExternalArtifact=true - env: - - name: SOURCE_CONTROLLER_LOCALHOST - value: localhost:9790 - - name: SOURCE_WATCHER_LOCALHOST - value: localhost:9691 - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: GOMEMLIMIT - valueFrom: - resourceFieldRef: - resource: limits.memory - - name: TUF_ROOT - value: /tmp/.sigstore - - name: NO_PROXY - value: .svc - {{- include "cozy.kubernetes_envs" . | nindent 12 }} - image: ghcr.io/fluxcd/helm-controller:v1.4.3 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz-hc - name: helm-controller - ports: - - containerPort: 9795 - name: http-prom-hc - protocol: TCP - - containerPort: 9796 - name: healthz-hc - protocol: TCP - readinessProbe: - httpGet: - path: /readyz - port: healthz-hc - resources: - limits: - memory: 1Gi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /tmp - name: tmp - - args: - - --watch-all-namespaces - - --log-level=info - - --log-encoding=json - - --enable-leader-election=false - - --receiverAddr=:9797 - - --metrics-addr=:9798 - - --health-addr=:9799 - - --events-addr=:9690 - env: - - name: SOURCE_CONTROLLER_LOCALHOST - value: localhost:9790 - - name: SOURCE_WATCHER_LOCALHOST - value: localhost:9691 - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: GOMEMLIMIT - valueFrom: - resourceFieldRef: - resource: limits.memory - - name: TUF_ROOT - value: /tmp/.sigstore - - name: NO_PROXY - value: .svc - {{- include "cozy.kubernetes_envs" . | nindent 12 }} - image: ghcr.io/fluxcd/notification-controller:v1.7.4 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz-nc - name: notification-controller - ports: - - containerPort: 9690 - name: http-nc - protocol: TCP - - containerPort: 9797 - name: http-webhook-nc - protocol: TCP - - containerPort: 9798 - name: http-prom-nc - protocol: TCP - - containerPort: 9799 - name: healthz-nc - protocol: TCP - readinessProbe: - httpGet: - path: /readyz - port: healthz-nc - resources: - limits: - memory: 1Gi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /tmp - name: tmp - - args: - - --watch-all-namespaces - - --log-level=info - - --log-encoding=json - - --enable-leader-election=false - - --metrics-addr=:9692 - - --health-addr=:9693 - - --storage-addr=:9691 - - --storage-path=/data - - --storage-adv-addr=source-watcher.$(RUNTIME_NAMESPACE).svc - - --events-addr=http://localhost:9690 - env: - - name: SOURCE_CONTROLLER_LOCALHOST - value: localhost:9790 - - name: SOURCE_WATCHER_LOCALHOST - value: localhost:9691 - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: GOMEMLIMIT - valueFrom: - resourceFieldRef: - resource: limits.memory - - name: TUF_ROOT - value: /tmp/.sigstore - - name: NO_PROXY - value: .svc - {{- include "cozy.kubernetes_envs" . | nindent 12 }} - image: ghcr.io/fluxcd/source-watcher:v2.0.2 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz-sw - name: source-watcher - ports: - - containerPort: 9691 - name: http-sw - protocol: TCP - - containerPort: 9692 - name: http-prom-sw - protocol: TCP - - containerPort: 9693 - name: healthz-sw - protocol: TCP - readinessProbe: - httpGet: - path: / - port: http-sw - resources: - limits: - memory: 1Gi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - volumeMounts: - - mountPath: /data - name: data - - mountPath: /tmp - name: tmp - dnsPolicy: ClusterFirstWithHostNet - hostNetwork: true - priorityClassName: system-cluster-critical - securityContext: - fsGroup: 1337 - serviceAccountName: flux - terminationGracePeriodSeconds: 120 - tolerations: - - key: node.kubernetes.io/not-ready - operator: Exists - - effect: NoExecute - key: node.kubernetes.io/unreachable - operator: Exists - tolerationSeconds: 300 - volumes: - - emptyDir: {} - name: data - - emptyDir: {} - name: tmp diff --git a/packages/core/installer/Makefile b/packages/core/installer/Makefile index 4c19c258..ad9982b5 100644 --- a/packages/core/installer/Makefile +++ b/packages/core/installer/Makefile @@ -1,57 +1,45 @@ NAME=installer NAMESPACE=cozy-system -include ../../../scripts/common-envs.mk +include ../../../hack/common-envs.mk pre-checks: ../../../hack/pre-checks.sh show: - cozyhr show -n $(NAMESPACE) $(NAME) --plain + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain apply: - cozyhr show -n $(NAMESPACE) $(NAME) --plain | kubectl apply -f- + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain | kubectl apply -f - diff: - cozyhr show -n $(NAMESPACE) $(NAME) --plain | kubectl diff -f - + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain | kubectl diff -f - -image: pre-checks image-cozystack - -image-cozystack: - docker buildx build -f images/cozystack/Dockerfile ../../.. \ - --tag $(REGISTRY)/installer:$(call settag,$(TAG)) \ - --cache-from type=registry,ref=$(REGISTRY)/installer:latest \ - --cache-to type=inline \ - --metadata-file images/installer.json \ - $(BUILDX_ARGS) - IMAGE="$(REGISTRY)/installer:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/installer.json -o json -r)" \ - yq -i '.cozystack.image = strenv(IMAGE)' values.yaml - rm -f images/installer.json - -update-version: - TAG="$(call settag,$(TAG))" \ - yq -i '.cozystackOperator.cozystackVersion = strenv(TAG)' values.yaml +image: pre-checks image-operator image-packages image-operator: docker buildx build -f images/cozystack-operator/Dockerfile ../../.. \ - --tag $(REGISTRY)/cozystack-operator:$(call settag,$(TAG)) \ - --cache-from type=registry,ref=$(REGISTRY)/cozystack-operator:latest \ - --cache-to type=inline \ - --metadata-file images/cozystack-operator.json \ - $(BUILDX_ARGS) - IMAGE="$(REGISTRY)/cozystack-operator:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/cozystack-operator.json -o json -r)" \ - yq -i '.cozystackOperator.image = strenv(IMAGE)' values.yaml + --tag $(REGISTRY)/cozystack-operator:$(call settag,$(TAG)) \ + --build-arg VERSION=$(call settag,$(TAG)) \ + --cache-from type=registry,ref=$(REGISTRY)/cozystack-operator:latest \ + --cache-to type=inline \ + --metadata-file images/cozystack-operator.json \ + $(BUILDX_ARGS) + IMAGE="$(REGISTRY)/cozystack-operator:$(call settag,$(TAG))@$$(yq -e '.["containerimage.digest"]' images/cozystack-operator.json -o json -r)" \ + yq -i '.cozystackOperator.image = strenv(IMAGE)' values.yaml rm -f images/cozystack-operator.json - -image-packages: update-version +image-packages: mkdir -p ../../../_out/assets images flux push artifact \ - oci://$(REGISTRY)/platform-packages:$(call settag,$(TAG)) \ - --path=../../../packages \ - --source=https://github.com/cozystack/cozystack \ - --revision="$$(git describe --tags):$$(git rev-parse HEAD)" \ - 2>&1 | tee images/cozystack-packages.log - export REPO="oci://$(REGISTRY)/platform-packages"; \ - export DIGEST=$$(awk -F@ '/artifact successfully pushed/ {print $$2}' images/cozystack-packages.log; rm -f images/cozystack-packages.log); \ - test -n "$$DIGEST" && yq -i '.cozystackOperator.platformSource = (strenv(REPO) + "@" + strenv(DIGEST))' values.yaml + oci://$(REGISTRY)/cozystack-packages:$(call settag,$(TAG)) \ + --path=../../../packages \ + --source=https://github.com/cozystack/cozystack \ + --revision="$$(git describe --tags):$$(git rev-parse HEAD)" \ + 2>&1 | tee images/cozystack-packages.log + export REPO="oci://$(REGISTRY)/cozystack-packages" \ + export DIGEST=$$(awk -F @ '/artifact successfully pushed/ {print $$2}' images/cozystack-packages.log) && \ + rm -f images/cozystack-packages.log && \ + test -n "$$DIGEST" && \ + yq -i '.cozystackOperator.platformSourceUrl = strenv(REPO)' values.yaml && \ + yq -i '.cozystackOperator.platformSourceRef = "digest=" + strenv(DIGEST)' values.yaml diff --git a/packages/core/installer/images/cozystack-operator/Dockerfile b/packages/core/installer/images/cozystack-operator/Dockerfile index 8c4cb79c..4268b2ba 100644 --- a/packages/core/installer/images/cozystack-operator/Dockerfile +++ b/packages/core/installer/images/cozystack-operator/Dockerfile @@ -2,6 +2,7 @@ FROM golang:1.25-alpine as builder ARG TARGETOS ARG TARGETARCH +ARG VERSION=dev RUN apk add --no-cache make git @@ -12,7 +13,7 @@ RUN go mod download # Build cozystack-operator RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build \ - -ldflags="-w -s" \ + -ldflags="-w -s -X github.com/cozystack/cozystack/pkg/version.Version=${VERSION}" \ -o /cozystack-operator \ ./cmd/cozystack-operator diff --git a/packages/core/installer/images/cozystack/Dockerfile b/packages/core/installer/images/cozystack/Dockerfile deleted file mode 100644 index 8e1ae219..00000000 --- a/packages/core/installer/images/cozystack/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -FROM golang:1.24-alpine AS k8s-await-election-builder - -ARG K8S_AWAIT_ELECTION_GITREPO=https://github.com/LINBIT/k8s-await-election -ARG K8S_AWAIT_ELECTION_VERSION=0.4.1 - -# TARGETARCH is a docker special variable: https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope -ARG TARGETARCH - -RUN apk add --no-cache git make -RUN git clone ${K8S_AWAIT_ELECTION_GITREPO} /usr/local/go/k8s-await-election/ \ - && cd /usr/local/go/k8s-await-election \ - && git reset --hard v${K8S_AWAIT_ELECTION_VERSION} \ - && make \ - && mv ./out/k8s-await-election-${TARGETARCH} /k8s-await-election - -FROM golang:1.25-alpine AS builder - -ARG TARGETOS -ARG TARGETARCH - -RUN apk add --no-cache make git -RUN apk add helm --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community - -COPY . /src/ -WORKDIR /src - -RUN go mod download - -FROM alpine:3.22 - -RUN wget -O- https://github.com/cozystack/cozyhr/raw/refs/heads/main/hack/install.sh | sh -s -- -v 1.5.0 - -RUN apk add --no-cache make kubectl helm coreutils git jq openssl - -COPY --from=builder /src/scripts /cozystack/scripts -COPY --from=builder /src/packages/core /cozystack/packages/core -COPY --from=builder /src/packages/system /cozystack/packages/system -COPY --from=k8s-await-election-builder /k8s-await-election /usr/bin/k8s-await-election - -WORKDIR /cozystack -ENTRYPOINT ["/usr/bin/k8s-await-election", "/cozystack/scripts/installer.sh" ] diff --git a/packages/core/installer/images/cozystack/Dockerfile.dockerignore b/packages/core/installer/images/cozystack/Dockerfile.dockerignore deleted file mode 100644 index c1d18d8a..00000000 --- a/packages/core/installer/images/cozystack/Dockerfile.dockerignore +++ /dev/null @@ -1 +0,0 @@ -_out diff --git a/packages/core/installer/templates/cozystack-operator-generic.yaml b/packages/core/installer/templates/cozystack-operator-generic.yaml new file mode 100644 index 00000000..510a92c8 --- /dev/null +++ b/packages/core/installer/templates/cozystack-operator-generic.yaml @@ -0,0 +1,90 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: cozy-system + labels: + cozystack.io/system: "true" + pod-security.kubernetes.io/enforce: privileged +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cozystack + namespace: cozy-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cozystack +subjects: +- kind: ServiceAccount + name: cozystack + namespace: cozy-system +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cozystack-operator + namespace: cozy-system +spec: + replicas: 1 + selector: + matchLabels: + app: cozystack-operator + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + template: + metadata: + labels: + app: cozystack-operator + spec: + serviceAccountName: cozystack + containers: + - name: cozystack-operator + image: "{{ .Values.cozystackOperator.image }}" + args: + - --leader-elect=true + - --install-flux=true + - --metrics-bind-address=0 + - --health-probe-bind-address= + {{- if .Values.cozystackOperator.disableTelemetry }} + - --disable-telemetry + {{- end }} + - --platform-source-name=cozystack-platform + - --platform-source-url={{ .Values.cozystackOperator.platformSourceUrl }} + {{- if .Values.cozystackOperator.platformSourceRef }} + - --platform-source-ref={{ .Values.cozystackOperator.platformSourceRef }} + {{- end }} + env: + # Generic Kubernetes: read from ConfigMap + # Create cozystack-operator-config ConfigMap before applying this manifest + - name: KUBERNETES_SERVICE_HOST + valueFrom: + configMapKeyRef: + name: cozystack-operator-config + key: KUBERNETES_SERVICE_HOST + optional: false + - name: KUBERNETES_SERVICE_PORT + valueFrom: + configMapKeyRef: + name: cozystack-operator-config + key: KUBERNETES_SERVICE_PORT + optional: false + hostNetwork: true + tolerations: + - key: "node.kubernetes.io/not-ready" + operator: "Exists" + - key: "node.kubernetes.io/unreachable" + operator: "Exists" + - key: "node.cilium.io/agent-not-ready" + operator: "Exists" + - key: "node.cloudprovider.kubernetes.io/uninitialized" + operator: "Exists" diff --git a/packages/core/installer/templates/cozystack.yaml b/packages/core/installer/templates/cozystack-operator-hosted.yaml similarity index 51% rename from packages/core/installer/templates/cozystack.yaml rename to packages/core/installer/templates/cozystack-operator-hosted.yaml index 24ca0557..38ccdf75 100644 --- a/packages/core/installer/templates/cozystack.yaml +++ b/packages/core/installer/templates/cozystack-operator-hosted.yaml @@ -1,4 +1,3 @@ -{{- if not .Values.cozystackOperator.enabled }} --- apiVersion: v1 kind: Namespace @@ -30,13 +29,13 @@ roleRef: apiVersion: apps/v1 kind: Deployment metadata: - name: cozystack + name: cozystack-operator namespace: cozy-system spec: replicas: 1 selector: matchLabels: - app: cozystack + app: cozystack-operator strategy: type: RollingUpdate rollingUpdate: @@ -45,37 +44,34 @@ spec: template: metadata: labels: - app: cozystack + app: cozystack-operator spec: - hostNetwork: true serviceAccountName: cozystack containers: - - name: cozystack - image: "{{ .Values.cozystack.image }}" - env: - - name: KUBERNETES_SERVICE_HOST - value: localhost - - name: INSTALL_FLUX - value: "true" - - name: KUBERNETES_SERVICE_PORT - value: "7445" - - name: K8S_AWAIT_ELECTION_ENABLED - value: "1" - - name: K8S_AWAIT_ELECTION_NAME - value: cozystack - - name: K8S_AWAIT_ELECTION_LOCK_NAME - value: cozystack - - name: K8S_AWAIT_ELECTION_LOCK_NAMESPACE - value: cozy-system - - name: K8S_AWAIT_ELECTION_IDENTITY - valueFrom: - fieldRef: - fieldPath: metadata.name + - name: cozystack-operator + image: "{{ .Values.cozystackOperator.image }}" + args: + - --leader-elect=true + - --install-flux=true + - --metrics-bind-address=0 + - --health-probe-bind-address= + {{- if .Values.cozystackOperator.disableTelemetry }} + - --disable-telemetry + {{- end }} + - --platform-source-name=cozystack-platform + - --platform-source-url={{ .Values.cozystackOperator.platformSourceUrl }} + {{- if .Values.cozystackOperator.platformSourceRef }} + - --platform-source-ref={{ .Values.cozystackOperator.platformSourceRef }} + {{- end }} + # Hosted: use in-cluster service account, no env override needed + env: [] + hostNetwork: true tolerations: - key: "node.kubernetes.io/not-ready" operator: "Exists" - effect: "NoSchedule" + - key: "node.kubernetes.io/unreachable" + operator: "Exists" - key: "node.cilium.io/agent-not-ready" operator: "Exists" - effect: "NoSchedule" -{{- end }} + - key: "node.cloudprovider.kubernetes.io/uninitialized" + operator: "Exists" diff --git a/packages/core/installer/templates/cozystack-operator.yaml b/packages/core/installer/templates/cozystack-operator.yaml index 514dcc32..c40dc663 100644 --- a/packages/core/installer/templates/cozystack-operator.yaml +++ b/packages/core/installer/templates/cozystack-operator.yaml @@ -1,4 +1,3 @@ -{{- if .Values.cozystackOperator.enabled }} --- apiVersion: v1 kind: Namespace @@ -56,7 +55,6 @@ spec: - --install-flux=true - --metrics-bind-address=0 - --health-probe-bind-address= - - --cozystack-version={{ .Values.cozystackOperator.cozystackVersion }} {{- if .Values.cozystackOperator.disableTelemetry }} - --disable-telemetry {{- end }} @@ -66,59 +64,18 @@ spec: - --platform-source-ref={{ .Values.cozystackOperator.platformSourceRef }} {{- end }} env: + # Talos KubePrism endpoint - name: KUBERNETES_SERVICE_HOST - value: localhost + value: "localhost" - name: KUBERNETES_SERVICE_PORT value: "7445" hostNetwork: true tolerations: - key: "node.kubernetes.io/not-ready" operator: "Exists" - effect: "NoSchedule" + - key: "node.kubernetes.io/unreachable" + operator: "Exists" - key: "node.cilium.io/agent-not-ready" operator: "Exists" - effect: "NoSchedule" ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.cozystack-platform - annotations: - operator.cozystack.io/skip-cozystack-values: "true" -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - components: - - install: - namespace: cozy-system - releaseName: cozystack-platform - name: cozystack-platform - path: core/platform - valuesFiles: - - values.yaml - - name: isp-full - components: - - install: - namespace: cozy-system - releaseName: cozystack-platform - name: cozystack-platform - path: core/platform - valuesFiles: - - values.yaml - - values-isp-full.yaml - - name: isp-hosted - components: - - install: - namespace: cozy-system - releaseName: cozystack-platform - name: cozystack-platform - path: core/platform - valuesFiles: - - values.yaml - - values-isp-hosted.yaml -{{- end }} + - key: "node.cloudprovider.kubernetes.io/uninitialized" + operator: "Exists" diff --git a/packages/core/installer/templates/crds.yaml b/packages/core/installer/templates/crds.yaml index cffc1205..7c7ea584 100644 --- a/packages/core/installer/templates/crds.yaml +++ b/packages/core/installer/templates/crds.yaml @@ -1,6 +1,3 @@ -{{- if .Values.cozystackOperator.enabled }} {{- range $path, $_ := .Files.Glob "definitions/*.yaml" }} ---- {{ $.Files.Get $path }} {{- end }} -{{- end }} diff --git a/packages/core/installer/templates/packagesource.yaml b/packages/core/installer/templates/packagesource.yaml new file mode 100644 index 00000000..f4a5f6d0 --- /dev/null +++ b/packages/core/installer/templates/packagesource.yaml @@ -0,0 +1,53 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.cozystack-platform + annotations: + operator.cozystack.io/skip-cozystack-values: "true" +spec: + sourceRef: + kind: OCIRepository + name: cozystack-platform + namespace: cozy-system + path: / + variants: + - name: default + components: + - install: + namespace: cozy-system + releaseName: cozystack-platform + name: platform + path: core/platform + valuesFiles: + - values.yaml + - name: isp-full + components: + - install: + namespace: cozy-system + releaseName: cozystack-platform + name: platform + path: core/platform + valuesFiles: + - values.yaml + - values-isp-full.yaml + - name: isp-hosted + components: + - install: + namespace: cozy-system + releaseName: cozystack-platform + name: platform + path: core/platform + valuesFiles: + - values.yaml + - values-isp-hosted.yaml + - name: isp-full-generic + components: + - install: + namespace: cozy-system + releaseName: cozystack-platform + name: platform + path: core/platform + valuesFiles: + - values.yaml + - values-isp-full-generic.yaml diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index 0fcf6c25..2325647e 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,8 +1,4 @@ -cozystack: - image: ghcr.io/cozystack/cozystack/installer:v0.38.2@sha256:9ff92b655de6f9bea3cba4cd42dcffabd9aace6966dcfb1cc02dda2420ea4a15 cozystackOperator: - enabled: false - image: ghcr.io/cozystack/cozystack/cozystack-operator:latest@sha256:f7f6e0fd9e896b7bfa642d0bfa4378bc14e646bc5c2e86e2e09a82770ef33181 - platformSourceUrl: 'oci://ghcr.io/cozystack/cozystack/platform-packages' - platformSourceRef: 'digest=sha256:0576491291b33936cdf770a5c5b5692add97339c1505fc67a92df9d69dfbfdf6' - cozystackVersion: latest + image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.0.0-beta.2@sha256:aaea9d8430187f208e6464cb6f102dcbbcdb0584b6a7a8a690ad91fc1f5d45e6 + platformSourceUrl: 'oci://ghcr.io/cozystack/cozystack/cozystack-packages' + platformSourceRef: 'digest=sha256:f59e562f2c91446117773ad457251d567706ea2964251a2b0acc65060fd1f3bc' diff --git a/packages/core/platform/Makefile b/packages/core/platform/Makefile index 2ea59153..7a53efa7 100644 --- a/packages/core/platform/Makefile +++ b/packages/core/platform/Makefile @@ -1,34 +1,29 @@ NAME=platform NAMESPACE=cozy-system -include ../../../scripts/common-envs.mk +include ../../../hack/common-envs.mk show: - cozyhr show -n $(NAMESPACE) $(NAME) --plain + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain apply: - cozyhr show -n $(NAMESPACE) $(NAME) --plain | kubectl apply -f- - kubectl delete helmreleases.helm.toolkit.fluxcd.io -l cozystack.io/marked-for-deletion=true -A + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain | kubectl apply --filename - + kubectl delete helmreleases.helm.toolkit.fluxcd.io --selector cozystack.io/marked-for-deletion=true --all-namespaces reconcile: apply -namespaces-show: - cozyhr show -n $(NAMESPACE) $(NAME) --plain -s templates/namespaces.yaml - -namespaces-apply: - cozyhr show -n $(NAMESPACE) $(NAME) --plain -s templates/namespaces.yaml | kubectl apply -f- - diff: - cozyhr show -n $(NAMESPACE) $(NAME) --plain | kubectl diff -f- + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain | kubectl diff --filename - -image: image-assets -image-assets: - docker buildx build -f images/cozystack-assets/Dockerfile ../../.. \ - --tag $(REGISTRY)/cozystack-assets:$(call settag,$(TAG)) \ - --cache-from type=registry,ref=$(REGISTRY)/cozystack-assets:latest \ +image: image-migrations + +image-migrations: + docker buildx build --file images/migrations/Dockerfile . \ + --tag $(REGISTRY)/platform-migrations:$(call settag,$(TAG)) \ + --cache-from type=registry,ref=$(REGISTRY)/platform-migrations:latest \ --cache-to type=inline \ - --metadata-file images/cozystack-assets.json \ + --metadata-file images/migrations.json \ $(BUILDX_ARGS) - IMAGE="$(REGISTRY)/cozystack-assets:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/cozystack-assets.json -o json -r)" \ - yq -i '.assets.image = strenv(IMAGE)' values.yaml - rm -f images/cozystack-assets.json + IMAGE="$(REGISTRY)/platform-migrations:$(call settag,$(TAG))@$$(yq --exit-status '.["containerimage.digest"]' images/migrations.json --output-format json --raw-output)" \ + yq --inplace '.migrations.image = strenv(IMAGE)' values.yaml + rm -f images/migrations.json diff --git a/packages/core/platform/bundles/distro-full.yaml b/packages/core/platform/bundles/distro-full.yaml deleted file mode 100644 index 13d58ded..00000000 --- a/packages/core/platform/bundles/distro-full.yaml +++ /dev/null @@ -1,435 +0,0 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} - -releases: -- name: cilium - releaseName: cilium - chart: cozy-cilium - namespace: cozy-cilium - privileged: true - dependsOn: [] - valuesFiles: - - values.yaml - - values-talos.yaml - values: - cilium: - enableIPv4Masquerade: true - enableIdentityMark: true - ipv4NativeRoutingCIDR: "{{ index $cozyConfig.data "ipv4-pod-cidr" }}" - autoDirectNodeRoutes: true - routingMode: native - -- name: cilium-networkpolicy - releaseName: cilium-networkpolicy - chart: cozy-cilium-networkpolicy - namespace: cozy-cilium - privileged: true - dependsOn: [cilium] - -- name: cozy-proxy - releaseName: cozystack - chart: cozy-cozy-proxy - namespace: cozy-system - optional: true - dependsOn: [cilium] - -- name: cert-manager-crds - releaseName: cert-manager-crds - chart: cozy-cert-manager-crds - namespace: cozy-cert-manager - dependsOn: [cilium] - -- name: cozystack-controller - releaseName: cozystack-controller - chart: cozy-cozystack-controller - namespace: cozy-system - dependsOn: [cilium] - {{- if eq (index $cozyConfig.data "telemetry-enabled") "false" }} - values: - cozystackController: - disableTelemetry: true - {{- end }} - -- name: lineage-controller-webhook - releaseName: lineage-controller-webhook - chart: cozy-lineage-controller-webhook - namespace: cozy-system - dependsOn: [cozystack-controller,cilium,cert-manager] - -- name: cozystack-resource-definition-crd - releaseName: cozystack-resource-definition-crd - chart: cozystack-resource-definition-crd - namespace: cozy-system - dependsOn: [cilium] - -- name: bootbox-rd - releaseName: bootbox-rd - chart: bootbox-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: bucket-rd - releaseName: bucket-rd - chart: bucket-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: clickhouse-rd - releaseName: clickhouse-rd - chart: clickhouse-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: etcd-rd - releaseName: etcd-rd - chart: etcd-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: ferretdb-rd - releaseName: ferretdb-rd - chart: ferretdb-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: foundationdb-rd - releaseName: foundationdb-rd - chart: foundationdb-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: http-cache-rd - releaseName: http-cache-rd - chart: http-cache-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: info-rd - releaseName: info-rd - chart: info-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: ingress-rd - releaseName: ingress-rd - chart: ingress-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: kafka-rd - releaseName: kafka-rd - chart: kafka-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: kubernetes-rd - releaseName: kubernetes-rd - chart: kubernetes-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: monitoring-rd - releaseName: monitoring-rd - chart: monitoring-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: mysql-rd - releaseName: mysql-rd - chart: mysql-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: nats-rd - releaseName: nats-rd - chart: nats-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: postgres-rd - releaseName: postgres-rd - chart: postgres-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: rabbitmq-rd - releaseName: rabbitmq-rd - chart: rabbitmq-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: redis-rd - releaseName: redis-rd - chart: redis-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: seaweedfs-rd - releaseName: seaweedfs-rd - chart: seaweedfs-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: tcp-balancer-rd - releaseName: tcp-balancer-rd - chart: tcp-balancer-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: tenant-rd - releaseName: tenant-rd - chart: tenant-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: virtual-machine-rd - releaseName: virtual-machine-rd - chart: virtual-machine-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: virtualprivatecloud-rd - releaseName: virtualprivatecloud-rd - chart: virtualprivatecloud-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vm-disk-rd - releaseName: vm-disk-rd - chart: vm-disk-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vm-instance-rd - releaseName: vm-instance-rd - chart: vm-instance-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vpn-rd - releaseName: vpn-rd - chart: vpn-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: cert-manager - releaseName: cert-manager - chart: cozy-cert-manager - namespace: cozy-cert-manager - dependsOn: [cert-manager-crds] - -- name: cert-manager-issuers - releaseName: cert-manager-issuers - chart: cozy-cert-manager-issuers - namespace: cozy-cert-manager - dependsOn: [cilium,cert-manager] - -- name: prometheus-operator-crds - releaseName: prometheus-operator-crds - chart: cozy-prometheus-operator-crds - namespace: cozy-victoria-metrics-operator - dependsOn: [] - -- name: metrics-server - releaseName: metrics-server - chart: cozy-metrics-server - namespace: cozy-monitoring - dependsOn: [cilium,prometheus-operator-crds] - -- name: victoria-metrics-operator - releaseName: victoria-metrics-operator - chart: cozy-victoria-metrics-operator - namespace: cozy-victoria-metrics-operator - optional: true - dependsOn: [cilium,cert-manager,prometheus-operator-crds] - -- name: monitoring-agents - releaseName: monitoring-agents - chart: cozy-monitoring-agents - namespace: cozy-monitoring - privileged: true - optional: true - dependsOn: [cilium,victoria-metrics-operator,metrics-server] - values: - scrapeRules: - etcd: - enabled: true - -- name: metallb - releaseName: metallb - chart: cozy-metallb - namespace: cozy-metallb - privileged: true - dependsOn: [cilium] - -- name: etcd-operator - releaseName: etcd-operator - chart: cozy-etcd-operator - namespace: cozy-etcd-operator - optional: true - dependsOn: [cilium,cert-manager] - -- name: grafana-operator - releaseName: grafana-operator - chart: cozy-grafana-operator - namespace: cozy-grafana-operator - optional: true - dependsOn: [cilium] - -- name: mariadb-operator - releaseName: mariadb-operator - chart: cozy-mariadb-operator - namespace: cozy-mariadb-operator - optional: true - dependsOn: [cilium,cert-manager,victoria-metrics-operator] - values: - mariadb-operator: - clusterName: {{ $clusterDomain }} - -- name: postgres-operator - releaseName: postgres-operator - chart: cozy-postgres-operator - namespace: cozy-postgres-operator - optional: true - dependsOn: [cilium,cert-manager,victoria-metrics-operator] - -- name: kafka-operator - releaseName: kafka-operator - chart: cozy-kafka-operator - namespace: cozy-kafka-operator - optional: true - dependsOn: [cilium,victoria-metrics-operator] - values: - strimzi-kafka-operator: - kubernetesServiceDnsDomain: {{ $clusterDomain }} - -- name: clickhouse-operator - releaseName: clickhouse-operator - chart: cozy-clickhouse-operator - namespace: cozy-clickhouse-operator - optional: true - dependsOn: [cilium,victoria-metrics-operator] - -- name: foundationdb-operator - releaseName: foundationdb-operator - chart: cozy-foundationdb-operator - namespace: cozy-foundationdb-operator - optional: true - dependsOn: [cilium,cert-manager] - -- name: rabbitmq-operator - releaseName: rabbitmq-operator - chart: cozy-rabbitmq-operator - namespace: cozy-rabbitmq-operator - optional: true - dependsOn: [cilium] - -- name: redis-operator - releaseName: redis-operator - chart: cozy-redis-operator - namespace: cozy-redis-operator - optional: true - dependsOn: [cilium] - -- name: piraeus-operator - releaseName: piraeus-operator - chart: cozy-piraeus-operator - namespace: cozy-linstor - dependsOn: [cilium,cert-manager] - -- name: snapshot-controller - releaseName: snapshot-controller - chart: cozy-snapshot-controller - namespace: cozy-snapshot-controller - dependsOn: [cilium,cert-manager-issuers] - -- name: objectstorage-controller - releaseName: objectstorage-controller - chart: cozy-objectstorage-controller - namespace: cozy-objectstorage-controller - optional: true - dependsOn: [cilium] - -- name: linstor - releaseName: linstor - chart: cozy-linstor - namespace: cozy-linstor - privileged: true - dependsOn: [piraeus-operator,cilium,cert-manager,snapshot-controller] - -- name: linstor-scheduler - releaseName: linstor-scheduler - chart: cozy-linstor-scheduler - namespace: cozy-linstor - dependsOn: [linstor,cert-manager] - -- name: nfs-driver - releaseName: nfs-driver - chart: cozy-nfs-driver - namespace: cozy-nfs-driver - privileged: true - dependsOn: [cilium] - optional: true - -- name: telepresence - releaseName: traffic-manager - chart: cozy-telepresence - namespace: cozy-telepresence - optional: true - dependsOn: [] - -- name: external-dns - releaseName: external-dns - chart: cozy-external-dns - namespace: cozy-external-dns - optional: true - dependsOn: [cilium] - -- name: external-secrets-operator - releaseName: external-secrets-operator - chart: cozy-external-secrets-operator - namespace: cozy-external-secrets-operator - optional: true - dependsOn: [cilium] - -- name: keycloak - releaseName: keycloak - chart: cozy-keycloak - namespace: cozy-keycloak - optional: true - dependsOn: [postgres-operator] - -- name: keycloak-operator - releaseName: keycloak-operator - chart: cozy-keycloak-operator - namespace: cozy-keycloak - optional: true - dependsOn: [keycloak] - -- name: bootbox - releaseName: bootbox - chart: cozy-bootbox - namespace: cozy-bootbox - privileged: true - optional: true - dependsOn: [cilium] - -- name: reloader - releaseName: reloader - chart: cozy-reloader - namespace: cozy-reloader - -- name: velero - releaseName: velero - chart: cozy-velero - namespace: cozy-velero - privileged: true - optional: true - dependsOn: [cilium] - -- name: hetzner-robotlb - releaseName: robotlb - optional: true - chart: cozy-hetzner-robotlb - namespace: cozy-hetzner-robotlb - dependsOn: [cilium] diff --git a/packages/core/platform/bundles/distro-hosted.yaml b/packages/core/platform/bundles/distro-hosted.yaml deleted file mode 100644 index e2aa5b03..00000000 --- a/packages/core/platform/bundles/distro-hosted.yaml +++ /dev/null @@ -1,186 +0,0 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} - -releases: -- name: cert-manager-crds - releaseName: cert-manager-crds - chart: cozy-cert-manager-crds - namespace: cozy-cert-manager - dependsOn: [] - -- name: cozystack-controller - releaseName: cozystack-controller - chart: cozy-cozystack-controller - namespace: cozy-system - {{- if eq (index $cozyConfig.data "telemetry-enabled") "false" }} - values: - cozystackController: - disableTelemetry: true - {{- end }} - -- name: lineage-controller-webhook - releaseName: lineage-controller-webhook - chart: cozy-lineage-controller-webhook - namespace: cozy-system - dependsOn: [cozystack-controller,cert-manager] - -- name: cert-manager - releaseName: cert-manager - chart: cozy-cert-manager - namespace: cozy-cert-manager - dependsOn: [cert-manager-crds] - -- name: cert-manager-issuers - releaseName: cert-manager-issuers - chart: cozy-cert-manager-issuers - namespace: cozy-cert-manager - optional: true - dependsOn: [cert-manager] - -- name: prometheus-operator-crds - releaseName: prometheus-operator-crds - chart: cozy-prometheus-operator-crds - namespace: cozy-victoria-metrics-operator - dependsOn: [] - -- name: metrics-server - releaseName: metrics-server - chart: cozy-metrics-server - namespace: cozy-monitoring - dependsOn: [prometheus-operator-crds] - -- name: victoria-metrics-operator - releaseName: victoria-metrics-operator - chart: cozy-victoria-metrics-operator - namespace: cozy-victoria-metrics-operator - optional: true - dependsOn: [prometheus-operator-crds,cert-manager] - -- name: monitoring-agents - releaseName: monitoring-agents - chart: cozy-monitoring-agents - namespace: cozy-monitoring - privileged: true - optional: true - dependsOn: [victoria-metrics-operator, metrics-server] - values: - scrapeRules: - etcd: - enabled: true - -- name: etcd-operator - releaseName: etcd-operator - chart: cozy-etcd-operator - namespace: cozy-etcd-operator - optional: true - dependsOn: [cert-manager] - -- name: grafana-operator - releaseName: grafana-operator - chart: cozy-grafana-operator - namespace: cozy-grafana-operator - optional: true - dependsOn: [] - -- name: mariadb-operator - releaseName: mariadb-operator - chart: cozy-mariadb-operator - namespace: cozy-mariadb-operator - optional: true - dependsOn: [victoria-metrics-operator] - values: - mariadb-operator: - clusterName: {{ $clusterDomain }} - -- name: postgres-operator - releaseName: postgres-operator - chart: cozy-postgres-operator - namespace: cozy-postgres-operator - optional: true - dependsOn: [victoria-metrics-operator] - -- name: kafka-operator - releaseName: kafka-operator - chart: cozy-kafka-operator - namespace: cozy-kafka-operator - optional: true - dependsOn: [victoria-metrics-operator] - values: - strimzi-kafka-operator: - kubernetesServiceDnsDomain: {{ $clusterDomain }} - -- name: clickhouse-operator - releaseName: clickhouse-operator - chart: cozy-clickhouse-operator - namespace: cozy-clickhouse-operator - optional: true - dependsOn: [victoria-metrics-operator] - -- name: foundationdb-operator - releaseName: foundationdb-operator - chart: cozy-foundationdb-operator - namespace: cozy-foundationdb-operator - optional: true - dependsOn: [cert-manager] - -- name: rabbitmq-operator - releaseName: rabbitmq-operator - chart: cozy-rabbitmq-operator - namespace: cozy-rabbitmq-operator - optional: true - dependsOn: [] - -- name: redis-operator - releaseName: redis-operator - chart: cozy-redis-operator - namespace: cozy-redis-operator - optional: true - dependsOn: [] - -- name: telepresence - releaseName: traffic-manager - chart: cozy-telepresence - namespace: cozy-telepresence - optional: true - dependsOn: [] - -- name: external-dns - releaseName: external-dns - chart: cozy-external-dns - namespace: cozy-external-dns - optional: true - dependsOn: [] - -- name: external-secrets-operator - releaseName: external-secrets-operator - chart: cozy-external-secrets-operator - namespace: cozy-external-secrets-operator - optional: true - dependsOn: [] - -- name: keycloak - releaseName: keycloak - chart: cozy-keycloak - namespace: cozy-keycloak - optional: true - dependsOn: [postgres-operator] - -- name: keycloak-operator - releaseName: keycloak-operator - chart: cozy-keycloak-operator - namespace: cozy-keycloak - optional: true - dependsOn: [keycloak] - -- name: velero - releaseName: velero - chart: cozy-velero - namespace: cozy-velero - privileged: true - optional: true - -- name: hetzner-robotlb - releaseName: robotlb - optional: true - chart: cozy-hetzner-robotlb - namespace: cozy-hetzner-robotlb diff --git a/packages/core/platform/bundles/paas-full.yaml b/packages/core/platform/bundles/paas-full.yaml deleted file mode 100644 index 6959fed7..00000000 --- a/packages/core/platform/bundles/paas-full.yaml +++ /dev/null @@ -1,611 +0,0 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} -{{- $oidcEnabled := index $cozyConfig.data "oidc-enabled" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- if not $host }} -{{- fail "ERROR need root-host in cozystack ConfigMap" }} -{{- end }} -{{- $apiServerEndpoint := index $cozyConfig.data "api-server-endpoint" }} -{{- if not $apiServerEndpoint }} -{{- fail "ERROR need api-server-endpoint in cozystack ConfigMap" }} -{{- end }} - -releases: -- name: cilium - releaseName: cilium - chart: cozy-cilium - namespace: cozy-cilium - privileged: true - dependsOn: [] - valuesFiles: - - values.yaml - - values-talos.yaml - - values-kubeovn.yaml - -- name: cilium-networkpolicy - releaseName: cilium-networkpolicy - chart: cozy-cilium-networkpolicy - namespace: cozy-cilium - privileged: true - dependsOn: [cilium] - -- name: kubeovn - releaseName: kubeovn - chart: cozy-kubeovn - namespace: cozy-kubeovn - privileged: true - dependsOn: [cilium] - values: - cozystack: - nodesHash: {{ include "cozystack.master-node-ips" . | sha256sum }} - kube-ovn: - ipv4: - POD_CIDR: "{{ index $cozyConfig.data "ipv4-pod-cidr" }}" - POD_GATEWAY: "{{ index $cozyConfig.data "ipv4-pod-gateway" }}" - SVC_CIDR: "{{ index $cozyConfig.data "ipv4-svc-cidr" }}" - JOIN_CIDR: "{{ index $cozyConfig.data "ipv4-join-cidr" }}" - -- name: kubeovn-webhook - releaseName: kubeovn-webhook - chart: cozy-kubeovn-webhook - namespace: cozy-kubeovn - privileged: true - dependsOn: [cilium,kubeovn,cert-manager] - -- name: kubeovn-plunger - releaseName: kubeovn-plunger - chart: cozy-kubeovn-plunger - namespace: cozy-kubeovn - dependsOn: [cilium,kubeovn] - -- name: multus - releaseName: multus - chart: cozy-multus - namespace: cozy-multus - privileged: true - dependsOn: [cilium,kubeovn] - -- name: cozy-proxy - releaseName: cozystack - chart: cozy-cozy-proxy - namespace: cozy-system - dependsOn: [cilium,kubeovn] - -- name: cert-manager-crds - releaseName: cert-manager-crds - chart: cozy-cert-manager-crds - namespace: cozy-cert-manager - dependsOn: [cilium, kubeovn] - -- name: cozystack-api - releaseName: cozystack-api - chart: cozy-cozystack-api - namespace: cozy-system - dependsOn: [cilium,kubeovn,cozystack-controller] - -- name: cozystack-controller - releaseName: cozystack-controller - chart: cozy-cozystack-controller - namespace: cozy-system - dependsOn: [cilium,kubeovn] - {{- if eq (index $cozyConfig.data "telemetry-enabled") "false" }} - values: - cozystackController: - disableTelemetry: true - {{- end }} - -- name: backup-controller - releaseName: backup-controller - chart: cozy-backup-controller - namespace: cozy-backup-controller - dependsOn: [cilium,kubeovn] - -- name: lineage-controller-webhook - releaseName: lineage-controller-webhook - chart: cozy-lineage-controller-webhook - namespace: cozy-system - dependsOn: [cozystack-controller,cilium,kubeovn,cert-manager] - -- name: cozystack-resource-definition-crd - releaseName: cozystack-resource-definition-crd - chart: cozystack-resource-definition-crd - namespace: cozy-system - dependsOn: [cilium,kubeovn,cozystack-api,cozystack-controller] - -- name: bootbox-rd - releaseName: bootbox-rd - chart: bootbox-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: bucket-rd - releaseName: bucket-rd - chart: bucket-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: clickhouse-rd - releaseName: clickhouse-rd - chart: clickhouse-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: etcd-rd - releaseName: etcd-rd - chart: etcd-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: ferretdb-rd - releaseName: ferretdb-rd - chart: ferretdb-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: foundationdb-rd - releaseName: foundationdb-rd - chart: foundationdb-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: http-cache-rd - releaseName: http-cache-rd - chart: http-cache-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: info-rd - releaseName: info-rd - chart: info-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: ingress-rd - releaseName: ingress-rd - chart: ingress-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: kafka-rd - releaseName: kafka-rd - chart: kafka-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: kubernetes-rd - releaseName: kubernetes-rd - chart: kubernetes-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: monitoring-rd - releaseName: monitoring-rd - chart: monitoring-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: mysql-rd - releaseName: mysql-rd - chart: mysql-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: nats-rd - releaseName: nats-rd - chart: nats-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: postgres-rd - releaseName: postgres-rd - chart: postgres-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: rabbitmq-rd - releaseName: rabbitmq-rd - chart: rabbitmq-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: redis-rd - releaseName: redis-rd - chart: redis-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: seaweedfs-rd - releaseName: seaweedfs-rd - chart: seaweedfs-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: tcp-balancer-rd - releaseName: tcp-balancer-rd - chart: tcp-balancer-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: tenant-rd - releaseName: tenant-rd - chart: tenant-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: virtual-machine-rd - releaseName: virtual-machine-rd - chart: virtual-machine-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: virtualprivatecloud-rd - releaseName: virtualprivatecloud-rd - chart: virtualprivatecloud-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vm-disk-rd - releaseName: vm-disk-rd - chart: vm-disk-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vm-instance-rd - releaseName: vm-instance-rd - chart: vm-instance-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vpn-rd - releaseName: vpn-rd - chart: vpn-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: cert-manager - releaseName: cert-manager - chart: cozy-cert-manager - namespace: cozy-cert-manager - dependsOn: [cert-manager-crds] - -- name: cert-manager-issuers - releaseName: cert-manager-issuers - chart: cozy-cert-manager-issuers - namespace: cozy-cert-manager - dependsOn: [cilium,kubeovn,cert-manager] - -- name: prometheus-operator-crds - releaseName: prometheus-operator-crds - chart: cozy-prometheus-operator-crds - namespace: cozy-victoria-metrics-operator - dependsOn: [] - -- name: metrics-server - releaseName: metrics-server - chart: cozy-metrics-server - namespace: cozy-monitoring - dependsOn: [cilium,kubeovn,prometheus-operator-crds] - -- name: victoria-metrics-operator - releaseName: victoria-metrics-operator - chart: cozy-victoria-metrics-operator - namespace: cozy-victoria-metrics-operator - dependsOn: [cilium,kubeovn,cert-manager,prometheus-operator-crds] - -- name: monitoring-agents - releaseName: monitoring-agents - chart: cozy-monitoring-agents - namespace: cozy-monitoring - privileged: true - dependsOn: [victoria-metrics-operator, vertical-pod-autoscaler-crds, metrics-server] - values: - scrapeRules: - etcd: - enabled: true - -- name: kubevirt-operator - releaseName: kubevirt-operator - chart: cozy-kubevirt-operator - namespace: cozy-kubevirt - dependsOn: [cilium,kubeovn,victoria-metrics-operator] - -- name: kubevirt - releaseName: kubevirt - chart: cozy-kubevirt - namespace: cozy-kubevirt - privileged: true - dependsOn: [cilium,kubeovn,kubevirt-operator] - {{- $cpuAllocationRatio := index $cozyConfig.data "cpu-allocation-ratio" }} - {{- if $cpuAllocationRatio }} - values: - cpuAllocationRatio: {{ $cpuAllocationRatio }} - {{- end }} - -- name: kubevirt-instancetypes - releaseName: kubevirt-instancetypes - chart: cozy-kubevirt-instancetypes - namespace: cozy-kubevirt - dependsOn: [cilium,kubeovn,kubevirt-operator,kubevirt] - -- name: kubevirt-cdi-operator - releaseName: kubevirt-cdi-operator - chart: cozy-kubevirt-cdi-operator - namespace: cozy-kubevirt-cdi - dependsOn: [cilium,kubeovn] - -- name: kubevirt-cdi - releaseName: kubevirt-cdi - chart: cozy-kubevirt-cdi - namespace: cozy-kubevirt-cdi - dependsOn: [cilium,kubeovn,kubevirt-cdi-operator] - -- name: gpu-operator - releaseName: gpu-operator - chart: cozy-gpu-operator - namespace: cozy-gpu-operator - privileged: true - optional: true - dependsOn: [cilium,kubeovn] - valuesFiles: - - values.yaml - - values-talos.yaml - -- name: metallb - releaseName: metallb - chart: cozy-metallb - namespace: cozy-metallb - privileged: true - dependsOn: [cilium,kubeovn] - -- name: etcd-operator - releaseName: etcd-operator - chart: cozy-etcd-operator - namespace: cozy-etcd-operator - dependsOn: [cilium,kubeovn,cert-manager] - -- name: grafana-operator - releaseName: grafana-operator - chart: cozy-grafana-operator - namespace: cozy-grafana-operator - dependsOn: [cilium,kubeovn] - -- name: mariadb-operator - releaseName: mariadb-operator - chart: cozy-mariadb-operator - namespace: cozy-mariadb-operator - dependsOn: [cilium,kubeovn,cert-manager,victoria-metrics-operator] - values: - mariadb-operator: - clusterName: {{ $clusterDomain }} - -- name: postgres-operator - releaseName: postgres-operator - chart: cozy-postgres-operator - namespace: cozy-postgres-operator - dependsOn: [cilium,kubeovn,cert-manager] - -- name: kafka-operator - releaseName: kafka-operator - chart: cozy-kafka-operator - namespace: cozy-kafka-operator - dependsOn: [cilium,kubeovn,victoria-metrics-operator] - values: - strimzi-kafka-operator: - kubernetesServiceDnsDomain: {{ $clusterDomain }} - -- name: clickhouse-operator - releaseName: clickhouse-operator - chart: cozy-clickhouse-operator - namespace: cozy-clickhouse-operator - dependsOn: [cilium,kubeovn,victoria-metrics-operator] - -- name: foundationdb-operator - releaseName: foundationdb-operator - chart: cozy-foundationdb-operator - namespace: cozy-foundationdb-operator - dependsOn: [cilium,kubeovn,cert-manager] - -- name: rabbitmq-operator - releaseName: rabbitmq-operator - chart: cozy-rabbitmq-operator - namespace: cozy-rabbitmq-operator - dependsOn: [cilium,kubeovn] - -- name: redis-operator - releaseName: redis-operator - chart: cozy-redis-operator - namespace: cozy-redis-operator - dependsOn: [cilium,kubeovn] - -- name: piraeus-operator - releaseName: piraeus-operator - chart: cozy-piraeus-operator - namespace: cozy-linstor - dependsOn: [cilium,kubeovn,cert-manager,victoria-metrics-operator] - -- name: linstor - releaseName: linstor - chart: cozy-linstor - namespace: cozy-linstor - privileged: true - dependsOn: [piraeus-operator,cilium,kubeovn,cert-manager,snapshot-controller] - -- name: linstor-scheduler - releaseName: linstor-scheduler - chart: cozy-linstor-scheduler - namespace: cozy-linstor - dependsOn: [linstor,cert-manager] - -- name: nfs-driver - releaseName: nfs-driver - chart: cozy-nfs-driver - namespace: cozy-nfs-driver - privileged: true - dependsOn: [cilium,kubeovn] - optional: true - -- name: snapshot-controller - releaseName: snapshot-controller - chart: cozy-snapshot-controller - namespace: cozy-snapshot-controller - dependsOn: [cilium,kubeovn,cert-manager-issuers] - -- name: objectstorage-controller - releaseName: objectstorage-controller - chart: cozy-objectstorage-controller - namespace: cozy-objectstorage-controller - dependsOn: [cilium,kubeovn] - -- name: telepresence - releaseName: traffic-manager - chart: cozy-telepresence - namespace: cozy-telepresence - optional: true - dependsOn: [cilium,kubeovn] - -- name: dashboard - releaseName: dashboard - chart: cozy-dashboard - namespace: cozy-dashboard - values: - {{- $dashboardKCconfig := lookup "v1" "ConfigMap" "cozy-dashboard" "kubeapps-auth-config" }} - {{- $dashboardKCValues := dig "data" "values.yaml" "" $dashboardKCconfig | fromYaml }} - {{- toYaml (deepCopy $dashboardKCValues | mergeOverwrite (fromYaml (include "cozystack.defaultDashboardValues" .))) | nindent 4 }} - dependsOn: - - cilium - - kubeovn - {{- if eq $oidcEnabled "true" }} - - keycloak-configure - {{- end }} - -- name: kamaji - releaseName: kamaji - chart: cozy-kamaji - namespace: cozy-kamaji - dependsOn: [cilium,kubeovn,cert-manager] - -- name: capi-operator - releaseName: capi-operator - chart: cozy-capi-operator - namespace: cozy-cluster-api - privileged: true - dependsOn: [cilium,kubeovn,cert-manager] - -- name: capi-providers-bootstrap - releaseName: capi-providers-bootstrap - chart: cozy-capi-providers-bootstrap - namespace: cozy-cluster-api - privileged: true - dependsOn: [cilium,kubeovn,capi-operator] - -- name: capi-providers-core - releaseName: capi-providers-core - chart: cozy-capi-providers-core - namespace: cozy-cluster-api - privileged: true - dependsOn: [cilium,kubeovn,capi-operator] - -- name: capi-providers-cpprovider - releaseName: capi-providers-cpprovider - chart: cozy-capi-providers-cpprovider - namespace: cozy-cluster-api - privileged: true - dependsOn: [cilium,kubeovn,capi-operator] - -- name: capi-providers-infraprovider - releaseName: capi-providers-infraprovider - chart: cozy-capi-providers-infraprovider - namespace: cozy-cluster-api - privileged: true - dependsOn: [cilium,kubeovn,capi-operator] - -- name: external-dns - releaseName: external-dns - chart: cozy-external-dns - namespace: cozy-external-dns - optional: true - dependsOn: [cilium,kubeovn] - -- name: external-secrets-operator - releaseName: external-secrets-operator - chart: cozy-external-secrets-operator - namespace: cozy-external-secrets-operator - optional: true - dependsOn: [cilium,kubeovn] - -- name: bootbox - releaseName: bootbox - chart: cozy-bootbox - namespace: cozy-bootbox - privileged: true - optional: true - dependsOn: [cilium,kubeovn] - -{{- if $oidcEnabled }} -- name: keycloak - releaseName: keycloak - chart: cozy-keycloak - namespace: cozy-keycloak - dependsOn: [postgres-operator] - -- name: keycloak-operator - releaseName: keycloak-operator - chart: cozy-keycloak-operator - namespace: cozy-keycloak - dependsOn: [keycloak] - -- name: keycloak-configure - releaseName: keycloak-configure - chart: cozy-keycloak-configure - namespace: cozy-keycloak - dependsOn: [keycloak-operator] - values: - cozystack: - configHash: {{ $cozyConfig | toJson | sha256sum }} -{{- end }} - -- name: goldpinger - releaseName: goldpinger - chart: cozy-goldpinger - namespace: cozy-goldpinger - privileged: true - dependsOn: [monitoring-agents] - -- name: vertical-pod-autoscaler - releaseName: vertical-pod-autoscaler - chart: cozy-vertical-pod-autoscaler - namespace: cozy-vertical-pod-autoscaler - privileged: true - dependsOn: [monitoring-agents] - values: - vertical-pod-autoscaler: - recommender: - extraArgs: - prometheus-address: http://vmselect-shortterm.tenant-root.svc.{{ $clusterDomain }}:8481/select/0/prometheus/ - -- name: vertical-pod-autoscaler-crds - releaseName: vertical-pod-autoscaler-crds - chart: cozy-vertical-pod-autoscaler-crds - namespace: cozy-vertical-pod-autoscaler - privileged: true - dependsOn: [cilium, kubeovn] - -- name: reloader - releaseName: reloader - chart: cozy-reloader - namespace: cozy-reloader - -- name: velero - releaseName: velero - chart: cozy-velero - namespace: cozy-velero - privileged: true - optional: true - dependsOn: [monitoring-agents] - -- name: hetzner-robotlb - releaseName: robotlb - optional: true - chart: cozy-hetzner-robotlb - namespace: cozy-hetzner-robotlb - dependsOn: [cilium, kubeovn] diff --git a/packages/core/platform/bundles/paas-hosted.yaml b/packages/core/platform/bundles/paas-hosted.yaml deleted file mode 100644 index 6db50c7f..00000000 --- a/packages/core/platform/bundles/paas-hosted.yaml +++ /dev/null @@ -1,417 +0,0 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }} -{{- $oidcEnabled := index $cozyConfig.data "oidc-enabled" }} -{{- $host := index $cozyConfig.data "root-host" }} -{{- if not $host }} -{{- fail "ERROR need root-host in cozystack ConfigMap" }} -{{- end }} -{{- $apiServerEndpoint := index $cozyConfig.data "api-server-endpoint" }} -{{- if not $apiServerEndpoint }} -{{- fail "ERROR need api-server-endpoint in cozystack ConfigMap" }} -{{- end }} - -releases: -- name: cert-manager-crds - releaseName: cert-manager-crds - chart: cozy-cert-manager-crds - namespace: cozy-cert-manager - dependsOn: [] - -- name: cozystack-api - releaseName: cozystack-api - chart: cozy-cozystack-api - namespace: cozy-system - dependsOn: [cozystack-controller] - values: - cozystackAPI: - localK8sAPIEndpoint: - enabled: false - -- name: cozystack-controller - releaseName: cozystack-controller - chart: cozy-cozystack-controller - namespace: cozy-system - dependsOn: [] - {{- if eq (index $cozyConfig.data "telemetry-enabled") "false" }} - values: - cozystackController: - disableTelemetry: true - {{- end }} - -- name: backup-controller - releaseName: backup-controller - chart: cozy-backup-controller - namespace: cozy-backup-controller - -- name: lineage-controller-webhook - releaseName: lineage-controller-webhook - chart: cozy-lineage-controller-webhook - namespace: cozy-system - dependsOn: [cozystack-controller,cert-manager] - -- name: cozystack-resource-definition-crd - releaseName: cozystack-resource-definition-crd - chart: cozystack-resource-definition-crd - namespace: cozy-system - dependsOn: [cozystack-api,cozystack-controller] - -- name: bootbox-rd - releaseName: bootbox-rd - chart: bootbox-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: bucket-rd - releaseName: bucket-rd - chart: bucket-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: clickhouse-rd - releaseName: clickhouse-rd - chart: clickhouse-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: etcd-rd - releaseName: etcd-rd - chart: etcd-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: ferretdb-rd - releaseName: ferretdb-rd - chart: ferretdb-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: foundationdb-rd - releaseName: foundationdb-rd - chart: foundationdb-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: http-cache-rd - releaseName: http-cache-rd - chart: http-cache-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: info-rd - releaseName: info-rd - chart: info-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: ingress-rd - releaseName: ingress-rd - chart: ingress-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: kafka-rd - releaseName: kafka-rd - chart: kafka-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: kubernetes-rd - releaseName: kubernetes-rd - chart: kubernetes-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: monitoring-rd - releaseName: monitoring-rd - chart: monitoring-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: mysql-rd - releaseName: mysql-rd - chart: mysql-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: nats-rd - releaseName: nats-rd - chart: nats-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: postgres-rd - releaseName: postgres-rd - chart: postgres-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: rabbitmq-rd - releaseName: rabbitmq-rd - chart: rabbitmq-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: redis-rd - releaseName: redis-rd - chart: redis-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: seaweedfs-rd - releaseName: seaweedfs-rd - chart: seaweedfs-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: tcp-balancer-rd - releaseName: tcp-balancer-rd - chart: tcp-balancer-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: tenant-rd - releaseName: tenant-rd - chart: tenant-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: virtual-machine-rd - releaseName: virtual-machine-rd - chart: virtual-machine-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: virtualprivatecloud-rd - releaseName: virtualprivatecloud-rd - chart: virtualprivatecloud-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vm-disk-rd - releaseName: vm-disk-rd - chart: vm-disk-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vm-instance-rd - releaseName: vm-instance-rd - chart: vm-instance-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: vpn-rd - releaseName: vpn-rd - chart: vpn-rd - namespace: cozy-system - dependsOn: [cozystack-resource-definition-crd] - -- name: cert-manager - releaseName: cert-manager - chart: cozy-cert-manager - namespace: cozy-cert-manager - dependsOn: [cert-manager-crds] - -- name: cert-manager-issuers - releaseName: cert-manager-issuers - chart: cozy-cert-manager-issuers - namespace: cozy-cert-manager - dependsOn: [cert-manager] - -- name: prometheus-operator-crds - releaseName: prometheus-operator-crds - chart: cozy-prometheus-operator-crds - namespace: cozy-victoria-metrics-operator - dependsOn: [] - -- name: metrics-server - releaseName: metrics-server - chart: cozy-metrics-server - namespace: cozy-monitoring - dependsOn: [prometheus-operator-crds] - -- name: victoria-metrics-operator - releaseName: victoria-metrics-operator - chart: cozy-victoria-metrics-operator - namespace: cozy-victoria-metrics-operator - dependsOn: [cert-manager,prometheus-operator-crds] - -- name: monitoring-agents - releaseName: monitoring-agents - chart: cozy-monitoring-agents - namespace: cozy-monitoring - privileged: true - dependsOn: [victoria-metrics-operator, vertical-pod-autoscaler-crds, metrics-server] - values: - scrapeRules: - etcd: - enabled: true - -- name: etcd-operator - releaseName: etcd-operator - chart: cozy-etcd-operator - namespace: cozy-etcd-operator - dependsOn: [cert-manager] - -- name: grafana-operator - releaseName: grafana-operator - chart: cozy-grafana-operator - namespace: cozy-grafana-operator - dependsOn: [] - -- name: mariadb-operator - releaseName: mariadb-operator - chart: cozy-mariadb-operator - namespace: cozy-mariadb-operator - dependsOn: [cert-manager,victoria-metrics-operator] - values: - mariadb-operator: - clusterName: {{ $clusterDomain }} - -- name: postgres-operator - releaseName: postgres-operator - chart: cozy-postgres-operator - namespace: cozy-postgres-operator - dependsOn: [cert-manager,victoria-metrics-operator] - -- name: kafka-operator - releaseName: kafka-operator - chart: cozy-kafka-operator - namespace: cozy-kafka-operator - dependsOn: [victoria-metrics-operator] - values: - strimzi-kafka-operator: - kubernetesServiceDnsDomain: {{ $clusterDomain }} - -- name: clickhouse-operator - releaseName: clickhouse-operator - chart: cozy-clickhouse-operator - namespace: cozy-clickhouse-operator - dependsOn: [victoria-metrics-operator] - -- name: foundationdb-operator - releaseName: foundationdb-operator - chart: cozy-foundationdb-operator - namespace: cozy-foundationdb-operator - dependsOn: [cert-manager] - -- name: rabbitmq-operator - releaseName: rabbitmq-operator - chart: cozy-rabbitmq-operator - namespace: cozy-rabbitmq-operator - dependsOn: [] - -- name: redis-operator - releaseName: redis-operator - chart: cozy-redis-operator - namespace: cozy-redis-operator - dependsOn: [] - -- name: piraeus-operator - releaseName: piraeus-operator - chart: cozy-piraeus-operator - namespace: cozy-linstor - dependsOn: [cert-manager] - -- name: objectstorage-controller - releaseName: objectstorage-controller - chart: cozy-objectstorage-controller - namespace: cozy-objectstorage-controller - dependsOn: [] - -- name: telepresence - releaseName: traffic-manager - chart: cozy-telepresence - namespace: cozy-telepresence - optional: true - dependsOn: [] - -- name: external-dns - releaseName: external-dns - chart: cozy-external-dns - namespace: cozy-external-dns - optional: true - dependsOn: [] - -- name: external-secrets-operator - releaseName: external-secrets-operator - chart: cozy-external-secrets-operator - namespace: cozy-external-secrets-operator - optional: true - dependsOn: [] - -- name: dashboard - releaseName: dashboard - chart: cozy-dashboard - namespace: cozy-dashboard - values: - {{- $dashboardKCconfig := lookup "v1" "ConfigMap" "cozy-dashboard" "kubeapps-auth-config" }} - {{- $dashboardKCValues := dig "data" "values.yaml" (dict) $dashboardKCconfig }} - {{- toYaml (deepCopy $dashboardKCValues | mergeOverwrite (fromYaml (include "cozystack.defaultDashboardValues" .))) | nindent 4 }} - {{- if eq $oidcEnabled "true" }} - dependsOn: [keycloak-configure,cozystack-api] - {{- else }} - dependsOn: [] - {{- end }} - -{{- if $oidcEnabled }} -- name: keycloak - releaseName: keycloak - chart: cozy-keycloak - namespace: cozy-keycloak - dependsOn: [postgres-operator] - -- name: keycloak-operator - releaseName: keycloak-operator - chart: cozy-keycloak-operator - namespace: cozy-keycloak - dependsOn: [keycloak] - -- name: keycloak-configure - releaseName: keycloak-configure - chart: cozy-keycloak-configure - namespace: cozy-keycloak - dependsOn: [keycloak-operator] - values: - cozystack: - configHash: {{ $cozyConfig | toJson | sha256sum }} -{{- end }} - -- name: goldpinger - releaseName: goldpinger - chart: cozy-goldpinger - namespace: cozy-goldpinger - privileged: true - dependsOn: [monitoring-agents] - -- name: vertical-pod-autoscaler - releaseName: vertical-pod-autoscaler - chart: cozy-vertical-pod-autoscaler - namespace: cozy-vertical-pod-autoscaler - privileged: true - dependsOn: [monitoring-agents] - values: - vertical-pod-autoscaler: - recommender: - extraArgs: - prometheus-address: http://vmselect-shortterm.tenant-root.svc.{{ $clusterDomain }}:8481/select/0/prometheus/ - -- name: vertical-pod-autoscaler-crds - releaseName: vertical-pod-autoscaler-crds - chart: cozy-vertical-pod-autoscaler-crds - namespace: cozy-vertical-pod-autoscaler - privileged: true - dependsOn: [] - -- name: velero - releaseName: velero - chart: cozy-velero - namespace: cozy-velero - privileged: true - optional: true - dependsOn: [monitoring-agents] - -- name: hetzner-robotlb - releaseName: robotlb - optional: true - chart: cozy-hetzner-robotlb - namespace: cozy-hetzner-robotlb diff --git a/packages/core/platform/images/cozystack-assets/Dockerfile b/packages/core/platform/images/cozystack-assets/Dockerfile deleted file mode 100644 index bf284de3..00000000 --- a/packages/core/platform/images/cozystack-assets/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM golang:1.25-alpine AS builder - -ARG TARGETOS -ARG TARGETARCH - -RUN apk add --no-cache make git -RUN apk add helm --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community - -COPY . /src/ -WORKDIR /src - -RUN go mod download - -RUN go build -o /cozystack-assets-server -ldflags '-extldflags "-static" -w -s' ./cmd/cozystack-assets-server - -RUN make repos - -FROM alpine:3.22 - -COPY --from=builder /src/_out/repos /cozystack/assets/repos -COPY --from=builder /cozystack-assets-server /usr/bin/cozystack-assets-server -COPY --from=builder /src/dashboards /cozystack/assets/dashboards - -WORKDIR /cozystack -ENTRYPOINT ["/usr/bin/cozystack-assets-server"] diff --git a/packages/core/platform/images/migrations/Dockerfile b/packages/core/platform/images/migrations/Dockerfile new file mode 100644 index 00000000..b35808d5 --- /dev/null +++ b/packages/core/platform/images/migrations/Dockerfile @@ -0,0 +1,12 @@ +FROM alpine:3.22 + +RUN wget -O- https://github.com/cozystack/cozyhr/raw/refs/heads/main/hack/install.sh | sh -s -- -v 1.6.1 + +RUN apk add --no-cache kubectl helm coreutils git jq ca-certificates bash curl + +COPY migrations /migrations +COPY run-migrations.sh /usr/bin/run-migrations.sh + +WORKDIR /migrations + +ENTRYPOINT ["/usr/bin/run-migrations.sh"] diff --git a/scripts/migrations/1 b/packages/core/platform/images/migrations/migrations/1 similarity index 100% rename from scripts/migrations/1 rename to packages/core/platform/images/migrations/migrations/1 diff --git a/scripts/migrations/10 b/packages/core/platform/images/migrations/migrations/10 similarity index 100% rename from scripts/migrations/10 rename to packages/core/platform/images/migrations/migrations/10 diff --git a/scripts/migrations/11 b/packages/core/platform/images/migrations/migrations/11 similarity index 100% rename from scripts/migrations/11 rename to packages/core/platform/images/migrations/migrations/11 diff --git a/scripts/migrations/12 b/packages/core/platform/images/migrations/migrations/12 similarity index 100% rename from scripts/migrations/12 rename to packages/core/platform/images/migrations/migrations/12 diff --git a/scripts/migrations/13 b/packages/core/platform/images/migrations/migrations/13 similarity index 100% rename from scripts/migrations/13 rename to packages/core/platform/images/migrations/migrations/13 diff --git a/scripts/migrations/14 b/packages/core/platform/images/migrations/migrations/14 similarity index 100% rename from scripts/migrations/14 rename to packages/core/platform/images/migrations/migrations/14 diff --git a/scripts/migrations/15 b/packages/core/platform/images/migrations/migrations/15 similarity index 100% rename from scripts/migrations/15 rename to packages/core/platform/images/migrations/migrations/15 diff --git a/scripts/migrations/16 b/packages/core/platform/images/migrations/migrations/16 similarity index 100% rename from scripts/migrations/16 rename to packages/core/platform/images/migrations/migrations/16 diff --git a/scripts/migrations/17 b/packages/core/platform/images/migrations/migrations/17 similarity index 100% rename from scripts/migrations/17 rename to packages/core/platform/images/migrations/migrations/17 diff --git a/scripts/migrations/18 b/packages/core/platform/images/migrations/migrations/18 similarity index 100% rename from scripts/migrations/18 rename to packages/core/platform/images/migrations/migrations/18 diff --git a/scripts/migrations/19 b/packages/core/platform/images/migrations/migrations/19 similarity index 100% rename from scripts/migrations/19 rename to packages/core/platform/images/migrations/migrations/19 diff --git a/scripts/migrations/2 b/packages/core/platform/images/migrations/migrations/2 similarity index 100% rename from scripts/migrations/2 rename to packages/core/platform/images/migrations/migrations/2 diff --git a/scripts/migrations/20 b/packages/core/platform/images/migrations/migrations/20 similarity index 92% rename from scripts/migrations/20 rename to packages/core/platform/images/migrations/migrations/20 index a27464ac..0c885338 100755 --- a/scripts/migrations/20 +++ b/packages/core/platform/images/migrations/migrations/20 @@ -33,11 +33,11 @@ else kubectl rollout status deploy/cozystack-api -n cozy-system --timeout=5m || exit 1 fi -helm upgrade --install -n cozy-system cozystack-controller ./packages/system/cozystack-controller/ --take-ownership +cozyhr -n cozy-system -C ./packages/system/cozystack-controller apply cozystack-controller --take-ownership echo "Waiting for cozystack-controller" kubectl rollout status deploy/cozystack-controller -n cozy-system --timeout=5m || exit 1 -helm upgrade --install -n cozy-system lineage-controller-webhook ./packages/system/lineage-controller-webhook/ --take-ownership +cozyhr -n cozy-system -C ./packages/system/lineage-controller-webhook/ apply lineage-controller-webhook --take-ownership echo "Waiting for lineage-webhook" kubectl rollout status ds/lineage-controller-webhook -n cozy-system --timeout=5m || exit 1 diff --git a/packages/core/platform/images/migrations/migrations/21 b/packages/core/platform/images/migrations/migrations/21 new file mode 100755 index 00000000..bd5fda5f --- /dev/null +++ b/packages/core/platform/images/migrations/migrations/21 @@ -0,0 +1,30 @@ +#!/bin/sh +# Migration 21 --> 22 + +set -euo pipefail + +# Disable pruning on Flux CRDs +for crd in $(kubectl get crd -o name | grep 'fluxcd.io$'); do + kubectl annotate $crd fluxcd.controlplane.io/prune=disabled +done + +# Remove flux instance +if kubectl get fluxinstance flux -n cozy-fluxcd >/dev/null 2>&1; then + kubectl annotate fluxinstance flux -n cozy-fluxcd fluxcd.controlplane.io/reconcile=disabled + kubectl delete fluxinstance flux -n cozy-fluxcd +fi +kubectl delete deploy -n cozy-fluxcd -l app.kubernetes.io/part-of=flux --ignore-not-found +kubectl delete hr -n cozy-fluxcd fluxcd --ignore-not-found --wait=false + +# Remove fluxcd-operator +kubectl delete hr -n cozy-fluxcd fluxcd-operator --ignore-not-found --wait=false +kubectl delete deploy -n cozy-fluxcd flux-operator --ignore-not-found + +# Remove labels from CRDs +for crd in $(kubectl get crd -o name | grep 'fluxcd\.io$'); do + kubectl label $crd fluxcd.controlplane.io/name- fluxcd.controlplane.io/namespace- +done + +# Stamp version +kubectl create configmap -n cozy-system cozystack-version \ + --from-literal=version=22 --dry-run=client -o yaml | kubectl apply -f- diff --git a/scripts/migrations/22 b/packages/core/platform/images/migrations/migrations/22 similarity index 73% rename from scripts/migrations/22 rename to packages/core/platform/images/migrations/migrations/22 index 192e431c..2dc8f281 100755 --- a/scripts/migrations/22 +++ b/packages/core/platform/images/migrations/migrations/22 @@ -3,6 +3,17 @@ set -euo pipefail +# Migrate Victoria Metrics Operator CRDs to prometheus-operator-crds Helm release +for crd in $(kubectl get crd -o name | grep 'coreos\.com$'); do + kubectl annotate $crd meta.helm.sh/release-namespace=cozy-victoria-metrics-operator meta.helm.sh/release-name=prometheus-operator-crds --overwrite + kubectl label $crd app.kubernetes.io/managed-by=Helm helm.toolkit.fluxcd.io/namespace=cozy-victoria-metrics-operator helm.toolkit.fluxcd.io/name=prometheus-operator-crds --overwrite +done +kubectl delete secret -n cozy-victoria-metrics-operator -l name=victoria-metrics-operator,owner=helm --ignore-not-found + +# Remove CozyStack Resource Definitions HR +kubectl delete hr -n cozy-system cozystack-resource-definitions --ignore-not-found --wait=false +kubectl delete cozystackresourcedefinitions.cozystack.io --all --ignore-not-found --wait=false + echo "Migrating HelmReleases: adding application labels for tenant-* namespaces" # Function to determine application type from HelmRelease name @@ -155,6 +166,16 @@ kubectl get helmreleases --all-namespaces -l cozystack.io/ui=true -o json | \ echo "Added application labels to $namespace/$name: $labels" done +echo "Migrating PostgreSQL HelmReleases: adding default version v17" + +# Patch all PostgreSQL HelmReleases to add spec.values.version: v17 +kubectl get helmreleases --all-namespaces -l apps.cozystack.io/application.kind=PostgreSQL -o json | \ + jq -r '.items[] | select(.spec.values.version == null) | "\(.metadata.namespace)|\(.metadata.name)"' | \ + while IFS='|' read -r namespace name; do + echo "Patching PostgreSQL HelmRelease $namespace/$name to add version v17" + kubectl patch helmrelease -n "$namespace" "$name" --type=merge -p '{"spec":{"values":{"version":"v17"}}}' + done + echo "Migration completed" # Stamp version diff --git a/packages/core/platform/images/migrations/migrations/23 b/packages/core/platform/images/migrations/migrations/23 new file mode 100755 index 00000000..4e8c8e18 --- /dev/null +++ b/packages/core/platform/images/migrations/migrations/23 @@ -0,0 +1,11 @@ +#!/bin/sh +# Migration 23 --> 24 + +set -euo pipefail + +# Remove old cozystack-resource-definition-crd HelmRelease (renamed to application-definition-crd) +kubectl delete hr -n cozy-system cozystack-resource-definition-crd --ignore-not-found + +# Stamp version +kubectl create configmap -n cozy-system cozystack-version \ + --from-literal=version=24 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/24 b/packages/core/platform/images/migrations/migrations/24 new file mode 100755 index 00000000..cb34b041 --- /dev/null +++ b/packages/core/platform/images/migrations/migrations/24 @@ -0,0 +1,73 @@ +#!/bin/sh +# Migration 24 --> 25 +# Migrate MongoDB users configuration to new databases format + +set -euo pipefail + +echo "Migrating MongoDB HelmReleases: converting users to databases format" + +# Process all MongoDB HelmReleases +kubectl get helmreleases --all-namespaces -o json | \ + jq -r '.items[] | select(.metadata.name | startswith("mongodb-")) | "\(.metadata.namespace)|\(.metadata.name)"' | \ + while IFS='|' read -r namespace name; do + echo "Processing MongoDB HelmRelease $namespace/$name" + + # Get current spec.values + values=$(kubectl get helmrelease -n "$namespace" "$name" -o jsonpath='{.spec.values}') + + # Check if users exist and have old format (with db and roles fields) + has_old_format=$(echo "$values" | jq -r '.users // {} | to_entries[] | select(.value.db != null or .value.roles != null) | .key' | head -1) + + if [ -z "$has_old_format" ]; then + echo "Skipping $namespace/$name: no users with old format found" + continue + fi + + echo "Converting users configuration for $namespace/$name" + + # Build new configuration using jq + new_values=$(echo "$values" | jq ' + # Extract users and build new format + .users as $old_users | + + # Build databases from user roles + ($old_users // {} | to_entries | reduce .[] as $user ( + {}; + ($user.value.roles // []) as $roles | + reduce $roles[] as $role ( + .; + # Determine role type: readWrite/dbAdmin -> admin, read -> readonly + if ($role.name == "readWrite" or $role.name == "dbAdmin") then + .[$role.db].roles.admin = ((.[$role.db].roles.admin // []) + [$user.key] | unique) + elif ($role.name == "read") then + .[$role.db].roles.readonly = ((.[$role.db].roles.readonly // []) + [$user.key] | unique) + else + . + end + ) + )) as $databases | + + # Build new users (only keep password if present) + ($old_users // {} | to_entries | reduce .[] as $user ( + {}; + if $user.value.password then + .[$user.key] = {password: $user.value.password} + else + .[$user.key] = {} + end + )) as $new_users | + + # Update values + . + {users: $new_users} + (if ($databases | length) > 0 then {databases: $databases} else {} end) + ') + + # Patch the HelmRelease + kubectl patch helmrelease -n "$namespace" "$name" --type=merge -p "{\"spec\":{\"values\":$new_values}}" + echo "Successfully migrated $namespace/$name" + done + +echo "MongoDB migration completed" + +# Stamp version +kubectl create configmap -n cozy-system cozystack-version \ + --from-literal=version=25 --dry-run=client -o yaml | kubectl apply -f- diff --git a/scripts/migrations/3 b/packages/core/platform/images/migrations/migrations/3 similarity index 100% rename from scripts/migrations/3 rename to packages/core/platform/images/migrations/migrations/3 diff --git a/scripts/migrations/4 b/packages/core/platform/images/migrations/migrations/4 similarity index 100% rename from scripts/migrations/4 rename to packages/core/platform/images/migrations/migrations/4 diff --git a/scripts/migrations/5 b/packages/core/platform/images/migrations/migrations/5 similarity index 100% rename from scripts/migrations/5 rename to packages/core/platform/images/migrations/migrations/5 diff --git a/scripts/migrations/6 b/packages/core/platform/images/migrations/migrations/6 similarity index 100% rename from scripts/migrations/6 rename to packages/core/platform/images/migrations/migrations/6 diff --git a/scripts/migrations/7 b/packages/core/platform/images/migrations/migrations/7 similarity index 100% rename from scripts/migrations/7 rename to packages/core/platform/images/migrations/migrations/7 diff --git a/scripts/migrations/8 b/packages/core/platform/images/migrations/migrations/8 similarity index 100% rename from scripts/migrations/8 rename to packages/core/platform/images/migrations/migrations/8 diff --git a/scripts/migrations/9 b/packages/core/platform/images/migrations/migrations/9 similarity index 100% rename from scripts/migrations/9 rename to packages/core/platform/images/migrations/migrations/9 diff --git a/packages/core/platform/images/migrations/run-migrations.sh b/packages/core/platform/images/migrations/run-migrations.sh new file mode 100755 index 00000000..c35ade21 --- /dev/null +++ b/packages/core/platform/images/migrations/run-migrations.sh @@ -0,0 +1,41 @@ +#!/bin/sh +set -euo pipefail + +NAMESPACE="${NAMESPACE:-cozy-system}" +CURRENT_VERSION="${CURRENT_VERSION:-0}" +TARGET_VERSION="${TARGET_VERSION:-0}" + +echo "Starting migrations from version $CURRENT_VERSION to $TARGET_VERSION" + +# Check if ConfigMap exists +if ! kubectl get configmap --namespace "$NAMESPACE" cozystack-version >/dev/null 2>&1; then + echo "ConfigMap cozystack-version does not exist, creating it with version $TARGET_VERSION" + kubectl create configmap --namespace "$NAMESPACE" cozystack-version \ + --from-literal=version="$TARGET_VERSION" \ + --dry-run=client --output yaml | kubectl apply --filename - + echo "ConfigMap created with version $TARGET_VERSION" + exit 0 +fi + +# If current version is already at target, nothing to do +if [ "$CURRENT_VERSION" -ge "$TARGET_VERSION" ]; then + echo "Current version $CURRENT_VERSION is already at or above target version $TARGET_VERSION" + exit 0 +fi + +# Run migrations sequentially from current version to target version +for i in $(seq $((CURRENT_VERSION + 1)) $TARGET_VERSION); do + if [ -f "/migrations/$i" ]; then + echo "Running migration $i" + chmod +x /migrations/$i + /migrations/$i || { + echo "Migration $i failed" + exit 1 + } + echo "Migration $i completed successfully" + else + echo "Migration $i not found, skipping" + fi +done + +echo "All migrations completed successfully" diff --git a/packages/core/platform/sources/backupstrategy-controller.yaml b/packages/core/platform/sources/backupstrategy-controller.yaml new file mode 100644 index 00000000..3647e8dc --- /dev/null +++ b/packages/core/platform/sources/backupstrategy-controller.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.backupstrategy-controller +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.networking + components: + - name: backupstrategy-controller + path: system/backupstrategy-controller + install: + privileged: true + namespace: cozy-backupstrategy-controller + releaseName: backupstrategy-controller diff --git a/packages/core/platform/sources/capi-providers-bootstrap.yaml b/packages/core/platform/sources/capi-provider-bootstrap-kubeadm.yaml similarity index 58% rename from packages/core/platform/sources/capi-providers-bootstrap.yaml rename to packages/core/platform/sources/capi-provider-bootstrap-kubeadm.yaml index 0469b1bc..90cea107 100644 --- a/packages/core/platform/sources/capi-providers-bootstrap.yaml +++ b/packages/core/platform/sources/capi-provider-bootstrap-kubeadm.yaml @@ -2,7 +2,7 @@ apiVersion: cozystack.io/v1alpha1 kind: PackageSource metadata: - name: cozystack.capi-providers-bootstrap + name: cozystack.capi-provider-bootstrap-kubeadm spec: sourceRef: kind: OCIRepository @@ -10,6 +10,17 @@ spec: namespace: cozy-system path: / variants: + - name: default + dependsOn: + - cozystack.networking + - cozystack.capi-operator + components: + - name: capi-providers-bootstrap + path: system/capi-providers-bootstrap + install: + privileged: true + namespace: cozy-cluster-api + releaseName: capi-providers-bootstrap - name: kubevirt dependsOn: - cozystack.networking diff --git a/packages/core/platform/sources/capi-providers-core.yaml b/packages/core/platform/sources/capi-provider-core.yaml similarity index 92% rename from packages/core/platform/sources/capi-providers-core.yaml rename to packages/core/platform/sources/capi-provider-core.yaml index e5b6cc99..91af6617 100644 --- a/packages/core/platform/sources/capi-providers-core.yaml +++ b/packages/core/platform/sources/capi-provider-core.yaml @@ -2,7 +2,7 @@ apiVersion: cozystack.io/v1alpha1 kind: PackageSource metadata: - name: cozystack.capi-providers-core + name: cozystack.capi-provider-core spec: sourceRef: kind: OCIRepository diff --git a/packages/core/platform/sources/capi-providers-cpprovider.yaml b/packages/core/platform/sources/capi-provider-cp-kamaji.yaml similarity index 58% rename from packages/core/platform/sources/capi-providers-cpprovider.yaml rename to packages/core/platform/sources/capi-provider-cp-kamaji.yaml index 7b63260d..08c29b8f 100644 --- a/packages/core/platform/sources/capi-providers-cpprovider.yaml +++ b/packages/core/platform/sources/capi-provider-cp-kamaji.yaml @@ -2,7 +2,7 @@ apiVersion: cozystack.io/v1alpha1 kind: PackageSource metadata: - name: cozystack.capi-providers-cpprovider + name: cozystack.capi-provider-cp-kamaji spec: sourceRef: kind: OCIRepository @@ -10,6 +10,18 @@ spec: namespace: cozy-system path: / variants: + - name: default + dependsOn: + - cozystack.networking + - cozystack.capi-operator + - cozystack.kamaji + components: + - name: capi-providers-cpprovider + path: system/capi-providers-cpprovider + install: + privileged: true + namespace: cozy-cluster-api + releaseName: capi-providers-cpprovider - name: kamaji dependsOn: - cozystack.networking diff --git a/packages/core/platform/sources/capi-providers-infraprovider.yaml b/packages/core/platform/sources/capi-provider-infra-kubevirt.yaml similarity index 57% rename from packages/core/platform/sources/capi-providers-infraprovider.yaml rename to packages/core/platform/sources/capi-provider-infra-kubevirt.yaml index 88bebc09..341e1920 100644 --- a/packages/core/platform/sources/capi-providers-infraprovider.yaml +++ b/packages/core/platform/sources/capi-provider-infra-kubevirt.yaml @@ -2,7 +2,7 @@ apiVersion: cozystack.io/v1alpha1 kind: PackageSource metadata: - name: cozystack.capi-providers-infraprovider + name: cozystack.capi-provider-infra-kubevirt spec: sourceRef: kind: OCIRepository @@ -10,6 +10,18 @@ spec: namespace: cozy-system path: / variants: + - name: default + dependsOn: + - cozystack.networking + - cozystack.capi-operator + - cozystack.kubevirt + components: + - name: capi-providers-infraprovider + path: system/capi-providers-infraprovider + install: + privileged: true + namespace: cozy-cluster-api + releaseName: capi-providers-infraprovider - name: kubevirt dependsOn: - cozystack.networking diff --git a/packages/core/platform/sources/cozy-proxy.yaml b/packages/core/platform/sources/cozy-proxy.yaml index fac0f5fc..041b968f 100644 --- a/packages/core/platform/sources/cozy-proxy.yaml +++ b/packages/core/platform/sources/cozy-proxy.yaml @@ -18,4 +18,4 @@ spec: path: system/cozy-proxy install: namespace: cozy-system - releaseName: cozystack + releaseName: cozy-proxy diff --git a/packages/core/platform/sources/cozystack-engine.yaml b/packages/core/platform/sources/cozystack-engine.yaml index ce06b9d8..596c81c4 100644 --- a/packages/core/platform/sources/cozystack-engine.yaml +++ b/packages/core/platform/sources/cozystack-engine.yaml @@ -17,18 +17,18 @@ spec: - name: cozy-lib path: library/cozy-lib components: - - name: cozystack-resource-definition-crd - path: system/cozystack-resource-definition-crd + - name: application-definition-crd + path: system/application-definition-crd install: namespace: cozy-system - releaseName: cozystack-resource-definition-crd + releaseName: application-definition-crd - name: cozystack-controller path: system/cozystack-controller install: namespace: cozy-system releaseName: cozystack-controller dependsOn: - - cozystack-resource-definition-crd + - application-definition-crd - name: cozystack-api path: system/cozystack-api install: @@ -36,7 +36,7 @@ spec: releaseName: cozystack-api dependsOn: - cozystack-controller - - cozystack-resource-definition-crd + - application-definition-crd - name: lineage-controller-webhook path: system/lineage-controller-webhook install: @@ -44,7 +44,7 @@ spec: releaseName: lineage-controller-webhook dependsOn: - cozystack-controller - - cozystack-resource-definition-crd + - application-definition-crd - name: dashboard path: system/dashboard install: @@ -53,27 +53,28 @@ spec: dependsOn: - cozystack-api - cozystack-controller - - cozystack-resource-definition-crd + - application-definition-crd - name: oidc dependsOn: - cozystack.networking - cozystack.keycloak + - cozystack.keycloak-operator libraries: - name: cozy-lib path: library/cozy-lib components: - - name: cozystack-resource-definition-crd - path: system/cozystack-resource-definition-crd + - name: application-definition-crd + path: system/application-definition-crd install: namespace: cozy-system - releaseName: cozystack-resource-definition-crd + releaseName: application-definition-crd - name: cozystack-controller path: system/cozystack-controller install: namespace: cozy-system releaseName: cozystack-controller dependsOn: - - cozystack-resource-definition-crd + - application-definition-crd - name: cozystack-api path: system/cozystack-api install: @@ -81,7 +82,7 @@ spec: releaseName: cozystack-api dependsOn: - cozystack-controller - - cozystack-resource-definition-crd + - application-definition-crd - name: lineage-controller-webhook path: system/lineage-controller-webhook install: @@ -89,7 +90,7 @@ spec: releaseName: lineage-controller-webhook dependsOn: - cozystack-controller - - cozystack-resource-definition-crd + - application-definition-crd - name: dashboard path: system/dashboard install: @@ -99,7 +100,7 @@ spec: - cozystack-api - cozystack-controller - keycloak-configure - - cozystack-resource-definition-crd + - application-definition-crd - name: keycloak-configure path: system/keycloak-configure install: diff --git a/packages/core/platform/sources/flux-plunger.yaml b/packages/core/platform/sources/flux-plunger.yaml new file mode 100644 index 00000000..bbee0b34 --- /dev/null +++ b/packages/core/platform/sources/flux-plunger.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.flux-plunger +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.cert-manager + - cozystack.cozystack-engine + components: + - name: flux-plunger + path: system/flux-plunger + install: + namespace: cozy-fluxcd + releaseName: flux-plunger diff --git a/packages/core/platform/sources/ingress-nginx.yaml b/packages/core/platform/sources/ingress-nginx.yaml new file mode 100644 index 00000000..b51e096f --- /dev/null +++ b/packages/core/platform/sources/ingress-nginx.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.ingress-nginx +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.networking + - cozystack.prometheus-operator-crds + components: + - name: ingress-nginx + path: system/ingress-nginx + install: + namespace: cozy-ingress-nginx + releaseName: ingress-nginx diff --git a/packages/core/platform/sources/keycloak.yaml b/packages/core/platform/sources/keycloak.yaml index a9dc64b4..545d70a5 100644 --- a/packages/core/platform/sources/keycloak.yaml +++ b/packages/core/platform/sources/keycloak.yaml @@ -14,9 +14,13 @@ spec: dependsOn: - cozystack.networking - cozystack.postgres-operator + libraries: + - name: cozy-lib + path: library/cozy-lib components: - name: keycloak path: system/keycloak + libraries: ["cozy-lib"] install: namespace: cozy-keycloak releaseName: keycloak diff --git a/packages/core/platform/sources/kilo.yaml b/packages/core/platform/sources/kilo.yaml new file mode 100644 index 00000000..72602164 --- /dev/null +++ b/packages/core/platform/sources/kilo.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.kilo +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.networking + components: + - name: kilo + path: system/kilo + install: + privileged: true + namespace: cozy-kilo + releaseName: kilo diff --git a/packages/core/platform/sources/kubernetes-application.yaml b/packages/core/platform/sources/kubernetes-application.yaml index 0acde1c4..9787cb19 100644 --- a/packages/core/platform/sources/kubernetes-application.yaml +++ b/packages/core/platform/sources/kubernetes-application.yaml @@ -14,10 +14,10 @@ spec: dependsOn: - cozystack.networking - cozystack.capi-operator - - cozystack.capi-providers-bootstrap - - cozystack.capi-providers-core - - cozystack.capi-providers-cpprovider - - cozystack.capi-providers-infraprovider + - cozystack.capi-provider-bootstrap-kubeadm + - cozystack.capi-provider-core + - cozystack.capi-provider-cp-kamaji + - cozystack.capi-provider-infra-kubevirt libraries: - name: cozy-lib path: library/cozy-lib diff --git a/packages/core/platform/sources/local-ccm.yaml b/packages/core/platform/sources/local-ccm.yaml new file mode 100644 index 00000000..5317abf8 --- /dev/null +++ b/packages/core/platform/sources/local-ccm.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.local-ccm +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.networking + components: + - name: local-ccm + path: system/local-ccm + install: + privileged: true + namespace: cozy-local-ccm + releaseName: local-ccm diff --git a/packages/core/platform/sources/metrics-server.yaml b/packages/core/platform/sources/metrics-server.yaml new file mode 100644 index 00000000..607cd7f0 --- /dev/null +++ b/packages/core/platform/sources/metrics-server.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.metrics-server +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.networking + - cozystack.prometheus-operator-crds + components: + - name: metrics-server + path: system/metrics-server + install: + namespace: cozy-monitoring + releaseName: metrics-server diff --git a/packages/core/platform/sources/mongodb-application.yaml b/packages/core/platform/sources/mongodb-application.yaml new file mode 100644 index 00000000..b6106fe1 --- /dev/null +++ b/packages/core/platform/sources/mongodb-application.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.mongodb-application +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.networking + libraries: + - name: cozy-lib + path: library/cozy-lib + components: + - name: mongodb + path: apps/mongodb + libraries: ["cozy-lib"] + - name: mongodb-rd + path: system/mongodb-rd + install: + namespace: cozy-system + releaseName: mongodb-rd diff --git a/packages/core/platform/sources/mongodb-operator.yaml b/packages/core/platform/sources/mongodb-operator.yaml new file mode 100644 index 00000000..e3d6fe9e --- /dev/null +++ b/packages/core/platform/sources/mongodb-operator.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.mongodb-operator +spec: + sourceRef: + kind: OCIRepository + name: cozystack-packages + namespace: cozy-system + path: / + variants: + - name: default + dependsOn: + - cozystack.networking + - cozystack.prometheus-operator-crds + - cozystack.cert-manager + components: + - name: mongodb-operator + path: system/mongodb-operator + install: + namespace: cozy-mongodb-operator + releaseName: mongodb-operator diff --git a/packages/core/platform/sources/monitoring-agents.yaml b/packages/core/platform/sources/monitoring-agents.yaml index 9585c5aa..206699b6 100644 --- a/packages/core/platform/sources/monitoring-agents.yaml +++ b/packages/core/platform/sources/monitoring-agents.yaml @@ -13,6 +13,7 @@ spec: - name: default dependsOn: - cozystack.networking + - cozystack.metrics-server - cozystack.victoria-metrics-operator - cozystack.vertical-pod-autoscaler components: diff --git a/packages/core/platform/sources/monitoring-application.yaml b/packages/core/platform/sources/monitoring-application.yaml index 0f01eddd..6ea5a2d0 100644 --- a/packages/core/platform/sources/monitoring-application.yaml +++ b/packages/core/platform/sources/monitoring-application.yaml @@ -13,6 +13,7 @@ spec: - name: default dependsOn: - cozystack.networking + - cozystack.postgres-operator libraries: - name: cozy-lib path: library/cozy-lib diff --git a/packages/core/platform/sources/networking.yaml b/packages/core/platform/sources/networking.yaml index 57fff6fc..9694dcc3 100644 --- a/packages/core/platform/sources/networking.yaml +++ b/packages/core/platform/sources/networking.yaml @@ -33,6 +33,27 @@ spec: releaseName: cilium-networkpolicy dependsOn: - cilium + # Generic Cilium variant for non-Talos clusters (kubeadm, k3s, RKE2, etc.) + - name: cilium-generic + dependsOn: [] + components: + - name: cilium + path: system/cilium + valuesFiles: + - values.yaml + install: + privileged: true + namespace: cozy-cilium + releaseName: cilium + dependsOn: [] + - name: cilium-networkpolicy + path: system/cilium-networkpolicy + install: + privileged: true + namespace: cozy-cilium + releaseName: cilium-networkpolicy + dependsOn: + - cilium - name: kubeovn-cilium dependsOn: [] components: @@ -63,3 +84,33 @@ spec: releaseName: kubeovn dependsOn: - cilium + # Generic KubeOVN+Cilium variant for non-Talos clusters (kubeadm, k3s, RKE2, etc.) + - name: kubeovn-cilium-generic + dependsOn: [] + components: + - name: cilium + path: system/cilium + valuesFiles: + - values.yaml + - values-kubeovn.yaml + install: + privileged: true + namespace: cozy-cilium + releaseName: cilium + dependsOn: [] + - name: cilium-networkpolicy + path: system/cilium-networkpolicy + install: + privileged: true + namespace: cozy-cilium + releaseName: cilium-networkpolicy + dependsOn: + - cilium + - name: kubeovn + path: system/kubeovn + install: + privileged: true + namespace: cozy-kubeovn + releaseName: kubeovn + dependsOn: + - cilium diff --git a/packages/core/platform/sources/postgres-application.yaml b/packages/core/platform/sources/postgres-application.yaml index b5953069..5d7b220b 100644 --- a/packages/core/platform/sources/postgres-application.yaml +++ b/packages/core/platform/sources/postgres-application.yaml @@ -13,6 +13,7 @@ spec: - name: default dependsOn: - cozystack.networking + - cozystack.postgres-operator libraries: - name: cozy-lib path: library/cozy-lib diff --git a/packages/core/platform/templates/_helpers.tpl b/packages/core/platform/templates/_helpers.tpl index c656c7f8..684ee812 100644 --- a/packages/core/platform/templates/_helpers.tpl +++ b/packages/core/platform/templates/_helpers.tpl @@ -1,108 +1,68 @@ -{{/* -Get IP-addresses of master nodes -*/}} -{{- define "cozystack.master-node-ips" -}} -{{- $nodes := lookup "v1" "Node" "" "" -}} -{{- $ips := list -}} -{{- range $node := $nodes.items -}} - {{- if eq (index $node.metadata.labels "node-role.kubernetes.io/control-plane") "" -}} - {{- range $address := $node.status.addresses -}} - {{- if eq $address.type "InternalIP" -}} - {{- $ips = append $ips $address.address -}} - {{- break -}} - {{- end -}} - {{- end -}} - {{- end -}} -{{- end -}} -{{ join "," $ips }} +{{- define "cozystack.platform.package" -}} +{{- $name := index . 0 -}} +{{- $variant := default "default" (index . 1) -}} +{{- $root := default $ (index . 2) -}} +{{- $components := dict -}} +{{- if gt (len .) 3 -}} +{{- $components = index . 3 -}} {{- end -}} +{{- $disabled := default (list) $root.Values.bundles.disabledPackages -}} +{{- if not (has $name $disabled) -}} +--- +apiVersion: cozystack.io/v1alpha1 +kind: Package +metadata: + name: {{ $name }} +spec: + variant: {{ $variant }} +{{- if $components }} + components: +{{ toYaml $components | indent 4 }} +{{- end }} +{{- end }} +{{ end }} + +{{- define "cozystack.platform.package.default" -}} +{{- $name := index . 0 -}} +{{- $root := index . 1 -}} +{{- include "cozystack.platform.package" (list $name "default" $root) }} +{{ end }} + +{{- define "cozystack.platform.package.optional" -}} +{{- $name := index . 0 -}} +{{- $variant := default "default" (index . 1) -}} +{{- $root := default $ (index . 2) -}} +{{- $disabled := default (list) $root.Values.bundles.disabledPackages -}} +{{- $enabled := default (list) $root.Values.bundles.enabledPackages -}} +{{- if and (has $name $enabled) (not (has $name $disabled)) -}} +--- +apiVersion: cozystack.io/v1alpha1 +kind: Package +metadata: + name: {{ $name }} +spec: + variant: {{ $variant }} +{{- end }} +{{ end }} + +{{- define "cozystack.platform.package.optional.default" -}} +{{- $name := index . 0 -}} +{{- $root := index . 1 -}} +{{- include "cozystack.platform.package.optional" (list $name "default" $root) }} +{{ end }} {{/* -Get Kubernetes API Endpoint from cozystack deployment -Returns host:port format +Common system packages shared between isp-full and isp-full-generic bundles. +Does NOT include: networking (variant differs), linstor (talos.enabled differs) */}} -{{- define "cozystack.kubernetesAPIEndpoint" -}} -{{- $cozyDeployment := lookup "apps/v1" "Deployment" "cozy-system" "cozystack" }} -{{- $cozyContainers := dig "spec" "template" "spec" "containers" list $cozyDeployment }} -{{- $kubernetesServiceHost := "" }} -{{- $kubernetesServicePort := "" }} -{{- range $cozyContainers }} -{{- if eq .name "cozystack" }} -{{- range .env }} -{{- if eq .name "KUBERNETES_SERVICE_HOST" }} -{{- $kubernetesServiceHost = .value }} -{{- end }} -{{- if eq .name "KUBERNETES_SERVICE_PORT" }} -{{- $kubernetesServicePort = .value }} -{{- end }} -{{- end }} -{{- end }} -{{- end }} -{{- if eq $kubernetesServiceHost "" }} -{{- $kubernetesServiceHost = "kubernetes.default.svc" }} -{{- end }} -{{- if eq $kubernetesServicePort "" }} -{{- $kubernetesServicePort = "443" }} -{{- end }} -{{- printf "%s:%s" $kubernetesServiceHost $kubernetesServicePort }} -{{- end -}} - -{{- define "cozystack.defaultDashboardValues" -}} -kubeapps: -{{- if .Capabilities.APIVersions.Has "source.toolkit.fluxcd.io/v1" }} -{{- with (lookup "source.toolkit.fluxcd.io/v1" "HelmRepository" "cozy-public" "").items }} - redis: - master: - podAnnotations: - {{- range $index, $repo := . }} - {{- with (($repo.status).artifact).revision }} - repository.cozystack.io/{{ $repo.metadata.name }}: {{ quote . }} - {{- end }} - {{- end }} -{{- end }} -{{- end }} - frontend: - resourcesPreset: "none" - dashboard: - resourcesPreset: "none" - {{- $cozystackBranding:= lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} - {{- $branding := dig "data" "branding" "" $cozystackBranding }} - {{- if $branding }} - customLocale: - "Kubeapps": {{ $branding }} - {{- end }} - customStyle: | - {{- $logoImage := dig "data" "logo" "" $cozystackBranding }} - {{- if $logoImage }} - .kubeapps-logo { - background-image: {{ $logoImage }} - } - {{- end }} - #serviceaccount-selector { - display: none; - } - .login-moreinfo { - display: none; - } - a[href="#/docs"] { - display: none; - } - .login-group .clr-form-control .clr-control-label { - display: none; - } - .appview-separator div.appview-first-row div.center { - display: none; - } - .appview-separator div.appview-first-row section[aria-labelledby="app-secrets"] { - display: none; - } - .appview-first-row section[aria-labelledby="access-urls-title"] { - width: 100%; - } - .header-version { - display: none; - } - .label.label-info-secondary { - display: none; - } +{{- define "cozystack.platform.system.common-packages" -}} +{{- $root := . -}} +{{include "cozystack.platform.package.default" (list "cozystack.kubeovn-webhook" $root) }} +{{include "cozystack.platform.package.default" (list "cozystack.kubeovn-plunger" $root) }} +{{include "cozystack.platform.package.default" (list "cozystack.cozy-proxy" $root) }} +{{include "cozystack.platform.package.default" (list "cozystack.multus" $root) }} +{{include "cozystack.platform.package.default" (list "cozystack.metallb" $root) }} +{{include "cozystack.platform.package.default" (list "cozystack.reloader" $root) }} +{{include "cozystack.platform.package.default" (list "cozystack.linstor-scheduler" $root) }} +{{include "cozystack.platform.package.default" (list "cozystack.snapshot-controller" $root) }} {{- end }} diff --git a/packages/core/platform/templates/apps.yaml b/packages/core/platform/templates/apps.yaml index b42aad87..ee3b35cf 100644 --- a/packages/core/platform/templates/apps.yaml +++ b/packages/core/platform/templates/apps.yaml @@ -1,118 +1,42 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $cozystackBranding := lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} -{{- $cozystackScheduling := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} {{- $kubeRootCa := lookup "v1" "ConfigMap" "kube-system" "kube-root-ca.crt" }} -{{- $bundleName := index $cozyConfig.data "bundle-name" }} +{{- $cozystackCm := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} +{{- $bundleName := .Values.bundles.system.variant }} {{- $bundle := tpl (.Files.Get (printf "bundles/%s.yaml" $bundleName)) . | fromYaml }} -{{/* Default values for _cluster config to ensure all required keys exist */}} -{{- $clusterDefaults := dict - "root-host" "" - "bundle-name" "" - "clusterissuer" "http01" - "oidc-enabled" "false" - "expose-services" "" - "expose-ingress" "tenant-root" - "expose-external-ips" "" - "cluster-domain" "cozy.local" - "api-server-endpoint" "" -}} -{{- $clusterConfig := mergeOverwrite $clusterDefaults ($cozyConfig.data | default dict) }} -{{- $host := "example.org" }} -{{- $host := "example.org" }} -{{- if $cozyConfig.data }} - {{- if hasKey $cozyConfig.data "root-host" }} - {{- $host = index $cozyConfig.data "root-host" }} - {{- end }} -{{- end }} -{{- $tenantRoot := dict }} -{{- if .Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} -{{- $tenantRoot = lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" "tenant-root" "tenant-root" }} -{{- end }} -{{- if and $tenantRoot $tenantRoot.spec $tenantRoot.spec.values $tenantRoot.spec.values.host }} -{{- $host = $tenantRoot.spec.values.host }} -{{- else }} -{{- end }} ---- -apiVersion: v1 -kind: Namespace -metadata: - annotations: - helm.sh/resource-policy: keep - labels: - tenant.cozystack.io/tenant-root: "" - namespace.cozystack.io/etcd: tenant-root - namespace.cozystack.io/monitoring: tenant-root - namespace.cozystack.io/ingress: tenant-root - namespace.cozystack.io/seaweedfs: tenant-root - namespace.cozystack.io/host: "{{ $host }}" - name: tenant-root +{{- /* Read root-host from ConfigMap if available, else use chart values */ -}} +{{- $rootHost := .Values.publishing.host -}} +{{- if and $cozystackCm $cozystackCm.data -}} +{{- $rootHost = default $rootHost (index $cozystackCm.data "root-host") -}} +{{- end -}} --- apiVersion: v1 kind: Secret metadata: name: cozystack-values - namespace: tenant-root + namespace: cozy-system labels: reconcile.fluxcd.io/watch: Enabled type: Opaque stringData: values.yaml: | _cluster: - {{- $clusterConfig | toYaml | nindent 6 }} - {{- with $cozystackBranding.data }} + root-host: {{ $rootHost | quote }} + bundle-name: {{ .Values.bundles.system.variant | quote }} + clusterissuer: {{ .Values.publishing.certificates.issuerType | quote }} + oidc-enabled: {{ .Values.authentication.oidc.enabled | quote }} + extra-keycloak-redirect-uri-for-dashboard: {{ index .Values.authentication.oidc.keycloakExtraRedirectUri | quote }} + expose-services: {{ .Values.publishing.exposedServices | join "," | quote }} + expose-ingress: {{ .Values.publishing.ingressName | quote }} + expose-external-ips: {{ .Values.publishing.externalIPs | join "," | quote }} + cluster-domain: {{ .Values.networking.clusterDomain | quote }} + api-server-endpoint: {{ .Values.publishing.apiServerEndpoint | quote }} + {{- with .Values.branding }} branding: {{- . | toYaml | nindent 8 }} {{- end }} - {{- with $cozystackScheduling.data }} + {{- with .Values.scheduling }} scheduling: {{- . | toYaml | nindent 8 }} {{- end }} {{- with $kubeRootCa.data }} kube-root-ca: {{ index . "ca.crt" | b64enc | quote }} {{- end }} - _namespace: - etcd: tenant-root - monitoring: tenant-root - ingress: tenant-root - seaweedfs: tenant-root - host: {{ $host | quote }} ---- -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: tenant-root - namespace: tenant-root - labels: - cozystack.io/ui: "true" - apps.cozystack.io/application.kind: Tenant - apps.cozystack.io/application.group: apps.cozystack.io - apps.cozystack.io/application.name: tenant-root -spec: - interval: 0s - releaseName: tenant-root - install: - remediation: - retries: -1 - upgrade: - remediation: - retries: -1 - chart: - spec: - chart: tenant - version: '>= 0.0.0-0' - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public - valuesFrom: - - kind: Secret - name: cozystack-values - values: - host: "{{ $host }}" - dependsOn: - {{- range $x := $bundle.releases }} - {{- if has $x.name (list "cilium" "kubeovn") }} - - name: {{ $x.name }} - namespace: {{ $x.namespace }} - {{- end }} - {{- end }} diff --git a/packages/core/platform/templates/bundles/iaas.yaml b/packages/core/platform/templates/bundles/iaas.yaml new file mode 100644 index 00000000..7c856b8c --- /dev/null +++ b/packages/core/platform/templates/bundles/iaas.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.bundles.iaas.enabled (not (or (eq .Values.bundles.system.variant "isp-full") (eq .Values.bundles.system.variant "isp-full-generic"))) }} +{{- fail "bundles.iaas.enabled can only be true when bundles.system.variant is 'isp-full' or 'isp-full-generic'" }} +{{- end }} +{{- if and .Values.bundles.iaas.enabled (or (eq .Values.bundles.system.variant "isp-full") (eq .Values.bundles.system.variant "isp-full-generic")) }} +{{include "cozystack.platform.package.default" (list "cozystack.kubevirt" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.kubevirt-cdi" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.gpu-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.kamaji" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.capi-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.capi-provider-bootstrap-kubeadm" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.capi-provider-core" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.capi-provider-cp-kamaji" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.capi-provider-infra-kubevirt" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.bucket-application" $) }} +{{include "cozystack.platform.package" (list "cozystack.kubernetes-application" "kubevirt" $) }} +{{include "cozystack.platform.package" (list "cozystack.virtual-machine-application" "kubevirt" $) }} +{{include "cozystack.platform.package" (list "cozystack.virtualprivatecloud-application" "kubevirt" $) }} +{{include "cozystack.platform.package" (list "cozystack.vm-disk-application" "kubevirt" $) }} +{{include "cozystack.platform.package" (list "cozystack.vm-instance-application" "kubevirt" $) }} +{{- end }} diff --git a/packages/core/platform/templates/bundles/naas.yaml b/packages/core/platform/templates/bundles/naas.yaml new file mode 100644 index 00000000..9682d447 --- /dev/null +++ b/packages/core/platform/templates/bundles/naas.yaml @@ -0,0 +1,8 @@ +{{- if and .Values.bundles.naas.enabled (not (or (eq .Values.bundles.system.variant "isp-full") (eq .Values.bundles.system.variant "isp-full-generic") (eq .Values.bundles.system.variant "isp-hosted"))) }} +{{- fail "bundles.naas.enabled can only be true when bundles.system.variant is 'isp-full', 'isp-full-generic', or 'isp-hosted'" }} +{{- end }} +{{- if and .Values.bundles.naas.enabled (or (eq .Values.bundles.system.variant "isp-full") (eq .Values.bundles.system.variant "isp-full-generic") (eq .Values.bundles.system.variant "isp-hosted")) }} +{{include "cozystack.platform.package.default" (list "cozystack.http-cache-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.tcp-balancer-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.vpn-application" $) }} +{{- end }} diff --git a/packages/core/platform/templates/bundles/paas.yaml b/packages/core/platform/templates/bundles/paas.yaml new file mode 100644 index 00000000..359f0959 --- /dev/null +++ b/packages/core/platform/templates/bundles/paas.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.bundles.paas.enabled (not (or (eq .Values.bundles.system.variant "isp-full") (eq .Values.bundles.system.variant "isp-full-generic") (eq .Values.bundles.system.variant "isp-hosted"))) }} +{{- fail "bundles.paas.enabled can only be true when bundles.system.variant is 'isp-full', 'isp-full-generic', or 'isp-hosted'" }} +{{- end }} +{{- if and .Values.bundles.paas.enabled (or (eq .Values.bundles.system.variant "isp-full") (eq .Values.bundles.system.variant "isp-full-generic") (eq .Values.bundles.system.variant "isp-hosted")) }} +{{include "cozystack.platform.package.default" (list "cozystack.mariadb-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.kafka-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.clickhouse-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.foundationdb-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.rabbitmq-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.redis-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.mongodb-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.clickhouse-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.ferretdb-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.foundationdb-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.kafka-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.mysql-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.mongodb-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.nats-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.postgres-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.rabbitmq-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.redis-application" $) }} +{{- end }} diff --git a/packages/core/platform/templates/bundles/system.yaml b/packages/core/platform/templates/bundles/system.yaml new file mode 100644 index 00000000..1ee7002e --- /dev/null +++ b/packages/core/platform/templates/bundles/system.yaml @@ -0,0 +1,155 @@ +{{- if .Values.bundles.system.enabled }} + +# Networking +{{- if eq .Values.bundles.system.variant "isp-full" }} +{{- $networkingComponents := dict -}} +{{- if .Values.networking -}} +{{- $kubeovnIpv4 := dict + "POD_CIDR" .Values.networking.podCIDR + "POD_GATEWAY" .Values.networking.podGateway + "SVC_CIDR" .Values.networking.serviceCIDR + "JOIN_CIDR" .Values.networking.joinCIDR -}} +{{- $kubeovnDict := dict "ipv4" $kubeovnIpv4 -}} +{{- if .Values.networking.kubeovn.MASTER_NODES -}} +{{- $_ := set $kubeovnDict "MASTER_NODES" .Values.networking.kubeovn.MASTER_NODES -}} +{{- end -}} +{{- $kubeovnValues := dict "kube-ovn" $kubeovnDict -}} +{{- $_ := set $networkingComponents "kubeovn" (dict "values" $kubeovnValues) -}} +{{- /* For Talos (isp-full): use KubePrism endpoint and disable cgroup autoMount */ -}} +{{- $ciliumValues := dict "cilium" (dict + "k8sServiceHost" "localhost" + "k8sServicePort" "7445" + "cgroup" (dict "autoMount" (dict "enabled" false))) -}} +{{- $_ := set $networkingComponents "cilium" (dict "values" $ciliumValues) -}} +{{- end -}} +{{include "cozystack.platform.package" (list "cozystack.networking" "kubeovn-cilium" $ $networkingComponents) }} +{{include "cozystack.platform.system.common-packages" $ }} +{{include "cozystack.platform.package.default" (list "cozystack.linstor" $) }} +{{- end }} + +{{- if eq .Values.bundles.system.variant "isp-hosted" }} +{{include "cozystack.platform.package" (list "cozystack.networking" "noop" $) }} +{{- end }} + +{{- if eq .Values.bundles.system.variant "isp-full-generic" }} +{{- $networkingComponents := dict -}} +{{- if .Values.networking -}} +{{- /* Parse apiServerEndpoint URL for generic k8s (used by both Cilium and KubeOVN) */ -}} +{{- /* First try cozystack ConfigMap, then fall back to chart values */ -}} +{{- $cozystackCm := lookup "v1" "ConfigMap" "cozy-system" "cozystack" -}} +{{- $apiServerEndpoint := .Values.publishing.apiServerEndpoint -}} +{{- if and $cozystackCm $cozystackCm.data -}} +{{- $apiServerEndpoint = default $apiServerEndpoint (index $cozystackCm.data "api-server-endpoint") -}} +{{- end -}} +{{- $apiHost := "" -}} +{{- $apiPort := "6443" -}} +{{- if $apiServerEndpoint -}} +{{- $parsed := urlParse $apiServerEndpoint -}} +{{- $hostPort := splitList ":" $parsed.host -}} +{{- $apiHost = index $hostPort 0 -}} +{{- if gt (len $hostPort) 1 -}} +{{- $apiPort = index $hostPort 1 -}} +{{- else -}} +{{- $apiPort = "6443" -}} +{{- end -}} +{{- end -}} +{{- /* KubeOVN IPv4 configuration - read from ConfigMap or fall back to chart values */ -}} +{{- $podCIDR := .Values.networking.podCIDR -}} +{{- $podGateway := .Values.networking.podGateway -}} +{{- $svcCIDR := .Values.networking.serviceCIDR -}} +{{- $joinCIDR := .Values.networking.joinCIDR -}} +{{- if and $cozystackCm $cozystackCm.data -}} +{{- $podCIDR = default $podCIDR (index $cozystackCm.data "ipv4-pod-cidr") -}} +{{- $podGateway = default $podGateway (index $cozystackCm.data "ipv4-pod-gateway") -}} +{{- $svcCIDR = default $svcCIDR (index $cozystackCm.data "ipv4-svc-cidr") -}} +{{- $joinCIDR = default $joinCIDR (index $cozystackCm.data "ipv4-join-cidr") -}} +{{- end -}} +{{- $kubeovnIpv4 := dict + "POD_CIDR" $podCIDR + "POD_GATEWAY" $podGateway + "SVC_CIDR" $svcCIDR + "JOIN_CIDR" $joinCIDR -}} +{{- $kubeovnDict := dict "ipv4" $kubeovnIpv4 -}} +{{- /* Set MASTER_NODES: explicit value > parsed from apiServerEndpoint > empty (use helm lookup) */ -}} +{{- $masterNodes := .Values.networking.kubeovn.MASTER_NODES -}} +{{- if and (not $masterNodes) $apiServerEndpoint -}} +{{- $masterNodes = $apiHost -}} +{{- end -}} +{{- if $masterNodes -}} +{{- $_ := set $kubeovnDict "MASTER_NODES" $masterNodes -}} +{{- end -}} +{{- /* For generic k8s (k3s, kubeadm), control-plane label has value "true" */ -}} +{{- $_ := set $kubeovnDict "MASTER_NODES_LABEL" "node-role.kubernetes.io/control-plane=true" -}} +{{- $kubeovnValues := dict "kube-ovn" $kubeovnDict -}} +{{- $_ := set $networkingComponents "kubeovn" (dict "values" $kubeovnValues) -}} +{{- /* Cilium configuration - for generic k8s, always enable cgroup autoMount */ -}} +{{- $ciliumValues := dict "cilium" (dict + "k8sServiceHost" $apiHost + "k8sServicePort" $apiPort + "cgroup" (dict "autoMount" (dict "enabled" true))) -}} +{{- $_ := set $networkingComponents "cilium" (dict "values" $ciliumValues) -}} +{{- end -}} +{{- /* Use kubeovn-cilium-generic variant (no values-talos.yaml) */ -}} +{{include "cozystack.platform.package" (list "cozystack.networking" "kubeovn-cilium-generic" $ $networkingComponents) }} +{{include "cozystack.platform.system.common-packages" $ }} +{{- /* Pass talos.enabled: false to linstor for generic Linux */ -}} +{{- $linstorComponents := dict "linstor" (dict "values" (dict "talos" (dict "enabled" false))) -}} +{{include "cozystack.platform.package" (list "cozystack.linstor" "default" $ $linstorComponents) }} +{{- end }} + +# Cozystack Engine +{{- $cozystackEngineComponents := dict -}} +{{- /* For generic k8s, DaemonSets with control-plane nodeSelector need value "true" */ -}} +{{- if eq .Values.bundles.system.variant "isp-full-generic" -}} +{{- $genericNodeSelector := dict "node-role.kubernetes.io/control-plane" "true" -}} +{{- /* cozystack-api DaemonSet */ -}} +{{- $apiValues := dict "cozystackAPI" (dict "nodeSelector" $genericNodeSelector) -}} +{{- $_ := set $cozystackEngineComponents "cozystack-api" (dict "values" $apiValues) -}} +{{- /* lineage-controller-webhook DaemonSet */ -}} +{{- $lineageValues := dict "lineageControllerWebhook" (dict "nodeSelector" $genericNodeSelector) -}} +{{- $_ := set $cozystackEngineComponents "lineage-controller-webhook" (dict "values" $lineageValues) -}} +{{- end -}} +{{- if .Values.authentication.oidc.enabled }} +{{include "cozystack.platform.package" (list "cozystack.cozystack-engine" "oidc" $ $cozystackEngineComponents) }} +{{include "cozystack.platform.package.default" (list "cozystack.keycloak" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.keycloak-operator" $) }} +{{- else }} +{{include "cozystack.platform.package" (list "cozystack.cozystack-engine" "default" $ $cozystackEngineComponents) }} +{{- end }} + +# Common Packages +{{include "cozystack.platform.package.default" (list "cozystack.cert-manager" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.flux-plunger" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.victoria-metrics-operator" $) }} +{{- $tenantComponents := dict -}} +{{- $tenantClusterValues := dict "_cluster" (dict "oidc-enabled" (ternary "true" "false" .Values.authentication.oidc.enabled)) -}} +{{- $_ := set $tenantComponents "tenant" (dict "values" $tenantClusterValues) }} +{{include "cozystack.platform.package" (list "cozystack.tenant-application" "default" $ $tenantComponents) }} +{{include "cozystack.platform.package.default" (list "cozystack.ingress-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.seaweedfs-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.info-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.monitoring-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.etcd-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.cozystack-basics" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.backupstrategy-controller" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.backup-controller" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.velero" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.vertical-pod-autoscaler" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.metrics-server" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.monitoring-agents" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.goldpinger" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.prometheus-operator-crds" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.grafana-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.etcd-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.postgres-operator" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.objectstorage-controller" $) }} + +# Optional System Packages (controlled via bundles.enabledPackages) +{{include "cozystack.platform.package.optional.default" (list "cozystack.nfs-driver" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.telepresence" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.external-dns" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.external-secrets-operator" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.bootbox" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.hetzner-robotlb" $) }} + +{{- end }} diff --git a/packages/core/platform/templates/containerd-registry-secret.yaml b/packages/core/platform/templates/containerd-registry-secret.yaml new file mode 100644 index 00000000..6e9fb640 --- /dev/null +++ b/packages/core/platform/templates/containerd-registry-secret.yaml @@ -0,0 +1,35 @@ +{{- if .Values.registries.mirrors }} +apiVersion: v1 +kind: Secret +metadata: + name: patch-containerd + namespace: cozy-system +type: Opaque +stringData: +{{- range $registry, $mirror := .Values.registries.mirrors }} +{{- if $mirror.endpoints }} + {{ $registry }}.toml: | + server = "https://{{ $registry }}" +{{- range $endpoint := $mirror.endpoints }} + [host."{{ $endpoint }}"] + capabilities = ["pull", "resolve"] +{{- $endpointConfig := index $.Values.registries.config $endpoint }} +{{- if $endpointConfig }} +{{- if $endpointConfig.tls }} +{{- if $endpointConfig.tls.insecureSkipVerify }} + skip_verify = true +{{- end }} +{{- end }} +{{- if $endpointConfig.auth }} + [host."{{ $endpoint }}".auth] + username = "{{ $endpointConfig.auth.username }}" + password = "{{ $endpointConfig.auth.password }}" +{{- end }} +{{- else }} + skip_verify = true +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} + diff --git a/packages/core/platform/templates/cozystack-assets.yaml b/packages/core/platform/templates/cozystack-assets.yaml deleted file mode 100644 index 61ab8dca..00000000 --- a/packages/core/platform/templates/cozystack-assets.yaml +++ /dev/null @@ -1,73 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: cozystack-assets - namespace: cozy-system - labels: - app: cozystack-assets -spec: - serviceName: cozystack-assets - replicas: 1 - selector: - matchLabels: - app: cozystack-assets - template: - metadata: - labels: - app: cozystack-assets - spec: - hostNetwork: true - containers: - - name: assets-server - image: "{{ .Values.assets.image }}" - args: - - "-dir=/cozystack/assets" - - "-address=:8123" - ports: - - name: http - containerPort: 8123 - hostPort: 8123 - tolerations: - - operator: Exists ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: cozystack-assets-reader - namespace: cozy-system -rules: - - apiGroups: [""] - resources: - - pods/proxy - resourceNames: - - cozystack-assets-0 - verbs: - - get ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: cozystack-assets-reader - namespace: cozy-system -subjects: - - kind: User - name: cozystack-assets-reader - apiGroup: rbac.authorization.k8s.io -roleRef: - kind: Role - name: cozystack-assets-reader - apiGroup: rbac.authorization.k8s.io ---- -apiVersion: v1 -kind: Service -metadata: - name: cozystack-assets - namespace: cozy-system -spec: - ports: - - name: http - port: 80 - targetPort: 8123 - selector: - app: cozystack-assets - type: ClusterIP diff --git a/packages/core/platform/templates/cozystack-version.yaml b/packages/core/platform/templates/cozystack-version.yaml new file mode 100644 index 00000000..8e3ff6c6 --- /dev/null +++ b/packages/core/platform/templates/cozystack-version.yaml @@ -0,0 +1,11 @@ +{{- $configMap := lookup "v1" "ConfigMap" .Release.Namespace "cozystack-version" }} +{{- if not $configMap }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cozystack-version + namespace: {{ .Release.Namespace }} +data: + version: {{ .Values.migrations.targetVersion | quote }} +{{- end }} diff --git a/packages/core/platform/templates/helmreleases.yaml b/packages/core/platform/templates/helmreleases.yaml deleted file mode 100644 index e3118b70..00000000 --- a/packages/core/platform/templates/helmreleases.yaml +++ /dev/null @@ -1,100 +0,0 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $bundleName := index $cozyConfig.data "bundle-name" }} -{{- $bundle := tpl (.Files.Get (printf "bundles/%s.yaml" $bundleName)) . | fromYaml }} -{{- $dependencyNamespaces := dict }} -{{- $disabledComponents := splitList "," ((index $cozyConfig.data "bundle-disable") | default "") }} -{{- $enabledComponents := splitList "," ((index $cozyConfig.data "bundle-enable") | default "") }} -{{- $oidcEnabled := (index (default dict $cozyConfig.data) "oidc-enabled") | default "false" | eq "true" }} - -{{/* collect dependency namespaces from releases */}} -{{- range $x := $bundle.releases }} -{{- $_ := set $dependencyNamespaces $x.name $x.namespace }} -{{- end }} - -{{- range $x := $bundle.releases }} - -{{- $shouldInstall := true }} -{{- $shouldDelete := false }} -{{- $notEnabledOptionalComponent := and ($x.optional) (not (has $x.name $enabledComponents)) }} -{{- $disabledComponent := has $x.name $disabledComponents }} -{{- $isKeycloakComponent := or (eq $x.name "keycloak") (eq $x.name "keycloak-operator") (eq $x.name "keycloak-configure") }} - -{{- if and $isKeycloakComponent (not $oidcEnabled) }} -{{- $shouldInstall = false }} -{{- if $.Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} -{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" $x.namespace $x.name }} -{{- $shouldDelete = true }} -{{- end }} -{{- end }} -{{- else if or $disabledComponent $notEnabledOptionalComponent }} -{{- $shouldInstall = false }} -{{- if $.Capabilities.APIVersions.Has "helm.toolkit.fluxcd.io/v2" }} -{{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" $x.namespace $x.name }} -{{- $shouldDelete = true }} -{{- end }} -{{- end }} -{{- end }} - -{{- if or $shouldInstall $shouldDelete }} ---- -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: {{ $x.name }} - namespace: {{ $x.namespace }} - labels: - cozystack.io/repository: system - cozystack.io/system-app: "true" - {{- if $shouldDelete }} - cozystack.io/marked-for-deletion: "true" - {{- end }} -spec: - interval: 5m - releaseName: {{ $x.releaseName | default $x.name }} - install: - crds: CreateReplace - remediation: - retries: -1 - upgrade: - crds: CreateReplace - remediation: - retries: -1 - chart: - spec: - chart: {{ $x.chart }} - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' - {{- with $x.valuesFiles }} - valuesFiles: - {{- toYaml $x.valuesFiles | nindent 6 }} - {{- end }} - {{- $values := dict }} - {{- with $x.values }} - {{- $values = merge . $values }} - {{- end }} - {{- with index $cozyConfig.data (printf "values-%s" $x.name) }} - {{- $values = mergeOverwrite $values (fromYaml .) }} - {{- end }} - {{- with $values }} - values: - {{- toYaml . | nindent 4}} - {{- end }} - valuesFrom: - - kind: Secret - name: cozystack-values - - {{- with $x.dependsOn }} - dependsOn: - {{- range $dep := . }} - {{- if not (has $dep $disabledComponents) }} - - name: {{ $dep }} - namespace: {{ index $dependencyNamespaces $dep }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} -{{- end }} diff --git a/packages/core/platform/templates/helmrepos.yaml b/packages/core/platform/templates/helmrepos.yaml deleted file mode 100644 index 47954869..00000000 --- a/packages/core/platform/templates/helmrepos.yaml +++ /dev/null @@ -1,40 +0,0 @@ ---- -apiVersion: source.toolkit.fluxcd.io/v1 -kind: HelmRepository -metadata: - name: cozystack-system - namespace: cozy-system - labels: - cozystack.io/repository: system -spec: - interval: 5m0s - url: https://{{ include "cozystack.kubernetesAPIEndpoint" . }}/api/v1/namespaces/cozy-system/pods/cozystack-assets-0/proxy/repos/system - certSecretRef: - name: cozystack-assets-tls ---- -apiVersion: source.toolkit.fluxcd.io/v1 -kind: HelmRepository -metadata: - name: cozystack-apps - namespace: cozy-public - labels: - cozystack.io/ui: "true" - cozystack.io/repository: apps -spec: - interval: 5m0s - url: https://{{ include "cozystack.kubernetesAPIEndpoint" . }}/api/v1/namespaces/cozy-system/pods/cozystack-assets-0/proxy/repos/apps - certSecretRef: - name: cozystack-assets-tls ---- -apiVersion: source.toolkit.fluxcd.io/v1 -kind: HelmRepository -metadata: - name: cozystack-extra - namespace: cozy-public - labels: - cozystack.io/repository: extra -spec: - interval: 5m0s - url: https://{{ include "cozystack.kubernetesAPIEndpoint" . }}/api/v1/namespaces/cozy-system/pods/cozystack-assets-0/proxy/repos/extra - certSecretRef: - name: cozystack-assets-tls diff --git a/packages/core/platform/templates/migration-hook.yaml b/packages/core/platform/templates/migration-hook.yaml new file mode 100644 index 00000000..67b09820 --- /dev/null +++ b/packages/core/platform/templates/migration-hook.yaml @@ -0,0 +1,69 @@ +{{- if .Values.migrations.enabled }} +{{- $shouldRunMigrationHook := false }} +{{- $currentVersion := 0 }} +{{- $targetVersion := .Values.migrations.targetVersion | int }} +{{- $configMap := lookup "v1" "ConfigMap" .Release.Namespace "cozystack-version" }} +{{- if $configMap }} + {{- $currentVersion = dig "data" "version" "0" $configMap | int }} + {{- if lt $currentVersion $targetVersion }} + {{- $shouldRunMigrationHook = true }} + {{- end }} +{{- end }} + +{{- if $shouldRunMigrationHook }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: cozystack-migration-hook + annotations: + helm.sh/hook: pre-upgrade,pre-install + helm.sh/hook-weight: "1" + helm.sh/hook-delete-policy: before-hook-creation +spec: + backoffLimit: 3 + template: + metadata: + labels: + policy.cozystack.io/allow-to-apiserver: "true" + spec: + serviceAccountName: cozystack-migration-hook + containers: + - name: migration + image: {{ .Values.migrations.image }} + env: + - name: NAMESPACE + value: {{ .Release.Namespace | quote }} + - name: CURRENT_VERSION + value: {{ $currentVersion | quote }} + - name: TARGET_VERSION + value: {{ $targetVersion | quote }} + restartPolicy: Never +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + annotations: + helm.sh/hook: pre-upgrade,pre-install + helm.sh/hook-weight: "1" + helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation + name: cozystack-migration-hook +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: cozystack-migration-hook + namespace: {{ .Release.Namespace | quote }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cozystack-migration-hook + annotations: + helm.sh/hook: pre-upgrade,pre-install + helm.sh/hook-weight: "1" + helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation +{{- end }} +{{- end }} diff --git a/packages/core/platform/templates/namespaces.yaml b/packages/core/platform/templates/namespaces.yaml deleted file mode 100644 index 2afe3445..00000000 --- a/packages/core/platform/templates/namespaces.yaml +++ /dev/null @@ -1,76 +0,0 @@ -{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} -{{- $cozystackBranding := lookup "v1" "ConfigMap" "cozy-system" "cozystack-branding" }} -{{- $cozystackScheduling := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }} -{{- $bundleName := index $cozyConfig.data "bundle-name" }} -{{/* Default values for _cluster config to ensure all required keys exist */}} -{{- $clusterDefaults := dict - "root-host" "" - "bundle-name" "" - "clusterissuer" "http01" - "oidc-enabled" "false" - "expose-services" "" - "expose-ingress" "tenant-root" - "expose-external-ips" "" - "cluster-domain" "cozy.local" - "api-server-endpoint" "" -}} -{{- $clusterConfig := mergeOverwrite $clusterDefaults ($cozyConfig.data | default dict) }} -{{- $bundle := tpl (.Files.Get (printf "bundles/%s.yaml" $bundleName)) . | fromYaml }} -{{- $disabledComponents := splitList "," ((index $cozyConfig.data "bundle-disable") | default "") }} -{{- $enabledComponents := splitList "," ((index $cozyConfig.data "bundle-enable") | default "") }} -{{- $namespaces := dict }} - -{{/* collect namespaces from releases */}} -{{- range $x := $bundle.releases }} - {{- if not (hasKey $namespaces $x.namespace) }} - {{- if not (has $x.name $disabledComponents) }} - {{- if or (not $x.optional) (and ($x.optional) (has $x.name $enabledComponents)) }} - {{- $_ := set $namespaces $x.namespace false }} - {{- end }} - {{- end }} - {{- end }} - {{/* if at least one release requires a privileged namespace, then it should be privileged */}} - {{- if or $x.privileged (index $namespaces $x.namespace) }} - {{- $_ := set $namespaces $x.namespace true }} - {{- end }} -{{- end }} - -{{/* Add extra namespaces */}} -{{- $_ := set $namespaces "cozy-system" true }} -{{- $_ := set $namespaces "cozy-public" false }} - -{{- range $namespace, $privileged := $namespaces }} ---- -apiVersion: v1 -kind: Namespace -metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - cozystack.io/system: "true" - {{- if $privileged }} - pod-security.kubernetes.io/enforce: privileged - {{- end }} - name: {{ $namespace }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: cozystack-values - namespace: {{ $namespace }} - labels: - reconcile.fluxcd.io/watch: Enabled -type: Opaque -stringData: - values.yaml: | - _cluster: - {{- $clusterConfig | toYaml | nindent 6 }} - {{- with $cozystackBranding.data }} - branding: - {{- . | toYaml | nindent 8 }} - {{- end }} - {{- with $cozystackScheduling.data }} - scheduling: - {{- . | toYaml | nindent 8 }} - {{- end }} -{{- end }} diff --git a/packages/core/platform/templates/repository.yaml b/packages/core/platform/templates/repository.yaml new file mode 100644 index 00000000..9bd9f5a1 --- /dev/null +++ b/packages/core/platform/templates/repository.yaml @@ -0,0 +1,17 @@ +{{- $sourceRef := .Values.sourceRef }} +{{- $apiVersion := "source.toolkit.fluxcd.io/v1" }} +{{- $kind := $sourceRef.kind }} +{{- $name := $sourceRef.name }} +{{- $namespace := $sourceRef.namespace }} +{{- $sourceRepo := lookup $apiVersion $kind $namespace $name }} +{{- if not $sourceRepo }} +{{- fail (printf "Source repository %s/%s of kind %s not found in namespace %s" $namespace $name $kind $namespace) }} +{{- end }} +--- +apiVersion: {{ $apiVersion }} +kind: {{ $kind }} +metadata: + name: cozystack-packages + namespace: cozy-system +spec: +{{- $sourceRepo.spec | toYaml | nindent 2 }} diff --git a/packages/core/platform/templates/scheduling.yaml b/packages/core/platform/templates/scheduling.yaml new file mode 100644 index 00000000..4486155a --- /dev/null +++ b/packages/core/platform/templates/scheduling.yaml @@ -0,0 +1,11 @@ +{{- if .Values.scheduling.globalAppTopologySpreadConstraints }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cozystack-scheduling + namespace: cozy-system +data: + globalAppTopologySpreadConstraints: | + {{- toYaml .Values.scheduling.globalAppTopologySpreadConstraints | nindent 4 }} +{{- end }} diff --git a/packages/core/platform/templates/sources.yaml b/packages/core/platform/templates/sources.yaml index 8b010f10..9d4eca37 100644 --- a/packages/core/platform/templates/sources.yaml +++ b/packages/core/platform/templates/sources.yaml @@ -1,6 +1,4 @@ -{{/* {{- range $path, $_ := .Files.Glob "sources/*.yaml" }} --- {{ $.Files.Get $path }} {{- end }} -*/}} diff --git a/packages/core/platform/values-isp-full-generic.yaml b/packages/core/platform/values-isp-full-generic.yaml new file mode 100644 index 00000000..4fd5ff59 --- /dev/null +++ b/packages/core/platform/values-isp-full-generic.yaml @@ -0,0 +1,15 @@ +migrations: + enabled: true +bundles: + system: + enabled: true + variant: "isp-full-generic" + iaas: + enabled: true + paas: + enabled: true + naas: + enabled: true + enabledPackages: + - cozystack.velero + - cozystack.backupstrategy-controller diff --git a/packages/core/platform/values-isp-full.yaml b/packages/core/platform/values-isp-full.yaml new file mode 100644 index 00000000..c79ff4ba --- /dev/null +++ b/packages/core/platform/values-isp-full.yaml @@ -0,0 +1,12 @@ +migrations: + enabled: true +bundles: + system: + enabled: true + variant: "isp-full" + iaas: + enabled: true + paas: + enabled: true + naas: + enabled: true diff --git a/packages/core/platform/values-isp-hosted.yaml b/packages/core/platform/values-isp-hosted.yaml new file mode 100644 index 00000000..c3af0deb --- /dev/null +++ b/packages/core/platform/values-isp-hosted.yaml @@ -0,0 +1,12 @@ +migrations: + enabled: true +bundles: + system: + enabled: false + variant: "isp-hosted" + iaas: + enabled: false + paas: + enabled: true + naas: + enabled: true diff --git a/packages/core/platform/values.yaml b/packages/core/platform/values.yaml index 363d1921..f7fec687 100644 --- a/packages/core/platform/values.yaml +++ b/packages/core/platform/values.yaml @@ -1,2 +1,95 @@ -assets: - image: ghcr.io/cozystack/cozystack/cozystack-assets:latest@sha256:19b166819d0205293c85d8351a3e038dc4c146b876a8e2ae21dce1d54f0b9e33 +sourceRef: + kind: OCIRepository + name: cozystack-platform + namespace: cozy-system + path: / +migrations: + enabled: false + image: ghcr.io/cozystack/cozystack/platform-migrations:latest + targetVersion: 24 +# Bundle deployment configuration +bundles: + system: + enabled: false + variant: "isp-full" # Options: "isp-full", "isp-full-generic", "isp-hosted", "distro-full" + iaas: + enabled: false + paas: + enabled: false + naas: + enabled: false + disabledPackages: [] + enabledPackages: [] +# Network configuration +networking: + clusterDomain: "cozy.local" + podCIDR: "10.244.0.0/16" + podGateway: "10.244.0.1" + serviceCIDR: "10.96.0.0/16" + joinCIDR: "100.64.0.0/16" + # KubeOVN master nodes override (optional) + # By default, KubeOVN helm chart uses `lookup` to find control-plane nodes + # by label `node-role.kubernetes.io/control-plane`. On fresh clusters or + # during initial deployment, lookup may return empty results. + # Set this to comma-separated list of master node IPs to override. + kubeovn: + MASTER_NODES: "" +# Service publishing and ingress configuration +publishing: + host: "example.org" + ingressName: tenant-root + exposedServices: + - api + - dashboard + - vm-exportproxy + - cdi-uploadproxy + apiServerEndpoint: "" # example: "https://api.example.org" + externalIPs: [] + certificates: + issuerType: http01 # "http01" or "cloudflare" +# Authentication configuration +authentication: + oidc: + enabled: false + keycloakExtraRedirectUri: "" +# Pod scheduling configuration +scheduling: + globalAppTopologySpreadConstraints: "" +# UI branding configuration +branding: {} +# Container registry mirrors configuration +# +# Example: +# registries: +# mirrors: +# docker.io: +# endpoints: +# - http://10.0.0.1:8082 +# ghcr.io: +# endpoints: +# - http://10.0.0.1:8083 +# gcr.io: +# endpoints: +# - http://10.0.0.1:8084 +# registry.k8s.io: +# endpoints: +# - http://10.0.0.1:8085 +# quay.io: +# endpoints: +# - http://10.0.0.1:8086 +# cr.fluentbit.io: +# endpoints: +# - http://10.0.0.1:8087 +# docker-registry3.mariadb.com: +# endpoints: +# - http://10.0.0.1:8088 +# config: +# "10.0.0.1:8082": +# tls: +# insecureSkipVerify: true +registries: {} +# Resource allocation ratios +resources: + cpuAllocationRatio: 10 + memoryAllocationRatio: 1 + ephemeralStorageAllocationRatio: 40 diff --git a/packages/core/talos/Makefile b/packages/core/talos/Makefile index 24d9c9f2..e06793b9 100644 --- a/packages/core/talos/Makefile +++ b/packages/core/talos/Makefile @@ -3,7 +3,7 @@ NAMESPACE=cozy-system TALOS_VERSION=$(shell awk '/^version:/ {print $$2}' images/talos/profiles/installer.yaml) -include ../../../scripts/common-envs.mk +include ../../../hack/common-envs.mk update: hack/gen-profiles.sh @@ -30,9 +30,27 @@ image-matchbox: assets: talos-iso talos-nocloud talos-metal talos-kernel talos-initramfs -talos-initramfs talos-kernel talos-installer talos-iso talos-nocloud talos-metal: +talos-initramfs: + test -f ../../../_out/assets/initramfs-metal-amd64.xz || $(MAKE) build-talos-initramfs + +talos-kernel: + test -f ../../../_out/assets/kernel-amd64 || $(MAKE) build-talos-kernel + +talos-installer: + test -f ../../../_out/assets/installer-amd64.tar || $(MAKE) build-talos-installer + +talos-iso: + test -f ../../../_out/assets/metal-amd64.iso || $(MAKE) build-talos-iso + +talos-nocloud: + test -f ../../../_out/assets/nocloud-amd64.raw.xz || $(MAKE) build-talos-nocloud + +talos-metal: + test -f ../../../_out/assets/metal-amd64.raw.xz || $(MAKE) build-talos-metal + +build-talos-initramfs build-talos-kernel build-talos-installer build-talos-iso build-talos-nocloud build-talos-metal: mkdir -p ../../../_out/assets - cat images/talos/profiles/$(subst talos-,,$@).yaml | \ + cat images/talos/profiles/$(subst build-talos-,,$@).yaml | \ docker run --rm -i -v /dev:/dev --privileged "ghcr.io/siderolabs/imager:$(TALOS_VERSION)" --tar-to-stdout - | \ tar -C ../../../_out/assets -xzf- diff --git a/packages/core/talos/images/talos/profiles/initramfs.yaml b/packages/core/talos/images/talos/profiles/initramfs.yaml index 9663d86f..20bc27d3 100644 --- a/packages/core/talos/images/talos/profiles/initramfs.yaml +++ b/packages/core/talos/images/talos/profiles/initramfs.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.11.3 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.11.3" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250917@sha256:ff11ee9f1565d9f9b095a3dc41fb7962b211169b2ef05d658a488398cb98e2d2 - - imageRef: ghcr.io/siderolabs/amdgpu:20250917-v1.11.3@sha256:527b694ddbc4b40e9529d736bfe9874cc786773aa5a1070bbefe77feb9a8a304 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250917@sha256:ac6aaaa0d3312e72279a5cde7de0d71fb61774aa2f97a4e56dd914a9f1dde4d1 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250917@sha256:c25225c371e81485c64f339864ede410b560f07eb0fc2702a73315e977a6323d - - imageRef: ghcr.io/siderolabs/i915:20250917-v1.11.3@sha256:e8db985ff2ef702d5f3989b0138e1b9dd5ac5e885a3adefa5b42ee6fa32b7027 - - imageRef: ghcr.io/siderolabs/intel-ucode:20250812@sha256:31142ac037235e6779eea9f638e6399080a1f09e7c323ffa30b37488004057a5 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250917@sha256:7094e5db6931a1b68240416b65ddc0f3b546bd9b8520e3cfb1ddebcbfc83e890 - - imageRef: ghcr.io/siderolabs/drbd:9.2.14-v1.11.3@sha256:4393756875751e2664a04e96c1ccff84c99958ca819dd93b46b82ad8f3b4be67 - - imageRef: ghcr.io/siderolabs/zfs:2.3.3-v1.11.3@sha256:3c0b34a760914980ac234e66f130d829e428018e46420b7bca33219b1cc2dd87 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: initramfs imageOptions: {} diff --git a/packages/core/talos/images/talos/profiles/installer.yaml b/packages/core/talos/images/talos/profiles/installer.yaml index aedff886..b219e012 100644 --- a/packages/core/talos/images/talos/profiles/installer.yaml +++ b/packages/core/talos/images/talos/profiles/installer.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.11.3 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.11.3" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250917@sha256:ff11ee9f1565d9f9b095a3dc41fb7962b211169b2ef05d658a488398cb98e2d2 - - imageRef: ghcr.io/siderolabs/amdgpu:20250917-v1.11.3@sha256:527b694ddbc4b40e9529d736bfe9874cc786773aa5a1070bbefe77feb9a8a304 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250917@sha256:ac6aaaa0d3312e72279a5cde7de0d71fb61774aa2f97a4e56dd914a9f1dde4d1 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250917@sha256:c25225c371e81485c64f339864ede410b560f07eb0fc2702a73315e977a6323d - - imageRef: ghcr.io/siderolabs/i915:20250917-v1.11.3@sha256:e8db985ff2ef702d5f3989b0138e1b9dd5ac5e885a3adefa5b42ee6fa32b7027 - - imageRef: ghcr.io/siderolabs/intel-ucode:20250812@sha256:31142ac037235e6779eea9f638e6399080a1f09e7c323ffa30b37488004057a5 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250917@sha256:7094e5db6931a1b68240416b65ddc0f3b546bd9b8520e3cfb1ddebcbfc83e890 - - imageRef: ghcr.io/siderolabs/drbd:9.2.14-v1.11.3@sha256:4393756875751e2664a04e96c1ccff84c99958ca819dd93b46b82ad8f3b4be67 - - imageRef: ghcr.io/siderolabs/zfs:2.3.3-v1.11.3@sha256:3c0b34a760914980ac234e66f130d829e428018e46420b7bca33219b1cc2dd87 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: installer imageOptions: {} diff --git a/packages/core/talos/images/talos/profiles/iso.yaml b/packages/core/talos/images/talos/profiles/iso.yaml index 1f46d36a..5773c6a6 100644 --- a/packages/core/talos/images/talos/profiles/iso.yaml +++ b/packages/core/talos/images/talos/profiles/iso.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.11.3 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.11.3" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250917@sha256:ff11ee9f1565d9f9b095a3dc41fb7962b211169b2ef05d658a488398cb98e2d2 - - imageRef: ghcr.io/siderolabs/amdgpu:20250917-v1.11.3@sha256:527b694ddbc4b40e9529d736bfe9874cc786773aa5a1070bbefe77feb9a8a304 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250917@sha256:ac6aaaa0d3312e72279a5cde7de0d71fb61774aa2f97a4e56dd914a9f1dde4d1 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250917@sha256:c25225c371e81485c64f339864ede410b560f07eb0fc2702a73315e977a6323d - - imageRef: ghcr.io/siderolabs/i915:20250917-v1.11.3@sha256:e8db985ff2ef702d5f3989b0138e1b9dd5ac5e885a3adefa5b42ee6fa32b7027 - - imageRef: ghcr.io/siderolabs/intel-ucode:20250812@sha256:31142ac037235e6779eea9f638e6399080a1f09e7c323ffa30b37488004057a5 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250917@sha256:7094e5db6931a1b68240416b65ddc0f3b546bd9b8520e3cfb1ddebcbfc83e890 - - imageRef: ghcr.io/siderolabs/drbd:9.2.14-v1.11.3@sha256:4393756875751e2664a04e96c1ccff84c99958ca819dd93b46b82ad8f3b4be67 - - imageRef: ghcr.io/siderolabs/zfs:2.3.3-v1.11.3@sha256:3c0b34a760914980ac234e66f130d829e428018e46420b7bca33219b1cc2dd87 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: iso imageOptions: {} diff --git a/packages/core/talos/images/talos/profiles/kernel.yaml b/packages/core/talos/images/talos/profiles/kernel.yaml index 4e4f3685..2f80bbda 100644 --- a/packages/core/talos/images/talos/profiles/kernel.yaml +++ b/packages/core/talos/images/talos/profiles/kernel.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.11.3 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.11.3" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250917@sha256:ff11ee9f1565d9f9b095a3dc41fb7962b211169b2ef05d658a488398cb98e2d2 - - imageRef: ghcr.io/siderolabs/amdgpu:20250917-v1.11.3@sha256:527b694ddbc4b40e9529d736bfe9874cc786773aa5a1070bbefe77feb9a8a304 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250917@sha256:ac6aaaa0d3312e72279a5cde7de0d71fb61774aa2f97a4e56dd914a9f1dde4d1 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250917@sha256:c25225c371e81485c64f339864ede410b560f07eb0fc2702a73315e977a6323d - - imageRef: ghcr.io/siderolabs/i915:20250917-v1.11.3@sha256:e8db985ff2ef702d5f3989b0138e1b9dd5ac5e885a3adefa5b42ee6fa32b7027 - - imageRef: ghcr.io/siderolabs/intel-ucode:20250812@sha256:31142ac037235e6779eea9f638e6399080a1f09e7c323ffa30b37488004057a5 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250917@sha256:7094e5db6931a1b68240416b65ddc0f3b546bd9b8520e3cfb1ddebcbfc83e890 - - imageRef: ghcr.io/siderolabs/drbd:9.2.14-v1.11.3@sha256:4393756875751e2664a04e96c1ccff84c99958ca819dd93b46b82ad8f3b4be67 - - imageRef: ghcr.io/siderolabs/zfs:2.3.3-v1.11.3@sha256:3c0b34a760914980ac234e66f130d829e428018e46420b7bca33219b1cc2dd87 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: kernel imageOptions: {} diff --git a/packages/core/talos/images/talos/profiles/metal.yaml b/packages/core/talos/images/talos/profiles/metal.yaml index 54a5a93d..d460e0d8 100644 --- a/packages/core/talos/images/talos/profiles/metal.yaml +++ b/packages/core/talos/images/talos/profiles/metal.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.11.3 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.11.3" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250917@sha256:ff11ee9f1565d9f9b095a3dc41fb7962b211169b2ef05d658a488398cb98e2d2 - - imageRef: ghcr.io/siderolabs/amdgpu:20250917-v1.11.3@sha256:527b694ddbc4b40e9529d736bfe9874cc786773aa5a1070bbefe77feb9a8a304 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250917@sha256:ac6aaaa0d3312e72279a5cde7de0d71fb61774aa2f97a4e56dd914a9f1dde4d1 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250917@sha256:c25225c371e81485c64f339864ede410b560f07eb0fc2702a73315e977a6323d - - imageRef: ghcr.io/siderolabs/i915:20250917-v1.11.3@sha256:e8db985ff2ef702d5f3989b0138e1b9dd5ac5e885a3adefa5b42ee6fa32b7027 - - imageRef: ghcr.io/siderolabs/intel-ucode:20250812@sha256:31142ac037235e6779eea9f638e6399080a1f09e7c323ffa30b37488004057a5 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250917@sha256:7094e5db6931a1b68240416b65ddc0f3b546bd9b8520e3cfb1ddebcbfc83e890 - - imageRef: ghcr.io/siderolabs/drbd:9.2.14-v1.11.3@sha256:4393756875751e2664a04e96c1ccff84c99958ca819dd93b46b82ad8f3b4be67 - - imageRef: ghcr.io/siderolabs/zfs:2.3.3-v1.11.3@sha256:3c0b34a760914980ac234e66f130d829e428018e46420b7bca33219b1cc2dd87 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: image imageOptions: { diskSize: 1306525696, diskFormat: raw } diff --git a/packages/core/talos/images/talos/profiles/nocloud.yaml b/packages/core/talos/images/talos/profiles/nocloud.yaml index 5e0f8cf1..3dfb37f7 100644 --- a/packages/core/talos/images/talos/profiles/nocloud.yaml +++ b/packages/core/talos/images/talos/profiles/nocloud.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: nocloud secureboot: false -version: v1.11.3 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.11.3" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20250917@sha256:ff11ee9f1565d9f9b095a3dc41fb7962b211169b2ef05d658a488398cb98e2d2 - - imageRef: ghcr.io/siderolabs/amdgpu:20250917-v1.11.3@sha256:527b694ddbc4b40e9529d736bfe9874cc786773aa5a1070bbefe77feb9a8a304 - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20250917@sha256:ac6aaaa0d3312e72279a5cde7de0d71fb61774aa2f97a4e56dd914a9f1dde4d1 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20250917@sha256:c25225c371e81485c64f339864ede410b560f07eb0fc2702a73315e977a6323d - - imageRef: ghcr.io/siderolabs/i915:20250917-v1.11.3@sha256:e8db985ff2ef702d5f3989b0138e1b9dd5ac5e885a3adefa5b42ee6fa32b7027 - - imageRef: ghcr.io/siderolabs/intel-ucode:20250812@sha256:31142ac037235e6779eea9f638e6399080a1f09e7c323ffa30b37488004057a5 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20250917@sha256:7094e5db6931a1b68240416b65ddc0f3b546bd9b8520e3cfb1ddebcbfc83e890 - - imageRef: ghcr.io/siderolabs/drbd:9.2.14-v1.11.3@sha256:4393756875751e2664a04e96c1ccff84c99958ca819dd93b46b82ad8f3b4be67 - - imageRef: ghcr.io/siderolabs/zfs:2.3.3-v1.11.3@sha256:3c0b34a760914980ac234e66f130d829e428018e46420b7bca33219b1cc2dd87 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: image imageOptions: { diskSize: 1306525696, diskFormat: raw } diff --git a/packages/core/testing/Makefile b/packages/core/testing/Makefile index f345d155..baccbfce 100644 --- a/packages/core/testing/Makefile +++ b/packages/core/testing/Makefile @@ -6,7 +6,7 @@ SANDBOX_NAME := cozy-e2e-sandbox-$(shell echo "$$(hostname):$$(pwd)" | sha256sum ROOT_DIR = $(dir $(abspath $(firstword $(MAKEFILE_LIST))/../../..)) -include ../../../scripts/common-envs.mk +include ../../../hack/common-envs.mk help: ## Show this help. @@ -31,7 +31,8 @@ copy-nocloud-image: docker cp ../../../_out/assets/nocloud-amd64.raw.xz "${SANDBOX_NAME}":/workspace/_out/assets/nocloud-amd64.raw.xz copy-installer-manifest: - docker cp ../../../_out/assets/cozystack-installer.yaml "${SANDBOX_NAME}":/workspace/_out/assets/cozystack-installer.yaml + docker cp ../../../_out/assets/cozystack-crds.yaml "${SANDBOX_NAME}":/workspace/_out/assets/cozystack-crds.yaml + docker cp ../../../_out/assets/cozystack-operator.yaml "${SANDBOX_NAME}":/workspace/_out/assets/cozystack-operator.yaml prepare-cluster: copy-nocloud-image docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && hack/cozytest.sh hack/e2e-prepare-cluster.bats' diff --git a/packages/core/testing/images/e2e-sandbox/Dockerfile b/packages/core/testing/images/e2e-sandbox/Dockerfile index ee57f193..2f94991f 100644 --- a/packages/core/testing/images/e2e-sandbox/Dockerfile +++ b/packages/core/testing/images/e2e-sandbox/Dockerfile @@ -3,7 +3,7 @@ FROM ubuntu:22.04 ARG KUBECTL_VERSION=1.33.2 ARG TALOSCTL_VERSION=1.10.4 ARG HELM_VERSION=3.18.3 -ARG COZYHR_VERSION=1.5.0 +ARG COZYHR_VERSION=1.6.1 ARG TARGETOS ARG TARGETARCH diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index de6bb330..1e77f663 100644 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.38.2@sha256:84be9e42bc2c04b0765c8b89e0a9728c49ebf4676a92522b007af96ae9aec68d + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.0.0-beta.2@sha256:eac71ef0de3450fce96255629e77903630c63ade62b81e7055f1a689f92ee153 diff --git a/packages/extra/Makefile b/packages/extra/Makefile index 5872855b..dd3293a0 100644 --- a/packages/extra/Makefile +++ b/packages/extra/Makefile @@ -1,7 +1,7 @@ OUT=../../_out/repos/extra CHARTS := $(shell find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}') -include ../../scripts/common-envs.mk +include ../../hack/common-envs.mk repo: rm -rf "$(OUT)" diff --git a/packages/extra/bootbox/Makefile b/packages/extra/bootbox/Makefile index d9a1e261..57fa0a77 100644 --- a/packages/extra/bootbox/Makefile +++ b/packages/extra/bootbox/Makefile @@ -1,7 +1,7 @@ NAME=bootbox NAMESPACE=tenant-root -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index 2e63d30b..05ee31c2 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v0.38.2@sha256:9cd7f46fcae119a3f8e35b428b018d0cb6da7b0cdd2ce764cc9fbf6dcd903f27 +ghcr.io/cozystack/cozystack/matchbox:v1.0.0-beta.2@sha256:3d8c93822ca7b344b718a9ab0fb196d8fab92fcf852907975b39528d129811f0 diff --git a/packages/extra/etcd/Makefile b/packages/extra/etcd/Makefile index b309346c..f37d6e1e 100644 --- a/packages/extra/etcd/Makefile +++ b/packages/extra/etcd/Makefile @@ -1,6 +1,6 @@ NAME=etcd -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/extra/etcd/templates/etcd-cluster.yaml b/packages/extra/etcd/templates/etcd-cluster.yaml index a26ae173..44851cc6 100644 --- a/packages/extra/etcd/templates/etcd-cluster.yaml +++ b/packages/extra/etcd/templates/etcd-cluster.yaml @@ -46,6 +46,15 @@ spec: - name: metrics containerPort: 2381 protocol: TCP + startupProbe: + failureThreshold: 300 + periodSeconds: 5 + livenessProbe: + failureThreshold: 10 + periodSeconds: 10 + readinessProbe: + failureThreshold: 3 + periodSeconds: 5 {{- with .Values.resources }} resources: {{- include "cozy-lib.resources.sanitize" (list . $) | nindent 10 }} {{- end }} diff --git a/packages/extra/info/Makefile b/packages/extra/info/Makefile index e09b33a0..02e04d53 100644 --- a/packages/extra/info/Makefile +++ b/packages/extra/info/Makefile @@ -1,6 +1,6 @@ NAME=etcd -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/extra/ingress/Makefile b/packages/extra/ingress/Makefile index 8134cb22..958ce484 100644 --- a/packages/extra/ingress/Makefile +++ b/packages/extra/ingress/Makefile @@ -1,6 +1,6 @@ NAME=ingress -include ../../../scripts/package.mk +include ../../../hack/package.mk update: get-cloudflare-ips diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index d375be2c..ca50d276 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -4,16 +4,13 @@ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: ingress-nginx-system + labels: + sharding.fluxcd.io/key: tenants spec: - chart: - spec: - chart: cozy-ingress-nginx - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-ingress-application-default-ingress-system + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/extra/monitoring/Makefile b/packages/extra/monitoring/Makefile index b21607ab..1ae213b6 100644 --- a/packages/extra/monitoring/Makefile +++ b/packages/extra/monitoring/Makefile @@ -2,8 +2,8 @@ GRAFANA_TAG = $(shell awk '$$1 == "version:" {print $$2}' Chart.yaml) NAME=monitoring -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/extra/monitoring/dashboards.list b/packages/extra/monitoring/dashboards.list index 21ecb974..1f4b2eea 100644 --- a/packages/extra/monitoring/dashboards.list +++ b/packages/extra/monitoring/dashboards.list @@ -39,3 +39,7 @@ goldpinger/goldpinger clickhouse/altinity-clickhouse-operator-dashboard storage/linstor seaweedfs/seaweedfs +hubble/overview +hubble/dns-namespace +hubble/l7-http-metrics +hubble/network-overview diff --git a/packages/extra/monitoring/images/grafana.tag b/packages/extra/monitoring/images/grafana.tag index 9d53b4f1..06fa403d 100644 --- a/packages/extra/monitoring/images/grafana.tag +++ b/packages/extra/monitoring/images/grafana.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/grafana:0.0.0@sha256:c63978e1ed0304e8518b31ddee56c4e8115541b997d8efbe1c0a74da57140399 +ghcr.io/cozystack/cozystack/grafana:0.0.0@sha256:8ce0cd90c8f614cdabf5a41f8aa50b7dfbd02b31b9a0bd7897927e7f89968e07 diff --git a/packages/extra/monitoring/templates/dashboards.yaml b/packages/extra/monitoring/templates/dashboards.yaml index 522df88b..3872f9b7 100644 --- a/packages/extra/monitoring/templates/dashboards.yaml +++ b/packages/extra/monitoring/templates/dashboards.yaml @@ -1,6 +1,6 @@ {{- range (split "\n" (.Files.Get "dashboards.list")) }} {{- $parts := split "/" . }} -{{- if eq (len $parts) 2 }} +{{- if eq (len $parts) 2 }} --- apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard @@ -11,6 +11,6 @@ spec: instanceSelector: matchLabels: dashboards: grafana - url: http://cozystack-assets.cozy-system.svc/dashboards/{{ . }}.json + url: http://grafana-dashboards.cozy-grafana-operator.svc/{{ . }}.json {{- end }} {{- end }} diff --git a/packages/extra/seaweedfs/Makefile b/packages/extra/seaweedfs/Makefile index be84180b..eaa1b906 100644 --- a/packages/extra/seaweedfs/Makefile +++ b/packages/extra/seaweedfs/Makefile @@ -1,6 +1,6 @@ NAME=seaweedfs -include ../../../scripts/package.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/extra/seaweedfs/images/objectstorage-sidecar.tag b/packages/extra/seaweedfs/images/objectstorage-sidecar.tag index ec59113f..1db178ca 100644 --- a/packages/extra/seaweedfs/images/objectstorage-sidecar.tag +++ b/packages/extra/seaweedfs/images/objectstorage-sidecar.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.38.2@sha256:ff3281fe53a97d2cd5cd94bd4c4d8ff08189508729869bb39b3f60c80da5f919 +ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-beta.2@sha256:ea035d4eff4a05d9d83f487d00438504cc27a95c0ee78c534d6eed53f4b2f04e diff --git a/packages/extra/seaweedfs/templates/seaweedfs.yaml b/packages/extra/seaweedfs/templates/seaweedfs.yaml index 747fc410..b04318bb 100644 --- a/packages/extra/seaweedfs/templates/seaweedfs.yaml +++ b/packages/extra/seaweedfs/templates/seaweedfs.yaml @@ -40,16 +40,13 @@ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: {{ .Release.Name }}-system + labels: + sharding.fluxcd.io/key: tenants spec: - chart: - spec: - chart: cozy-seaweedfs - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-seaweedfs-application-default-seaweedfs-system + namespace: cozy-system interval: 5m timeout: 10m install: diff --git a/packages/library/Makefile b/packages/library/Makefile index da811e7e..620dcf10 100644 --- a/packages/library/Makefile +++ b/packages/library/Makefile @@ -1,7 +1,7 @@ OUT=../../_out/repos/library CHARTS := $(shell find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}') -include ../../scripts/common-envs.mk +include ../../hack/common-envs.mk repo: rm -rf "$(OUT)" diff --git a/packages/library/cozy-lib/Makefile b/packages/library/cozy-lib/Makefile index 362bf32c..925f90c1 100644 --- a/packages/library/cozy-lib/Makefile +++ b/packages/library/cozy-lib/Makefile @@ -1,5 +1,5 @@ -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md diff --git a/packages/system/Makefile b/packages/system/Makefile index e068be8a..9173d353 100644 --- a/packages/system/Makefile +++ b/packages/system/Makefile @@ -2,7 +2,7 @@ OUT=../../_out/repos/system CHARTS := $(shell grep -F 'version: 0.0.0' */Chart.yaml | cut -f1 -d/) VERSIONED_CHARTS := $(shell grep '^version:' */Chart.yaml | grep -Fv '0.0.0' | cut -f1 -d/) -include ../../scripts/common-envs.mk +include ../../hack/common-envs.mk repo: rm -rf "$(OUT)" diff --git a/packages/system/cozystack-resource-definition-crd/Chart.yaml b/packages/system/application-definition-crd/Chart.yaml similarity index 74% rename from packages/system/cozystack-resource-definition-crd/Chart.yaml rename to packages/system/application-definition-crd/Chart.yaml index 9924c7fa..f272bf43 100644 --- a/packages/system/cozystack-resource-definition-crd/Chart.yaml +++ b/packages/system/application-definition-crd/Chart.yaml @@ -1,3 +1,3 @@ apiVersion: v2 -name: cozystack-resource-definition-crd +name: application-definition-crd version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/application-definition-crd/Makefile b/packages/system/application-definition-crd/Makefile new file mode 100644 index 00000000..adb378af --- /dev/null +++ b/packages/system/application-definition-crd/Makefile @@ -0,0 +1,4 @@ +export NAME=application-definition-crd +export NAMESPACE=cozy-system + +include ../../../hack/package.mk diff --git a/packages/system/cozystack-resource-definition-crd/definition/cozystack.io_cozystackresourcedefinitions.yaml b/packages/system/application-definition-crd/definition/cozystack.io_applicationdefinitions.yaml similarity index 72% rename from packages/system/cozystack-resource-definition-crd/definition/cozystack.io_cozystackresourcedefinitions.yaml rename to packages/system/application-definition-crd/definition/cozystack.io_applicationdefinitions.yaml index 685d4ac5..44d33865 100644 --- a/packages/system/cozystack-resource-definition-crd/definition/cozystack.io_cozystackresourcedefinitions.yaml +++ b/packages/system/application-definition-crd/definition/cozystack.io_applicationdefinitions.yaml @@ -4,20 +4,20 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.4 - name: cozystackresourcedefinitions.cozystack.io + name: applicationdefinitions.cozystack.io spec: group: cozystack.io names: - kind: CozystackResourceDefinition - listKind: CozystackResourceDefinitionList - plural: cozystackresourcedefinitions - singular: cozystackresourcedefinition + kind: ApplicationDefinition + listKind: ApplicationDefinitionList + plural: applicationdefinitions + singular: applicationdefinition scope: Cluster versions: - name: v1alpha1 schema: openAPIV3Schema: - description: CozystackResourceDefinition is the Schema for the cozystackresourcedefinitions + description: ApplicationDefinition is the Schema for the applicationdefinitions API properties: apiVersion: @@ -135,29 +135,22 @@ spec: If a resource matches the selector in any of the elements in the array, it is hidden from the user, regardless of the matches in the include array. items: - description: |- - CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support. - A resource matches this selector only if it satisfies ALL criteria: - - Label selector conditions (matchExpressions and matchLabels) - - AND has a name that matches one of the names in resourceNames (if specified) - - The resourceNames field supports Go templates with the following variables available: - - {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name) - - {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind) - - {{ .namespace }}: The namespace of the resource being processed - - Example YAML: - secrets: - include: - - matchExpressions: - - key: badlabel - operator: DoesNotExist - matchLabels: - goodlabel: goodvalue - resourceNames: - - "{{ .name }}-secret" - - "{{ .kind }}-{{ .name }}-tls" - - "specificname" + description: "ApplicationDefinitionResourceSelector extends + metav1.LabelSelector with resourceNames support.\nA resource + matches this selector only if it satisfies ALL criteria:\n- + Label selector conditions (matchExpressions and matchLabels)\n- + AND has a name that matches one of the names in resourceNames + (if specified)\n\nThe resourceNames field supports Go templates + with the following variables available:\n- {{ .name }}: The + name of the managing application (from apps.cozystack.io/application.name)\n- + {{ .kind }}: The lowercased kind of the managing application + (from apps.cozystack.io/application.kind)\n- {{ .namespace + }}: The namespace of the resource being processed\n\nExample + YAML:\n\n\tsecrets:\n\t include:\n\t - matchExpressions:\n\t + \ - key: badlabel\n\t operator: DoesNotExist\n\t matchLabels:\n\t + \ goodlabel: goodvalue\n\t resourceNames:\n\t - + \"{{ .name }}-secret\"\n\t - \"{{ .kind }}-{{ .name }}-tls\"\n\t + \ - \"specificname\"" properties: matchExpressions: description: matchExpressions is a list of label selector @@ -217,29 +210,22 @@ spec: matches none of the selectors in the exclude array that resource is marked as a tenant resource and is visible to users. items: - description: |- - CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support. - A resource matches this selector only if it satisfies ALL criteria: - - Label selector conditions (matchExpressions and matchLabels) - - AND has a name that matches one of the names in resourceNames (if specified) - - The resourceNames field supports Go templates with the following variables available: - - {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name) - - {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind) - - {{ .namespace }}: The namespace of the resource being processed - - Example YAML: - secrets: - include: - - matchExpressions: - - key: badlabel - operator: DoesNotExist - matchLabels: - goodlabel: goodvalue - resourceNames: - - "{{ .name }}-secret" - - "{{ .kind }}-{{ .name }}-tls" - - "specificname" + description: "ApplicationDefinitionResourceSelector extends + metav1.LabelSelector with resourceNames support.\nA resource + matches this selector only if it satisfies ALL criteria:\n- + Label selector conditions (matchExpressions and matchLabels)\n- + AND has a name that matches one of the names in resourceNames + (if specified)\n\nThe resourceNames field supports Go templates + with the following variables available:\n- {{ .name }}: The + name of the managing application (from apps.cozystack.io/application.name)\n- + {{ .kind }}: The lowercased kind of the managing application + (from apps.cozystack.io/application.kind)\n- {{ .namespace + }}: The namespace of the resource being processed\n\nExample + YAML:\n\n\tsecrets:\n\t include:\n\t - matchExpressions:\n\t + \ - key: badlabel\n\t operator: DoesNotExist\n\t matchLabels:\n\t + \ goodlabel: goodvalue\n\t resourceNames:\n\t - + \"{{ .name }}-secret\"\n\t - \"{{ .kind }}-{{ .name }}-tls\"\n\t + \ - \"specificname\"" properties: matchExpressions: description: matchExpressions is a list of label selector @@ -296,34 +282,34 @@ spec: release: description: Release configuration properties: - chart: - description: Helm chart configuration + chartRef: + description: Reference to the chart source properties: - name: - description: Name of the Helm chart + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - OCIRepository + - HelmChart + - ExternalArtifact + type: string + name: + description: Name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace of the referent, defaults to the namespace of the Kubernetes + resource object that contains the reference. + maxLength: 63 + minLength: 1 type: string - sourceRef: - description: Source reference for the Helm chart - properties: - kind: - default: HelmRepository - description: Kind of the source reference - type: string - name: - description: Name of the source reference - type: string - namespace: - default: cozy-public - description: Namespace of the source reference - type: string - required: - - kind - - name - - namespace - type: object required: + - kind - name - - sourceRef type: object labels: additionalProperties: @@ -334,7 +320,7 @@ spec: description: Prefix for the release name type: string required: - - chart + - chartRef - prefix type: object secrets: @@ -346,29 +332,22 @@ spec: If a resource matches the selector in any of the elements in the array, it is hidden from the user, regardless of the matches in the include array. items: - description: |- - CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support. - A resource matches this selector only if it satisfies ALL criteria: - - Label selector conditions (matchExpressions and matchLabels) - - AND has a name that matches one of the names in resourceNames (if specified) - - The resourceNames field supports Go templates with the following variables available: - - {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name) - - {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind) - - {{ .namespace }}: The namespace of the resource being processed - - Example YAML: - secrets: - include: - - matchExpressions: - - key: badlabel - operator: DoesNotExist - matchLabels: - goodlabel: goodvalue - resourceNames: - - "{{ .name }}-secret" - - "{{ .kind }}-{{ .name }}-tls" - - "specificname" + description: "ApplicationDefinitionResourceSelector extends + metav1.LabelSelector with resourceNames support.\nA resource + matches this selector only if it satisfies ALL criteria:\n- + Label selector conditions (matchExpressions and matchLabels)\n- + AND has a name that matches one of the names in resourceNames + (if specified)\n\nThe resourceNames field supports Go templates + with the following variables available:\n- {{ .name }}: The + name of the managing application (from apps.cozystack.io/application.name)\n- + {{ .kind }}: The lowercased kind of the managing application + (from apps.cozystack.io/application.kind)\n- {{ .namespace + }}: The namespace of the resource being processed\n\nExample + YAML:\n\n\tsecrets:\n\t include:\n\t - matchExpressions:\n\t + \ - key: badlabel\n\t operator: DoesNotExist\n\t matchLabels:\n\t + \ goodlabel: goodvalue\n\t resourceNames:\n\t - + \"{{ .name }}-secret\"\n\t - \"{{ .kind }}-{{ .name }}-tls\"\n\t + \ - \"specificname\"" properties: matchExpressions: description: matchExpressions is a list of label selector @@ -428,29 +407,22 @@ spec: matches none of the selectors in the exclude array that resource is marked as a tenant resource and is visible to users. items: - description: |- - CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support. - A resource matches this selector only if it satisfies ALL criteria: - - Label selector conditions (matchExpressions and matchLabels) - - AND has a name that matches one of the names in resourceNames (if specified) - - The resourceNames field supports Go templates with the following variables available: - - {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name) - - {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind) - - {{ .namespace }}: The namespace of the resource being processed - - Example YAML: - secrets: - include: - - matchExpressions: - - key: badlabel - operator: DoesNotExist - matchLabels: - goodlabel: goodvalue - resourceNames: - - "{{ .name }}-secret" - - "{{ .kind }}-{{ .name }}-tls" - - "specificname" + description: "ApplicationDefinitionResourceSelector extends + metav1.LabelSelector with resourceNames support.\nA resource + matches this selector only if it satisfies ALL criteria:\n- + Label selector conditions (matchExpressions and matchLabels)\n- + AND has a name that matches one of the names in resourceNames + (if specified)\n\nThe resourceNames field supports Go templates + with the following variables available:\n- {{ .name }}: The + name of the managing application (from apps.cozystack.io/application.name)\n- + {{ .kind }}: The lowercased kind of the managing application + (from apps.cozystack.io/application.kind)\n- {{ .namespace + }}: The namespace of the resource being processed\n\nExample + YAML:\n\n\tsecrets:\n\t include:\n\t - matchExpressions:\n\t + \ - key: badlabel\n\t operator: DoesNotExist\n\t matchLabels:\n\t + \ goodlabel: goodvalue\n\t resourceNames:\n\t - + \"{{ .name }}-secret\"\n\t - \"{{ .kind }}-{{ .name }}-tls\"\n\t + \ - \"specificname\"" properties: matchExpressions: description: matchExpressions is a list of label selector @@ -513,29 +485,22 @@ spec: If a resource matches the selector in any of the elements in the array, it is hidden from the user, regardless of the matches in the include array. items: - description: |- - CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support. - A resource matches this selector only if it satisfies ALL criteria: - - Label selector conditions (matchExpressions and matchLabels) - - AND has a name that matches one of the names in resourceNames (if specified) - - The resourceNames field supports Go templates with the following variables available: - - {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name) - - {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind) - - {{ .namespace }}: The namespace of the resource being processed - - Example YAML: - secrets: - include: - - matchExpressions: - - key: badlabel - operator: DoesNotExist - matchLabels: - goodlabel: goodvalue - resourceNames: - - "{{ .name }}-secret" - - "{{ .kind }}-{{ .name }}-tls" - - "specificname" + description: "ApplicationDefinitionResourceSelector extends + metav1.LabelSelector with resourceNames support.\nA resource + matches this selector only if it satisfies ALL criteria:\n- + Label selector conditions (matchExpressions and matchLabels)\n- + AND has a name that matches one of the names in resourceNames + (if specified)\n\nThe resourceNames field supports Go templates + with the following variables available:\n- {{ .name }}: The + name of the managing application (from apps.cozystack.io/application.name)\n- + {{ .kind }}: The lowercased kind of the managing application + (from apps.cozystack.io/application.kind)\n- {{ .namespace + }}: The namespace of the resource being processed\n\nExample + YAML:\n\n\tsecrets:\n\t include:\n\t - matchExpressions:\n\t + \ - key: badlabel\n\t operator: DoesNotExist\n\t matchLabels:\n\t + \ goodlabel: goodvalue\n\t resourceNames:\n\t - + \"{{ .name }}-secret\"\n\t - \"{{ .kind }}-{{ .name }}-tls\"\n\t + \ - \"specificname\"" properties: matchExpressions: description: matchExpressions is a list of label selector @@ -595,29 +560,22 @@ spec: matches none of the selectors in the exclude array that resource is marked as a tenant resource and is visible to users. items: - description: |- - CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support. - A resource matches this selector only if it satisfies ALL criteria: - - Label selector conditions (matchExpressions and matchLabels) - - AND has a name that matches one of the names in resourceNames (if specified) - - The resourceNames field supports Go templates with the following variables available: - - {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name) - - {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind) - - {{ .namespace }}: The namespace of the resource being processed - - Example YAML: - secrets: - include: - - matchExpressions: - - key: badlabel - operator: DoesNotExist - matchLabels: - goodlabel: goodvalue - resourceNames: - - "{{ .name }}-secret" - - "{{ .kind }}-{{ .name }}-tls" - - "specificname" + description: "ApplicationDefinitionResourceSelector extends + metav1.LabelSelector with resourceNames support.\nA resource + matches this selector only if it satisfies ALL criteria:\n- + Label selector conditions (matchExpressions and matchLabels)\n- + AND has a name that matches one of the names in resourceNames + (if specified)\n\nThe resourceNames field supports Go templates + with the following variables available:\n- {{ .name }}: The + name of the managing application (from apps.cozystack.io/application.name)\n- + {{ .kind }}: The lowercased kind of the managing application + (from apps.cozystack.io/application.kind)\n- {{ .namespace + }}: The namespace of the resource being processed\n\nExample + YAML:\n\n\tsecrets:\n\t include:\n\t - matchExpressions:\n\t + \ - key: badlabel\n\t operator: DoesNotExist\n\t matchLabels:\n\t + \ goodlabel: goodvalue\n\t resourceNames:\n\t - + \"{{ .name }}-secret\"\n\t - \"{{ .kind }}-{{ .name }}-tls\"\n\t + \ - \"specificname\"" properties: matchExpressions: description: matchExpressions is a list of label selector diff --git a/packages/system/application-definition-crd/templates/crd.yaml b/packages/system/application-definition-crd/templates/crd.yaml new file mode 100644 index 00000000..3c94f229 --- /dev/null +++ b/packages/system/application-definition-crd/templates/crd.yaml @@ -0,0 +1,2 @@ +--- +{{ .Files.Get "definition/cozystack.io_applicationdefinitions.yaml" }} diff --git a/packages/system/cozystack-resource-definition-crd/values.yaml b/packages/system/application-definition-crd/values.yaml similarity index 100% rename from packages/system/cozystack-resource-definition-crd/values.yaml rename to packages/system/application-definition-crd/values.yaml diff --git a/packages/system/backup-controller/Makefile b/packages/system/backup-controller/Makefile index 56d58f20..472a99ba 100644 --- a/packages/system/backup-controller/Makefile +++ b/packages/system/backup-controller/Makefile @@ -1,8 +1,8 @@ NAME=backup-controller NAMESPACE=cozy-backup-controller -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk image: image-backup-controller diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_backupclasses.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_backupclasses.yaml new file mode 100644 index 00000000..b0f0fec2 --- /dev/null +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_backupclasses.yaml @@ -0,0 +1,171 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: backupclasses.backups.cozystack.io +spec: + group: backups.cozystack.io + names: + kind: BackupClass + listKind: BackupClassList + plural: backupclasses + singular: backupclass + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + BackupClass defines a class of backup configurations that can be referenced + by BackupJob and Plan resources. It encapsulates strategy and storage configuration + per application type. + 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: BackupClassSpec defines the desired state of a BackupClass. + properties: + strategies: + description: Strategies is a list of backup strategies, each matching + a specific application type. + items: + description: BackupClassStrategy defines a backup strategy for a + specific application type. + properties: + application: + description: Application specifies which application types this + strategy applies to. + properties: + apiGroup: + description: |- + APIGroup is the API group of the application. + If not specified, defaults to "apps.cozystack.io". + type: string + kind: + description: Kind is the kind of the application (e.g., + VirtualMachine, MySQL). + type: string + required: + - kind + type: object + parameters: + additionalProperties: + type: string + description: |- + Parameters holds strategy-specific and storage-specific parameters. + Common parameters include: + - backupStorageLocationName: Name of Velero BackupStorageLocation + type: object + strategyRef: + description: StrategyRef references the driver-specific BackupStrategy + (e.g., Velero). + 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 + required: + - application + - strategyRef + type: object + type: array + required: + - strategies + type: object + status: + description: BackupClassStatus defines the observed state of a BackupClass. + properties: + conditions: + description: Conditions represents the latest available observations + of a BackupClass's 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 + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_backupjobs.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_backupjobs.yaml index 74349181..686c079f 100644 --- a/packages/system/backup-controller/definitions/backups.cozystack.io_backupjobs.yaml +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_backupjobs.yaml @@ -50,6 +50,7 @@ spec: description: |- ApplicationRef holds a reference to the managed application whose state is being backed up. + If apiGroup is not specified, it defaults to "apps.cozystack.io". properties: apiGroup: description: |- @@ -68,6 +69,12 @@ spec: - name type: object x-kubernetes-map-type: atomic + backupClassName: + description: |- + BackupClassName references a BackupClass that contains strategy and storage configuration. + The BackupClass will be resolved to determine the appropriate strategy and storage + based on the ApplicationRef. + type: string planRef: description: |- PlanRef refers to the Plan that requested this backup run. @@ -84,54 +91,9 @@ spec: type: string type: object x-kubernetes-map-type: atomic - storageRef: - description: |- - StorageRef holds a reference to the Storage object that describes where - the backup will be stored. - 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 - strategyRef: - description: |- - StrategyRef holds a reference to the driver-specific BackupStrategy object - that describes how the backup should be created. - 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 required: - applicationRef - - storageRef - - strategyRef + - backupClassName type: object status: description: BackupJobStatus represents the observed state of a BackupJob. diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml index 13d9bc62..6d55cb84 100644 --- a/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml @@ -85,28 +85,6 @@ spec: type: string type: object x-kubernetes-map-type: atomic - storageRef: - description: |- - StorageRef refers to the Storage object that describes where the backup - artifact is stored. - 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 strategyRef: description: |- StrategyRef refers to the driver-specific BackupStrategy that was used @@ -137,7 +115,6 @@ spec: type: string required: - applicationRef - - storageRef - strategyRef - takenAt type: object diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_plans.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_plans.yaml index 1c6829cc..94c09334 100644 --- a/packages/system/backup-controller/definitions/backups.cozystack.io_plans.yaml +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_plans.yaml @@ -47,6 +47,7 @@ spec: description: |- ApplicationRef holds a reference to the managed application, whose state and configuration must be backed up. + If apiGroup is not specified, it defaults to "apps.cozystack.io". properties: apiGroup: description: |- @@ -65,6 +66,12 @@ spec: - name type: object x-kubernetes-map-type: atomic + backupClassName: + description: |- + BackupClassName references a BackupClass that contains strategy and storage configuration. + The BackupClass will be resolved to determine the appropriate strategy and storage + based on the ApplicationRef. + type: string schedule: description: Schedule specifies when backup copies are created. properties: @@ -80,55 +87,10 @@ spec: [`cron`]. If omitted, defaults to `cron`. type: string type: object - storageRef: - description: |- - StorageRef holds a reference to the Storage object that - describes the location where the backup will be stored. - 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 - strategyRef: - description: |- - StrategyRef holds a reference to the Strategy object that - describes, how a backup copy is to be created. - 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 required: - applicationRef + - backupClassName - schedule - - storageRef - - strategyRef type: object status: properties: diff --git a/packages/system/backup-controller/templates/strategy.yaml b/packages/system/backup-controller/templates/strategy.yaml index 68109332..a8396d66 100644 --- a/packages/system/backup-controller/templates/strategy.yaml +++ b/packages/system/backup-controller/templates/strategy.yaml @@ -2,4 +2,9 @@ apiVersion: strategy.backups.cozystack.io/v1alpha1 kind: Velero metadata: name: velero-strategy-default -spec: {} +spec: + template: + spec: + ttl: 720h + includedNamespaces: + - "*" diff --git a/packages/system/backup-controller/values.yaml b/packages/system/backup-controller/values.yaml index 557c201a..84038de8 100644 --- a/packages/system/backup-controller/values.yaml +++ b/packages/system/backup-controller/values.yaml @@ -1,5 +1,5 @@ backupController: - image: "" + image: "ghcr.io/cozystack/cozystack/backup-controller:v1.0.0-beta.2@sha256:556cc41e4ec24c173e01c1679cf96915c7ca8c0b532b7945d461bf3797c8afbc" replicas: 2 debug: false metrics: diff --git a/packages/system/backupstrategy-controller/Chart.yaml b/packages/system/backupstrategy-controller/Chart.yaml index fd135712..bf556f3b 100644 --- a/packages/system/backupstrategy-controller/Chart.yaml +++ b/packages/system/backupstrategy-controller/Chart.yaml @@ -1,3 +1,3 @@ apiVersion: v2 -name: cozy-backup-controller +name: cozy-backupstrategy-controller version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/backupstrategy-controller/Makefile b/packages/system/backupstrategy-controller/Makefile index a5556838..e6f23ca7 100644 --- a/packages/system/backupstrategy-controller/Makefile +++ b/packages/system/backupstrategy-controller/Makefile @@ -1,8 +1,8 @@ NAME=backupstrategy-controller NAMESPACE=cozy-backup-controller -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk image: image-backupstrategy-controller diff --git a/packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml b/packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml index 4433c7cb..e817de23 100644 --- a/packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml +++ b/packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml @@ -39,6 +39,502 @@ spec: spec: description: VeleroSpec specifies the desired strategy for backing up with Velero. + properties: + template: + description: |- + VeleroTemplate describes the data a backup.velero.io should have when + templated from a Velero backup strategy. + properties: + spec: + description: BackupSpec defines the specification for a Velero + backup. + properties: + csiSnapshotTimeout: + description: |- + CSISnapshotTimeout specifies the time used to wait for CSI VolumeSnapshot status turns to + ReadyToUse during creation, before returning error as timeout. + The default value is 10 minute. + type: string + datamover: + description: |- + DataMover specifies the data mover to be used by the backup. + If DataMover is "" or "velero", the built-in data mover will be used. + type: string + defaultVolumesToFsBackup: + description: |- + DefaultVolumesToFsBackup specifies whether pod volume file system backup should be used + for all volumes by default. + nullable: true + type: boolean + defaultVolumesToRestic: + description: |- + DefaultVolumesToRestic specifies whether restic should be used to take a + backup of all pod volumes by default. + + Deprecated: this field is no longer used and will be removed entirely in future. Use DefaultVolumesToFsBackup instead. + nullable: true + type: boolean + excludedClusterScopedResources: + description: |- + ExcludedClusterScopedResources is a slice of cluster-scoped + resource type names to exclude from the backup. + If set to "*", all cluster-scoped resource types are excluded. + The default value is empty. + items: + type: string + nullable: true + type: array + excludedNamespaceScopedResources: + description: |- + ExcludedNamespaceScopedResources is a slice of namespace-scoped + resource type names to exclude from the backup. + If set to "*", all namespace-scoped resource types are excluded. + The default value is empty. + items: + type: string + nullable: true + type: array + excludedNamespaces: + description: |- + ExcludedNamespaces contains a list of namespaces that are not + included in the backup. + items: + type: string + nullable: true + type: array + excludedResources: + description: |- + ExcludedResources is a slice of resource names that are not + included in the backup. + items: + type: string + nullable: true + type: array + hooks: + description: Hooks represent custom behaviors that should + be executed at different phases of the backup. + properties: + resources: + description: Resources are hooks that should be executed + when backing up individual instances of a resource. + items: + description: |- + BackupResourceHookSpec defines one or more BackupResourceHooks that should be executed based on + the rules defined for namespaces, resources, and label selector. + properties: + excludedNamespaces: + description: ExcludedNamespaces specifies the namespaces + to which this hook spec does not apply. + items: + type: string + nullable: true + type: array + excludedResources: + description: ExcludedResources specifies the resources + to which this hook spec does not apply. + items: + type: string + nullable: true + type: array + includedNamespaces: + description: |- + IncludedNamespaces specifies the namespaces to which this hook spec applies. If empty, it applies + to all namespaces. + items: + type: string + nullable: true + type: array + includedResources: + description: |- + IncludedResources specifies the resources to which this hook spec applies. If empty, it applies + to all resources. + items: + type: string + nullable: true + type: array + labelSelector: + description: LabelSelector, if specified, filters + the resources to which this hook spec applies. + nullable: true + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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: Name is the name of this hook. + type: string + post: + description: |- + PostHooks is a list of BackupResourceHooks to execute after storing the item in the backup. + These are executed after all "additional items" from item actions are processed. + items: + description: BackupResourceHook defines a hook + for a resource. + properties: + exec: + description: Exec defines an exec hook. + properties: + command: + description: Command is the command and + arguments to execute. + items: + type: string + minItems: 1 + type: array + container: + description: |- + Container is the container in the pod where the command should be executed. If not specified, + the pod's first container is used. + type: string + onError: + description: OnError specifies how Velero + should behave if it encounters an error + executing this hook. + enum: + - Continue + - Fail + type: string + timeout: + description: |- + Timeout defines the maximum amount of time Velero should wait for the hook to complete before + considering the execution a failure. + type: string + required: + - command + type: object + required: + - exec + type: object + type: array + pre: + description: |- + PreHooks is a list of BackupResourceHooks to execute prior to storing the item in the backup. + These are executed before any "additional items" from item actions are processed. + items: + description: BackupResourceHook defines a hook + for a resource. + properties: + exec: + description: Exec defines an exec hook. + properties: + command: + description: Command is the command and + arguments to execute. + items: + type: string + minItems: 1 + type: array + container: + description: |- + Container is the container in the pod where the command should be executed. If not specified, + the pod's first container is used. + type: string + onError: + description: OnError specifies how Velero + should behave if it encounters an error + executing this hook. + enum: + - Continue + - Fail + type: string + timeout: + description: |- + Timeout defines the maximum amount of time Velero should wait for the hook to complete before + considering the execution a failure. + type: string + required: + - command + type: object + required: + - exec + type: object + type: array + required: + - name + type: object + nullable: true + type: array + type: object + includeClusterResources: + description: |- + IncludeClusterResources specifies whether cluster-scoped resources + should be included for consideration in the backup. + nullable: true + type: boolean + includedClusterScopedResources: + description: |- + IncludedClusterScopedResources is a slice of cluster-scoped + resource type names to include in the backup. + If set to "*", all cluster-scoped resource types are included. + The default value is empty, which means only related + cluster-scoped resources are included. + items: + type: string + nullable: true + type: array + includedNamespaceScopedResources: + description: |- + IncludedNamespaceScopedResources is a slice of namespace-scoped + resource type names to include in the backup. + The default value is "*". + items: + type: string + nullable: true + type: array + includedNamespaces: + description: |- + IncludedNamespaces is a slice of namespace names to include objects + from. If empty, all namespaces are included. + items: + type: string + nullable: true + type: array + includedResources: + description: |- + IncludedResources is a slice of resource names to include + in the backup. If empty, all resources are included. + items: + type: string + nullable: true + type: array + itemOperationTimeout: + description: |- + ItemOperationTimeout specifies the time used to wait for asynchronous BackupItemAction operations + The default value is 4 hour. + type: string + labelSelector: + description: |- + LabelSelector is a metav1.LabelSelector to filter with + when adding individual objects to the backup. If empty + or nil, all objects are included. Optional. + nullable: true + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + metadata: + properties: + labels: + additionalProperties: + type: string + type: object + type: object + orLabelSelectors: + description: |- + OrLabelSelectors is list of metav1.LabelSelector to filter with + when adding individual objects to the backup. If multiple provided + they will be joined by the OR operator. LabelSelector as well as + OrLabelSelectors cannot co-exist in backup request, only one of them + can be used. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + nullable: true + type: array + orderedResources: + additionalProperties: + type: string + description: |- + OrderedResources specifies the backup order of resources of specific Kind. + The map key is the resource name and value is a list of object names separated by commas. + Each resource name has format "namespace/objectname". For cluster resources, simply use "objectname". + nullable: true + type: object + resourcePolicy: + description: ResourcePolicy specifies the referenced resource + policies that backup should follow + 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 + snapshotMoveData: + description: SnapshotMoveData specifies whether snapshot data + should be moved + nullable: true + type: boolean + snapshotVolumes: + description: |- + SnapshotVolumes specifies whether to take snapshots + of any PV's referenced in the set of objects included + in the Backup. + nullable: true + type: boolean + storageLocation: + description: StorageLocation is a string containing the name + of a BackupStorageLocation where the backup should be stored. + type: string + ttl: + description: |- + TTL is a time.Duration-parseable string describing how long + the Backup should be retained for. + type: string + uploaderConfig: + description: UploaderConfig specifies the configuration for + the uploader. + nullable: true + properties: + parallelFilesUpload: + description: ParallelFilesUpload is the number of files + parallel uploads to perform when using the uploader. + type: integer + type: object + volumeGroupSnapshotLabelKey: + description: VolumeGroupSnapshotLabelKey specifies the label + key to group PVCs under a VGS. + type: string + volumeSnapshotLocations: + description: VolumeSnapshotLocations is a list containing + names of VolumeSnapshotLocations associated with this backup. + items: + type: string + type: array + type: object + required: + - spec + type: object + required: + - template type: object status: properties: diff --git a/packages/system/backupstrategy-controller/images/backupstrategy-controller/Dockerfile b/packages/system/backupstrategy-controller/images/backupstrategy-controller/Dockerfile index e896f473..c4f60746 100644 --- a/packages/system/backupstrategy-controller/images/backupstrategy-controller/Dockerfile +++ b/packages/system/backupstrategy-controller/images/backupstrategy-controller/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24-alpine AS builder +FROM golang:1.25-alpine AS builder ARG TARGETOS ARG TARGETARCH diff --git a/packages/system/backupstrategy-controller/values.yaml b/packages/system/backupstrategy-controller/values.yaml index 6b04244a..d4c9f253 100644 --- a/packages/system/backupstrategy-controller/values.yaml +++ b/packages/system/backupstrategy-controller/values.yaml @@ -1,5 +1,5 @@ backupStrategyController: - image: "" + image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.0.0-beta.2@sha256:5cbc85679790aa14fb55568439c669a704e29f02236df179abbb3a25c56a2aa7" replicas: 2 debug: false metrics: diff --git a/packages/system/bootbox-rd/Makefile b/packages/system/bootbox-rd/Makefile index b570a84f..9d03ab2b 100644 --- a/packages/system/bootbox-rd/Makefile +++ b/packages/system/bootbox-rd/Makefile @@ -1,4 +1,4 @@ export NAME=bootbox-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/bootbox-rd/cozyrds/bootbox.yaml b/packages/system/bootbox-rd/cozyrds/bootbox.yaml index f47bf8f6..62e87931 100644 --- a/packages/system/bootbox-rd/cozyrds/bootbox.yaml +++ b/packages/system/bootbox-rd/cozyrds/bootbox.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: bootbox spec: @@ -12,13 +12,11 @@ spec: release: prefix: "" labels: - cozystack.io/ui: "true" - chart: - name: bootbox - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-bootbox-application-default-bootbox + namespace: cozy-system dashboard: category: Administration singular: BootBox diff --git a/packages/system/bootbox/Makefile b/packages/system/bootbox/Makefile index ce4e1af0..2e666462 100644 --- a/packages/system/bootbox/Makefile +++ b/packages/system/bootbox/Makefile @@ -1,7 +1,7 @@ export NAME=bootbox export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/bootbox/templates/bootbox.yaml b/packages/system/bootbox/templates/bootbox.yaml index 45cd07ce..fb0c8fe5 100644 --- a/packages/system/bootbox/templates/bootbox.yaml +++ b/packages/system/bootbox/templates/bootbox.yaml @@ -4,21 +4,16 @@ metadata: annotations: helm.sh/resource-policy: keep labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants apps.cozystack.io/application.kind: BootBox apps.cozystack.io/application.group: apps.cozystack.io apps.cozystack.io/application.name: bootbox name: bootbox namespace: tenant-root spec: - chart: - spec: - chart: bootbox - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-bootbox-application-default-bootbox + namespace: cozy-system interval: 1m0s timeout: 5m0s diff --git a/packages/system/bucket-rd/Makefile b/packages/system/bucket-rd/Makefile index 53e89367..259617e8 100644 --- a/packages/system/bucket-rd/Makefile +++ b/packages/system/bucket-rd/Makefile @@ -1,4 +1,4 @@ export NAME=bucket-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/bucket-rd/cozyrds/bucket.yaml b/packages/system/bucket-rd/cozyrds/bucket.yaml index 889a36b5..2a19f89e 100644 --- a/packages/system/bucket-rd/cozyrds/bucket.yaml +++ b/packages/system/bucket-rd/cozyrds/bucket.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: bucket spec: @@ -12,13 +12,11 @@ spec: release: prefix: bucket- labels: - cozystack.io/ui: "true" - chart: - name: bucket - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-bucket-application-default-bucket + namespace: cozy-system dashboard: singular: Bucket plural: Buckets diff --git a/packages/system/bucket/Makefile b/packages/system/bucket/Makefile index d555b71c..87944b28 100644 --- a/packages/system/bucket/Makefile +++ b/packages/system/bucket/Makefile @@ -2,8 +2,8 @@ S3MANAGER_TAG=v0.5.0 export NAME=s3manager-system -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: @echo Nothing to update diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index 1e12e68b..8ef294d1 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:3825c9b4b6238f88f1b0de73bd18866a7e5f83f178d28fe2830f3bf24efb187d +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:3013e13ba967070948653cc5b913a920dea93a24370b10731fafcfd8fb6a21b0 diff --git a/packages/system/capi-operator/Makefile b/packages/system/capi-operator/Makefile index dc421cee..9349f549 100644 --- a/packages/system/capi-operator/Makefile +++ b/packages/system/capi-operator/Makefile @@ -5,7 +5,7 @@ export REPO_URL=https://kubernetes-sigs.github.io/cluster-api-operator export CHART_NAME=cluster-api-operator export CHART_VERSION=^0.19 -include ../../../scripts/package.mk +include ../../../hack/package.mk update: clean capi-operator-update rm -rf charts/cluster-api-operator/charts/ diff --git a/packages/system/capi-providers-bootstrap/Makefile b/packages/system/capi-providers-bootstrap/Makefile index f588e439..54d8ca8b 100644 --- a/packages/system/capi-providers-bootstrap/Makefile +++ b/packages/system/capi-providers-bootstrap/Makefile @@ -1,4 +1,4 @@ export NAME=capi-providers-bootstrap export NAMESPACE=cozy-cluster-api -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/capi-providers-core/Makefile b/packages/system/capi-providers-core/Makefile index a9bae779..f5f038c1 100644 --- a/packages/system/capi-providers-core/Makefile +++ b/packages/system/capi-providers-core/Makefile @@ -1,4 +1,4 @@ export NAME=capi-providers-core export NAMESPACE=cozy-cluster-api -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/capi-providers-cpprovider/Makefile b/packages/system/capi-providers-cpprovider/Makefile index 06f0dd6d..caec8d96 100644 --- a/packages/system/capi-providers-cpprovider/Makefile +++ b/packages/system/capi-providers-cpprovider/Makefile @@ -1,4 +1,4 @@ export NAME=capi-providers-cpprovider export NAMESPACE=cozy-cluster-api -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/capi-providers-infraprovider/Makefile b/packages/system/capi-providers-infraprovider/Makefile index 8e4423f3..042a4f0e 100644 --- a/packages/system/capi-providers-infraprovider/Makefile +++ b/packages/system/capi-providers-infraprovider/Makefile @@ -1,4 +1,4 @@ export NAME=capi-providers-infraprovider export NAMESPACE=cozy-cluster-api -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/cert-manager-crds/Makefile b/packages/system/cert-manager-crds/Makefile index 0d665914..48e5644c 100644 --- a/packages/system/cert-manager-crds/Makefile +++ b/packages/system/cert-manager-crds/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/cert-manager-issuers/Makefile b/packages/system/cert-manager-issuers/Makefile index a7a6ce10..8808dbfd 100644 --- a/packages/system/cert-manager-issuers/Makefile +++ b/packages/system/cert-manager-issuers/Makefile @@ -1,4 +1,4 @@ export NAME=cert-manager-issuers export NAMESPACE=cozy-cert-manager -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/cert-manager/Makefile b/packages/system/cert-manager/Makefile index d48ad5be..2d256086 100644 --- a/packages/system/cert-manager/Makefile +++ b/packages/system/cert-manager/Makefile @@ -1,7 +1,7 @@ export NAME=cert-manager export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/cilium-networkpolicy/Makefile b/packages/system/cilium-networkpolicy/Makefile index c81b87e9..a24a54b5 100644 --- a/packages/system/cilium-networkpolicy/Makefile +++ b/packages/system/cilium-networkpolicy/Makefile @@ -1,5 +1,5 @@ export NAME=cilium-networkpolicy export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk diff --git a/packages/system/cilium/Makefile b/packages/system/cilium/Makefile index 4d1c6ae7..267c75cc 100644 --- a/packages/system/cilium/Makefile +++ b/packages/system/cilium/Makefile @@ -3,8 +3,8 @@ CILIUM_TAG=$(shell awk '$$1 == "version:" {print $$2}' charts/cilium/Chart.yaml) export NAME=cilium export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/cilium/charts/cilium/Chart.yaml b/packages/system/cilium/charts/cilium/Chart.yaml index 479d2347..0de0d9c7 100644 --- a/packages/system/cilium/charts/cilium/Chart.yaml +++ b/packages/system/cilium/charts/cilium/Chart.yaml @@ -79,7 +79,7 @@ annotations: Cilium Gateway Class Config\n description: |\n CiliumGatewayClassConfig defines a configuration for Gateway API GatewayClass.\n" apiVersion: v2 -appVersion: 1.18.5 +appVersion: 1.18.6 description: eBPF-based Networking, Security, and Observability home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg @@ -95,4 +95,4 @@ kubeVersion: '>= 1.21.0-0' name: cilium sources: - https://github.com/cilium/cilium -version: 1.18.5 +version: 1.18.6 diff --git a/packages/system/cilium/charts/cilium/README.md b/packages/system/cilium/charts/cilium/README.md index 4244e8e0..840d0126 100644 --- a/packages/system/cilium/charts/cilium/README.md +++ b/packages/system/cilium/charts/cilium/README.md @@ -1,6 +1,6 @@ # cilium -![Version: 1.18.5](https://img.shields.io/badge/Version-1.18.5-informational?style=flat-square) ![AppVersion: 1.18.5](https://img.shields.io/badge/AppVersion-1.18.5-informational?style=flat-square) +![Version: 1.18.6](https://img.shields.io/badge/Version-1.18.6-informational?style=flat-square) ![AppVersion: 1.18.6](https://img.shields.io/badge/AppVersion-1.18.6-informational?style=flat-square) Cilium is open source software for providing and transparently securing network connectivity and loadbalancing between application workloads such as @@ -85,7 +85,7 @@ contributors across the globe, there is almost always someone available to help. | authentication.mutual.spire.install.agent.tolerations | list | `[{"effect":"NoSchedule","key":"node.kubernetes.io/not-ready"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized","value":"true"},{"key":"CriticalAddonsOnly","operator":"Exists"}]` | SPIRE agent tolerations configuration By default it follows the same tolerations as the agent itself to allow the Cilium agent on this node to connect to SPIRE. ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | authentication.mutual.spire.install.enabled | bool | `true` | Enable SPIRE installation. This will only take effect only if authentication.mutual.spire.enabled is true | | authentication.mutual.spire.install.existingNamespace | bool | `false` | SPIRE namespace already exists. Set to true if Helm should not create, manage, and import the SPIRE namespace. | -| authentication.mutual.spire.install.initImage | object | `{"digest":"sha256:d80cd694d3e9467884fcb94b8ca1e20437d8a501096cdf367a5a1918a34fc2fd","override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/library/busybox","tag":"1.37.0","useDigest":true}` | init container image of SPIRE agent and server | +| authentication.mutual.spire.install.initImage | object | `{"digest":"sha256:2383baad1860bbe9d8a7a843775048fd07d8afe292b94bd876df64a69aae7cb1","override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/library/busybox","tag":"1.37.0","useDigest":true}` | init container image of SPIRE agent and server | | authentication.mutual.spire.install.namespace | string | `"cilium-spire"` | SPIRE namespace to install into | | authentication.mutual.spire.install.server.affinity | object | `{}` | SPIRE server affinity configuration | | authentication.mutual.spire.install.server.annotations | object | `{}` | SPIRE server annotations | @@ -205,7 +205,7 @@ contributors across the globe, there is almost always someone available to help. | clustermesh.apiserver.extraVolumeMounts | list | `[]` | Additional clustermesh-apiserver volumeMounts. | | clustermesh.apiserver.extraVolumes | list | `[]` | Additional clustermesh-apiserver volumes. | | clustermesh.apiserver.healthPort | int | `9880` | TCP port for the clustermesh-apiserver health API. | -| clustermesh.apiserver.image | object | `{"digest":"sha256:952f07c30390847e4d9dfaa19a76c4eca946251ffbc4f6459946570f93ee72f1","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.18.5","useDigest":true}` | Clustermesh API server image. | +| clustermesh.apiserver.image | object | `{"digest":"sha256:8ee142912a0e261850c0802d9256ddbe3729e1cd35c6bea2d93077f334c3cf3b","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.18.6","useDigest":true}` | Clustermesh API server image. | | clustermesh.apiserver.kvstoremesh.enabled | bool | `true` | Enable KVStoreMesh. KVStoreMesh caches the information retrieved from the remote clusters in the local etcd instance (deprecated - KVStoreMesh will always be enabled once the option is removed). | | clustermesh.apiserver.kvstoremesh.extraArgs | list | `[]` | Additional KVStoreMesh arguments. | | clustermesh.apiserver.kvstoremesh.extraEnv | list | `[]` | Additional KVStoreMesh environment variables. | @@ -394,7 +394,7 @@ contributors across the globe, there is almost always someone available to help. | envoy.httpRetryCount | int | `3` | Maximum number of retries for each HTTP request | | envoy.httpUpstreamLingerTimeout | string | `nil` | Time in seconds to block Envoy worker thread while an upstream HTTP connection is closing. If set to 0, the connection is closed immediately (with TCP RST). If set to -1, the connection is closed asynchronously in the background. | | envoy.idleTimeoutDurationSeconds | int | `60` | Set Envoy upstream HTTP idle connection timeout seconds. Does not apply to connections with pending requests. Default 60s | -| envoy.image | object | `{"digest":"sha256:3108521821c6922695ff1f6ef24b09026c94b195283f8bfbfc0fa49356a156e1","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.34.12-1765374555-6a93b0bbba8d6dc75b651cbafeedb062b2997716","useDigest":true}` | Envoy container image. | +| envoy.image | object | `{"digest":"sha256:81398e449f2d3d0a6a70527e4f641aaa685d3156bea0bb30712fae3fd8822b86","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9","useDigest":true}` | Envoy container image. | | envoy.initialFetchTimeoutSeconds | int | `30` | Time in seconds after which the initial fetch on an xDS stream is considered timed out | | envoy.livenessProbe.enabled | bool | `true` | Enable liveness probe for cilium-envoy | | envoy.livenessProbe.failureThreshold | int | `10` | failure threshold of liveness probe | @@ -535,7 +535,7 @@ contributors across the globe, there is almost always someone available to help. | hubble.relay.extraVolumes | list | `[]` | Additional hubble-relay volumes. | | hubble.relay.gops.enabled | bool | `true` | Enable gops for hubble-relay | | hubble.relay.gops.port | int | `9893` | Configure gops listen port for hubble-relay | -| hubble.relay.image | object | `{"digest":"sha256:17212962c92ff52384f94e407ffe3698714fcbd35c7575f67f24032d6224e446","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.18.5","useDigest":true}` | Hubble-relay container image. | +| hubble.relay.image | object | `{"digest":"sha256:fb6135e34c31e5f175cb5e75f86cea52ef2ff12b49bcefb7088ed93f5009eb8e","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.18.6","useDigest":true}` | Hubble-relay container image. | | hubble.relay.listenHost | string | `""` | Host to listen to. Specify an empty string to bind to all the interfaces. | | hubble.relay.listenPort | string | `"4245"` | Port to listen to. | | hubble.relay.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | @@ -647,7 +647,7 @@ contributors across the globe, there is almost always someone available to help. | identityAllocationMode | string | `"crd"` | Method to use for identity allocation (`crd`, `kvstore` or `doublewrite-readkvstore` / `doublewrite-readcrd` for migrating between identity backends). | | identityChangeGracePeriod | string | `"5s"` | Time to wait before using new identity on endpoint identity change. | | identityManagementMode | string | `"agent"` | Control whether CiliumIdentities are created by the agent ("agent"), the operator ("operator") or both ("both"). "Both" should be used only to migrate between "agent" and "operator". Operator-managed identities is a beta feature. | -| image | object | `{"digest":"sha256:2c92fb05962a346eaf0ce11b912ba434dc10bd54b9989e970416681f4a069628","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.18.5","useDigest":true}` | Agent container image. | +| image | object | `{"digest":"sha256:42ec562a5ff6c8a860c0639f5a7611685e253fd9eb2d2fcdade693724c9166a4","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.18.6","useDigest":true}` | Agent container image. | | imagePullSecrets | list | `[]` | Configure image pull secrets for pulling container images | | ingressController.default | bool | `false` | Set cilium ingress controller to be the default ingress controller This will let cilium ingress controller route entries without ingress class set | | ingressController.defaultSecretName | string | `nil` | Default secret name for ingresses without .spec.tls[].secretName set. | @@ -793,7 +793,7 @@ contributors across the globe, there is almost always someone available to help. | operator.hostNetwork | bool | `true` | HostNetwork setting | | operator.identityGCInterval | string | `"15m0s"` | Interval for identity garbage collection. | | operator.identityHeartbeatTimeout | string | `"30m0s"` | Timeout for identity heartbeats. | -| operator.image | object | `{"alibabacloudDigest":"sha256:2e60f635495eb2837296ced5475875c281a05765d5ddd644a05e126bbb080b3c","awsDigest":"sha256:7608025d8b727a10f21d924d8e4f40beb176cefd690320433452816ad8776f52","azureDigest":"sha256:126667e000267f893cb81042bf8a710ad2f219619eb9ce06e8949333bd325ac6","genericDigest":"sha256:36c3f6f14c8ced7f45b40b0a927639894b44269dd653f9528e7a0dc363a4eb99","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.18.5","useDigest":true}` | cilium-operator image. | +| operator.image | object | `{"alibabacloudDigest":"sha256:212c4cbe27da3772bcb952b8f8cbaa0b0eef72488b52edf90ad2b32072a3ca4c","awsDigest":"sha256:47dbc1a5bd483fec170dab7fb0bf2cca3585a4893675b0324d41d97bac8be5eb","azureDigest":"sha256:a57aff47aeb32eccfedaa2a49d1af984d996d6d6de79609c232e0c4cf9ce97a1","genericDigest":"sha256:34a827ce9ed021c8adf8f0feca131f53b3c54a3ef529053d871d0347ec4d69af","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.18.6","useDigest":true}` | cilium-operator image. | | operator.nodeGCInterval | string | `"5m0s"` | Interval for cilium node garbage collection. | | operator.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for cilium-operator pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | operator.podAnnotations | object | `{}` | Annotations to be added to cilium-operator pods | @@ -842,11 +842,11 @@ contributors across the globe, there is almost always someone available to help. | preflight.affinity | object | `{"podAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-preflight | | preflight.annotations | object | `{}` | Annotations to be added to all top-level preflight objects (resources under templates/cilium-preflight) | | preflight.enabled | bool | `false` | Enable Cilium pre-flight resources (required for upgrade) | -| preflight.envoy.image | object | `{"digest":"sha256:3108521821c6922695ff1f6ef24b09026c94b195283f8bfbfc0fa49356a156e1","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.34.12-1765374555-6a93b0bbba8d6dc75b651cbafeedb062b2997716","useDigest":true}` | Envoy pre-flight image. | +| preflight.envoy.image | object | `{"digest":"sha256:81398e449f2d3d0a6a70527e4f641aaa685d3156bea0bb30712fae3fd8822b86","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9","useDigest":true}` | Envoy pre-flight image. | | preflight.extraEnv | list | `[]` | Additional preflight environment variables. | | preflight.extraVolumeMounts | list | `[]` | Additional preflight volumeMounts. | | preflight.extraVolumes | list | `[]` | Additional preflight volumes. | -| preflight.image | object | `{"digest":"sha256:2c92fb05962a346eaf0ce11b912ba434dc10bd54b9989e970416681f4a069628","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.18.5","useDigest":true}` | Cilium pre-flight image. | +| preflight.image | object | `{"digest":"sha256:42ec562a5ff6c8a860c0639f5a7611685e253fd9eb2d2fcdade693724c9166a4","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.18.6","useDigest":true}` | Cilium pre-flight image. | | preflight.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for preflight pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | preflight.podAnnotations | object | `{}` | Annotations to be added to preflight pods | | preflight.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | diff --git a/packages/system/cilium/charts/cilium/templates/cilium-envoy/configmap.yaml b/packages/system/cilium/charts/cilium/templates/cilium-envoy/configmap.yaml index 91c981cb..4511e7ad 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-envoy/configmap.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-envoy/configmap.yaml @@ -1,5 +1,5 @@ {{- $envoyDS := eq (include "envoyDaemonSetEnabled" .) "true" -}} -{{- if $envoyDS }} +{{- if (and $envoyDS (not .Values.preflight.enabled)) }} --- apiVersion: v1 diff --git a/packages/system/cilium/charts/cilium/templates/cilium-preflight/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-preflight/daemonset.yaml index 17c39a41..b5418fe5 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-preflight/daemonset.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-preflight/daemonset.yaml @@ -213,9 +213,6 @@ spec: - name: envoy-artifacts mountPath: /var/run/cilium/envoy/artifacts readOnly: true - - name: envoy-config - mountPath: /var/run/cilium/envoy/ - readOnly: true {{- with .Values.preflight.resources }} resources: {{- toYaml . | trim | nindent 12 }} @@ -280,14 +277,6 @@ spec: hostPath: path: "{{ .Values.daemon.runPath }}/envoy/artifacts" type: DirectoryOrCreate - - name: envoy-config - configMap: - name: {{ .Values.envoy.bootstrapConfigMap | default "cilium-envoy-config" | quote }} - # note: the leading zero means this number is in octal representation: do not remove it - defaultMode: 0400 - items: - - key: bootstrap-config.json - path: bootstrap-config.json {{- end }} {{- with .Values.preflight.extraVolumes }} {{- toYaml . | nindent 6 }} diff --git a/packages/system/cilium/charts/cilium/values.yaml b/packages/system/cilium/charts/cilium/values.yaml index 5fac5be5..eff7f902 100644 --- a/packages/system/cilium/charts/cilium/values.yaml +++ b/packages/system/cilium/charts/cilium/values.yaml @@ -219,10 +219,10 @@ image: # @schema override: ~ repository: "quay.io/cilium/cilium" - tag: "v1.18.5" + tag: "v1.18.6" pullPolicy: "IfNotPresent" # cilium-digest - digest: sha256:2c92fb05962a346eaf0ce11b912ba434dc10bd54b9989e970416681f4a069628 + digest: sha256:42ec562a5ff6c8a860c0639f5a7611685e253fd9eb2d2fcdade693724c9166a4 useDigest: true # -- Scheduling configurations for cilium pods scheduling: @@ -1503,9 +1503,9 @@ hubble: # @schema override: ~ repository: "quay.io/cilium/hubble-relay" - tag: "v1.18.5" + tag: "v1.18.6" # hubble-relay-digest - digest: sha256:17212962c92ff52384f94e407ffe3698714fcbd35c7575f67f24032d6224e446 + digest: sha256:fb6135e34c31e5f175cb5e75f86cea52ef2ff12b49bcefb7088ed93f5009eb8e useDigest: true pullPolicy: "IfNotPresent" # -- Specifies the resources for the hubble-relay pods @@ -2465,9 +2465,9 @@ envoy: # @schema override: ~ repository: "quay.io/cilium/cilium-envoy" - tag: "v1.34.12-1765374555-6a93b0bbba8d6dc75b651cbafeedb062b2997716" + tag: "v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9" pullPolicy: "IfNotPresent" - digest: "sha256:3108521821c6922695ff1f6ef24b09026c94b195283f8bfbfc0fa49356a156e1" + digest: "sha256:81398e449f2d3d0a6a70527e4f641aaa685d3156bea0bb30712fae3fd8822b86" useDigest: true # -- Additional containers added to the cilium Envoy DaemonSet. extraContainers: [] @@ -2841,15 +2841,15 @@ operator: # @schema override: ~ repository: "quay.io/cilium/operator" - tag: "v1.18.5" + tag: "v1.18.6" # operator-generic-digest - genericDigest: sha256:36c3f6f14c8ced7f45b40b0a927639894b44269dd653f9528e7a0dc363a4eb99 + genericDigest: sha256:34a827ce9ed021c8adf8f0feca131f53b3c54a3ef529053d871d0347ec4d69af # operator-azure-digest - azureDigest: sha256:126667e000267f893cb81042bf8a710ad2f219619eb9ce06e8949333bd325ac6 + azureDigest: sha256:a57aff47aeb32eccfedaa2a49d1af984d996d6d6de79609c232e0c4cf9ce97a1 # operator-aws-digest - awsDigest: sha256:7608025d8b727a10f21d924d8e4f40beb176cefd690320433452816ad8776f52 + awsDigest: sha256:47dbc1a5bd483fec170dab7fb0bf2cca3585a4893675b0324d41d97bac8be5eb # operator-alibabacloud-digest - alibabacloudDigest: sha256:2e60f635495eb2837296ced5475875c281a05765d5ddd644a05e126bbb080b3c + alibabacloudDigest: sha256:212c4cbe27da3772bcb952b8f8cbaa0b0eef72488b52edf90ad2b32072a3ca4c useDigest: true pullPolicy: "IfNotPresent" suffix: "" @@ -3148,9 +3148,9 @@ preflight: # @schema override: ~ repository: "quay.io/cilium/cilium" - tag: "v1.18.5" + tag: "v1.18.6" # cilium-digest - digest: sha256:2c92fb05962a346eaf0ce11b912ba434dc10bd54b9989e970416681f4a069628 + digest: sha256:42ec562a5ff6c8a860c0639f5a7611685e253fd9eb2d2fcdade693724c9166a4 useDigest: true pullPolicy: "IfNotPresent" envoy: @@ -3161,9 +3161,9 @@ preflight: # @schema override: ~ repository: "quay.io/cilium/cilium-envoy" - tag: "v1.34.12-1765374555-6a93b0bbba8d6dc75b651cbafeedb062b2997716" + tag: "v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9" pullPolicy: "IfNotPresent" - digest: "sha256:3108521821c6922695ff1f6ef24b09026c94b195283f8bfbfc0fa49356a156e1" + digest: "sha256:81398e449f2d3d0a6a70527e4f641aaa685d3156bea0bb30712fae3fd8822b86" useDigest: true # -- The priority class to use for the preflight pod. priorityClassName: "" @@ -3317,9 +3317,9 @@ clustermesh: # @schema override: ~ repository: "quay.io/cilium/clustermesh-apiserver" - tag: "v1.18.5" + tag: "v1.18.6" # clustermesh-apiserver-digest - digest: sha256:952f07c30390847e4d9dfaa19a76c4eca946251ffbc4f6459946570f93ee72f1 + digest: sha256:8ee142912a0e261850c0802d9256ddbe3729e1cd35c6bea2d93077f334c3cf3b useDigest: true pullPolicy: "IfNotPresent" # -- TCP port for the clustermesh-apiserver health API. @@ -3849,7 +3849,7 @@ authentication: override: ~ repository: "docker.io/library/busybox" tag: "1.37.0" - digest: "sha256:d80cd694d3e9467884fcb94b8ca1e20437d8a501096cdf367a5a1918a34fc2fd" + digest: "sha256:2383baad1860bbe9d8a7a843775048fd07d8afe292b94bd876df64a69aae7cb1" useDigest: true pullPolicy: "IfNotPresent" # SPIRE agent configuration diff --git a/packages/system/cilium/images/cilium/Dockerfile b/packages/system/cilium/images/cilium/Dockerfile index 23c3d16a..ebe65c83 100644 --- a/packages/system/cilium/images/cilium/Dockerfile +++ b/packages/system/cilium/images/cilium/Dockerfile @@ -1,2 +1,2 @@ -ARG VERSION=v1.18.5 +ARG VERSION=v1.18.6 FROM quay.io/cilium/cilium:${VERSION} diff --git a/packages/system/cilium/values.yaml b/packages/system/cilium/values.yaml index 95159b1f..49a028f0 100644 --- a/packages/system/cilium/values.yaml +++ b/packages/system/cilium/values.yaml @@ -15,8 +15,8 @@ cilium: mode: "kubernetes" image: repository: ghcr.io/cozystack/cozystack/cilium - tag: 1.17.8 - digest: "sha256:81262986a41487bfa3d0465091d3a386def5bd1ab476350bd4af2fdee5846fe6" + tag: 1.18.6 + digest: "sha256:4f4585f8adc3b8becd15d3999f3900a4d3d650f2ab7f85ca8c661f3807113d01" envoy: enabled: false rollOutCiliumPods: true diff --git a/packages/system/clickhouse-operator/Makefile b/packages/system/clickhouse-operator/Makefile index e821b664..289631d6 100644 --- a/packages/system/clickhouse-operator/Makefile +++ b/packages/system/clickhouse-operator/Makefile @@ -1,7 +1,7 @@ export NAME=clickhouse-operator export NAMESPACE=cozy-clickhouse-operator -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/clickhouse-rd/Makefile b/packages/system/clickhouse-rd/Makefile index 4ac0738a..792ef31b 100644 --- a/packages/system/clickhouse-rd/Makefile +++ b/packages/system/clickhouse-rd/Makefile @@ -1,4 +1,4 @@ export NAME=clickhouse-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/clickhouse-rd/cozyrds/clickhouse.yaml b/packages/system/clickhouse-rd/cozyrds/clickhouse.yaml index 6948fce0..eb6c67f6 100644 --- a/packages/system/clickhouse-rd/cozyrds/clickhouse.yaml +++ b/packages/system/clickhouse-rd/cozyrds/clickhouse.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: clickhouse spec: @@ -12,13 +12,11 @@ spec: release: prefix: clickhouse- labels: - cozystack.io/ui: "true" - chart: - name: clickhouse - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-clickhouse-application-default-clickhouse + namespace: cozy-system dashboard: category: PaaS singular: ClickHouse diff --git a/packages/system/coredns/Makefile b/packages/system/coredns/Makefile index a610a862..4aca5b38 100644 --- a/packages/system/coredns/Makefile +++ b/packages/system/coredns/Makefile @@ -1,7 +1,7 @@ export NAME=coredns export NAMESPACE=kube-system -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/cozy-proxy/Makefile b/packages/system/cozy-proxy/Makefile index 8f4f6192..c1da95c7 100644 --- a/packages/system/cozy-proxy/Makefile +++ b/packages/system/cozy-proxy/Makefile @@ -1,8 +1,8 @@ NAME=cozy-proxy NAMESPACE=cozy-system -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/cozystack-api/Makefile b/packages/system/cozystack-api/Makefile index a3e0d931..c4e6f459 100644 --- a/packages/system/cozystack-api/Makefile +++ b/packages/system/cozystack-api/Makefile @@ -1,8 +1,8 @@ NAME=cozystack-api NAMESPACE=cozy-system -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk run-local: openssl req -nodes -new -x509 -keyout /tmp/ca.key -out /tmp/ca.crt -subj "/CN=kube-ca" diff --git a/packages/system/cozystack-api/templates/deployment.yaml b/packages/system/cozystack-api/templates/deployment.yaml index ee7e532f..aa877266 100644 --- a/packages/system/cozystack-api/templates/deployment.yaml +++ b/packages/system/cozystack-api/templates/deployment.yaml @@ -25,8 +25,10 @@ spec: - operator: Exists serviceAccountName: cozystack-api {{- if .Values.cozystackAPI.localK8sAPIEndpoint.enabled }} + {{- with .Values.cozystackAPI.nodeSelector }} nodeSelector: - node-role.kubernetes.io/control-plane: "" + {{- toYaml . | nindent 8 }} + {{- end }} {{- end }} containers: - name: cozystack-api diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index 8bf0a803..b5abfaec 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,5 +1,10 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v0.38.2@sha256:d17f1c59658731e5a2063c3db348adbc03b5cd31720052016b68449164cf2f14 + image: ghcr.io/cozystack/cozystack/cozystack-api:v1.0.0-beta.2@sha256:2815ee65d13e3bde376ca3975a1106e1e32b8b911f2004d85a824a9fc30eebbd localK8sAPIEndpoint: enabled: true replicas: 2 + # nodeSelector for DaemonSet mode (localK8sAPIEndpoint.enabled: true) + # Talos uses empty value: "node-role.kubernetes.io/control-plane": "" + # Generic k8s (k3s, kubeadm) uses: "node-role.kubernetes.io/control-plane": "true" + nodeSelector: + node-role.kubernetes.io/control-plane: "" diff --git a/packages/system/cozystack-basics/Chart.yaml b/packages/system/cozystack-basics/Chart.yaml new file mode 100644 index 00000000..8135baef --- /dev/null +++ b/packages/system/cozystack-basics/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-basics +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/cozystack-basics/Makefile b/packages/system/cozystack-basics/Makefile new file mode 100644 index 00000000..2d5f6c59 --- /dev/null +++ b/packages/system/cozystack-basics/Makefile @@ -0,0 +1,4 @@ +export NAME=tenant-root +export NAMESPACE=cozy-system + +include ../../../hack/package.mk diff --git a/packages/system/cozystack-basics/templates/cozy-public.yaml b/packages/system/cozystack-basics/templates/cozy-public.yaml new file mode 100644 index 00000000..b76816b4 --- /dev/null +++ b/packages/system/cozystack-basics/templates/cozy-public.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: cozy-public diff --git a/packages/system/cozystack-basics/templates/cozystack-values-secret.yaml b/packages/system/cozystack-basics/templates/cozystack-values-secret.yaml new file mode 100644 index 00000000..b625435f --- /dev/null +++ b/packages/system/cozystack-basics/templates/cozystack-values-secret.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: cozystack-values + namespace: tenant-root + labels: + reconcile.fluxcd.io/watch: Enabled +type: Opaque +stringData: + values.yaml: | + _cluster: + {{- .Values._cluster | toYaml | nindent 6 }} + _namespace: + host: {{ index .Values._cluster "root-host" | quote }} + etcd: tenant-root + ingress: tenant-root + monitoring: tenant-root + seaweedfs: tenant-root diff --git a/packages/system/cozystack-basics/templates/tenant-root.yaml b/packages/system/cozystack-basics/templates/tenant-root.yaml new file mode 100644 index 00000000..95af9d7f --- /dev/null +++ b/packages/system/cozystack-basics/templates/tenant-root.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: tenant-root +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + annotations: + helm.sh/resource-policy: keep + labels: + sharding.fluxcd.io/key: tenants + apps.cozystack.io/application.kind: Tenant + apps.cozystack.io/application.group: apps.cozystack.io + apps.cozystack.io/application.name: tenant-root + name: tenant-root + namespace: tenant-root +spec: + chartRef: + kind: ExternalArtifact + name: cozystack-tenant-application-default-tenant + namespace: cozy-system + interval: 1m0s + timeout: 5m0s + values: + _cluster: + oidc-enabled: {{ .Values.oidcEnabled | quote }} + root-host: {{ .Values.rootHost | quote }} diff --git a/packages/system/cozystack-basics/values.yaml b/packages/system/cozystack-basics/values.yaml new file mode 100644 index 00000000..b8b5e457 --- /dev/null +++ b/packages/system/cozystack-basics/values.yaml @@ -0,0 +1 @@ +_cluster: {} diff --git a/packages/system/cozystack-controller/Makefile b/packages/system/cozystack-controller/Makefile index 9bbfb5a6..d1cc1871 100644 --- a/packages/system/cozystack-controller/Makefile +++ b/packages/system/cozystack-controller/Makefile @@ -1,14 +1,15 @@ NAME=cozystack-controller NAMESPACE=cozy-system -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk -image: image-cozystack-controller update-version +image: image-cozystack-controller image-cozystack-controller: docker buildx build -f images/cozystack-controller/Dockerfile ../../.. \ --tag $(REGISTRY)/cozystack-controller:$(call settag,$(TAG)) \ + --build-arg VERSION=$(call settag,$(TAG)) \ --cache-from type=registry,ref=$(REGISTRY)/cozystack-controller:latest \ --cache-to type=inline \ --metadata-file images/cozystack-controller.json \ @@ -16,7 +17,3 @@ image-cozystack-controller: IMAGE="$(REGISTRY)/cozystack-controller:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/cozystack-controller.json -o json -r)" \ yq -i '.cozystackController.image = strenv(IMAGE)' values.yaml rm -f images/cozystack-controller.json - -update-version: - TAG="$(call settag,$(TAG))" \ - yq -i '.cozystackController.cozystackVersion = strenv(TAG)' values.yaml diff --git a/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile b/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile index bd6cfb38..ea475317 100644 --- a/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile +++ b/packages/system/cozystack-controller/images/cozystack-controller/Dockerfile @@ -2,6 +2,7 @@ FROM golang:1.25-alpine AS builder ARG TARGETOS ARG TARGETARCH +ARG VERSION=dev WORKDIR /workspace @@ -13,7 +14,9 @@ COPY pkg pkg/ COPY cmd cmd/ COPY internal internal/ -RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o /cozystack-controller cmd/cozystack-controller/main.go +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build \ + -ldflags="-extldflags=-static -X github.com/cozystack/cozystack/pkg/version.Version=${VERSION}" \ + -o /cozystack-controller cmd/cozystack-controller/main.go FROM scratch diff --git a/packages/system/cozystack-controller/templates/deployment.yaml b/packages/system/cozystack-controller/templates/deployment.yaml index 6dc21b1c..201aeb72 100644 --- a/packages/system/cozystack-controller/templates/deployment.yaml +++ b/packages/system/cozystack-controller/templates/deployment.yaml @@ -19,7 +19,6 @@ spec: - name: cozystack-controller image: "{{ .Values.cozystackController.image }}" args: - - --cozystack-version={{ .Values.cozystackController.cozystackVersion }} {{- if .Values.cozystackController.debug }} - --zap-log-level=debug {{- else }} diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index 1b365a43..7adbea35 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,6 +1,5 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.38.2@sha256:468b2eccbc0aa00bd3d72d56624a46e6ba178fa279cdd19248af74d32ea7d319 + image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.0.0-beta.2@sha256:3149c8341de741bce35de27591f72be82f22634ebc5dba8889b2bbae7892579a debug: false disableTelemetry: false - cozystackVersion: "v0.38.2" cozystackAPIKind: "DaemonSet" diff --git a/packages/system/cozystack-resource-definition-crd/Makefile b/packages/system/cozystack-resource-definition-crd/Makefile deleted file mode 100644 index ddb24aef..00000000 --- a/packages/system/cozystack-resource-definition-crd/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -export NAME=cozystack-resource-definition-crd -export NAMESPACE=cozy-system - -include ../../../scripts/package.mk diff --git a/packages/system/cozystack-resource-definition-crd/templates/crd.yaml b/packages/system/cozystack-resource-definition-crd/templates/crd.yaml deleted file mode 100644 index 40a93ad3..00000000 --- a/packages/system/cozystack-resource-definition-crd/templates/crd.yaml +++ /dev/null @@ -1,2 +0,0 @@ ---- -{{ .Files.Get "definition/cozystack.io_cozystackresourcedefinitions.yaml" }} diff --git a/packages/system/dashboard/Makefile b/packages/system/dashboard/Makefile index f89cba0d..a9f680a3 100644 --- a/packages/system/dashboard/Makefile +++ b/packages/system/dashboard/Makefile @@ -1,8 +1,8 @@ export NAME=dashboard export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: update-crd update-dockerfiles image: image-openapi-ui image-openapi-ui-k8s-bff image-token-proxy update-tenant-text diff --git a/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff b/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff new file mode 100644 index 00000000..03212014 --- /dev/null +++ b/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff @@ -0,0 +1,90 @@ +diff --git a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts +index 87a0f12..fb2e1cc 100644 +--- a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts ++++ b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts +@@ -134,22 +134,6 @@ export const prepare = ({ + // impossible in k8s + return {} + }) +- if (customFields.length > 0) { +- dataSource = dataSource.map((el: TJSON) => { +- const newFieldsForComplexJsonPath: Record = {} +- customFields.forEach(({ dataIndex, jsonPath }) => { +- const jpQueryResult = jp.query(el, `$${jsonPath}`) +- newFieldsForComplexJsonPath[dataIndex] = +- Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult +- }) +- if (typeof el === 'object') { +- return { ...el, ...newFieldsForComplexJsonPath } +- } +- // impossible in k8s +- return { ...newFieldsForComplexJsonPath } +- }) +- } +- + // Handle flatMap: expand rows for map objects + // Process all flatMap columns sequentially + if (flatMapColumns.length > 0 && dataSource) { +@@ -204,6 +188,62 @@ export const prepare = ({ + currentDataSource = expandedDataSource + }) + dataSource = currentDataSource ++ } ++ ++ if (customFields.length > 0) { ++ dataSource = dataSource.map((el: TJSON) => { ++ const newFieldsForComplexJsonPath: Record = {} ++ customFields.forEach(({ dataIndex, jsonPath }) => { ++ let fieldValue: TJSON = null ++ let handled = false ++ ++ const flatMapMatch = jsonPath.match(/^(.*)\[(_flatMap[^\]]+_Key)\](.*)$/) ++ if (flatMapMatch && el && typeof el === 'object' && !Array.isArray(el)) { ++ const basePath = flatMapMatch[1] ++ const keyField = flatMapMatch[2] ++ const tailPath = flatMapMatch[3] ++ const keyValue = (el as Record)[keyField] ++ if (keyValue !== null && keyValue !== undefined) { ++ const baseResult = jp.query(el, `$${basePath}`)[0] ++ if (baseResult && typeof baseResult === 'object' && !Array.isArray(baseResult)) { ++ const baseValue = (baseResult as Record)[String(keyValue)] ++ if (tailPath) { ++ const normalizedTailPath = ++ tailPath.startsWith('.') || tailPath.startsWith('[') ? tailPath : `.${tailPath}` ++ const tailResult = jp.query(baseValue, `$${normalizedTailPath}`) ++ fieldValue = Array.isArray(tailResult) && tailResult.length === 1 ? tailResult[0] : tailResult ++ } else { ++ fieldValue = baseValue as TJSON ++ } ++ handled = true ++ } ++ } ++ } ++ ++ if (!handled) { ++ let resolvedJsonPath = jsonPath ++ if (el && typeof el === 'object' && !Array.isArray(el)) { ++ resolvedJsonPath = jsonPath.replace(/\[(_flatMap[^\]]+_Key)\]/g, (match, keyField) => { ++ const keyValue = (el as Record)[keyField] ++ if (keyValue === null || keyValue === undefined) { ++ return match ++ } ++ const escaped = String(keyValue).replace(/'/g, "\\'") ++ return `['${escaped}']` ++ }) ++ } ++ const jpQueryResult = jp.query(el, `$${resolvedJsonPath}`) ++ fieldValue = Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult ++ } ++ ++ newFieldsForComplexJsonPath[dataIndex] = fieldValue ++ }) ++ if (typeof el === 'object') { ++ return { ...el, ...newFieldsForComplexJsonPath } ++ } ++ // impossible in k8s ++ return { ...newFieldsForComplexJsonPath } ++ }) + } + } else { + dataSource = dataItems.map((el: TJSON) => { diff --git a/packages/system/dashboard/templates/configmap.yaml b/packages/system/dashboard/templates/configmap.yaml index f148109f..c3ee0595 100644 --- a/packages/system/dashboard/templates/configmap.yaml +++ b/packages/system/dashboard/templates/configmap.yaml @@ -1,6 +1,6 @@ {{- $brandingConfig := .Values._cluster.branding | default dict }} -{{- $tenantText := "v0.38.2" }} +{{- $tenantText := "v1.0.0-beta.2" }} {{- $footerText := "Cozystack" }} {{- $titleText := "Cozystack Dashboard" }} {{- $logoText := "" }} diff --git a/packages/system/dashboard/templates/gatekeeper.yaml b/packages/system/dashboard/templates/gatekeeper.yaml index 40f2565f..984ec03e 100644 --- a/packages/system/dashboard/templates/gatekeeper.yaml +++ b/packages/system/dashboard/templates/gatekeeper.yaml @@ -64,6 +64,7 @@ spec: - --cookie-secure=true - --cookie-secret=$(OAUTH2_PROXY_COOKIE_SECRET) - --skip-provider-button + - --scope=openid email profile offline_access env: - name: OAUTH2_PROXY_CLIENT_ID value: dashboard diff --git a/packages/system/dashboard/templates/keycloakclient.yaml b/packages/system/dashboard/templates/keycloakclient.yaml index e1caea71..d8e47e8a 100644 --- a/packages/system/dashboard/templates/keycloakclient.yaml +++ b/packages/system/dashboard/templates/keycloakclient.yaml @@ -66,6 +66,12 @@ spec: defaultClientScopes: - groups - kubernetes-client + optionalClientScopes: + - offline_access + attributes: + post.logout.redirect.uris: "+" + client.session.idle.timeout: "86400" + client.session.max.lifespan: "604800" redirectUris: - "https://dashboard.{{ $host }}/oauth2/callback/*" {{- range $i, $v := $extraRedirectUris }} diff --git a/packages/system/dashboard/values.yaml b/packages/system/dashboard/values.yaml index fed8149b..b1eae64c 100644 --- a/packages/system/dashboard/values.yaml +++ b/packages/system/dashboard/values.yaml @@ -1,6 +1,6 @@ openapiUI: - image: ghcr.io/cozystack/cozystack/openapi-ui:v0.38.2@sha256:5aafb6c864c5523418d021a9fe5b514990d36972b6f1de9c34a1cd41f9d8bf7e + image: ghcr.io/cozystack/cozystack/openapi-ui:v1.0.0-beta.2@sha256:ed695cd89086df9bae6e3519bbcaeb2f26a36109f000dec4bc917bedcbd17d69 openapiUIK8sBff: - image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v0.38.2@sha256:7ffd8ae7b9da73fec7ae61a71c9c821a718d89a1b1df0197e09fda57678e1220 + image: ghcr.io/cozystack/cozystack/openapi-ui-k8s-bff:v1.0.0-beta.2@sha256:1f7827a1978bd9c81ac924dd0e78f6a3ce834a9a64af55047e220812bc15a944 tokenProxy: - image: ghcr.io/cozystack/cozystack/token-proxy:v0.38.2@sha256:fad27112617bb17816702571e1f39d0ac3fe5283468d25eb12f79906cdab566b + image: ghcr.io/cozystack/cozystack/token-proxy:v1.0.0-beta.2@sha256:063d34c25333e110dd7fad999279d4a5497e918723f1341991af48632b96ada1 diff --git a/packages/system/etcd-operator/Makefile b/packages/system/etcd-operator/Makefile index a2154952..54a1edad 100644 --- a/packages/system/etcd-operator/Makefile +++ b/packages/system/etcd-operator/Makefile @@ -1,7 +1,7 @@ export NAME=etcd-operator export NAMESPACE=cozy-${NAME} -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/etcd-rd/Makefile b/packages/system/etcd-rd/Makefile index ad91bad9..df993ae6 100644 --- a/packages/system/etcd-rd/Makefile +++ b/packages/system/etcd-rd/Makefile @@ -1,4 +1,4 @@ export NAME=etcd-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/etcd-rd/cozyrds/etcd.yaml b/packages/system/etcd-rd/cozyrds/etcd.yaml index 7381469d..49e25708 100644 --- a/packages/system/etcd-rd/cozyrds/etcd.yaml +++ b/packages/system/etcd-rd/cozyrds/etcd.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: etcd spec: @@ -12,14 +12,12 @@ spec: release: prefix: "" labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" - chart: - name: etcd - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public + chartRef: + kind: ExternalArtifact + name: cozystack-etcd-application-default-etcd + namespace: cozy-system dashboard: category: Administration singular: Etcd diff --git a/packages/system/external-dns/Makefile b/packages/system/external-dns/Makefile index 1ddfa773..5b0197e1 100644 --- a/packages/system/external-dns/Makefile +++ b/packages/system/external-dns/Makefile @@ -1,7 +1,7 @@ export NAME=external-dns export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/external-secrets-operator/Makefile b/packages/system/external-secrets-operator/Makefile index f4d9215d..0e1cd83a 100644 --- a/packages/system/external-secrets-operator/Makefile +++ b/packages/system/external-secrets-operator/Makefile @@ -1,7 +1,7 @@ export NAME=external-secrets-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/ferretdb-rd/Makefile b/packages/system/ferretdb-rd/Makefile index f6814169..1cc7ac30 100644 --- a/packages/system/ferretdb-rd/Makefile +++ b/packages/system/ferretdb-rd/Makefile @@ -1,4 +1,4 @@ export NAME=ferretdb-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/ferretdb-rd/cozyrds/ferretdb.yaml b/packages/system/ferretdb-rd/cozyrds/ferretdb.yaml index f7bdeb82..c54570a2 100644 --- a/packages/system/ferretdb-rd/cozyrds/ferretdb.yaml +++ b/packages/system/ferretdb-rd/cozyrds/ferretdb.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: ferretdb spec: @@ -12,13 +12,11 @@ spec: release: prefix: ferretdb- labels: - cozystack.io/ui: "true" - chart: - name: ferretdb - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-ferretdb-application-default-ferretdb + namespace: cozy-system dashboard: category: PaaS singular: FerretDB diff --git a/packages/system/flux-plunger/Chart.yaml b/packages/system/flux-plunger/Chart.yaml new file mode 100644 index 00000000..b87ca73a --- /dev/null +++ b/packages/system/flux-plunger/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: cozy-flux-plunger +description: Controller that automatically fixes HelmRelease resources with "has no deployed releases" error +type: application +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process +appVersion: "1.0.0" diff --git a/packages/system/flux-plunger/Makefile b/packages/system/flux-plunger/Makefile new file mode 100644 index 00000000..e1a561af --- /dev/null +++ b/packages/system/flux-plunger/Makefile @@ -0,0 +1,19 @@ +export NAME=flux-plunger +export NAMESPACE=cozy-fluxcd + +include ../../../scripts/common-envs.mk +include ../../../hack/package.mk + +image: + docker buildx build -f images/flux-plunger/Dockerfile ../../../ \ + --provenance false \ + --tag $(REGISTRY)/flux-plunger:$(call settag,$(TAG)) \ + --cache-from type=registry,ref=$(REGISTRY)/flux-plunger:latest \ + --cache-to type=inline \ + --metadata-file images/flux-plunger.json \ + --push=$(PUSH) \ + --label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" \ + --load=$(LOAD) + IMAGE="$(REGISTRY)/flux-plunger:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/flux-plunger.json -o json -r)" \ + yq -i '.image = strenv(IMAGE)' values.yaml + rm -f images/flux-plunger.json diff --git a/packages/system/flux-plunger/images/flux-plunger/Dockerfile b/packages/system/flux-plunger/images/flux-plunger/Dockerfile new file mode 100644 index 00000000..37821699 --- /dev/null +++ b/packages/system/flux-plunger/images/flux-plunger/Dockerfile @@ -0,0 +1,23 @@ +FROM golang:1.25-alpine AS builder + +ARG TARGETOS +ARG TARGETARCH + +WORKDIR /workspace + +COPY go.mod go.sum ./ +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go mod download + +COPY pkg pkg/ +COPY cmd cmd/ +COPY internal internal/ +COPY api api/ + +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o /flux-plunger cmd/flux-plunger/main.go + +FROM scratch + +COPY --from=builder /flux-plunger /flux-plunger +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt + +ENTRYPOINT ["/flux-plunger"] diff --git a/packages/system/flux-plunger/templates/deployment.yaml b/packages/system/flux-plunger/templates/deployment.yaml new file mode 100644 index 00000000..7ce6bb13 --- /dev/null +++ b/packages/system/flux-plunger/templates/deployment.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flux-plunger + labels: + app.kubernetes.io/name: flux-plunger + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: flux-plunger + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: flux-plunger + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + serviceAccountName: flux-plunger + containers: + - name: flux-plunger + image: "{{ .Values.image }}" + args: + {{- if .Values.debug }} + - --zap-log-level=debug + {{- else }} + - --zap-log-level=info + {{- end }} + - --metrics-bind-address=:8080 + - --metrics-secure=false + ports: + - name: metrics + containerPort: 8080 + - name: health + containerPort: 8081 + livenessProbe: + httpGet: + path: /healthz + port: health + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: health + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi diff --git a/packages/system/flux-plunger/templates/rbac.yaml b/packages/system/flux-plunger/templates/rbac.yaml new file mode 100644 index 00000000..97d4eac7 --- /dev/null +++ b/packages/system/flux-plunger/templates/rbac.yaml @@ -0,0 +1,37 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: flux-plunger +rules: +- apiGroups: + - helm.toolkit.fluxcd.io + resources: + - helmreleases + verbs: + - get + - list + - watch + - update + - patch +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: flux-plunger +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: flux-plunger +subjects: +- kind: ServiceAccount + name: flux-plunger + namespace: {{ .Release.Namespace }} diff --git a/packages/system/flux-plunger/templates/service.yaml b/packages/system/flux-plunger/templates/service.yaml new file mode 100644 index 00000000..69aa6afb --- /dev/null +++ b/packages/system/flux-plunger/templates/service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: flux-plunger + labels: + app.kubernetes.io/name: flux-plunger + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + selector: + app.kubernetes.io/name: flux-plunger + app.kubernetes.io/instance: {{ .Release.Name }} + ports: + - name: metrics + port: 8080 + targetPort: 8080 + - name: health + port: 8081 + targetPort: 8081 diff --git a/packages/system/flux-plunger/templates/serviceaccount.yaml b/packages/system/flux-plunger/templates/serviceaccount.yaml new file mode 100644 index 00000000..aff76a13 --- /dev/null +++ b/packages/system/flux-plunger/templates/serviceaccount.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + name: flux-plunger + labels: + app.kubernetes.io/name: flux-plunger + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/packages/system/flux-plunger/values.yaml b/packages/system/flux-plunger/values.yaml new file mode 100644 index 00000000..1da12610 --- /dev/null +++ b/packages/system/flux-plunger/values.yaml @@ -0,0 +1 @@ +image: "ghcr.io/cozystack/cozystack/flux-plunger:latest@sha256:6a6ec938973e6583c5e1573f7d25beddc1852a6699a089116b2407e29a564a72" diff --git a/packages/system/fluxcd-operator/Makefile b/packages/system/fluxcd-operator/Makefile index a603b85f..d9778f53 100644 --- a/packages/system/fluxcd-operator/Makefile +++ b/packages/system/fluxcd-operator/Makefile @@ -1,7 +1,7 @@ NAME=fluxcd-operator NAMESPACE=cozy-fluxcd -include ../../../scripts/package.mk +include ../../../hack/package.mk apply-locally: cozyhr apply --plain -n $(NAMESPACE) $(NAME) diff --git a/packages/system/fluxcd/Makefile b/packages/system/fluxcd/Makefile index 2c88b52d..9aa32fe9 100644 --- a/packages/system/fluxcd/Makefile +++ b/packages/system/fluxcd/Makefile @@ -1,7 +1,7 @@ NAME=fluxcd NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk apply-locally: cozyhr apply --plain -n $(NAMESPACE) $(NAME) diff --git a/packages/system/foundationdb-operator/Makefile b/packages/system/foundationdb-operator/Makefile index f735e7c5..16ca953f 100644 --- a/packages/system/foundationdb-operator/Makefile +++ b/packages/system/foundationdb-operator/Makefile @@ -1,7 +1,7 @@ export NAME=foundationdb-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/foundationdb-rd/Makefile b/packages/system/foundationdb-rd/Makefile index b6e6d41a..2b3b51c6 100644 --- a/packages/system/foundationdb-rd/Makefile +++ b/packages/system/foundationdb-rd/Makefile @@ -1,4 +1,4 @@ export NAME=foundationdb-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/foundationdb-rd/cozyrds/foundationdb.yaml b/packages/system/foundationdb-rd/cozyrds/foundationdb.yaml index e7759380..e6f23f79 100644 --- a/packages/system/foundationdb-rd/cozyrds/foundationdb.yaml +++ b/packages/system/foundationdb-rd/cozyrds/foundationdb.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: foundationdb spec: @@ -12,13 +12,11 @@ spec: release: prefix: foundationdb- labels: - cozystack.io/ui: "true" - chart: - name: foundationdb - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-foundationdb-application-default-foundationdb + namespace: cozy-system dashboard: category: PaaS singular: FoundationDB @@ -27,4 +25,4 @@ spec: tags: - database icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX3JhZGlhbF84NThfMzA3MikiLz4KPHBhdGggZD0iTTEzNS43ODQgNzUuNjQ0NkwxMzUuOTM5IDg3Ljc2MzhMODkuNjg0NiA4MS41MzYyTDYyLjA4NjggODQuNTA3OUwzNS4zNDE3IDgxLjQzMjlMOC43NTE2NyA4NC41ODU0TDguNzI1ODMgODEuNTEwNEwzNS4zNjc2IDc3LjU4MjZWNjQuMTcxM0w2Mi4yOTM1IDcwLjczNDhMNjIuMzQ1MiA4MS4yNzc4TDg5LjQ3NzkgNzcuNjg2TDg5LjQwMDQgNjQuMTk3MkwxMzUuNzg0IDc1LjY0NDZaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNODkuNDc3OCA4Ni4wMzI1TDEzNS44ODggOTAuODM4OFYxMDIuNzI2SDguNjQ4MjVMOC41MTkwNCA5OS41NzNIMzUuMjY0MUMzNS4yNjQxIDk5LjU3MyAzNS4yNjQxIDkwLjczNTUgMzUuMjY0MSA4Ni4wNTgzQzQ0LjI1NjcgODYuOTM2OSA2Mi4wODY3IDg4LjY5NDEgNjIuMDg2NyA4OC42OTQxVjk5LjI2MjlIODkuNDc3OFY4Ni4wMzI1WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTYyLjI5MzQgNjYuODg0Nkw2Mi4yMTU4IDYzLjYyODZDNjIuMjE1OCA2My42Mjg2IDc5LjgxMzMgNTguMzU3MSA4OC45MDkyIDU1LjY2OTdDODguOTA5MiA1MS4zMDI2IDg4LjkwOTIgNDcuMDkwNiA4OC45MDkyIDQyQzEwNC44NzkgNDguNDA4NSAxMjAuMjI4IDU0LjYxMDIgMTM1LjczMyA2MC44Mzc4QzEzNS43MzMgNjQuNzEzOSAxMzUuNzMzIDY4LjQzNSAxMzUuNzMzIDcyLjU2OTVDMTE5Ljg0MSA2OC4yMDI0IDEwNC4yODQgNjMuOTEyOSA4OS4xNjc2IDU5Ljc1MjVDNzkuOTY4NCA2Mi4yMDc0IDYyLjI5MzQgNjYuODg0NiA2Mi4yOTM0IDY2Ljg4NDZaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMzUuMzk2MiA4MS43MDczTDguODA2MTIgODQuODU5OEw4Ljc4MDI3IDgxLjc4NDhMMzUuNDIyIDc3Ljg1N1Y2NC40NDU3TDYyLjM0OCA3MS4wMDkzTDYyLjM5OTYgODEuNTUyMkw4OS41MzIzIDc3Ljk2MDRMODkuNDU0OCA2NC40NzE2TDEzNS44MzkgNzUuOTE5TDEzNS45OTQgODguMDM4Mkw4OS43MzkxIDgxLjgxMDZMNjIuMTQxMiA4NC43ODIzTDM1LjM5NjIgODEuNzA3M1oiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik04OS41MzIzIDg2LjMwNjlMMTM1Ljk0MiA5MS4xMTMzVjEwM0g4LjcwMjdMOC41NzM0OSA5OS44NDc0SDM1LjMxODZDMzUuMzE4NiA5OS44NDc0IDM1LjMxODYgOTEuMDA5OSAzNS4zMTg2IDg2LjMzMjhDNDQuMzExMSA4Ny4yMTE0IDYyLjE0MTIgODguOTY4NSA2Mi4xNDEyIDg4Ljk2ODVWOTkuNTM3M0g4OS41MzIzVjg2LjMwNjlaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNjIuMzQ4MyA2Ny4xNTlMNjIuMjcwOCA2My45MDMxQzYyLjI3MDggNjMuOTAzMSA3OS44NjgyIDU4LjYzMTYgODguOTY0MiA1NS45NDQyQzg4Ljk2NDIgNTEuNTc3MSA4OC45NjQyIDQ3LjM2NTEgODguOTY0MiA0Mi4yNzQ0QzEwNC45MzQgNDguNjgyOSAxMjAuMjgzIDU0Ljg4NDcgMTM1Ljc4NyA2MS4xMTIzQzEzNS43ODcgNjQuOTg4NCAxMzUuNzg3IDY4LjcwOTQgMTM1Ljc4NyA3Mi44NDM5QzExOS44OTUgNjguNDc2OSAxMDQuMzM5IDY0LjE4NzMgODkuMjIyNiA2MC4wMjdDODAuMDIzMyA2Mi40ODE4IDYyLjM0ODMgNjcuMTU5IDYyLjM0ODMgNjcuMTU5WiIgZmlsbD0id2hpdGUiLz4KPGRlZnM+CjxyYWRpYWxHcmFkaWVudCBpZD0icGFpbnQwX3JhZGlhbF84NThfMzA3MiIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSgtMjkuNSAtMTgpIHJvdGF0ZSgzOS42OTYzKSBzY2FsZSgzMDIuMTY4IDI3NS4yNzEpIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0JFRERGRiIvPgo8c3RvcCBvZmZzZXQ9IjAuMjU5NjE1IiBzdG9wLWNvbG9yPSIjOUVDQ0ZEIi8+CjxzdG9wIG9mZnNldD0iMC41OTEzNDYiIHN0b3AtY29sb3I9IiMzRjlBRkIiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMEI3MEUwIi8+CjwvcmFkaWFsR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg== - # keysOrder: [] + # keysOrder: [] diff --git a/packages/system/gateway-api-crds/Makefile b/packages/system/gateway-api-crds/Makefile index c4311662..ad51d591 100644 --- a/packages/system/gateway-api-crds/Makefile +++ b/packages/system/gateway-api-crds/Makefile @@ -1,7 +1,7 @@ export NAME=gateway-api-crds export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/packages/system/goldpinger/Makefile b/packages/system/goldpinger/Makefile index 3ddd79ba..0aeef2ad 100644 --- a/packages/system/goldpinger/Makefile +++ b/packages/system/goldpinger/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/gpu-operator/Makefile b/packages/system/gpu-operator/Makefile index 286451f3..49b26e26 100644 --- a/packages/system/gpu-operator/Makefile +++ b/packages/system/gpu-operator/Makefile @@ -1,8 +1,8 @@ export NAME=gpu-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/grafana-operator/Makefile b/packages/system/grafana-operator/Makefile index 82c734d4..34d36142 100644 --- a/packages/system/grafana-operator/Makefile +++ b/packages/system/grafana-operator/Makefile @@ -1,10 +1,22 @@ export NAME=grafana-operator export NAMESPACE=cozy-grafana-operator -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts mkdir -p charts curl -sSL https://github.com/grafana-operator/grafana-operator/archive/refs/heads/master.tar.gz | \ tar xzvf - --strip 3 -C charts grafana-operator-master/deploy/helm/grafana-operator + +image: + docker buildx build --file images/grafana-dashboards/Dockerfile ../../.. \ + --tag $(REGISTRY)/grafana-dashboards:$(call settag,$(TAG)) \ + --cache-from type=registry,ref=$(REGISTRY)/grafana-dashboards:latest \ + --cache-to type=inline \ + --metadata-file images/grafana-dashboards.json \ + $(BUILDX_ARGS) + echo "$(REGISTRY)/grafana-dashboards:$(call settag,$(TAG))@$$(yq --exit-status '.["containerimage.digest"]' images/grafana-dashboards.json --output-format json -r)" \ + > images/grafana-dashboards.tag + rm -f images/grafana-dashboards.json diff --git a/packages/system/grafana-operator/images/grafana-dashboards.tag b/packages/system/grafana-operator/images/grafana-dashboards.tag new file mode 100644 index 00000000..dd4b8a60 --- /dev/null +++ b/packages/system/grafana-operator/images/grafana-dashboards.tag @@ -0,0 +1 @@ +ghcr.io/cozystack/cozystack/grafana-dashboards:v1.0.0-beta.2@sha256:e866b5b3874b9d390b341183d2ee070e1387440c14cfe51af831695def6dc2ec diff --git a/packages/system/grafana-operator/images/grafana-dashboards/Dockerfile b/packages/system/grafana-operator/images/grafana-dashboards/Dockerfile new file mode 100644 index 00000000..8ea43e76 --- /dev/null +++ b/packages/system/grafana-operator/images/grafana-dashboards/Dockerfile @@ -0,0 +1,11 @@ +FROM alpine:3.22 + +RUN apk add --no-cache darkhttpd + +COPY dashboards /var/www/dashboards + +WORKDIR /var/www + +EXPOSE 8080 + +CMD ["darkhttpd", "/var/www/dashboards", "--port", "8080", "--addr", "0.0.0.0"] diff --git a/packages/system/grafana-operator/images/grafana-dashboards/Dockerfile.dockerignore b/packages/system/grafana-operator/images/grafana-dashboards/Dockerfile.dockerignore new file mode 100644 index 00000000..fa588871 --- /dev/null +++ b/packages/system/grafana-operator/images/grafana-dashboards/Dockerfile.dockerignore @@ -0,0 +1,3 @@ +# Exclude everything except dashboards directory +* +!dashboards/** diff --git a/packages/system/grafana-operator/templates/dashboards-deployment.yaml b/packages/system/grafana-operator/templates/dashboards-deployment.yaml new file mode 100644 index 00000000..f9b1f99b --- /dev/null +++ b/packages/system/grafana-operator/templates/dashboards-deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: grafana-dashboards + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grafana-dashboards + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: dashboards +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: grafana-dashboards + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: grafana-dashboards + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: dashboards + spec: + containers: + - name: dashboards + image: {{ $.Files.Get "images/grafana-dashboards.tag" | trim }} + ports: + - containerPort: 8080 + name: http + protocol: TCP + livenessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 diff --git a/packages/system/grafana-operator/templates/dashboards-service.yaml b/packages/system/grafana-operator/templates/dashboards-service.yaml new file mode 100644 index 00000000..011072c3 --- /dev/null +++ b/packages/system/grafana-operator/templates/dashboards-service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: grafana-dashboards + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: grafana-dashboards + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: dashboards +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 8080 + protocol: TCP + name: http + selector: + app.kubernetes.io/name: grafana-dashboards + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/packages/system/hetzner-robotlb/Makefile b/packages/system/hetzner-robotlb/Makefile index 9cd69463..c5ea0e4d 100644 --- a/packages/system/hetzner-robotlb/Makefile +++ b/packages/system/hetzner-robotlb/Makefile @@ -1,7 +1,7 @@ export NAME=hetzner-robotlb export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/http-cache-rd/Makefile b/packages/system/http-cache-rd/Makefile index cf367cf4..1d4b5be4 100644 --- a/packages/system/http-cache-rd/Makefile +++ b/packages/system/http-cache-rd/Makefile @@ -1,4 +1,4 @@ export NAME=http-cache-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/http-cache-rd/cozyrds/http-cache.yaml b/packages/system/http-cache-rd/cozyrds/http-cache.yaml index 70de0418..0fe2c9cf 100644 --- a/packages/system/http-cache-rd/cozyrds/http-cache.yaml +++ b/packages/system/http-cache-rd/cozyrds/http-cache.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: http-cache spec: @@ -12,13 +12,11 @@ spec: release: prefix: http-cache- labels: - cozystack.io/ui: "true" - chart: - name: http-cache - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-http-cache-application-default-http-cache + namespace: cozy-system dashboard: category: NaaS singular: HTTP Cache diff --git a/packages/system/info-rd/Makefile b/packages/system/info-rd/Makefile index 7cfed08d..15cf2513 100644 --- a/packages/system/info-rd/Makefile +++ b/packages/system/info-rd/Makefile @@ -1,4 +1,4 @@ export NAME=info-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/info-rd/cozyrds/info.yaml b/packages/system/info-rd/cozyrds/info.yaml index 43cda091..61016f01 100644 --- a/packages/system/info-rd/cozyrds/info.yaml +++ b/packages/system/info-rd/cozyrds/info.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: info spec: @@ -12,14 +12,12 @@ spec: release: prefix: "" labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" - chart: - name: info - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public + chartRef: + kind: ExternalArtifact + name: cozystack-info-application-default-info + namespace: cozy-system dashboard: name: info category: Administration diff --git a/packages/system/ingress-nginx/Makefile b/packages/system/ingress-nginx/Makefile index 9ad10ae1..573c253b 100644 --- a/packages/system/ingress-nginx/Makefile +++ b/packages/system/ingress-nginx/Makefile @@ -1,6 +1,6 @@ NAME=ingress-nginx-system -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/ingress-rd/Makefile b/packages/system/ingress-rd/Makefile index 82976cc6..be48593e 100644 --- a/packages/system/ingress-rd/Makefile +++ b/packages/system/ingress-rd/Makefile @@ -1,4 +1,4 @@ export NAME=ingress-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/ingress-rd/cozyrds/ingress.yaml b/packages/system/ingress-rd/cozyrds/ingress.yaml index 2e00f6ed..5743856f 100644 --- a/packages/system/ingress-rd/cozyrds/ingress.yaml +++ b/packages/system/ingress-rd/cozyrds/ingress.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: ingress spec: @@ -12,14 +12,12 @@ spec: release: prefix: "" labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" - chart: - name: ingress - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public + chartRef: + kind: ExternalArtifact + name: cozystack-ingress-application-default-ingress + namespace: cozy-system dashboard: category: Administration singular: Ingress diff --git a/packages/system/kafka-operator/Makefile b/packages/system/kafka-operator/Makefile index 32fa2207..0e4811e5 100644 --- a/packages/system/kafka-operator/Makefile +++ b/packages/system/kafka-operator/Makefile @@ -1,7 +1,7 @@ export NAME=kafka-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/kafka-rd/Makefile b/packages/system/kafka-rd/Makefile index 3c333dcf..f7d2b87d 100644 --- a/packages/system/kafka-rd/Makefile +++ b/packages/system/kafka-rd/Makefile @@ -1,4 +1,4 @@ export NAME=kafka-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/kafka-rd/cozyrds/kafka.yaml b/packages/system/kafka-rd/cozyrds/kafka.yaml index 7009d241..a4cc11e1 100644 --- a/packages/system/kafka-rd/cozyrds/kafka.yaml +++ b/packages/system/kafka-rd/cozyrds/kafka.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: kafka spec: @@ -12,13 +12,11 @@ spec: release: prefix: kafka- labels: - cozystack.io/ui: "true" - chart: - name: kafka - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-kafka-application-default-kafka + namespace: cozy-system dashboard: category: PaaS singular: Kafka diff --git a/packages/system/kamaji/Makefile b/packages/system/kamaji/Makefile index c24e2d4e..f82c4c7a 100644 --- a/packages/system/kamaji/Makefile +++ b/packages/system/kamaji/Makefile @@ -1,8 +1,8 @@ export NAME=kamaji export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/kamaji/images/kamaji/patches/increase-startup-probe-threshold.diff b/packages/system/kamaji/images/kamaji/patches/increase-startup-probe-threshold.diff new file mode 100644 index 00000000..1938c9f6 --- /dev/null +++ b/packages/system/kamaji/images/kamaji/patches/increase-startup-probe-threshold.diff @@ -0,0 +1,31 @@ +diff --git a/internal/builders/controlplane/deployment.go b/internal/builders/controlplane/deployment.go +index e7f0b88..d67a851 100644 +--- a/internal/builders/controlplane/deployment.go ++++ b/internal/builders/controlplane/deployment.go +@@ -376,7 +376,7 @@ func (d Deployment) buildScheduler(podSpec *corev1.PodSpec, tenantControlPlane k + TimeoutSeconds: 1, + PeriodSeconds: 10, + SuccessThreshold: 1, +- FailureThreshold: 3, ++ FailureThreshold: 30, + } + + switch { +@@ -469,7 +469,7 @@ func (d Deployment) buildControllerManager(podSpec *corev1.PodSpec, tenantContro + TimeoutSeconds: 1, + PeriodSeconds: 10, + SuccessThreshold: 1, +- FailureThreshold: 3, ++ FailureThreshold: 30, + } + switch { + case tenantControlPlane.Spec.ControlPlane.Deployment.Resources == nil: +@@ -600,7 +600,7 @@ func (d Deployment) buildKubeAPIServer(podSpec *corev1.PodSpec, tenantControlPla + TimeoutSeconds: 1, + PeriodSeconds: 10, + SuccessThreshold: 1, +- FailureThreshold: 3, ++ FailureThreshold: 30, + } + podSpec.Containers[index].ImagePullPolicy = corev1.PullAlways + // Volume mounts diff --git a/packages/system/kamaji/values.yaml b/packages/system/kamaji/values.yaml index b5b77213..f8f169f9 100644 --- a/packages/system/kamaji/values.yaml +++ b/packages/system/kamaji/values.yaml @@ -3,7 +3,7 @@ kamaji: deploy: false image: pullPolicy: IfNotPresent - tag: v0.38.2@sha256:13741b8f6dfede3ea0fd16d8bbebae810bc19254a81d7e5a139535efa17eabff + tag: v1.0.0-beta.2@sha256:d5f2fa2972ba33cd2ccb855256e4bda4734d7e250638811b77f2e0dc72ad6b19 repository: ghcr.io/cozystack/cozystack/kamaji resources: limits: @@ -13,4 +13,4 @@ kamaji: cpu: 100m memory: 100Mi extraArgs: - - --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v0.38.2@sha256:13741b8f6dfede3ea0fd16d8bbebae810bc19254a81d7e5a139535efa17eabff + - --migrate-image=ghcr.io/cozystack/cozystack/kamaji:v1.0.0-beta.2@sha256:d5f2fa2972ba33cd2ccb855256e4bda4734d7e250638811b77f2e0dc72ad6b19 diff --git a/packages/system/keycloak-configure/Makefile b/packages/system/keycloak-configure/Makefile index b9fd5c10..4cd5bd2e 100644 --- a/packages/system/keycloak-configure/Makefile +++ b/packages/system/keycloak-configure/Makefile @@ -1,5 +1,5 @@ export NAME=keycloak-configure export NAMESPACE=cozy-keycloak -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk diff --git a/packages/system/keycloak-configure/templates/configure-kk.yaml b/packages/system/keycloak-configure/templates/configure-kk.yaml index cc15b161..29afc6c0 100644 --- a/packages/system/keycloak-configure/templates/configure-kk.yaml +++ b/packages/system/keycloak-configure/templates/configure-kk.yaml @@ -5,12 +5,6 @@ {{- $existingKubeappsSecret := lookup "v1" "Secret" .Release.Namespace "kubeapps-client" }} {{- $existingAuthConfig := lookup "v1" "Secret" "cozy-dashboard" "kubeapps-auth-config" }} {{- $brandingConfig := .Values._cluster.branding | default dict }} - -{{ $branding := "" }} -{{- if $brandingConfig }} - {{- $branding = $brandingConfig.branding }} -{{- end }} - --- apiVersion: v1.edp.epam.com/v1alpha1 @@ -32,9 +26,15 @@ metadata: spec: realmName: cozy clusterKeycloakRef: keycloak-cozy - {{- if $branding }} - displayHtmlName: {{ $branding }} - displayName: {{ $branding }} + {{- if $brandingConfig }} + {{- if hasKey $brandingConfig "brandName" }} + displayName: {{ $brandingConfig.brandName }} + {{- end }} + {{- if hasKey $brandingConfig "brandHtmlName" }} + displayHtmlName: {{ $brandingConfig.brandHtmlName }} + {{- else if hasKey $brandingConfig "branding" }} + displayHtmlName: {{ $brandingConfig.branding }} + {{- end }} {{- end }} --- diff --git a/packages/system/keycloak-operator/Makefile b/packages/system/keycloak-operator/Makefile index a4f50b67..9c8d63c1 100644 --- a/packages/system/keycloak-operator/Makefile +++ b/packages/system/keycloak-operator/Makefile @@ -1,8 +1,8 @@ export NAME=keycloak-operator export NAMESPACE=cozy-keycloak -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/keycloak/Makefile b/packages/system/keycloak/Makefile index 62f4e98d..09afc864 100644 --- a/packages/system/keycloak/Makefile +++ b/packages/system/keycloak/Makefile @@ -1,5 +1,5 @@ export NAME=keycloak export NAMESPACE=cozy-keycloak -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk diff --git a/packages/system/kilo/Chart.yaml b/packages/system/kilo/Chart.yaml new file mode 100644 index 00000000..d533883e --- /dev/null +++ b/packages/system/kilo/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-kilo +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/kilo/Makefile b/packages/system/kilo/Makefile new file mode 100644 index 00000000..3d278db3 --- /dev/null +++ b/packages/system/kilo/Makefile @@ -0,0 +1,25 @@ +export NAME=kilo +export NAMESPACE=cozy-$(NAME) + +include ../../../hack/common-envs.mk +include ../../../hack/package.mk + +update: + wget https://raw.githubusercontent.com/squat/kilo/refs/heads/main/manifests/crds.yaml -O templates/crds.yaml + wget https://raw.githubusercontent.com/squat/kilo/refs/heads/main/manifests/kilo-typhoon-flannel.yaml -O templates/kilo.yaml + sed -i 's|kube-system|cozy-kilo|g' templates/kilo.yaml + sed -i 's|--compatibility=flannel|--compatibility=cilium|' templates/kilo.yaml + sed -i '/- --local=false/a \ - --mesh-granularity=full\n - --service-cidr=10.244.0.0/24\n - --service-cidr=10.96.0.0/24' templates/kilo.yaml + +image: + docker buildx build images/kilo \ + --tag $(REGISTRY)/kilo:$(call settag,$(TAG)) \ + --cache-from type=registry,ref=$(REGISTRY)/kilo:latest \ + --cache-to type=inline \ + --metadata-file images/kilo.json \ + $(BUILDX_ARGS) + REPOSITORY="$(REGISTRY)/kilo" \ + yq -i '.kilo.image.repository = strenv(REPOSITORY)' values.yaml + TAG=$(TAG)@$$(yq e '."containerimage.digest"' images/kilo.json -o json -r) \ + yq -i '.kilo.image.tag = strenv(TAG)' values.yaml + rm -f images/kilo.json diff --git a/packages/system/kilo/images/kilo/Dockerfile b/packages/system/kilo/images/kilo/Dockerfile new file mode 100644 index 00000000..b36a85d0 --- /dev/null +++ b/packages/system/kilo/images/kilo/Dockerfile @@ -0,0 +1,47 @@ +# Build the manager binary +ARG FROM=alpine +FROM $FROM AS cni +ARG GOARCH=amd64 +ARG CNI_PLUGINS_VERSION=v1.1.1 +RUN apk add --no-cache curl && \ + curl -Lo cni.tar.gz https://github.com/containernetworking/plugins/releases/download/$CNI_PLUGINS_VERSION/cni-plugins-linux-$GOARCH-$CNI_PLUGINS_VERSION.tgz && \ + tar -xf cni.tar.gz + +FROM golang:1.19.0 as builder + +ARG VERSION=0.6.0 +ARG TARGETOS +ARG TARGETARCH + +WORKDIR /workspace + +RUN curl -sSL https://github.com/squat/kilo/archive/refs/tags/${VERSION}.tar.gz | tar -xzvf- --strip=1 + +COPY patches /patches +RUN git apply /patches/*.diff + + +RUN set -eux; \ + GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 \ + go build -mod=vendor \ + -ldflags "-X github.com/squat/kilo/pkg/version.Version=$VERSION" \ + -o /out/kg \ + ./cmd/kg/... ; \ + GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 \ + go build -mod=vendor \ + -ldflags "-X github.com/squat/kilo/pkg/version.Version=$VERSION" \ + -o /out/kgctl \ + ./cmd/kgctl/... + +FROM alpine:3.20 +ARG GOARCH +ARG ALPINE_VERSION=v3.20 +LABEL maintainer="squat " +RUN echo -e "https://alpine.global.ssl.fastly.net/alpine/$ALPINE_VERSION/main\nhttps://alpine.global.ssl.fastly.net/alpine/$ALPINE_VERSION/community" > /etc/apk/repositories && \ + apk add --no-cache ipset iptables ip6tables graphviz font-noto +COPY --from=cni bridge host-local loopback portmap /opt/cni/bin/ +ADD https://raw.githubusercontent.com/kubernetes-sigs/iptables-wrappers/e139a115350974aac8a82ec4b815d2845f86997e/iptables-wrapper-installer.sh / +RUN chmod 700 /iptables-wrapper-installer.sh && /iptables-wrapper-installer.sh --no-sanity-check +COPY --from=builder /out/kg /opt/bin/ +COPY --from=builder /out/kgctl /opt/bin/ +ENTRYPOINT ["/opt/bin/kg"] \ No newline at end of file diff --git a/packages/system/kilo/images/kilo/patches/1.diff b/packages/system/kilo/images/kilo/patches/1.diff new file mode 100644 index 00000000..9597593e --- /dev/null +++ b/packages/system/kilo/images/kilo/patches/1.diff @@ -0,0 +1,246 @@ +diff --git a/cmd/kg/main.go b/cmd/kg/main.go +index c2ad6d5..301819f 100644 +--- a/cmd/kg/main.go ++++ b/cmd/kg/main.go +@@ -120,6 +120,7 @@ var ( + topologyLabel string + port int + serviceCIDRsRaw []string ++ internalCIDRsRaw []string + subnet string + resyncPeriod time.Duration + iptablesForwardRule bool +@@ -152,6 +153,7 @@ func init() { + cmd.Flags().StringVar(&topologyLabel, "topology-label", k8s.RegionLabelKey, "Kubernetes node label used to group nodes into logical locations.") + cmd.Flags().IntVar(&port, "port", mesh.DefaultKiloPort, "The port over which WireGuard peers should communicate.") + cmd.Flags().StringSliceVar(&serviceCIDRsRaw, "service-cidr", nil, "The service CIDR for the Kubernetes cluster. Can be provided optionally to avoid masquerading packets sent to service IPs. Can be specified multiple times.") ++ cmd.Flags().StringSliceVar(&internalCIDRsRaw, "internal-cidr", nil, "CIDRs to consider for internal IP auto-detection. If specified, only IPs within these CIDRs will be used. Can be specified multiple times.") + cmd.Flags().StringVar(&subnet, "subnet", mesh.DefaultKiloSubnet.String(), "CIDR from which to allocate addresses for WireGuard interfaces.") + cmd.Flags().DurationVar(&resyncPeriod, "resync-period", 30*time.Second, "How often should the Kilo controllers reconcile?") + cmd.Flags().BoolVar(&iptablesForwardRule, "iptables-forward-rules", false, "Add default accept rules to the FORWARD chain in iptables. Warning: this may break firewalls with a deny all policy and is potentially insecure!") +@@ -266,7 +268,16 @@ func runRoot(_ *cobra.Command, _ []string) error { + serviceCIDRs = append(serviceCIDRs, s) + } + +- m, err := mesh.New(b, enc, gr, hostname, port, s, local, cni, cniPath, iface, cleanUp, cleanUpIface, createIface, mtu, resyncPeriod, prioritisePrivateAddr, iptablesForwardRule, serviceCIDRs, log.With(logger, "component", "kilo"), registry) ++ var internalCIDRs []*net.IPNet ++ for _, internalCIDR := range internalCIDRsRaw { ++ _, s, err := net.ParseCIDR(internalCIDR) ++ if err != nil { ++ return fmt.Errorf("failed to parse %q as CIDR: %v", internalCIDR, err) ++ } ++ internalCIDRs = append(internalCIDRs, s) ++ } ++ ++ m, err := mesh.New(b, enc, gr, hostname, port, s, local, cni, cniPath, iface, cleanUp, cleanUpIface, createIface, mtu, resyncPeriod, prioritisePrivateAddr, iptablesForwardRule, internalCIDRs, serviceCIDRs, log.With(logger, "component", "kilo"), registry) + if err != nil { + return fmt.Errorf("failed to create Kilo mesh: %v", err) + } +diff --git a/manifests/kilo-bootkube-flannel.yaml b/manifests/kilo-bootkube-flannel.yaml +index 64e3500..fb3d25f 100644 +--- a/manifests/kilo-bootkube-flannel.yaml ++++ b/manifests/kilo-bootkube-flannel.yaml +@@ -74,11 +74,16 @@ spec: + - --cni=false + - --compatibility=flannel + - --local=false ++ - --internal-cidr=$(NODE_IP)/32 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName ++ - name: NODE_IP ++ valueFrom: ++ fieldRef: ++ fieldPath: status.hostIP + ports: + - containerPort: 1107 + name: metrics +diff --git a/manifests/kilo-k3s-cilium.yaml b/manifests/kilo-k3s-cilium.yaml +index d75c93c..c98e518 100644 +--- a/manifests/kilo-k3s-cilium.yaml ++++ b/manifests/kilo-k3s-cilium.yaml +@@ -106,11 +106,16 @@ spec: + - --encapsulate=crosssubnet + - --clean-up-interface=true + - --log-level=all ++ - --internal-cidr=$(NODE_IP)/32 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName ++ - name: NODE_IP ++ valueFrom: ++ fieldRef: ++ fieldPath: status.hostIP + ports: + - containerPort: 1107 + name: metrics +diff --git a/manifests/kilo-k3s-flannel.yaml b/manifests/kilo-k3s-flannel.yaml +index 612cb11..07b4c87 100644 +--- a/manifests/kilo-k3s-flannel.yaml ++++ b/manifests/kilo-k3s-flannel.yaml +@@ -103,11 +103,16 @@ spec: + - --cni=false + - --compatibility=flannel + - --local=false ++ - --internal-cidr=$(NODE_IP)/32 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName ++ - name: NODE_IP ++ valueFrom: ++ fieldRef: ++ fieldPath: status.hostIP + ports: + - containerPort: 1107 + name: metrics +diff --git a/manifests/kilo-kubeadm-cilium.yaml b/manifests/kilo-kubeadm-cilium.yaml +index 5bf065a..ac0bf90 100644 +--- a/manifests/kilo-kubeadm-cilium.yaml ++++ b/manifests/kilo-kubeadm-cilium.yaml +@@ -79,11 +79,16 @@ spec: + - --clean-up-interface=true + - --subnet=172.31.254.0/24 + - --log-level=all ++ - --internal-cidr=$(NODE_IP)/32 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName ++ - name: NODE_IP ++ valueFrom: ++ fieldRef: ++ fieldPath: status.hostIP + ports: + - containerPort: 1107 + name: metrics +diff --git a/manifests/kilo-kubeadm-flannel-userspace.yaml b/manifests/kilo-kubeadm-flannel-userspace.yaml +index c4ce25b..5d1824e 100644 +--- a/manifests/kilo-kubeadm-flannel-userspace.yaml ++++ b/manifests/kilo-kubeadm-flannel-userspace.yaml +@@ -88,11 +88,16 @@ spec: + - --cni=false + - --compatibility=flannel + - --local=false ++ - --internal-cidr=$(NODE_IP)/32 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName ++ - name: NODE_IP ++ valueFrom: ++ fieldRef: ++ fieldPath: status.hostIP + ports: + - containerPort: 1107 + name: metrics +diff --git a/manifests/kilo-kubeadm-flannel.yaml b/manifests/kilo-kubeadm-flannel.yaml +index fea35dc..ff6bb25 100644 +--- a/manifests/kilo-kubeadm-flannel.yaml ++++ b/manifests/kilo-kubeadm-flannel.yaml +@@ -74,11 +74,16 @@ spec: + - --cni=false + - --compatibility=flannel + - --local=false ++ - --internal-cidr=$(NODE_IP)/32 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName ++ - name: NODE_IP ++ valueFrom: ++ fieldRef: ++ fieldPath: status.hostIP + ports: + - containerPort: 1107 + name: metrics +diff --git a/manifests/kilo-typhoon-flannel.yaml b/manifests/kilo-typhoon-flannel.yaml +index 0e4d9b2..cbd467a 100644 +--- a/manifests/kilo-typhoon-flannel.yaml ++++ b/manifests/kilo-typhoon-flannel.yaml +@@ -74,11 +74,16 @@ spec: + - --cni=false + - --compatibility=flannel + - --local=false ++ - --internal-cidr=$(NODE_IP)/32 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName ++ - name: NODE_IP ++ valueFrom: ++ fieldRef: ++ fieldPath: status.hostIP + ports: + - containerPort: 1107 + name: metrics +diff --git a/pkg/mesh/discoverips.go b/pkg/mesh/discoverips.go +index c8991d9..4598472 100644 +--- a/pkg/mesh/discoverips.go ++++ b/pkg/mesh/discoverips.go +@@ -40,7 +40,8 @@ import ( + // - private IP assigned to interface of default route + // - private IP assigned to local interface + // - if no IP was found, return nil and an error. +-func getIP(hostname string, ignoreIfaces ...int) (*net.IPNet, *net.IPNet, error) { ++// If allowedCIDRs is not empty, only IPs within these CIDRs will be considered for private IP selection. ++func getIP(hostname string, allowedCIDRs []*net.IPNet, ignoreIfaces ...int) (*net.IPNet, *net.IPNet, error) { + ignore := make(map[string]struct{}) + for i := range ignoreIfaces { + if ignoreIfaces[i] == 0 { +@@ -144,6 +145,10 @@ func getIP(hostname string, ignoreIfaces ...int) (*net.IPNet, *net.IPNet, error) + if _, ok := ignore[tmpPriv[i].String()]; ok { + continue + } ++ // If allowedCIDRs is specified, filter private IPs by these CIDRs. ++ if len(allowedCIDRs) > 0 && !isInCIDRs(tmpPriv[i].IP, allowedCIDRs) { ++ continue ++ } + priv = append(priv, tmpPriv[i]) + } + for i := range tmpPub { +@@ -290,3 +295,13 @@ func defaultInterface() (*net.Interface, error) { + + return nil, errors.New("failed to find default route") + } ++ ++// isInCIDRs checks if the given IP is within any of the provided CIDRs. ++func isInCIDRs(ip net.IP, cidrs []*net.IPNet) bool { ++ for _, cidr := range cidrs { ++ if cidr.Contains(ip) { ++ return true ++ } ++ } ++ return false ++} +diff --git a/pkg/mesh/mesh.go b/pkg/mesh/mesh.go +index 3057d2a..e042467 100644 +--- a/pkg/mesh/mesh.go ++++ b/pkg/mesh/mesh.go +@@ -89,7 +89,7 @@ type Mesh struct { + } + + // New returns a new Mesh instance. +-func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularity, hostname string, port int, subnet *net.IPNet, local, cni bool, cniPath, iface string, cleanup bool, cleanUpIface bool, createIface bool, mtu uint, resyncPeriod time.Duration, prioritisePrivateAddr, iptablesForwardRule bool, serviceCIDRs []*net.IPNet, logger log.Logger, registerer prometheus.Registerer) (*Mesh, error) { ++func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularity, hostname string, port int, subnet *net.IPNet, local, cni bool, cniPath, iface string, cleanup bool, cleanUpIface bool, createIface bool, mtu uint, resyncPeriod time.Duration, prioritisePrivateAddr, iptablesForwardRule bool, allowedInternalCIDRs []*net.IPNet, serviceCIDRs []*net.IPNet, logger log.Logger, registerer prometheus.Registerer) (*Mesh, error) { + if err := os.MkdirAll(kiloPath, 0700); err != nil { + return nil, fmt.Errorf("failed to create directory to store configuration: %v", err) + } +@@ -134,7 +134,7 @@ func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularit + } + kiloIface = link.Attrs().Index + } +- privateIP, publicIP, err := getIP(hostname, kiloIface, enc.Index(), cniIndex) ++ privateIP, publicIP, err := getIP(hostname, allowedInternalCIDRs, kiloIface, enc.Index(), cniIndex) + if err != nil { + return nil, fmt.Errorf("failed to find public IP: %v", err) + } diff --git a/packages/system/kilo/images/kilo/patches/2.diff b/packages/system/kilo/images/kilo/patches/2.diff new file mode 100644 index 00000000..730c4469 --- /dev/null +++ b/packages/system/kilo/images/kilo/patches/2.diff @@ -0,0 +1,30 @@ +diff --git a/pkg/mesh/topology.go b/pkg/mesh/topology.go +index ca22bf6..1de8ae4 100644 +--- a/pkg/mesh/topology.go ++++ b/pkg/mesh/topology.go +@@ -263,17 +263,22 @@ CheckIPs: + } + } + // Check if allowed location IPs intersect with the allowed IPs. ++ // If the allowed location IP fully contains an allowed IP, that's fine - ++ // the more specific route will be used. Only warn if it's a partial overlap ++ // or if the allowed IP contains the allowed location IP. + for _, i := range s.allowedIPs { +- if intersect(ip, i) { ++ if intersect(ip, i) && !ip.Contains(i.IP) { + level.Warn(t.logger).Log("msg", "overlapping allowed location IPnet with allowed IPnets", "IP", ip.String(), "IP2", i.String(), "segment-location", s.location) + continue CheckIPs + } + } + // Check if allowed location IPs intersect with the private IPs of the segment. ++ // If the allowed location IP fully contains a private IP, that's fine. + for _, i := range s.privateIPs { + if ip.Contains(i) { +- level.Warn(t.logger).Log("msg", "overlapping allowed location IPnet with privateIP", "IP", ip.String(), "IP2", i.String(), "segment-location", s.location) +- continue CheckIPs ++ // This is OK - the allowed location IP contains the private IP, ++ // so the more specific route to the private IP will still work. ++ level.Debug(t.logger).Log("msg", "allowed location IPnet contains privateIP", "IP", ip.String(), "IP2", i.String(), "segment-location", s.location) + } + } + } diff --git a/packages/system/kilo/templates/configmap.yaml b/packages/system/kilo/templates/configmap.yaml new file mode 100644 index 00000000..36956984 --- /dev/null +++ b/packages/system/kilo/templates/configmap.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: kubeconfig-in-cluster + namespace: cozy-kilo +data: + kubeconfig: | + apiVersion: v1 + clusters: + - cluster: + certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + server: https://127.0.0.1:7445 + name: local + contexts: + - context: + cluster: local + user: service-account + name: local + current-context: local + kind: Config + users: + - name: service-account + user: + tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token \ No newline at end of file diff --git a/packages/system/kilo/templates/crds.yaml b/packages/system/kilo/templates/crds.yaml new file mode 100644 index 00000000..fdc3dee4 --- /dev/null +++ b/packages/system/kilo/templates/crds.yaml @@ -0,0 +1,93 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + creationTimestamp: null + name: peers.kilo.squat.ai +spec: + group: kilo.squat.ai + names: + kind: Peer + listKind: PeerList + plural: peers + singular: peer + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Peer is a WireGuard peer that should have access to the VPN. + 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 Kilo Peer. + More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status' + properties: + allowedIPs: + description: AllowedIPs is the list of IP addresses that are allowed + for the given peer's tunnel. + items: + type: string + type: array + endpoint: + description: Endpoint is the initial endpoint for connections to the + peer. + properties: + dnsOrIP: + description: DNSOrIP is a DNS name or an IP address. + properties: + dns: + description: DNS must be a valid RFC 1123 subdomain. + type: string + ip: + description: IP must be a valid IP address. + type: string + type: object + port: + description: Port must be a valid port number. + format: int32 + type: integer + required: + - dnsOrIP + - port + type: object + persistentKeepalive: + description: PersistentKeepalive is the interval in seconds of the + emission of keepalive packets by the peer. This defaults to 0, which + disables the feature. + type: integer + presharedKey: + description: PresharedKey is the optional symmetric encryption key + for the peer. + type: string + publicKey: + description: PublicKey is the WireGuard public key for the peer. + type: string + required: + - allowedIPs + - publicKey + type: object + required: + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/packages/system/kilo/templates/kilo.yaml b/packages/system/kilo/templates/kilo.yaml new file mode 100644 index 00000000..298c0400 --- /dev/null +++ b/packages/system/kilo/templates/kilo.yaml @@ -0,0 +1,89 @@ +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: kilo + namespace: cozy-kilo + labels: + app.kubernetes.io/name: kilo + app.kubernetes.io/part-of: kilo +spec: + selector: + matchLabels: + app.kubernetes.io/name: kilo + app.kubernetes.io/part-of: kilo + template: + metadata: + labels: + app.kubernetes.io/name: kilo + app.kubernetes.io/part-of: kilo + spec: + serviceAccountName: kilo + hostNetwork: true + containers: + - name: kilo + image: "{{ .Values.kilo.image.repository }}:{{ .Values.kilo.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.kilo.image.pullPolicy }} + args: + - --kubeconfig=/etc/kubernetes/kubeconfig + - --hostname=$(NODE_NAME) + - --cni=false + - --clean-up-interface={{ .Values.kilo.cleanUpInterface | default "false" }} + - --encapsulate=crosssubnet + - --local=false + - --mesh-granularity={{ .Values.kilo.meshGranularity | default "location" }} + {{- with .Values.kilo.podCIDR }} + - --service-cidr={{ . }} + {{- end }} + {{- with .Values.kilo.serviceCIDR }} + - --service-cidr={{ . }} + {{- end }} + {{- with .Values.kilo.transitCIDR }} + - --subnet={{ . }} + {{- end }} + - --internal-cidr=$(NODE_IP)/32 + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: NODE_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + ports: + - containerPort: 1107 + name: metrics + securityContext: + privileged: true + volumeMounts: + - name: kilo-dir + mountPath: /var/lib/kilo + - name: kubeconfig + mountPath: /etc/kubernetes + readOnly: true + - name: lib-modules + mountPath: /lib/modules + readOnly: true + - name: xtables-lock + mountPath: /run/xtables.lock + readOnly: false + tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + operator: Exists + volumes: + - name: kilo-dir + hostPath: + path: /var/lib/kilo + - name: kubeconfig + configMap: + name: kubeconfig-in-cluster + - name: lib-modules + hostPath: + path: /lib/modules + - name: xtables-lock + hostPath: + path: /run/xtables.lock + type: FileOrCreate diff --git a/packages/system/kilo/templates/rbac.yaml b/packages/system/kilo/templates/rbac.yaml new file mode 100644 index 00000000..73bc4786 --- /dev/null +++ b/packages/system/kilo/templates/rbac.yaml @@ -0,0 +1,45 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kilo + namespace: cozy-kilo +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kilo +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - list + - patch + - watch +- apiGroups: + - kilo.squat.ai + resources: + - peers + verbs: + - list + - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kilo +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kilo +subjects: + - kind: ServiceAccount + name: kilo + namespace: cozy-kilo \ No newline at end of file diff --git a/packages/system/kilo/values.yaml b/packages/system/kilo/values.yaml new file mode 100644 index 00000000..7bcfc55c --- /dev/null +++ b/packages/system/kilo/values.yaml @@ -0,0 +1,10 @@ +kilo: + image: + pullPolicy: IfNotPresent + tag: v1.0.0-beta.2@sha256:45ad01a89ebb5311735660a0d1a1df36eda4b6f960be1b6319d2b94d2a7db701 + repository: ghcr.io/cozystack/cozystack/kilo + podCIDR: 10.244.0.0/16 + serviceCIDR: 10.96.0.0/16 + transitCIDR: 100.66.0.0/16 + meshGranularity: location + cleanUpInterface: false diff --git a/packages/system/kubeovn-plunger/Makefile b/packages/system/kubeovn-plunger/Makefile index a80c7e06..f56d935b 100644 --- a/packages/system/kubeovn-plunger/Makefile +++ b/packages/system/kubeovn-plunger/Makefile @@ -1,8 +1,8 @@ export NAME=kubeovn-plunger export NAMESPACE=cozy-kubeovn -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk image: docker buildx build -f images/kubeovn-plunger/Dockerfile ../../../ \ diff --git a/packages/system/kubeovn-plunger/values.yaml b/packages/system/kubeovn-plunger/values.yaml index 2e6fc195..ed7c84dd 100644 --- a/packages/system/kubeovn-plunger/values.yaml +++ b/packages/system/kubeovn-plunger/values.yaml @@ -1,4 +1,4 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v0.38.2@sha256:76c8af24cbec0261718c13c0150aa81c238a956626d4fd7baa8970b47fb3a6f0 +image: ghcr.io/cozystack/cozystack/kubeovn-plunger:v1.0.0-beta.2@sha256:387fe9eca078edfb631511a091da9f2a7fcdc214867b4e2c269b55122a0f4ce7 ovnCentralName: ovn-central diff --git a/packages/system/kubeovn-webhook/Makefile b/packages/system/kubeovn-webhook/Makefile index 9134d55f..9b2e2744 100644 --- a/packages/system/kubeovn-webhook/Makefile +++ b/packages/system/kubeovn-webhook/Makefile @@ -1,8 +1,8 @@ export NAME=kubeovn-webhook export NAMESPACE=cozy-kubeovn -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk image: docker buildx build images/kubeovn-webhook \ diff --git a/packages/system/kubeovn-webhook/values.yaml b/packages/system/kubeovn-webhook/values.yaml index 9304c59d..244879e7 100644 --- a/packages/system/kubeovn-webhook/values.yaml +++ b/packages/system/kubeovn-webhook/values.yaml @@ -1,3 +1,3 @@ portSecurity: true routes: "" -image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.38.2@sha256:8e67b2971f8c079a8b0636be1d091a9545d6cb653d745ff222a5966f56f903bd +image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v1.0.0-beta.2@sha256:e18f9fd679e38f65362a8d0042f25468272f6d081136ad47027168d8e7e07a4a diff --git a/packages/system/kubeovn/Chart.yaml b/packages/system/kubeovn/Chart.yaml index d1532794..b1a4e05b 100644 --- a/packages/system/kubeovn/Chart.yaml +++ b/packages/system/kubeovn/Chart.yaml @@ -1,3 +1,3 @@ apiVersion: v2 name: cozy-kubeovn -version: 0.39.0 +version: 0.38.0 diff --git a/packages/system/kubeovn/Makefile b/packages/system/kubeovn/Makefile index a4a0d1ed..7e6d0d34 100644 --- a/packages/system/kubeovn/Makefile +++ b/packages/system/kubeovn/Makefile @@ -1,10 +1,10 @@ -KUBEOVN_TAG=v0.39.0 +KUBEOVN_TAG=v0.40.0 export NAME=kubeovn export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts values.yaml Chart.yaml diff --git a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml index f7be2d3b..0621c7c7 100644 --- a/packages/system/kubeovn/charts/kube-ovn/Chart.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/Chart.yaml @@ -15,12 +15,12 @@ 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: v1.14.11 +version: v1.14.25 # 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.14.11" +appVersion: "1.14.25" kubeVersion: ">= 1.29.0-0" diff --git a/packages/system/kubeovn/charts/kube-ovn/README.md b/packages/system/kubeovn/charts/kube-ovn/README.md index 3af408e6..74e5c3f1 100644 --- a/packages/system/kubeovn/charts/kube-ovn/README.md +++ b/packages/system/kubeovn/charts/kube-ovn/README.md @@ -2,6 +2,18 @@ Currently supported version: 1.9 +## Installing the Chart + +### From OCI Registry + +The Helm chart is available from GitHub Container Registry: + +```bash +helm install kube-ovn oci://ghcr.io/kubeovn/charts/kube-ovn --version v1.15.0 +``` + +### From Source + Installation : ```bash diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/_helpers.tpl b/packages/system/kubeovn/charts/kube-ovn/templates/_helpers.tpl index e6697c6e..fd6db240 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/_helpers.tpl +++ b/packages/system/kubeovn/charts/kube-ovn/templates/_helpers.tpl @@ -1,8 +1,10 @@ {{/* -Get IP-addresses of master nodes +Get IP-addresses of master nodes. If no nodes are returned, we assume this is +a dry-run/template call and return nothing. */}} {{- define "kubeovn.nodeIPs" -}} {{- $nodes := lookup "v1" "Node" "" "" -}} +{{- if $nodes -}} {{- $ips := list -}} {{- range $node := $nodes.items -}} {{- $label := splitList "=" $.Values.MASTER_NODES_LABEL }} @@ -25,6 +27,7 @@ Get IP-addresses of master nodes {{- end -}} {{ join "," $ips }} {{- end -}} +{{- end -}} {{/* Number of master nodes diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/central-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/central-deploy.yaml index bbc1e09d..505e0925 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/central-deploy.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/central-deploy.yaml @@ -39,7 +39,11 @@ spec: topologyKey: kubernetes.io/hostname priorityClassName: system-cluster-critical serviceAccountName: ovn-ovs + automountServiceAccountToken: true hostNetwork: true + securityContext: + seccompProfile: + type: RuntimeDefault initContainers: - name: hostpath-init image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml index 5c4587f9..219e4ca0 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/controller-deploy.yaml @@ -46,7 +46,11 @@ spec: topologyKey: kubernetes.io/hostname priorityClassName: system-cluster-critical serviceAccountName: ovn + automountServiceAccountToken: true hostNetwork: true + securityContext: + seccompProfile: + type: RuntimeDefault initContainers: - name: hostpath-init image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} @@ -70,19 +74,18 @@ spec: image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} imagePullPolicy: {{ .Values.image.pullPolicy }} args: - {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} - /kube-ovn/start-controller.sh - --default-ls={{ .Values.networking.DEFAULT_SUBNET }} - - --default-cidr={{ index $cozyConfig.data "ipv4-pod-cidr" }} - - --default-gateway={{ index $cozyConfig.data "ipv4-pod-gateway" }} + - --default-cidr={{ .Values.ipv4.POD_CIDR }} + - --default-gateway={{ .Values.ipv4.POD_GATEWAY }} - --default-gateway-check={{- .Values.func.CHECK_GATEWAY }} - --default-logical-gateway={{- .Values.func.LOGICAL_GATEWAY }} - --default-u2o-interconnection={{- .Values.func.U2O_INTERCONNECTION }} - --default-exclude-ips={{- .Values.networking.EXCLUDE_IPS }} - --cluster-router={{ .Values.networking.DEFAULT_VPC }} - --node-switch={{ .Values.networking.NODE_SUBNET }} - - --node-switch-cidr={{ index $cozyConfig.data "ipv4-join-cidr" }} - - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} + - --node-switch-cidr={{ .Values.ipv4.JOIN_CIDR }} + - --service-cluster-ip-range={{ .Values.ipv4.SVC_CIDR }} {{- if .Values.global.logVerbosity }} - --v={{ .Values.global.logVerbosity }} {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ic-controller-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ic-controller-deploy.yaml index ee3e1461..53ecfa24 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ic-controller-deploy.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ic-controller-deploy.yaml @@ -40,7 +40,11 @@ spec: topologyKey: kubernetes.io/hostname priorityClassName: system-cluster-critical serviceAccountName: ovn + automountServiceAccountToken: true hostNetwork: true + securityContext: + seccompProfile: + type: RuntimeDefault initContainers: - name: hostpath-init image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml index 3bddfbe1..78ac7d38 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml @@ -1200,6 +1200,52 @@ spec: required: - key - operator + tolerations: + description: optional tolerations applied to the workload pods + 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 + enum: + - NoSchedule + - PreferNoSchedule + - NoExecute + 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 + enum: + - Exists + - Equal + 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 --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -2871,6 +2917,8 @@ spec: type: array items: type: string + autoCreateVlanSubinterfaces: + type: boolean required: - defaultInterface status: diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/monitor-deploy.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/monitor-deploy.yaml index e4c3322c..dc4eac22 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/monitor-deploy.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/monitor-deploy.yaml @@ -37,7 +37,11 @@ spec: topologyKey: kubernetes.io/hostname priorityClassName: system-cluster-critical serviceAccountName: kube-ovn-app + automountServiceAccountToken: true hostNetwork: true + securityContext: + seccompProfile: + type: RuntimeDefault initContainers: - name: hostpath-init image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-dpdk-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-dpdk-ds.yaml index 9a1d591f..330c9b6f 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-dpdk-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-dpdk-ds.yaml @@ -27,8 +27,12 @@ spec: - operator: Exists priorityClassName: system-node-critical serviceAccountName: ovn-ovs + automountServiceAccountToken: true hostNetwork: true hostPID: true + securityContext: + seccompProfile: + type: RuntimeDefault containers: - name: openvswitch image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.DPDK_IMAGE_TAG }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-sa.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-sa.yaml index 1e5e9b5c..744b3b90 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovn-sa.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovn-sa.yaml @@ -3,6 +3,7 @@ kind: ServiceAccount metadata: name: ovn namespace: {{ .Values.namespace }} +automountServiceAccountToken: false {{- if .Values.global.registry.imagePullSecrets }} imagePullSecrets: {{- range $index, $secret := .Values.global.registry.imagePullSecrets }} @@ -18,6 +19,7 @@ kind: ServiceAccount metadata: name: ovn-ovs namespace: {{ .Values.namespace }} +automountServiceAccountToken: false {{- if .Values.global.registry.imagePullSecrets }} imagePullSecrets: {{- range $index, $secret := .Values.global.registry.imagePullSecrets }} @@ -33,6 +35,7 @@ kind: ServiceAccount metadata: name: kube-ovn-cni namespace: {{ .Values.namespace }} +automountServiceAccountToken: false {{- if .Values.global.registry.imagePullSecrets }} imagePullSecrets: {{- range $index, $secret := .Values.global.registry.imagePullSecrets }} @@ -48,6 +51,7 @@ kind: ServiceAccount metadata: name: kube-ovn-app namespace: {{ .Values.namespace }} +automountServiceAccountToken: false {{- if .Values.global.registry.imagePullSecrets }} imagePullSecrets: {{- range $index, $secret := .Values.global.registry.imagePullSecrets }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml index 947ec454..d53c06c2 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovncni-ds.yaml @@ -26,8 +26,12 @@ spec: operator: Exists priorityClassName: system-node-critical serviceAccountName: kube-ovn-cni + automountServiceAccountToken: true hostNetwork: true hostPID: true + securityContext: + seccompProfile: + type: RuntimeDefault initContainers: - name: hostpath-init image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} @@ -35,7 +39,9 @@ spec: command: - sh - -xec - - iptables -V + - | + chmod +t /usr/local/sbin + iptables -V securityContext: allowPrivilegeEscalation: true capabilities: @@ -60,16 +66,21 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} command: - /kube-ovn/install-cni.sh - - --cni-conf-dir={{ .Values.cni_conf.CNI_CONF_DIR }} + - --cni-conf-dir={{ .Values.cni_conf.MOUNT_CNI_CONF_DIR }} - --cni-conf-file={{ .Values.cni_conf.CNI_CONF_FILE }} - --cni-conf-name={{- .Values.cni_conf.CNI_CONFIG_PRIORITY -}}-kube-ovn.conflist + env: + - name: POD_IPS + valueFrom: + fieldRef: + fieldPath: status.podIPs securityContext: runAsUser: 0 privileged: true volumeMounts: - mountPath: /opt/cni/bin name: cni-bin - - mountPath: /etc/cni/net.d + - mountPath: {{ .Values.cni_conf.MOUNT_CNI_CONF_DIR }} name: cni-conf {{- if .Values.cni_conf.MOUNT_LOCAL_BIN_DIR }} - mountPath: /usr/local/bin @@ -83,12 +94,11 @@ spec: - bash - /kube-ovn/start-cniserver.sh args: - {{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }} - --enable-mirror={{- .Values.debug.ENABLE_MIRROR }} - --mirror-iface={{- .Values.debug.MIRROR_IFACE }} - --node-switch={{ .Values.networking.NODE_SUBNET }} - --encap-checksum=true - - --service-cluster-ip-range={{ index $cozyConfig.data "ipv4-svc-cidr" }} + - --service-cluster-ip-range={{ .Values.ipv4.SVC_CIDR }} {{- if .Values.global.logVerbosity }} - --v={{ .Values.global.logVerbosity }} {{- end }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml index 17743d5f..7146ec71 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/ovsovn-ds.yaml @@ -34,8 +34,12 @@ spec: operator: Exists priorityClassName: system-node-critical serviceAccountName: ovn-ovs + automountServiceAccountToken: true hostNetwork: true hostPID: true + securityContext: + seccompProfile: + type: RuntimeDefault initContainers: - name: hostpath-init image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} @@ -44,6 +48,7 @@ spec: - sh - -xec - | + chmod +t /usr/local/sbin chown -R nobody: /var/run/ovn /var/log/ovn /etc/openvswitch /var/run/openvswitch /var/log/openvswitch iptables -V {{- if not .Values.DISABLE_MODULES_MANAGEMENT }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/pinger-ds.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/pinger-ds.yaml index 66a34853..fbc82171 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/pinger-ds.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/pinger-ds.yaml @@ -28,7 +28,11 @@ spec: - key: CriticalAddonsOnly operator: Exists serviceAccountName: kube-ovn-app - hostPID: true + automountServiceAccountToken: true + hostPID: false + securityContext: + seccompProfile: + type: RuntimeDefault initContainers: - name: hostpath-init image: {{ .Values.global.registry.address }}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }} diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/post-delete-hook.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/post-delete-hook.yaml index a4c0d618..682b5a96 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/post-delete-hook.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/post-delete-hook.yaml @@ -9,6 +9,7 @@ metadata: "helm.sh/hook": post-delete "helm.sh/hook-weight": "1" "helm.sh/hook-delete-policy": hook-succeeded +automountServiceAccountToken: false --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -102,8 +103,11 @@ spec: hostNetwork: true nodeSelector: kubernetes.io/os: "linux" - serviceAccount: kube-ovn-post-delete-hook serviceAccountName: kube-ovn-post-delete-hook + automountServiceAccountToken: true + securityContext: + seccompProfile: + type: RuntimeDefault containers: - name: remove-subnet-finalizer image: "{{ .Values.global.registry.address}}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}" diff --git a/packages/system/kubeovn/charts/kube-ovn/templates/upgrade-ovs-ovn.yaml b/packages/system/kubeovn/charts/kube-ovn/templates/upgrade-ovs-ovn.yaml index fc5ac4ba..ab646e03 100644 --- a/packages/system/kubeovn/charts/kube-ovn/templates/upgrade-ovs-ovn.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/templates/upgrade-ovs-ovn.yaml @@ -11,6 +11,7 @@ metadata: "helm.sh/hook": post-upgrade "helm.sh/hook-weight": "1" "helm.sh/hook-delete-policy": hook-succeeded +automountServiceAccountToken: false --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -133,8 +134,11 @@ spec: hostNetwork: true nodeSelector: kubernetes.io/os: "linux" - serviceAccount: ovs-ovn-upgrade serviceAccountName: ovs-ovn-upgrade + automountServiceAccountToken: true + securityContext: + seccompProfile: + type: RuntimeDefault containers: - name: ovs-ovn-upgrade image: "{{ .Values.global.registry.address}}/{{ .Values.global.images.kubeovn.repository }}:{{ .Values.global.images.kubeovn.tag }}" diff --git a/packages/system/kubeovn/charts/kube-ovn/values.yaml b/packages/system/kubeovn/charts/kube-ovn/values.yaml index 3652386d..430ea428 100644 --- a/packages/system/kubeovn/charts/kube-ovn/values.yaml +++ b/packages/system/kubeovn/charts/kube-ovn/values.yaml @@ -9,7 +9,7 @@ global: kubeovn: repository: kube-ovn vpcRepository: vpc-nat-gateway - tag: v1.14.11 + tag: v1.14.25 support_arm: true thirdparty: true @@ -111,6 +111,7 @@ debug: cni_conf: CNI_CONFIG_PRIORITY: "01" CNI_CONF_DIR: "/etc/cni/net.d" + MOUNT_CNI_CONF_DIR: "/etc/cni/net.d" CNI_BIN_DIR: "/opt/cni/bin" CNI_CONF_FILE: "/kube-ovn/01-kube-ovn.conflist" LOCAL_BIN_DIR: "/usr/local/bin" diff --git a/packages/system/kubeovn/values.yaml b/packages/system/kubeovn/values.yaml index 89f20e7c..700960ee 100644 --- a/packages/system/kubeovn/values.yaml +++ b/packages/system/kubeovn/values.yaml @@ -65,4 +65,4 @@ global: images: kubeovn: repository: kubeovn - tag: v1.14.11@sha256:0e3e9db960a9600d58c33c0787cabd0e9bf263930fd8c9fe65417e258c383d01 + tag: v1.14.25@sha256:d0b29daaf36e81cac0f9fb15d0ea6b1b49f1abba81a14c73b88a2e60ffcc5978 diff --git a/packages/system/kubernetes-rd/Makefile b/packages/system/kubernetes-rd/Makefile index 45969603..2d38b5d3 100644 --- a/packages/system/kubernetes-rd/Makefile +++ b/packages/system/kubernetes-rd/Makefile @@ -1,4 +1,4 @@ export NAME=kubernetes-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/kubernetes-rd/cozyrds/kubernetes.yaml b/packages/system/kubernetes-rd/cozyrds/kubernetes.yaml index 05ed110f..1b4c7361 100644 --- a/packages/system/kubernetes-rd/cozyrds/kubernetes.yaml +++ b/packages/system/kubernetes-rd/cozyrds/kubernetes.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: kubernetes spec: @@ -8,17 +8,15 @@ spec: singular: kubernetes plural: kuberneteses openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"addons":{"description":"Cluster addons configuration.","type":"object","default":{},"required":["certManager","cilium","coredns","fluxcd","gatewayAPI","gpuOperator","ingressNginx","monitoringAgents","velero","verticalPodAutoscaler"],"properties":{"certManager":{"description":"Cert-manager addon.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable cert-manager.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"cilium":{"description":"Cilium CNI plugin.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"coredns":{"description":"CoreDNS addon.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"fluxcd":{"description":"FluxCD GitOps operator.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable FluxCD.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"gatewayAPI":{"description":"Gateway API addon.","type":"object","default":{},"required":["enabled"],"properties":{"enabled":{"description":"Enable Gateway API.","type":"boolean","default":false}}},"gpuOperator":{"description":"NVIDIA GPU Operator.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable GPU Operator.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"ingressNginx":{"description":"Ingress-NGINX controller.","type":"object","default":{},"required":["enabled","exposeMethod","valuesOverride"],"properties":{"enabled":{"description":"Enable the controller (requires nodes labeled `ingress-nginx`).","type":"boolean","default":false},"exposeMethod":{"description":"Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.","type":"string","default":"Proxied"},"hosts":{"description":"Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.","type":"array","default":[],"items":{"type":"string"}},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"monitoringAgents":{"description":"Monitoring agents.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable monitoring agents.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"velero":{"description":"Velero backup/restore addon.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable Velero.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"verticalPodAutoscaler":{"description":"Vertical Pod Autoscaler.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}}}},"controlPlane":{"description":"Kubernetes control-plane configuration.","type":"object","default":{},"required":["apiServer","controllerManager","konnectivity","replicas","scheduler"],"properties":{"apiServer":{"description":"API Server configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for API Server.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"medium","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"controllerManager":{"description":"Controller Manager configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Controller Manager.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"konnectivity":{"description":"Konnectivity configuration.","type":"object","default":{},"required":["server"],"properties":{"server":{"description":"Konnectivity Server configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Konnectivity.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}}}},"replicas":{"description":"Number of control-plane replicas.","type":"integer","default":2},"scheduler":{"description":"Scheduler configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Scheduler.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}}}},"host":{"description":"External hostname for Kubernetes cluster. Defaults to `.` if empty.","type":"string","default":""},"nodeGroups":{"description":"Worker nodes configuration map.","type":"object","default":{"md0":{"ephemeralStorage":"20Gi","gpus":[],"instanceType":"u1.medium","maxReplicas":10,"minReplicas":0,"resources":{},"roles":["ingress-nginx"]}},"additionalProperties":{"type":"object","required":["ephemeralStorage","instanceType","maxReplicas","minReplicas","resources"],"properties":{"ephemeralStorage":{"description":"Ephemeral storage size.","default":"20Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"gpus":{"description":"List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).","type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"description":"Name of GPU, such as \"nvidia.com/AD102GL_L40S\".","type":"string"}}}},"instanceType":{"description":"Virtual machine instance type.","type":"string","default":"u1.medium"},"maxReplicas":{"description":"Maximum number of replicas.","type":"integer","default":10},"minReplicas":{"description":"Minimum number of replicas.","type":"integer","default":0},"resources":{"description":"CPU and memory resources for each worker node.","type":"object","properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"roles":{"description":"List of node roles.","type":"array","items":{"type":"string"}}}}},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":"replicated"},"version":{"description":"Kubernetes major.minor version to deploy","type":"string","default":"v1.33","enum":["v1.33","v1.32","v1.31","v1.30","v1.29","v1.28"]}}} + {"title":"Chart Values","type":"object","properties":{"addons":{"description":"Cluster addons configuration.","type":"object","default":{},"required":["certManager","cilium","coredns","fluxcd","gatewayAPI","gpuOperator","ingressNginx","monitoringAgents","velero","verticalPodAutoscaler"],"properties":{"certManager":{"description":"Cert-manager addon.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable cert-manager.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"cilium":{"description":"Cilium CNI plugin.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"coredns":{"description":"CoreDNS addon.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"fluxcd":{"description":"FluxCD GitOps operator.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable FluxCD.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"gatewayAPI":{"description":"Gateway API addon.","type":"object","default":{},"required":["enabled"],"properties":{"enabled":{"description":"Enable Gateway API.","type":"boolean","default":false}}},"gpuOperator":{"description":"NVIDIA GPU Operator.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable GPU Operator.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"ingressNginx":{"description":"Ingress-NGINX controller.","type":"object","default":{},"required":["enabled","exposeMethod","valuesOverride"],"properties":{"enabled":{"description":"Enable the controller (requires nodes labeled `ingress-nginx`).","type":"boolean","default":false},"exposeMethod":{"description":"Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.","type":"string","default":"Proxied","enum":["Proxied","LoadBalancer"]},"hosts":{"description":"Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.","type":"array","default":[],"items":{"type":"string"}},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"monitoringAgents":{"description":"Monitoring agents.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable monitoring agents.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"velero":{"description":"Velero backup/restore addon.","type":"object","default":{},"required":["enabled","valuesOverride"],"properties":{"enabled":{"description":"Enable Velero.","type":"boolean","default":false},"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}},"verticalPodAutoscaler":{"description":"Vertical Pod Autoscaler.","type":"object","default":{},"required":["valuesOverride"],"properties":{"valuesOverride":{"description":"Custom Helm values overrides.","type":"object","default":{},"x-kubernetes-preserve-unknown-fields":true}}}}},"controlPlane":{"description":"Kubernetes control-plane configuration.","type":"object","default":{},"required":["apiServer","controllerManager","konnectivity","replicas","scheduler"],"properties":{"apiServer":{"description":"API Server configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for API Server.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"large","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"controllerManager":{"description":"Controller Manager configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Controller Manager.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"konnectivity":{"description":"Konnectivity configuration.","type":"object","default":{},"required":["server"],"properties":{"server":{"description":"Konnectivity Server configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Konnectivity.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}}}},"replicas":{"description":"Number of control-plane replicas.","type":"integer","default":2},"scheduler":{"description":"Scheduler configuration.","type":"object","default":{},"required":["resources","resourcesPreset"],"properties":{"resources":{"description":"CPU and memory resources for Scheduler.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Preset if `resources` omitted.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}}}},"host":{"description":"External hostname for Kubernetes cluster. Defaults to `.` if empty.","type":"string","default":""},"nodeGroups":{"description":"Worker nodes configuration map.","type":"object","default":{"md0":{"ephemeralStorage":"20Gi","gpus":[],"instanceType":"u1.medium","maxReplicas":10,"minReplicas":0,"resources":{},"roles":["ingress-nginx"]}},"additionalProperties":{"type":"object","required":["ephemeralStorage","instanceType","maxReplicas","minReplicas","resources"],"properties":{"ephemeralStorage":{"description":"Ephemeral storage size.","default":"20Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"gpus":{"description":"List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).","type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"description":"Name of GPU, such as \"nvidia.com/AD102GL_L40S\".","type":"string"}}}},"instanceType":{"description":"Virtual machine instance type.","type":"string","default":"u1.medium"},"maxReplicas":{"description":"Maximum number of replicas.","type":"integer","default":10},"minReplicas":{"description":"Minimum number of replicas.","type":"integer","default":0},"resources":{"description":"CPU and memory resources for each worker node.","type":"object","properties":{"cpu":{"description":"CPU available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"roles":{"description":"List of node roles.","type":"array","items":{"type":"string"}}}}},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":"replicated"},"version":{"description":"Kubernetes major.minor version to deploy","type":"string","default":"v1.33","enum":["v1.33","v1.32","v1.31","v1.30","v1.29","v1.28"]}}} release: prefix: kubernetes- labels: - cozystack.io/ui: "true" - chart: - name: kubernetes - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-kubernetes-application-kubevirt-kubernetes + namespace: cozy-system dashboard: category: IaaS singular: Kubernetes @@ -39,8 +37,12 @@ spec: include: - resourceNames: - kubernetes-{{ .name }} + - kubernetes-{{ .name }}-ingress-nginx + - matchLabels: + cluster.x-k8s.io/cluster-name: kubernetes-{{ .name }} ingresses: exclude: [] include: - resourceNames: - kubernetes-{{ .name }} + - kubernetes-{{ .name }}-ingress-nginx diff --git a/packages/system/kubevirt-cdi-operator/Makefile b/packages/system/kubevirt-cdi-operator/Makefile index 7022599f..7232216f 100644 --- a/packages/system/kubevirt-cdi-operator/Makefile +++ b/packages/system/kubevirt-cdi-operator/Makefile @@ -1,7 +1,7 @@ export NAME=kubevirt-cdi-operator export NAMESPACE=cozy-kubevirt-cdi -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/packages/system/kubevirt-cdi/Makefile b/packages/system/kubevirt-cdi/Makefile index 0b3791a1..709e4880 100644 --- a/packages/system/kubevirt-cdi/Makefile +++ b/packages/system/kubevirt-cdi/Makefile @@ -1,7 +1,7 @@ export NAME=kubevirt-cdi export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/packages/system/kubevirt-csi-node/values.yaml b/packages/system/kubevirt-csi-node/values.yaml index 8d2a7d45..8457b6d1 100644 --- a/packages/system/kubevirt-csi-node/values.yaml +++ b/packages/system/kubevirt-csi-node/values.yaml @@ -1,3 +1,3 @@ storageClass: replicated csiDriver: - image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:d5c836ba33cf5dbed7e6f866784f668f80ffe69179e7c75847b680111984eefb + image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:726d9287e8caaea94eaf24c4f44734e3fbf4f8aa032b66b81848ebf95297cffe diff --git a/packages/system/kubevirt-instancetypes/Makefile b/packages/system/kubevirt-instancetypes/Makefile index d0498f10..b9f84b83 100644 --- a/packages/system/kubevirt-instancetypes/Makefile +++ b/packages/system/kubevirt-instancetypes/Makefile @@ -1,7 +1,7 @@ export NAME=kubevirt-instancetypes export NAMESPACE=cozy-kubevirt -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/packages/system/kubevirt-operator/Makefile b/packages/system/kubevirt-operator/Makefile index 42bf80a7..69b6a692 100644 --- a/packages/system/kubevirt-operator/Makefile +++ b/packages/system/kubevirt-operator/Makefile @@ -1,7 +1,7 @@ export NAME=kubevirt-operator export NAMESPACE=cozy-kubevirt -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/packages/system/kubevirt/Makefile b/packages/system/kubevirt/Makefile index 2c2e57ab..246001d0 100644 --- a/packages/system/kubevirt/Makefile +++ b/packages/system/kubevirt/Makefile @@ -1,7 +1,7 @@ export NAME=kubevirt export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/packages/system/lineage-controller-webhook/Makefile b/packages/system/lineage-controller-webhook/Makefile index 04d81a12..d5bada31 100644 --- a/packages/system/lineage-controller-webhook/Makefile +++ b/packages/system/lineage-controller-webhook/Makefile @@ -1,8 +1,8 @@ NAME=lineage-controller-webhook NAMESPACE=cozy-system -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk image: image-lineage-controller-webhook diff --git a/packages/system/lineage-controller-webhook/templates/daemonset.yaml b/packages/system/lineage-controller-webhook/templates/daemonset.yaml index b6b73ac7..860aee6e 100644 --- a/packages/system/lineage-controller-webhook/templates/daemonset.yaml +++ b/packages/system/lineage-controller-webhook/templates/daemonset.yaml @@ -13,8 +13,10 @@ spec: labels: app: lineage-controller-webhook spec: + {{- with .Values.lineageControllerWebhook.nodeSelector }} nodeSelector: - node-role.kubernetes.io/control-plane: "" + {{- toYaml . | nindent 8 }} + {{- end }} tolerations: - operator: Exists serviceAccountName: lineage-controller-webhook diff --git a/packages/system/lineage-controller-webhook/values.yaml b/packages/system/lineage-controller-webhook/values.yaml index ab5ccbbf..6c19c22b 100644 --- a/packages/system/lineage-controller-webhook/values.yaml +++ b/packages/system/lineage-controller-webhook/values.yaml @@ -1,5 +1,10 @@ lineageControllerWebhook: - image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v0.38.2@sha256:a5c750a0f46e8e25329b3ee2110d5dfb077c73e473195f1ed768d28d6f43902c + image: ghcr.io/cozystack/cozystack/lineage-controller-webhook:v1.0.0-beta.2@sha256:e2ffc29d244b9b5916ab048c338a8f284a47b0f4bd00e903dcf36df2a0299b72 debug: false localK8sAPIEndpoint: enabled: true + # nodeSelector for the DaemonSet + # Talos uses empty value: "node-role.kubernetes.io/control-plane": "" + # Generic k8s (k3s, kubeadm) uses: "node-role.kubernetes.io/control-plane": "true" + nodeSelector: + node-role.kubernetes.io/control-plane: "" diff --git a/packages/system/linstor-scheduler/Makefile b/packages/system/linstor-scheduler/Makefile index 90a31bc8..79b50c28 100644 --- a/packages/system/linstor-scheduler/Makefile +++ b/packages/system/linstor-scheduler/Makefile @@ -1,7 +1,7 @@ export NAME=linstor-scheduler export NAMESPACE=cozy-linstor -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/linstor-scheduler/charts/linstor-scheduler/templates/_helpers.tpl b/packages/system/linstor-scheduler/charts/linstor-scheduler/templates/_helpers.tpl index ad24453b..04c793f9 100644 --- a/packages/system/linstor-scheduler/charts/linstor-scheduler/templates/_helpers.tpl +++ b/packages/system/linstor-scheduler/charts/linstor-scheduler/templates/_helpers.tpl @@ -62,10 +62,12 @@ Create the name of the service account to use {{- end }} {{/* -Get the kubernetes version we should assume for creating scheduler configs +Get the kubernetes version we should assume for creating scheduler configs. +Strips distribution suffixes like +k3s1, +rke2r1 from version string. */}} {{- define "linstor-scheduler.kubeVersion" }} -{{- .Values.scheduler.image.compatibleKubernetesRelease | default .Capabilities.KubeVersion.Version }} +{{- $version := .Values.scheduler.image.compatibleKubernetesRelease | default .Capabilities.KubeVersion.Version }} +{{- regexReplaceAll "\\+.*$" $version "" }} {{- end }} {{/* diff --git a/packages/system/linstor-scheduler/charts/linstor-scheduler/templates/deployment.yaml b/packages/system/linstor-scheduler/charts/linstor-scheduler/templates/deployment.yaml index 49898b8d..ea43cb83 100644 --- a/packages/system/linstor-scheduler/charts/linstor-scheduler/templates/deployment.yaml +++ b/packages/system/linstor-scheduler/charts/linstor-scheduler/templates/deployment.yaml @@ -30,7 +30,7 @@ spec: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: kube-scheduler - image: "{{ .Values.scheduler.image.repository }}:{{ .Values.scheduler.image.tag | default .Capabilities.KubeVersion.Version }}" + image: "{{ .Values.scheduler.image.repository }}:{{ .Values.scheduler.image.tag | default (include "linstor-scheduler.kubeVersion" .) }}" securityContext: {{- toYaml .Values.scheduler.securityContext | nindent 12 }} command: diff --git a/packages/system/linstor/Makefile b/packages/system/linstor/Makefile index da895085..b211baec 100644 --- a/packages/system/linstor/Makefile +++ b/packages/system/linstor/Makefile @@ -1,12 +1,15 @@ export NAME=linstor export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk LINSTOR_VERSION ?= 1.32.3 +LINSTOR_CSI_VERSION ?= v1.10.5 -image: +image: image-piraeus-server image-linstor-csi + +image-piraeus-server: docker buildx build images/piraeus-server \ --build-arg LINSTOR_VERSION=$(LINSTOR_VERSION) \ --build-arg K8S_AWAIT_ELECTION_VERSION=v0.4.2 \ @@ -21,3 +24,18 @@ image: TAG="$(call settag,$(LINSTOR_VERSION))@$$(yq e '."containerimage.digest"' images/piraeus-server.json -o json -r)" \ yq -i '.piraeusServer.image.tag = strenv(TAG)' values.yaml rm -f images/piraeus-server.json + +image-linstor-csi: + docker buildx build images/linstor-csi \ + --build-arg VERSION=$(LINSTOR_CSI_VERSION) \ + --tag $(REGISTRY)/linstor-csi:$(call settag,$(LINSTOR_CSI_VERSION)) \ + --tag $(REGISTRY)/linstor-csi:$(call settag,$(LINSTOR_CSI_VERSION)-$(TAG)) \ + --cache-from type=registry,ref=$(REGISTRY)/linstor-csi:latest \ + --cache-to type=inline \ + --metadata-file images/linstor-csi.json \ + $(BUILDX_ARGS) + REPOSITORY="$(REGISTRY)/linstor-csi" \ + yq -i '.linstorCSI.image.repository = strenv(REPOSITORY)' values.yaml + TAG="$(call settag,$(LINSTOR_CSI_VERSION))@$$(yq e '."containerimage.digest"' images/linstor-csi.json -o json -r)" \ + yq -i '.linstorCSI.image.tag = strenv(TAG)' values.yaml + rm -f images/linstor-csi.json diff --git a/packages/system/linstor/images/linstor-csi/Dockerfile b/packages/system/linstor/images/linstor-csi/Dockerfile new file mode 100644 index 00000000..6cfd44aa --- /dev/null +++ b/packages/system/linstor/images/linstor-csi/Dockerfile @@ -0,0 +1,36 @@ +FROM golang:1.25 AS builder + +ARG VERSION=v1.10.5 +ARG LINSTOR_WAIT_UNTIL_VERSION=v0.3.1 +ARG TARGETARCH +ARG TARGETOS + +WORKDIR /src + +RUN curl -sSL https://github.com/piraeusdatastore/linstor-csi/archive/refs/tags/${VERSION}.tar.gz | tar -xzvf- --strip=1 + +COPY patches /patches +RUN git apply /patches/*.diff + +RUN go mod download + +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 \ + go build \ + -a \ + -ldflags "-X github.com/piraeusdatastore/linstor-csi/pkg/driver.Version=$VERSION -extldflags -static" \ + -o /linstor-csi \ + ./cmd/linstor-csi/linstor-csi.go + +RUN curl -fsSL https://github.com/LINBIT/linstor-wait-until/releases/download/$LINSTOR_WAIT_UNTIL_VERSION/linstor-wait-until-$LINSTOR_WAIT_UNTIL_VERSION-$TARGETOS-$TARGETARCH.tar.gz | tar xvzC / + +FROM debian:trixie-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + xfsprogs e2fsprogs nfs-common \ + && apt-get clean && rm -rf /var/lib/apt/lists/* \ + && ln -sf /proc/mounts /etc/mtab + +COPY --from=builder /linstor-csi / +COPY --from=builder /linstor-wait-until /linstor-wait-until + +ENTRYPOINT ["/linstor-csi"] diff --git a/packages/system/linstor/images/linstor-csi/patches/001-rwx-validation.diff b/packages/system/linstor/images/linstor-csi/patches/001-rwx-validation.diff new file mode 100644 index 00000000..7da0f137 --- /dev/null +++ b/packages/system/linstor/images/linstor-csi/patches/001-rwx-validation.diff @@ -0,0 +1,718 @@ +diff --git a/cmd/linstor-csi/linstor-csi.go b/cmd/linstor-csi/linstor-csi.go +index 143f6cee..bd28e06e 100644 +--- a/cmd/linstor-csi/linstor-csi.go ++++ b/cmd/linstor-csi/linstor-csi.go +@@ -41,22 +41,23 @@ import ( + + func main() { + var ( +- lsEndpoint = flag.String("linstor-endpoint", "", "Controller API endpoint for LINSTOR") +- lsSkipTLSVerification = flag.Bool("linstor-skip-tls-verification", false, "If true, do not verify tls") +- csiEndpoint = flag.String("csi-endpoint", "unix:///var/lib/kubelet/plugins/linstor.csi.linbit.com/csi.sock", "CSI endpoint") +- node = flag.String("node", "", "Node ID to pass to node service") +- logLevel = flag.String("log-level", "info", "Enable debug log output. Choose from: panic, fatal, error, warn, info, debug") +- rps = flag.Float64("linstor-api-requests-per-second", 0, "Maximum allowed number of LINSTOR API requests per second. Default: Unlimited") +- burst = flag.Int("linstor-api-burst", 1, "Maximum number of API requests allowed before being limited by requests-per-second. Default: 1 (no bursting)") +- bearerTokenFile = flag.String("bearer-token", "", "Read the bearer token from the given file and use it for authentication.") +- propNs = flag.String("property-namespace", linstor.NamespcAuxiliary, "Limit the reported topology keys to properties from the given namespace.") +- labelBySP = flag.Bool("label-by-storage-pool", true, "Set to false to disable labeling of nodes based on their configured storage pools.") +- nodeCacheTimeout = flag.Duration("node-cache-timeout", 1*time.Minute, "Duration for which the results of node and storage pool related API responses should be cached.") +- resourceCacheTimeout = flag.Duration("resource-cache-timeout", 30*time.Second, "Duration for which the results of resource related API responses should be cached.") +- resyncAfter = flag.Duration("resync-after", 5*time.Minute, "Duration after which reconciliations (such as for VolumeSnapshotClasses) should be rerun. Set to 0 to disable.") +- enableRWX = flag.Bool("enable-rwx", false, "Enable RWX support via NFS (requires running in Kubernetes).") +- namespace = flag.String("nfs-service-namespace", "", "The namespace the NFS service is running in.") +- reactorConfigMapName = flag.String("nfs-reactor-config-map-name", "linstor-csi-nfs-reactor-config", "Name of the config map used to store promoter configuration") ++ lsEndpoint = flag.String("linstor-endpoint", "", "Controller API endpoint for LINSTOR") ++ lsSkipTLSVerification = flag.Bool("linstor-skip-tls-verification", false, "If true, do not verify tls") ++ csiEndpoint = flag.String("csi-endpoint", "unix:///var/lib/kubelet/plugins/linstor.csi.linbit.com/csi.sock", "CSI endpoint") ++ node = flag.String("node", "", "Node ID to pass to node service") ++ logLevel = flag.String("log-level", "info", "Enable debug log output. Choose from: panic, fatal, error, warn, info, debug") ++ rps = flag.Float64("linstor-api-requests-per-second", 0, "Maximum allowed number of LINSTOR API requests per second. Default: Unlimited") ++ burst = flag.Int("linstor-api-burst", 1, "Maximum number of API requests allowed before being limited by requests-per-second. Default: 1 (no bursting)") ++ bearerTokenFile = flag.String("bearer-token", "", "Read the bearer token from the given file and use it for authentication.") ++ propNs = flag.String("property-namespace", linstor.NamespcAuxiliary, "Limit the reported topology keys to properties from the given namespace.") ++ labelBySP = flag.Bool("label-by-storage-pool", true, "Set to false to disable labeling of nodes based on their configured storage pools.") ++ nodeCacheTimeout = flag.Duration("node-cache-timeout", 1*time.Minute, "Duration for which the results of node and storage pool related API responses should be cached.") ++ resourceCacheTimeout = flag.Duration("resource-cache-timeout", 30*time.Second, "Duration for which the results of resource related API responses should be cached.") ++ resyncAfter = flag.Duration("resync-after", 5*time.Minute, "Duration after which reconciliations (such as for VolumeSnapshotClasses) should be rerun. Set to 0 to disable.") ++ enableRWX = flag.Bool("enable-rwx", false, "Enable RWX support via NFS (requires running in Kubernetes).") ++ namespace = flag.String("nfs-service-namespace", "", "The namespace the NFS service is running in.") ++ reactorConfigMapName = flag.String("nfs-reactor-config-map-name", "linstor-csi-nfs-reactor-config", "Name of the config map used to store promoter configuration") ++ disableRWXBlockValidation = flag.Bool("disable-rwx-block-validation", false, "Disable KubeVirt VM ownership validation for RWX block volumes.") + ) + + flag.Var(&volume.DefaultRemoteAccessPolicy, "default-remote-access-policy", "") +@@ -169,6 +170,10 @@ func main() { + opts = append(opts, driver.ConfigureRWX(*namespace, *reactorConfigMapName)) + } + ++ if *disableRWXBlockValidation { ++ opts = append(opts, driver.DisableRWXBlockValidation()) ++ } ++ + drv, err := driver.NewDriver(opts...) + if err != nil { + log.Fatal(err) +diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go +index bea69a8b..a39674b6 100644 +--- a/pkg/driver/driver.go ++++ b/pkg/driver/driver.go +@@ -83,6 +83,8 @@ type Driver struct { + topologyPrefix string + // resyncAfter is the interval after which reconciliations should be retried + resyncAfter time.Duration ++ // disableRWXBlockValidation disables KubeVirt VM ownership validation for RWX block volumes ++ disableRWXBlockValidation bool + + // Embed for forward compatibility. + csi.UnimplementedIdentityServer +@@ -300,6 +302,17 @@ func ResyncAfter(resyncAfter time.Duration) func(*Driver) error { + } + } + ++// DisableRWXBlockValidation disables the KubeVirt VM ownership validation for RWX block volumes. ++// When disabled, the driver will not check if multiple pods using the same RWX block volume ++// belong to the same VM. This may be needed in environments where the validation causes issues ++// or when using RWX block volumes outside of KubeVirt. ++func DisableRWXBlockValidation() func(*Driver) error { ++ return func(d *Driver) error { ++ d.disableRWXBlockValidation = true ++ return nil ++ } ++} ++ + // GetPluginInfo https://github.com/container-storage-interface/spec/blob/v1.9.0/spec.md#getplugininfo + func (d Driver) GetPluginInfo(ctx context.Context, req *csi.GetPluginInfoRequest) (*csi.GetPluginInfoResponse, error) { + return &csi.GetPluginInfoResponse{ +@@ -751,6 +764,14 @@ func (d Driver) ControllerPublishVolume(ctx context.Context, req *csi.Controller + // ReadWriteMany block volume + rwxBlock := req.VolumeCapability.AccessMode.GetMode() == csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER && req.VolumeCapability.GetBlock() != nil + ++ // Validate RWX block attachment to prevent misuse of allow-two-primaries ++ if rwxBlock && !d.disableRWXBlockValidation { ++ if _, err := utils.ValidateRWXBlockAttachment(ctx, d.kubeClient, d.log, req.GetVolumeId()); err != nil { ++ return nil, status.Errorf(codes.FailedPrecondition, ++ "ControllerPublishVolume failed for %s: %v", req.GetVolumeId(), err) ++ } ++ } ++ + devPath, err := d.Assignments.Attach(ctx, req.GetVolumeId(), req.GetNodeId(), rwxBlock) + if err != nil { + return nil, status.Errorf(codes.Internal, +diff --git a/pkg/utils/rwx_validation.go b/pkg/utils/rwx_validation.go +new file mode 100644 +index 00000000..9fe82768 +--- /dev/null ++++ b/pkg/utils/rwx_validation.go +@@ -0,0 +1,263 @@ ++/* ++CSI Driver for Linstor ++Copyright © 2018 LINBIT USA, LLC ++ ++This program is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 2 of the License, or ++(at your option) any later version. ++ ++This program is distributed in the hope that it will be useful, ++but WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++GNU General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, see . ++*/ ++ ++package utils ++ ++import ( ++ "context" ++ "fmt" ++ ++ "github.com/sirupsen/logrus" ++ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ++ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ++ "k8s.io/apimachinery/pkg/runtime/schema" ++ "k8s.io/client-go/dynamic" ++) ++ ++// KubeVirtVMLabel is the label that KubeVirt adds to pods to identify the VM they belong to. ++const KubeVirtVMLabel = "vm.kubevirt.io/name" ++ ++// KubeVirtHotplugDiskLabel is the label that KubeVirt adds to hotplug disk pods. ++const KubeVirtHotplugDiskLabel = "kubevirt.io" ++ ++// PodGVR is the GroupVersionResource for pods. ++var PodGVR = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"} ++ ++// PVGVR is the GroupVersionResource for persistent volumes. ++var PVGVR = schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumes"} ++ ++// ValidateRWXBlockAttachment checks that RWX block volumes are only used by pods belonging to the same VM. ++// This prevents misuse of allow-two-primaries while still permitting live migration. ++// Returns the VM name if validation passes, or an error if: ++// - Multiple pods from different VMs are trying to use the same volume ++// - A pod without the KubeVirt VM label is trying to use a volume already attached elsewhere (strict mode) ++// Returns empty string for VM name when no pods are using the volume or validation is skipped. ++func ValidateRWXBlockAttachment(ctx context.Context, kubeClient dynamic.Interface, log *logrus.Entry, volumeID string) (string, error) { ++ log.WithField("volumeID", volumeID).Info("validateRWXBlockAttachment called") ++ ++ if kubeClient == nil { ++ // Not running in Kubernetes, skip validation ++ log.Warn("validateRWXBlockAttachment: kubeClient is nil, skipping validation") ++ return "", nil ++ } ++ ++ // Get PV to find PVC reference ++ pv, err := kubeClient.Resource(PVGVR).Get(ctx, volumeID, metav1.GetOptions{}) ++ if err != nil { ++ log.WithError(err).Warn("cannot validate RWX attachment: failed to get PV") ++ return "", nil ++ } ++ ++ // Verify that PV's volumeHandle matches the volumeID ++ volumeHandle, found, err := unstructured.NestedString(pv.Object, "spec", "csi", "volumeHandle") ++ if err != nil { ++ log.WithError(err).Warnf("cannot validate RWX attachment: failed to read volumeHandle for PV %s", volumeID) ++ ++ return "", nil ++ } ++ ++ if !found { ++ log.Warnf("cannot validate RWX attachment: volumeHandle not found for PV %s", volumeID) ++ ++ return "", nil ++ } ++ ++ if volumeHandle != volumeID { ++ log.WithFields(logrus.Fields{ ++ "volumeID": volumeID, ++ "volumeHandle": volumeHandle, ++ }).Warn("cannot validate RWX attachment: PV volumeHandle does not match volumeID") ++ ++ return "", nil ++ } ++ ++ // Extract claimRef from PV ++ claimRef, found, _ := unstructured.NestedMap(pv.Object, "spec", "claimRef") ++ if !found { ++ log.Warn("cannot validate RWX attachment: PV has no claimRef") ++ return "", nil ++ } ++ ++ pvcName, _, _ := unstructured.NestedString(claimRef, "name") ++ pvcNamespace, _, _ := unstructured.NestedString(claimRef, "namespace") ++ ++ if pvcNamespace == "" || pvcName == "" { ++ log.Warn("cannot validate RWX attachment: PVC name or namespace is empty in claimRef") ++ return "", nil ++ } ++ ++ // List all pods in the namespace ++ podList, err := kubeClient.Resource(PodGVR).Namespace(pvcNamespace).List(ctx, metav1.ListOptions{}) ++ if err != nil { ++ return "", fmt.Errorf("failed to list pods in namespace %s: %w", pvcNamespace, err) ++ } ++ ++ // Filter pods that use this PVC and are in a running/pending state ++ type podInfo struct { ++ name string ++ vmName string ++ } ++ ++ var podsUsingPVC []podInfo ++ ++ for _, item := range podList.Items { ++ // Get pod phase from status ++ phase, _, _ := unstructured.NestedString(item.Object, "status", "phase") ++ if phase == "Succeeded" || phase == "Failed" { ++ continue ++ } ++ ++ // Check if pod uses the PVC ++ volumes, found, _ := unstructured.NestedSlice(item.Object, "spec", "volumes") ++ if !found { ++ continue ++ } ++ ++ for _, vol := range volumes { ++ volMap, ok := vol.(map[string]interface{}) ++ if !ok { ++ continue ++ } ++ ++ claimName, found, _ := unstructured.NestedString(volMap, "persistentVolumeClaim", "claimName") ++ if !found || claimName != pvcName { ++ continue ++ } ++ ++ // Extract VM name, handling both regular and hotplug disk pods ++ vmName, err := GetVMNameFromPod(ctx, kubeClient, log, &item) ++ if err != nil { ++ log.WithError(err).WithField("pod", item.GetName()).Warn("failed to get VM name from pod") ++ // Continue with empty vmName - will be caught by strict mode check ++ vmName = "" ++ } ++ ++ podsUsingPVC = append(podsUsingPVC, podInfo{ ++ name: item.GetName(), ++ vmName: vmName, ++ }) ++ ++ break ++ } ++ } ++ ++ // If 0 or 1 pod uses the PVC, no conflict possible ++ if len(podsUsingPVC) <= 1 { ++ // Return VM name if there's exactly one pod ++ if len(podsUsingPVC) == 1 { ++ log.WithFields(logrus.Fields{ ++ "volumeID": volumeID, ++ "vmName": podsUsingPVC[0].vmName, ++ "podCount": 1, ++ "pvcNamespace": pvcNamespace, ++ "pvcName": pvcName, ++ }).Info("validateRWXBlockAttachment: single pod found, returning VM name") ++ ++ return podsUsingPVC[0].vmName, nil ++ } ++ ++ log.WithFields(logrus.Fields{ ++ "volumeID": volumeID, ++ "pvcNamespace": pvcNamespace, ++ "pvcName": pvcName, ++ }).Info("validateRWXBlockAttachment: no pods found using PVC") ++ ++ return "", nil ++ } ++ ++ // Check that all pods belong to the same VM ++ var vmName string ++ for _, pod := range podsUsingPVC { ++ if pod.vmName == "" { ++ // Strict mode: if any pod doesn't have the KubeVirt label and there are multiple pods, ++ // deny the attachment ++ return "", fmt.Errorf("RWX block volume %s/%s is used by multiple pods but pod %s does not have the %s label; "+ ++ "RWX block volumes with allow-two-primaries are only supported for KubeVirt live migration", ++ pvcNamespace, pvcName, pod.name, KubeVirtVMLabel) ++ } ++ ++ if vmName == "" { ++ vmName = pod.vmName ++ } else if vmName != pod.vmName { ++ // Different VMs are trying to use the same volume ++ return "", fmt.Errorf("RWX block volume %s/%s is being used by pods from different VMs (%s and %s); "+ ++ "this is not supported - RWX block volumes with allow-two-primaries are only for live migration of a single VM", ++ pvcNamespace, pvcName, vmName, pod.vmName) ++ } ++ } ++ ++ log.WithFields(logrus.Fields{ ++ "pvcNamespace": pvcNamespace, ++ "pvcName": pvcName, ++ "vmName": vmName, ++ "podCount": len(podsUsingPVC), ++ }).Debug("RWX block attachment validated: all pods belong to the same VM (likely live migration)") ++ ++ return vmName, nil ++} ++ ++// GetVMNameFromPod extracts the VM name from a pod, handling both regular virt-launcher pods ++// and hotplug disk pods (which reference the virt-launcher pod via ownerReferences). ++func GetVMNameFromPod(ctx context.Context, kubeClient dynamic.Interface, log *logrus.Entry, pod *unstructured.Unstructured) (string, error) { ++ labels := pod.GetLabels() ++ if labels == nil { ++ return "", nil ++ } ++ ++ // Direct case: pod has vm.kubevirt.io/name label (virt-launcher pod) ++ if vmName, ok := labels[KubeVirtVMLabel]; ok && vmName != "" { ++ return vmName, nil ++ } ++ ++ // Hotplug disk case: pod has kubevirt.io: hotplug-disk label ++ // Follow ownerReferences to find the virt-launcher pod ++ if hotplugValue, ok := labels[KubeVirtHotplugDiskLabel]; ok && hotplugValue == "hotplug-disk" { ++ ownerRefs := pod.GetOwnerReferences() ++ for _, owner := range ownerRefs { ++ if owner.Kind != "Pod" || owner.Controller == nil || !*owner.Controller { ++ continue ++ } ++ ++ // Get the owner pod (virt-launcher) ++ ownerPod, err := kubeClient.Resource(PodGVR).Namespace(pod.GetNamespace()).Get(ctx, owner.Name, metav1.GetOptions{}) ++ if err != nil { ++ return "", fmt.Errorf("failed to get owner pod %s: %w", owner.Name, err) ++ } ++ ++ // Extract VM name from owner pod ++ ownerLabels := ownerPod.GetLabels() ++ if ownerLabels != nil { ++ if vmName, ok := ownerLabels[KubeVirtVMLabel]; ok && vmName != "" { ++ log.WithFields(logrus.Fields{ ++ "hotplugPod": pod.GetName(), ++ "virtLauncher": owner.Name, ++ "vmName": vmName, ++ }).Debug("resolved VM name from hotplug disk pod via owner reference") ++ ++ return vmName, nil ++ } ++ } ++ ++ return "", fmt.Errorf("owner pod %s does not have %s label", owner.Name, KubeVirtVMLabel) ++ } ++ ++ return "", fmt.Errorf("hotplug disk pod %s has no controller owner reference", pod.GetName()) ++ } ++ ++ return "", nil ++} +diff --git a/pkg/utils/rwx_validation_test.go b/pkg/utils/rwx_validation_test.go +new file mode 100644 +index 00000000..d75690f9 +--- /dev/null ++++ b/pkg/utils/rwx_validation_test.go +@@ -0,0 +1,342 @@ ++/* ++CSI Driver for Linstor ++Copyright © 2018 LINBIT USA, LLC ++ ++This program is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 2 of the License, or ++(at your option) any later version. ++ ++This program is distributed in the hope that it will be useful, ++but WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++GNU General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program; if not, see . ++*/ ++ ++package utils ++ ++import ( ++ "context" ++ "testing" ++ ++ "github.com/sirupsen/logrus" ++ "github.com/stretchr/testify/assert" ++ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ++ "k8s.io/apimachinery/pkg/runtime" ++ "k8s.io/apimachinery/pkg/runtime/schema" ++ dynamicfake "k8s.io/client-go/dynamic/fake" ++) ++ ++func TestValidateRWXBlockAttachment(t *testing.T) { ++ testCases := []struct { ++ name string ++ pods []*unstructured.Unstructured ++ pvcName string ++ namespace string ++ expectError bool ++ errorMsg string ++ }{ ++ { ++ name: "no pods using PVC", ++ pods: []*unstructured.Unstructured{}, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "single pod using PVC", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("pod1", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "two pods same VM (live migration)", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("virt-launcher-vm1-abc", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("virt-launcher-vm1-xyz", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "two pods different VMs (should fail)", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("virt-launcher-vm1-abc", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("virt-launcher-vm2-xyz", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm2"}, "Running"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: true, ++ errorMsg: "different VMs", ++ }, ++ { ++ name: "pod without KubeVirt label when multiple pods exist (strict mode)", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("pod1", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("pod2", "default", "test-pvc", map[string]string{}, "Running"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: true, ++ errorMsg: "does not have the vm.kubevirt.io/name label", ++ }, ++ { ++ name: "completed pods should be ignored", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("pod1", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("pod2", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm2"}, "Succeeded"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "failed pods should be ignored", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("pod1", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("pod2", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm2"}, "Failed"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "pods in different namespace should not conflict", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("pod1", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("pod2", "other", "test-pvc", map[string]string{KubeVirtVMLabel: "vm2"}, "Running"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "pods using different PVCs should not conflict", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("pod1", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("pod2", "default", "other-pvc", map[string]string{KubeVirtVMLabel: "vm2"}, "Running"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "three pods from same VM (multi-node live migration scenario)", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("virt-launcher-vm1-a", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("virt-launcher-vm1-b", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createUnstructuredPod("virt-launcher-vm1-c", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Pending"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "hotplug disk pod with virt-launcher (should succeed)", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("virt-launcher-vm1-abc", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createHotplugDiskPod("hp-volume-xyz", "default", "test-pvc", "virt-launcher-vm1-abc", "Running"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: false, ++ }, ++ { ++ name: "hotplug disks from different VMs (should fail)", ++ pods: []*unstructured.Unstructured{ ++ createUnstructuredPod("virt-launcher-vm1-abc", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm1"}, "Running"), ++ createHotplugDiskPod("hp-volume-vm1", "default", "test-pvc", "virt-launcher-vm1-abc", "Running"), ++ createUnstructuredPod("virt-launcher-vm2-xyz", "default", "test-pvc", map[string]string{KubeVirtVMLabel: "vm2"}, "Running"), ++ createHotplugDiskPod("hp-volume-vm2", "default", "test-pvc", "virt-launcher-vm2-xyz", "Running"), ++ }, ++ pvcName: "test-pvc", ++ namespace: "default", ++ expectError: true, ++ errorMsg: "different VMs", ++ }, ++ } ++ ++ for _, tc := range testCases { ++ t.Run(tc.name, func(t *testing.T) { ++ // Create fake dynamic client with test pods and PV ++ scheme := runtime.NewScheme() ++ ++ // Create PV object that references the PVC ++ pv := createUnstructuredPV("test-volume-id", tc.namespace, tc.pvcName) ++ ++ objects := make([]runtime.Object, 0, len(tc.pods)+1) ++ objects = append(objects, pv) ++ ++ for _, pod := range tc.pods { ++ objects = append(objects, pod) ++ } ++ ++ gvrToListKind := map[schema.GroupVersionResource]string{ ++ PodGVR: "PodList", ++ PVGVR: "PersistentVolumeList", ++ } ++ client := dynamicfake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objects...) ++ ++ // Create logger ++ logger := logrus.NewEntry(logrus.New()) ++ logger.Logger.SetLevel(logrus.DebugLevel) ++ ++ // Run validation ++ vmName, err := ValidateRWXBlockAttachment(context.Background(), client, logger, "test-volume-id") ++ ++ if tc.expectError { ++ assert.Error(t, err) ++ ++ if tc.errorMsg != "" { ++ assert.Contains(t, err.Error(), tc.errorMsg) ++ } ++ } else { ++ assert.NoError(t, err) ++ // VM name is returned when there are pods using the volume ++ if len(tc.pods) > 0 { ++ assert.NotEmpty(t, vmName) ++ } ++ } ++ }) ++ } ++} ++ ++func TestValidateRWXBlockAttachmentNoKubeClient(t *testing.T) { ++ // When not running in Kubernetes (no client), validation should be skipped ++ logger := logrus.NewEntry(logrus.New()) ++ ++ vmName, err := ValidateRWXBlockAttachment(context.Background(), nil, logger, "test-volume-id") ++ assert.NoError(t, err) ++ assert.Empty(t, vmName) ++} ++ ++func TestValidateRWXBlockAttachmentPVNotFound(t *testing.T) { ++ // When PV is not found, validation should be skipped with warning ++ scheme := runtime.NewScheme() ++ ++ gvrToListKind := map[schema.GroupVersionResource]string{ ++ PodGVR: "PodList", ++ PVGVR: "PersistentVolumeList", ++ } ++ client := dynamicfake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind) ++ ++ logger := logrus.NewEntry(logrus.New()) ++ logger.Logger.SetLevel(logrus.DebugLevel) ++ ++ vmName, err := ValidateRWXBlockAttachment(context.Background(), client, logger, "non-existent-pv") ++ assert.NoError(t, err) ++ assert.Empty(t, vmName) ++} ++ ++// createUnstructuredPod creates an unstructured pod object for testing. ++func createUnstructuredPod(name, namespace, pvcName string, labels map[string]string, phase string) *unstructured.Unstructured { ++ pod := &unstructured.Unstructured{ ++ Object: map[string]interface{}{ ++ "apiVersion": "v1", ++ "kind": "Pod", ++ "metadata": map[string]interface{}{ ++ "name": name, ++ "namespace": namespace, ++ "labels": toStringInterfaceMap(labels), ++ }, ++ "spec": map[string]interface{}{ ++ "volumes": []interface{}{ ++ map[string]interface{}{ ++ "name": "data", ++ "persistentVolumeClaim": map[string]interface{}{ ++ "claimName": pvcName, ++ }, ++ }, ++ }, ++ }, ++ "status": map[string]interface{}{ ++ "phase": phase, ++ }, ++ }, ++ } ++ ++ return pod ++} ++ ++// createUnstructuredPV creates an unstructured PersistentVolume object for testing. ++func createUnstructuredPV(name, pvcNamespace, pvcName string) *unstructured.Unstructured { ++ pv := &unstructured.Unstructured{ ++ Object: map[string]interface{}{ ++ "apiVersion": "v1", ++ "kind": "PersistentVolume", ++ "metadata": map[string]interface{}{ ++ "name": name, ++ }, ++ "spec": map[string]interface{}{ ++ "claimRef": map[string]interface{}{ ++ "name": pvcName, ++ "namespace": pvcNamespace, ++ }, ++ "csi": map[string]interface{}{ ++ "volumeHandle": name, ++ }, ++ }, ++ }, ++ } ++ ++ return pv ++} ++ ++// toStringInterfaceMap converts map[string]string to map[string]interface{}. ++func toStringInterfaceMap(m map[string]string) map[string]interface{} { ++ result := make(map[string]interface{}) ++ ++ for k, v := range m { ++ result[k] = v ++ } ++ ++ return result ++} ++ ++// createHotplugDiskPod creates a hotplug disk pod that references a virt-launcher pod via ownerReferences. ++func createHotplugDiskPod(name, namespace, pvcName, ownerPodName, phase string) *unstructured.Unstructured { ++ pod := &unstructured.Unstructured{ ++ Object: map[string]interface{}{ ++ "apiVersion": "v1", ++ "kind": "Pod", ++ "metadata": map[string]interface{}{ ++ "name": name, ++ "namespace": namespace, ++ "labels": map[string]interface{}{ ++ "kubevirt.io": "hotplug-disk", ++ }, ++ "ownerReferences": []interface{}{ ++ map[string]interface{}{ ++ "apiVersion": "v1", ++ "kind": "Pod", ++ "name": ownerPodName, ++ "controller": true, ++ "blockOwnerDeletion": true, ++ }, ++ }, ++ }, ++ "spec": map[string]interface{}{ ++ "volumes": []interface{}{ ++ map[string]interface{}{ ++ "name": "data", ++ "persistentVolumeClaim": map[string]interface{}{ ++ "claimName": pvcName, ++ }, ++ }, ++ }, ++ }, ++ "status": map[string]interface{}{ ++ "phase": phase, ++ }, ++ }, ++ } ++ ++ return pod ++} diff --git a/packages/system/linstor/images/piraeus-server/patches/README.md b/packages/system/linstor/images/piraeus-server/patches/README.md index c219eaf3..5ee29318 100644 --- a/packages/system/linstor/images/piraeus-server/patches/README.md +++ b/packages/system/linstor/images/piraeus-server/patches/README.md @@ -8,5 +8,7 @@ Custom patches for piraeus-server (linstor-server) v1.32.3. - Upstream: [#475](https://github.com/LINBIT/linstor-server/pull/475) - **force-metadata-check-on-disk-add.diff** — Create metadata during toggle-disk from diskless to diskful - Upstream: [#474](https://github.com/LINBIT/linstor-server/pull/474) -- **skip-adjust-when-device-inaccessible.diff** — Skip DRBD adjust/res file regeneration when child layer device is inaccessible - - Upstream: [#471](https://github.com/LINBIT/linstor-server/pull/471) +- **fix-duplicate-tcp-ports.diff** — Prevent duplicate TCP ports after toggle-disk operations + - Upstream: [#476](https://github.com/LINBIT/linstor-server/pull/476) +- **skip-adjust-when-device-inaccessible.diff** — Fix resources stuck in StandAlone after reboot, Unknown state race condition, and encrypted resource deletion + - Upstream: [#477](https://github.com/LINBIT/linstor-server/pull/477) diff --git a/packages/system/linstor/images/piraeus-server/patches/fix-duplicate-tcp-ports.diff b/packages/system/linstor/images/piraeus-server/patches/fix-duplicate-tcp-ports.diff new file mode 100644 index 00000000..07cd9eac --- /dev/null +++ b/packages/system/linstor/images/piraeus-server/patches/fix-duplicate-tcp-ports.diff @@ -0,0 +1,87 @@ +From 1250abe99d64a0501795e37d3b6af62410002239 Mon Sep 17 00:00:00 2001 +From: Andrei Kvapil +Date: Mon, 12 Jan 2026 13:44:46 +0100 +Subject: [PATCH] fix(drbd): prevent duplicate TCP ports after toggle-disk + operations + +Remove redundant ensureStackDataExists() call with empty payload from +resetStoragePools() method that was causing TCP port conflicts after +toggle-disk operations. + +Root Cause: +----------- +The resetStoragePools() method, introduced in 2019 (commit 95cc17d0b8), +calls ensureStackDataExists() with an empty LayerPayload. This worked +correctly when TCP ports were stored at RscDfn level. + +After the TCP port migration to per-node level (commit f754943463, May +2025), this empty payload results in DrbdRscData being created without +TCP ports assigned. The controller then sends a Pojo with an empty port +Set to satellites. + +On satellites, when DrbdRscData is initialized with an empty port list, +initPorts() uses preferredNewPortsRef from peer resources. Since +SatelliteDynamicNumberPool.tryAllocate() always returns true (no-op), +any port from preferredNewPortsRef is accepted without conflict checking, +leading to duplicate TCP port assignments. + +Impact: +------- +This regression affects toggle-disk operations, particularly: +- Snapshot creation/restore operations +- Manual toggle-disk operations +- Any operation calling resetStoragePools() + +Symptoms include: +- DRBD resources failing to adjust with "port is also used" errors +- Resources stuck in StandAlone or Connecting states +- Multiple resources on the same node using identical TCP ports + +Solution: +--------- +Remove the ensureStackDataExists() call from resetStoragePools() as it +is redundant. The calling code (e.g., CtrlRscToggleDiskApiCallHandler +line 1071) already invokes ensureStackDataExists() with the correct +payload immediately after resetStoragePools(). + +This fix ensures: +1. resetStoragePools() only resets storage pool assignments +2. Layer data creation with proper TCP ports happens via the caller's + ensureStackDataExists() with correct payload +3. No DrbdRscData objects are created without TCP port assignments + +Related Issues: +--------------- +Fixes #454 - Duplicate TCP ports after backup/restore operations +Related to user reports of resources stuck in StandAlone after node +reboots when toggle-disk or backup operations were in progress. + +Testing: +-------- +Verified that: +- Toggle-disk operations no longer create resources without TCP ports +- Backup/restore operations complete without TCP port conflicts +- Resources maintain unique TCP ports across toggle-disk cycles + +Co-Authored-By: Claude +Signed-off-by: Andrei Kvapil +--- + .../linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/controller/src/main/java/com/linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java b/controller/src/main/java/com/linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java +index 3538b380c..4f589145e 100644 +--- a/controller/src/main/java/com/linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java ++++ b/controller/src/main/java/com/linbit/linstor/layer/resource/CtrlRscLayerDataFactory.java +@@ -276,8 +276,6 @@ public class CtrlRscLayerDataFactory + + rscDataToProcess.addAll(rscData.getChildren()); + } +- +- ensureStackDataExists(rscRef, null, new LayerPayload()); + } + catch (AccessDeniedException exc) + { +-- +2.39.5 (Apple Git-154) + diff --git a/packages/system/linstor/images/piraeus-server/patches/skip-adjust-when-device-inaccessible.diff b/packages/system/linstor/images/piraeus-server/patches/skip-adjust-when-device-inaccessible.diff deleted file mode 100644 index 09e7ccf9..00000000 --- a/packages/system/linstor/images/piraeus-server/patches/skip-adjust-when-device-inaccessible.diff +++ /dev/null @@ -1,93 +0,0 @@ -diff --git a/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java b/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java -index 01967a3..871d830 100644 ---- a/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java -+++ b/satellite/src/main/java/com/linbit/linstor/layer/drbd/DrbdLayer.java -@@ -592,7 +592,29 @@ public class DrbdLayer implements DeviceLayer - // The .res file might not have been generated in the prepare method since it was - // missing information from the child-layers. Now that we have processed them, we - // need to make sure the .res file exists in all circumstances. -- regenerateResFile(drbdRscData); -+ // However, if the underlying devices are not accessible (e.g., LUKS device is closed -+ // during resource deletion), we skip regenerating the res file to avoid errors -+ boolean canRegenerateResFile = true; -+ if (!skipDisk && !drbdRscData.getAbsResource().isDrbdDiskless(workerCtx)) -+ { -+ AbsRscLayerObject dataChild = drbdRscData.getChildBySuffix(RscLayerSuffixes.SUFFIX_DATA); -+ if (dataChild != null) -+ { -+ for (DrbdVlmData drbdVlmData : drbdRscData.getVlmLayerObjects().values()) -+ { -+ VlmProviderObject childVlm = dataChild.getVlmProviderObject(drbdVlmData.getVlmNr()); -+ if (childVlm == null || !childVlm.exists() || childVlm.getDevicePath() == null) -+ { -+ canRegenerateResFile = false; -+ break; -+ } -+ } -+ } -+ } -+ if (canRegenerateResFile) -+ { -+ regenerateResFile(drbdRscData); -+ } - - // createMetaData needs rendered resFile - for (DrbdVlmData drbdVlmData : createMetaData) -@@ -766,19 +788,47 @@ public class DrbdLayer implements DeviceLayer - - if (drbdRscData.isAdjustRequired()) - { -- try -+ // Check if underlying devices are accessible before adjusting -+ // This is important for encrypted resources (LUKS) where the device -+ // might be closed during deletion -+ boolean canAdjust = true; -+ if (!skipDisk && !drbdRscData.getAbsResource().isDrbdDiskless(workerCtx)) - { -- drbdUtils.adjust( -- drbdRscData, -- false, -- skipDisk, -- false -- ); -+ AbsRscLayerObject dataChild = drbdRscData.getChildBySuffix(RscLayerSuffixes.SUFFIX_DATA); -+ if (dataChild != null) -+ { -+ for (DrbdVlmData drbdVlmData : drbdRscData.getVlmLayerObjects().values()) -+ { -+ VlmProviderObject childVlm = dataChild.getVlmProviderObject(drbdVlmData.getVlmNr()); -+ if (childVlm == null || !childVlm.exists() || childVlm.getDevicePath() == null) -+ { -+ canAdjust = false; -+ break; -+ } -+ } -+ } - } -- catch (ExtCmdFailedException extCmdExc) -+ -+ if (canAdjust) -+ { -+ try -+ { -+ drbdUtils.adjust( -+ drbdRscData, -+ false, -+ skipDisk, -+ false -+ ); -+ } -+ catch (ExtCmdFailedException extCmdExc) -+ { -+ restoreBackupResFile(drbdRscData); -+ throw extCmdExc; -+ } -+ } -+ else - { -- restoreBackupResFile(drbdRscData); -- throw extCmdExc; -+ drbdRscData.setAdjustRequired(false); - } - } - diff --git a/packages/system/linstor/templates/cluster.yaml b/packages/system/linstor/templates/cluster.yaml index bde24726..ba611e17 100644 --- a/packages/system/linstor/templates/cluster.yaml +++ b/packages/system/linstor/templates/cluster.yaml @@ -60,6 +60,24 @@ spec: configMap: name: linstor-plunger defaultMode: 0755 + csiController: + podTemplate: + spec: + initContainers: + - name: linstor-wait-api-online + image: {{ .Values.linstorCSI.image.repository }}:{{ .Values.linstorCSI.image.tag }} + containers: + - name: linstor-csi + image: {{ .Values.linstorCSI.image.repository }}:{{ .Values.linstorCSI.image.tag }} + csiNode: + podTemplate: + spec: + initContainers: + - name: linstor-wait-node-online + image: {{ .Values.linstorCSI.image.repository }}:{{ .Values.linstorCSI.image.tag }} + containers: + - name: linstor-csi + image: {{ .Values.linstorCSI.image.repository }}:{{ .Values.linstorCSI.image.tag }} patches: - target: kind: Deployment diff --git a/packages/system/linstor/templates/satellites-talos.yaml b/packages/system/linstor/templates/satellites-talos.yaml index c5be9204..21da32a6 100644 --- a/packages/system/linstor/templates/satellites-talos.yaml +++ b/packages/system/linstor/templates/satellites-talos.yaml @@ -1,3 +1,4 @@ +{{- if .Values.talos.enabled }} apiVersion: piraeus.io/v1 kind: LinstorSatelliteConfiguration metadata: @@ -41,3 +42,4 @@ spec: hostPath: path: /var/etc/lvm/archive type: DirectoryOrCreate +{{- end }} diff --git a/packages/system/linstor/values.yaml b/packages/system/linstor/values.yaml index 1a94793b..8c22ac6b 100644 --- a/packages/system/linstor/values.yaml +++ b/packages/system/linstor/values.yaml @@ -1,10 +1,16 @@ piraeusServer: image: repository: ghcr.io/cozystack/cozystack/piraeus-server - tag: latest@sha256:417532baa2801288147cd9ac9ae260751c1a7754f0b829725d09b72a770c111a - + tag: 1.32.3@sha256:0e78fa31a3fe4ec2af43d1e59a9fc0f6d765780e32d473e18e1c495714051802 +# Talos-specific workarounds (disable for generic Linux like Ubuntu/Debian) +talos: + enabled: true linstor: autoDiskful: enabled: true minutes: 30 allowCleanup: true +linstorCSI: + image: + repository: ghcr.io/cozystack/cozystack/linstor-csi + tag: v1.10.5@sha256:68465f120cfeec3d7ccbb389dd9bdbf7df1675da3ab9ba91c3feff21a799bc36 diff --git a/packages/system/local-ccm/.helmignore b/packages/system/local-ccm/.helmignore new file mode 100644 index 00000000..1e107f52 --- /dev/null +++ b/packages/system/local-ccm/.helmignore @@ -0,0 +1 @@ +examples diff --git a/packages/system/local-ccm/Chart.yaml b/packages/system/local-ccm/Chart.yaml new file mode 100644 index 00000000..1ca0527b --- /dev/null +++ b/packages/system/local-ccm/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-local-ccm +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/local-ccm/Makefile b/packages/system/local-ccm/Makefile new file mode 100644 index 00000000..aff6386e --- /dev/null +++ b/packages/system/local-ccm/Makefile @@ -0,0 +1,15 @@ +export NAME=local-ccm +export NAMESPACE=cozy-$(NAME) + +include ../../../hack/package.mk + +update: + rm -rf charts + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/cozystack/local-ccm | awk -F'[/^]' 'END{print $$3}') && \ + if [ -z "$$tag" ]; then \ + curl -sSL https://github.com/cozystack/local-ccm/archive/refs/heads/main.tar.gz | \ + tar xzvf - --strip 1 local-ccm-main/charts; \ + else \ + curl -sSL https://github.com/cozystack/local-ccm/archive/refs/tags/$${tag}.tar.gz | \ + tar xzvf - --strip 1 local-ccm-$${tag#*v}/charts; \ + fi diff --git a/packages/system/local-ccm/charts/local-ccm/.helmignore b/packages/system/local-ccm/charts/local-ccm/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/.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/packages/system/local-ccm/charts/local-ccm/Chart.yaml b/packages/system/local-ccm/charts/local-ccm/Chart.yaml new file mode 100644 index 00000000..ef68023d --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +name: local-ccm +description: Local Cloud Controller Manager for Kubernetes - detects and manages node IP addresses +type: application +version: 0.1.0 +appVersion: "0.1.0" +keywords: + - kubernetes + - cloud-controller-manager + - ccm + - node-controller +home: https://github.com/cozystack/local-ccm +sources: + - https://github.com/cozystack/local-ccm +maintainers: + - name: Andrei Kvapil + email: kvapss@gmail.com diff --git a/packages/system/local-ccm/charts/local-ccm/README.md b/packages/system/local-ccm/charts/local-ccm/README.md new file mode 100644 index 00000000..7b9187df --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/README.md @@ -0,0 +1,97 @@ +# local-ccm Helm Chart + +Local Cloud Controller Manager for Kubernetes - automatically detects and manages node IP addresses. + +## Features + +- Automatic node IP address detection using routing table +- Support for both internal and external IP detection +- Automatic removal of cloud provider initialization taint +- Minimal resource footprint +- Runs as DaemonSet on all nodes + +## Installation + +### Quick Start + +Install with default configuration: + +```bash +helm install local-ccm ./charts/local-ccm --namespace kube-system +``` + +### Custom Configuration + +Create a `values.yaml` file: + +```yaml +ipDetection: + externalIPTarget: "1.1.1.1" + internalIPTarget: "10.0.0.1" + +controller: + verbosity: 3 +``` + +Install with custom values: + +```bash +helm install local-ccm ./charts/local-ccm \ + --namespace kube-system \ + --values values.yaml +``` + +### Inline Configuration + +```bash +helm install local-ccm ./charts/local-ccm \ + --namespace kube-system \ + --set ipDetection.externalIPTarget=1.1.1.1 \ + --set ipDetection.internalIPTarget=10.0.0.1 +``` + +## Configuration + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `image.repository` | Container image repository | `ghcr.io/cozystack/local-ccm` | +| `image.tag` | Container image tag | `v0.1.0` | +| `image.pullPolicy` | Image pull policy | `Always` | +| `serviceAccount.create` | Create service account | `true` | +| `serviceAccount.name` | Service account name | `local-ccm` | +| `ipDetection.externalIPTarget` | Target IP for external IP detection | `8.8.8.8` | +| `ipDetection.internalIPTarget` | Target IP for internal IP detection (empty = disabled) | `""` | +| `controller.removeTaint` | Remove uninitialized taint | `true` | +| `controller.reconcileInterval` | Reconciliation interval | `10s` | +| `controller.verbosity` | Log verbosity level (0-5) | `2` | +| `resources.requests.cpu` | CPU resource requests | `10m` | +| `resources.requests.memory` | Memory resource requests | `32Mi` | +| `resources.limits.cpu` | CPU resource limits | `100m` | +| `resources.limits.memory` | Memory resource limits | `64Mi` | +| `tolerations` | Pod tolerations | `[{operator: Exists}]` | +| `affinity` | Pod affinity rules | See values.yaml | +| `labels` | Additional labels for all resources | `{}` | +| `podAnnotations` | Additional pod annotations | `{}` | + +## Uninstallation + +```bash +helm uninstall local-ccm --namespace kube-system +``` + +## Upgrading + +```bash +helm upgrade local-ccm ./charts/local-ccm \ + --namespace kube-system \ + --values values.yaml +``` + +## Requirements + +- Kubernetes 1.19+ +- Helm 3.0+ + +## License + +Licensed under the Apache License, Version 2.0 diff --git a/packages/system/local-ccm/charts/local-ccm/templates/NOTES.txt b/packages/system/local-ccm/charts/local-ccm/templates/NOTES.txt new file mode 100644 index 00000000..3dd29683 --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/templates/NOTES.txt @@ -0,0 +1,29 @@ +Thank you for installing {{ .Chart.Name }}! + +Your release is named {{ .Release.Name }}. + +The local-ccm DaemonSet has been deployed to namespace {{ .Release.Namespace }}. + +To check the status of the DaemonSet: + + kubectl --namespace {{ .Release.Namespace }} get daemonset {{ include "local-ccm.fullname" . }} + +To view the pods: + + kubectl --namespace {{ .Release.Namespace }} get pods -l "{{ include "local-ccm.selectorLabels" . | replace "\n" "," }}" + +To check logs from a specific pod: + + kubectl --namespace {{ .Release.Namespace }} logs -l app=local-ccm -c local-ccm + +Configuration: + - External IP detection target: {{ .Values.ipDetection.externalIPTarget }} + {{- if .Values.ipDetection.internalIPTarget }} + - Internal IP detection target: {{ .Values.ipDetection.internalIPTarget }} + {{- else }} + - Internal IP detection: disabled (using kubelet's InternalIP) + {{- end }} + - Remove uninitialized taint: {{ .Values.controller.removeTaint }} + - Reconcile interval: {{ .Values.controller.reconcileInterval }} + +For more information, visit: https://github.com/cozystack/local-ccm diff --git a/packages/system/local-ccm/charts/local-ccm/templates/_helpers.tpl b/packages/system/local-ccm/charts/local-ccm/templates/_helpers.tpl new file mode 100644 index 00000000..0de841f5 --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/templates/_helpers.tpl @@ -0,0 +1,65 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "local-ccm.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "local-ccm.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 "local-ccm.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "local-ccm.labels" -}} +helm.sh/chart: {{ include "local-ccm.chart" . }} +{{ include "local-ccm.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.labels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "local-ccm.selectorLabels" -}} +app.kubernetes.io/name: {{ include "local-ccm.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app: local-ccm +component: node-controller +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "local-ccm.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "local-ccm.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/packages/system/local-ccm/charts/local-ccm/templates/clusterrole.yaml b/packages/system/local-ccm/charts/local-ccm/templates/clusterrole.yaml new file mode 100644 index 00000000..d9d3dab3 --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/templates/clusterrole.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "local-ccm.fullname" . }} + labels: + {{- include "local-ccm.labels" . | nindent 4 }} +rules: +# Permissions to get and update nodes +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch", "patch"] +# Permissions to update node status (for addresses) +- apiGroups: [""] + resources: ["nodes/status"] + verbs: ["patch"] diff --git a/packages/system/local-ccm/charts/local-ccm/templates/clusterrolebinding.yaml b/packages/system/local-ccm/charts/local-ccm/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..0be6cc71 --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/templates/clusterrolebinding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "local-ccm.fullname" . }} + labels: + {{- include "local-ccm.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "local-ccm.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "local-ccm.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/packages/system/local-ccm/charts/local-ccm/templates/daemonset.yaml b/packages/system/local-ccm/charts/local-ccm/templates/daemonset.yaml new file mode 100644 index 00000000..c45afc67 --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/templates/daemonset.yaml @@ -0,0 +1,54 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "local-ccm.fullname" . }} + labels: + {{- include "local-ccm.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "local-ccm.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "local-ccm.selectorLabels" . | nindent 8 }} + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "local-ccm.serviceAccountName" . }} + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: local-ccm + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /usr/local/bin/local-ccm + args: + - --node-name=$(NODE_NAME) + - --external-ip-target={{ .Values.ipDetection.externalIPTarget }} + {{- if .Values.ipDetection.internalIPTarget }} + - --internal-ip-target={{ .Values.ipDetection.internalIPTarget }} + {{- end }} + - --remove-taint={{ .Values.controller.removeTaint }} + - --reconcile-interval={{ .Values.controller.reconcileInterval }} + - --v={{ .Values.controller.verbosity }} + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + resources: + {{- toYaml .Values.resources | nindent 10 }} diff --git a/packages/system/local-ccm/charts/local-ccm/templates/serviceaccount.yaml b/packages/system/local-ccm/charts/local-ccm/templates/serviceaccount.yaml new file mode 100644 index 00000000..a3582c56 --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/templates/serviceaccount.yaml @@ -0,0 +1,8 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "local-ccm.serviceAccountName" . }} + labels: + {{- include "local-ccm.labels" . | nindent 4 }} +{{- end }} diff --git a/packages/system/local-ccm/charts/local-ccm/values.yaml b/packages/system/local-ccm/charts/local-ccm/values.yaml new file mode 100644 index 00000000..cdd14c0c --- /dev/null +++ b/packages/system/local-ccm/charts/local-ccm/values.yaml @@ -0,0 +1,57 @@ +# Default values for local-ccm + +image: + repository: ghcr.io/cozystack/local-ccm + tag: v0.2.1 + pullPolicy: Always +# Service account configuration +serviceAccount: + create: true + name: local-ccm +# IP detection configuration +ipDetection: + # Target IP for external IP detection via 'ip route get' + externalIPTarget: "8.8.8.8" + # Target IP for internal IP detection via 'ip route get' + # If empty, internal IP detection is disabled and kubelet's InternalIP is preserved + internalIPTarget: "" +# Controller configuration +controller: + # Remove node.cloudprovider.kubernetes.io/uninitialized taint + removeTaint: true + # Interval between reconciliation loops + reconcileInterval: 10s + # Verbosity level (0-5) + verbosity: 2 +# Pod resources +resources: + requests: + cpu: 10m + memory: 32Mi + limits: + cpu: 100m + memory: 64Mi +# Security context for the container +securityContext: + capabilities: + add: + - NET_ADMIN # Required for netlink route queries + - NET_RAW + runAsUser: 0 # Must run as root to access netlink +# Tolerations - by default tolerate all taints to run on every node +tolerations: + - operator: Exists +# Node affinity configuration +affinity: + nodeAffinity: + # Prefer to schedule on nodes needing initialization first + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + preference: + matchExpressions: + - key: node.cloudprovider.kubernetes.io/uninitialized + operator: Exists +# Additional labels for all resources +labels: {} +# Additional annotations for pods +podAnnotations: {} diff --git a/packages/system/mariadb-operator/Makefile b/packages/system/mariadb-operator/Makefile index ecbd51d9..905653ca 100644 --- a/packages/system/mariadb-operator/Makefile +++ b/packages/system/mariadb-operator/Makefile @@ -1,7 +1,7 @@ export NAME=mariadb-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/metallb/Makefile b/packages/system/metallb/Makefile index 5323f414..5262e558 100644 --- a/packages/system/metallb/Makefile +++ b/packages/system/metallb/Makefile @@ -1,8 +1,8 @@ export NAME=metallb export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/metallb/values.yaml b/packages/system/metallb/values.yaml index d392f4c4..dd5f76e6 100644 --- a/packages/system/metallb/values.yaml +++ b/packages/system/metallb/values.yaml @@ -4,8 +4,8 @@ metallb: controller: image: repository: ghcr.io/cozystack/cozystack/metallb-controller - tag: v0.15.2@sha256:0e9080234fc8eedab78ad2831fb38df375c383e901a752d72b353c8d13b9605f + tag: v0.15.2@sha256:623ce74b5802bff6e29f29478ccab29ce4162a64148be006c69e16cc3207e289 speaker: image: repository: ghcr.io/cozystack/cozystack/metallb-speaker - tag: v0.15.2@sha256:e14d4c328c3ab91a6eadfeea90da96388503492d165e7e8582f291b1872e53b2 + tag: v0.15.2@sha256:f264058afd9228452a260ab9c9dd1859404745627a2a38c2ba4671e27f3b3bb2 diff --git a/packages/system/metrics-server/Makefile b/packages/system/metrics-server/Makefile index fb89db64..87477ea0 100644 --- a/packages/system/metrics-server/Makefile +++ b/packages/system/metrics-server/Makefile @@ -1,7 +1,7 @@ export NAME=metrics-server export NAMESPACE=cozy-monitoring -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/mongodb-operator/.helmignore b/packages/system/mongodb-operator/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packages/system/mongodb-operator/.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/packages/system/mongodb-operator/Chart.yaml b/packages/system/mongodb-operator/Chart.yaml new file mode 100644 index 00000000..6dc477a8 --- /dev/null +++ b/packages/system/mongodb-operator/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-mongodb-operator +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/mongodb-operator/Makefile b/packages/system/mongodb-operator/Makefile new file mode 100644 index 00000000..886eb569 --- /dev/null +++ b/packages/system/mongodb-operator/Makefile @@ -0,0 +1,11 @@ +export NAME=mongodb-operator +export NAMESPACE=cozy-$(NAME) + +include ../../../hack/package.mk + +update: + rm -rf charts + helm repo add percona https://percona.github.io/percona-helm-charts + helm repo update percona + helm pull percona/psmdb-operator --untar --untardir charts + rm -rf charts/psmdb-operator/charts diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/.helmignore b/packages/system/mongodb-operator/charts/psmdb-operator/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-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/packages/system/mongodb-operator/charts/psmdb-operator/Chart.yaml b/packages/system/mongodb-operator/charts/psmdb-operator/Chart.yaml new file mode 100644 index 00000000..4c268c13 --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +appVersion: 1.21.1 +description: A Helm chart for deploying the Percona Operator for MongoDB +home: https://docs.percona.com/percona-operator-for-mongodb/ +maintainers: +- email: natalia.marukovich@percona.com + name: nmarukovich +- email: julio.pasinatto@percona.com + name: jvpasinatto +- email: eleonora.zinchenko@percona.com + name: eleo007 +name: psmdb-operator +version: 1.21.2 diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/LICENSE.txt b/packages/system/mongodb-operator/charts/psmdb-operator/LICENSE.txt new file mode 100644 index 00000000..6a31453a --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/LICENSE.txt @@ -0,0 +1,13 @@ +Copyright 2019 Paul Czarkowski + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/README.md b/packages/system/mongodb-operator/charts/psmdb-operator/README.md new file mode 100644 index 00000000..18292d17 --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/README.md @@ -0,0 +1,77 @@ +# Percona Operator for MongoDB + +Percona Operator for MongoDB allows users to deploy and manage Percona Server for MongoDB Clusters on Kubernetes. +Useful links: +- [Operator Github repository](https://github.com/percona/percona-server-mongodb-operator) +- [Operator Documentation](https://www.percona.com/doc/kubernetes-operator-for-psmongodb/index.html) + +## Pre-requisites +* Kubernetes 1.30+ +* Helm v3 + +# Installation + +This chart will deploy the Operator Pod for the further Percona Server for MongoDB creation in Kubernetes. + +## Installing the chart + +To install the chart with the `psmdb` release name using a dedicated namespace (recommended): + +```sh +helm repo add percona https://percona.github.io/percona-helm-charts/ +helm install my-operator percona/psmdb-operator --version 1.21.2 --namespace my-namespace +``` + +The chart can be customized using the following configurable parameters: + +| Parameter | Description | Default | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | +| `image.repository` | PSMDB Operator Container image name | `percona/percona-server-mongodb-operator` | +| `image.tag` | PSMDB Operator Container image tag | `1.21.1` | +| `image.pullPolicy` | PSMDB Operator Container pull policy | `Always` | +| `image.pullSecrets` | PSMDB Operator Pod pull secret | `[]` | +| `replicaCount` | PSMDB Operator Pod quantity | `1` | +| `tolerations` | List of node taints to tolerate | `[]` | +| `annotations` | PSMDB Operator Deployment annotations | `{}` | +| `podAnnotations` | PSMDB Operator Pod annotations | `{}` | +| `labels` | PSMDB Operator Deployment labels | `{}` | +| `podLabels` | PSMDB Operator Pod labels | `{}` | +| `resources` | Resource requests and limits | `{}` | +| `nodeSelector` | Labels for Pod assignment | `{}` | +| `podAnnotations` | Annotations for pod | `{}` | +| `podSecurityContext` | Pod Security Context | `{}` | +| `watchNamespace` | Set when a different from default namespace is needed to watch (comma separated if multiple needed) | `""` | +| `createNamespace` | Set if you want to create watched namespaces with helm | `false` | +| `rbac.create` | If false RBAC will not be created. RBAC resources will need to be created manually | `true` | +| `securityContext` | Container Security Context | `{}` | +| `serviceAccount.create` | If false the ServiceAccounts will not be created. The ServiceAccounts must be created manually | `true` | +| `serviceAccount.annotations` | PSMDB Operator ServiceAccount annotations | `{}` | +| `logStructured` | Force PSMDB operator to print JSON-wrapped log messages | `false` | +| `logLevel` | PSMDB Operator logging level | `INFO` | +| `disableTelemetry` | Disable sending PSMDB Operator telemetry data to Percona | `false` | +| `maxConcurrentReconciles` | Number of concurrent workers that can reconcile resources in Percona Server for MongoDB clusters in parallel | `1` | + +Specify parameters using `--set key=value[,key=value]` argument to `helm install` + +Alternatively a YAML file that specifies the values for the parameters can be provided like this: + +```sh +helm install psmdb-operator -f values.yaml percona/psmdb-operator +``` + +## Deploy the database + +To deploy Percona Server for MongoDB run the following command: + +```sh +helm install my-db percona/psmdb-db +``` + +See more about Percona Server for MongoDB deployment in its chart [here](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-db) or in the [Helm chart installation guide](https://www.percona.com/doc/kubernetes-operator-for-psmongodb/helm.html). + +# Need help? + +**Commercial Support** | **Community Support** | +:-: | :-: | +|
Enterprise-grade assistance for your mission-critical database deployments in containers and Kubernetes. Get expert guidance for complex tasks like multi-cloud replication, database migration and building platforms.

|
Connect with our engineers and fellow users for general questions, troubleshooting, and sharing feedback and ideas.

| +| **[Get Percona Support](https://hubs.ly/Q02ZTH8Q0)** | **[Visit our Forum](https://forums.percona.com/)** | diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/crds/crd.yaml b/packages/system/mongodb-operator/charts/psmdb-operator/crds/crd.yaml new file mode 100644 index 00000000..47d11591 --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/crds/crd.yaml @@ -0,0 +1,25729 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.19.0 + labels: + app.kubernetes.io/component: crd + app.kubernetes.io/name: percona-server-mongodb + app.kubernetes.io/part-of: percona-server-mongodb-operator + app.kubernetes.io/version: v1.21.1 + name: perconaservermongodbbackups.psmdb.percona.com +spec: + group: psmdb.percona.com + names: + kind: PerconaServerMongoDBBackup + listKind: PerconaServerMongoDBBackupList + plural: perconaservermongodbbackups + shortNames: + - psmdb-backup + singular: perconaservermongodbbackup + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Cluster name + jsonPath: .spec.clusterName + name: Cluster + type: string + - description: Storage name + jsonPath: .spec.storageName + name: Storage + type: string + - description: Backup destination + jsonPath: .status.destination + name: Destination + type: string + - description: Backup type + jsonPath: .status.type + name: Type + type: string + - description: Backup size + jsonPath: .status.size + name: Size + type: string + - description: Job status + jsonPath: .status.state + name: Status + type: string + - description: Completed time + jsonPath: .status.completed + name: Completed + type: date + - description: Created time + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + clusterName: + type: string + compressionLevel: + type: integer + compressionType: + type: string + startingDeadlineSeconds: + format: int64 + type: integer + storageName: + type: string + type: + enum: + - logical + - physical + - incremental + - incremental-base + type: string + type: object + status: + properties: + azure: + properties: + container: + type: string + credentialsSecret: + type: string + endpointUrl: + type: string + prefix: + type: string + required: + - credentialsSecret + type: object + completed: + format: date-time + type: string + destination: + type: string + error: + type: string + filesystem: + properties: + path: + type: string + required: + - path + type: object + gcs: + properties: + bucket: + type: string + chunkSize: + type: integer + credentialsSecret: + type: string + prefix: + type: string + retryer: + properties: + backoffInitial: + format: int64 + type: integer + backoffMax: + format: int64 + type: integer + backoffMultiplier: + type: number + required: + - backoffInitial + - backoffMax + - backoffMultiplier + type: object + required: + - bucket + - credentialsSecret + type: object + lastTransition: + format: date-time + type: string + lastWriteAt: + format: date-time + type: string + latestRestorableTime: + format: date-time + type: string + pbmName: + type: string + pbmPod: + type: string + pbmPods: + additionalProperties: + type: string + type: object + replsetNames: + items: + type: string + type: array + s3: + properties: + bucket: + type: string + credentialsSecret: + type: string + debugLogLevels: + type: string + endpointUrl: + type: string + forcePathStyle: + type: boolean + insecureSkipTLSVerify: + type: boolean + maxUploadParts: + format: int32 + type: integer + prefix: + type: string + region: + type: string + retryer: + properties: + maxRetryDelay: + type: string + minRetryDelay: + type: string + numMaxRetries: + type: integer + type: object + serverSideEncryption: + properties: + kmsKeyID: + type: string + sseAlgorithm: + type: string + sseCustomerAlgorithm: + type: string + sseCustomerKey: + type: string + type: object + storageClass: + type: string + uploadPartSize: + type: integer + required: + - bucket + type: object + size: + type: string + start: + format: date-time + type: string + state: + type: string + storageName: + type: string + type: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.19.0 + labels: + app.kubernetes.io/component: crd + app.kubernetes.io/name: percona-server-mongodb + app.kubernetes.io/part-of: percona-server-mongodb-operator + app.kubernetes.io/version: v1.21.1 + name: perconaservermongodbrestores.psmdb.percona.com +spec: + group: psmdb.percona.com + names: + kind: PerconaServerMongoDBRestore + listKind: PerconaServerMongoDBRestoreList + plural: perconaservermongodbrestores + shortNames: + - psmdb-restore + singular: perconaservermongodbrestore + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Cluster name + jsonPath: .spec.clusterName + name: Cluster + type: string + - description: Job status + jsonPath: .status.state + name: Status + type: string + - description: Created time + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + backupName: + type: string + backupSource: + properties: + azure: + properties: + container: + type: string + credentialsSecret: + type: string + endpointUrl: + type: string + prefix: + type: string + required: + - credentialsSecret + type: object + completed: + format: date-time + type: string + destination: + type: string + error: + type: string + filesystem: + properties: + path: + type: string + required: + - path + type: object + gcs: + properties: + bucket: + type: string + chunkSize: + type: integer + credentialsSecret: + type: string + prefix: + type: string + retryer: + properties: + backoffInitial: + format: int64 + type: integer + backoffMax: + format: int64 + type: integer + backoffMultiplier: + type: number + required: + - backoffInitial + - backoffMax + - backoffMultiplier + type: object + required: + - bucket + - credentialsSecret + type: object + lastTransition: + format: date-time + type: string + lastWriteAt: + format: date-time + type: string + latestRestorableTime: + format: date-time + type: string + pbmName: + type: string + pbmPod: + type: string + pbmPods: + additionalProperties: + type: string + type: object + replsetNames: + items: + type: string + type: array + s3: + properties: + bucket: + type: string + credentialsSecret: + type: string + debugLogLevels: + type: string + endpointUrl: + type: string + forcePathStyle: + type: boolean + insecureSkipTLSVerify: + type: boolean + maxUploadParts: + format: int32 + type: integer + prefix: + type: string + region: + type: string + retryer: + properties: + maxRetryDelay: + type: string + minRetryDelay: + type: string + numMaxRetries: + type: integer + type: object + serverSideEncryption: + properties: + kmsKeyID: + type: string + sseAlgorithm: + type: string + sseCustomerAlgorithm: + type: string + sseCustomerKey: + type: string + type: object + storageClass: + type: string + uploadPartSize: + type: integer + required: + - bucket + type: object + size: + type: string + start: + format: date-time + type: string + state: + type: string + storageName: + type: string + type: + type: string + type: object + clusterName: + type: string + pitr: + properties: + date: + type: string + type: + type: string + type: object + x-kubernetes-validations: + - message: 'Time should be in format YYYY-MM-DD HH:MM:SS with valid + ranges (MM: 01-12, DD: 01-31, HH: 00-23, MM/SS: 00-59)' + rule: self.type != 'date' || (has(self.date) && self.date.matches('^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01]) + ([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$')) + - message: Date should not be used when 'latest' type is used + rule: self.type != 'latest' || !has(self.date) + replset: + type: string + selective: + properties: + namespaces: + items: + type: string + type: array + withUsersAndRoles: + type: boolean + type: object + storageName: + type: string + type: object + status: + properties: + completed: + format: date-time + type: string + error: + type: string + lastTransition: + format: date-time + type: string + pbmName: + type: string + pitrTarget: + type: string + state: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.19.0 + labels: + app.kubernetes.io/component: crd + app.kubernetes.io/name: percona-server-mongodb + app.kubernetes.io/part-of: percona-server-mongodb-operator + app.kubernetes.io/version: v1.21.1 + name: perconaservermongodbs.psmdb.percona.com +spec: + group: psmdb.percona.com + names: + kind: PerconaServerMongoDB + listKind: PerconaServerMongoDBList + plural: perconaservermongodbs + shortNames: + - psmdb + singular: perconaservermongodb + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-2-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-2-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-3-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-3-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-4-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-4-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-5-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-5-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-6-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-6-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-7-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-7-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-8-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-8-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-9-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-9-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-10-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-10-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-11-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-11-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: psmdb.percona.com/v1-12-0 PerconaServerMongoDB is deprecated + and will be removed in v1.17.0; see v1.13.0 release notes for instructions to + migrate to psmdb.percona.com/v1 + name: v1-12-0 + schema: + openAPIV3Schema: + properties: + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + status: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.host + name: ENDPOINT + type: string + - jsonPath: .status.state + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + allowUnsafeConfigurations: + type: boolean + backup: + properties: + annotations: + additionalProperties: + type: string + type: object + configuration: + properties: + backupOptions: + properties: + numParallelCollections: + type: integer + oplogSpanMin: + type: number + priority: + additionalProperties: + type: number + type: object + timeouts: + properties: + startingStatus: + format: int32 + type: integer + type: object + required: + - oplogSpanMin + type: object + restoreOptions: + properties: + batchSize: + type: integer + downloadChunkMb: + type: integer + maxDownloadBufferMb: + type: integer + mongodLocation: + type: string + mongodLocationMap: + additionalProperties: + type: string + type: object + numDownloadWorkers: + type: integer + numInsertionWorkers: + type: integer + numParallelCollections: + type: integer + type: object + type: object + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + enabled: + type: boolean + image: + type: string + labels: + additionalProperties: + type: string + type: object + pitr: + properties: + compressionLevel: + type: integer + compressionType: + type: string + enabled: + type: boolean + oplogOnly: + type: boolean + oplogSpanMin: + type: number + type: object + podSecurityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + startingDeadlineSeconds: + format: int64 + type: integer + storages: + additionalProperties: + properties: + azure: + properties: + container: + type: string + credentialsSecret: + type: string + endpointUrl: + type: string + prefix: + type: string + required: + - credentialsSecret + type: object + filesystem: + properties: + path: + type: string + required: + - path + type: object + gcs: + properties: + bucket: + type: string + chunkSize: + type: integer + credentialsSecret: + type: string + prefix: + type: string + retryer: + properties: + backoffInitial: + format: int64 + type: integer + backoffMax: + format: int64 + type: integer + backoffMultiplier: + type: number + required: + - backoffInitial + - backoffMax + - backoffMultiplier + type: object + required: + - bucket + - credentialsSecret + type: object + main: + type: boolean + s3: + properties: + bucket: + type: string + credentialsSecret: + type: string + debugLogLevels: + type: string + endpointUrl: + type: string + forcePathStyle: + type: boolean + insecureSkipTLSVerify: + type: boolean + maxUploadParts: + format: int32 + type: integer + prefix: + type: string + region: + type: string + retryer: + properties: + maxRetryDelay: + type: string + minRetryDelay: + type: string + numMaxRetries: + type: integer + type: object + serverSideEncryption: + properties: + kmsKeyID: + type: string + sseAlgorithm: + type: string + sseCustomerAlgorithm: + type: string + sseCustomerKey: + type: string + type: object + storageClass: + type: string + uploadPartSize: + type: integer + required: + - bucket + type: object + type: + type: string + required: + - type + type: object + type: object + tasks: + items: + properties: + compressionLevel: + type: integer + compressionType: + type: string + enabled: + type: boolean + keep: + type: integer + name: + type: string + retention: + properties: + count: + minimum: 0 + type: integer + deleteFromStorage: + default: true + type: boolean + type: + enum: + - count + type: string + required: + - deleteFromStorage + - type + type: object + schedule: + type: string + storageName: + type: string + type: + enum: + - logical + - physical + - incremental + - incremental-base + type: string + required: + - enabled + - name + type: object + type: array + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + required: + - enabled + - image + type: object + clusterServiceDNSMode: + type: string + clusterServiceDNSSuffix: + type: string + crVersion: + type: string + enableExternalVolumeAutoscaling: + type: boolean + enableVolumeExpansion: + type: boolean + ignoreAnnotations: + items: + type: string + type: array + ignoreLabels: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + initContainerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + initImage: + type: string + logcollector: + properties: + configuration: + type: string + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + enabled: + type: boolean + image: + type: string + imagePullPolicy: + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + type: object + multiCluster: + properties: + DNSSuffix: + type: string + enabled: + type: boolean + required: + - enabled + type: object + pause: + type: boolean + platform: + type: string + pmm: + properties: + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + customClusterName: + type: string + enabled: + type: boolean + image: + type: string + mongodParams: + type: string + mongosParams: + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + serverHost: + type: string + required: + - image + type: object + replsets: + items: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + arbiter: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + enabled: + type: boolean + labels: + additionalProperties: + type: string + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + priorityClassName: + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + required: + - enabled + - size + type: object + clusterRole: + type: string + configuration: + type: string + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + expose: + properties: + annotations: + additionalProperties: + type: string + type: object + enabled: + type: boolean + exposeType: + type: string + externalTrafficPolicy: + type: string + internalTrafficPolicy: + type: string + labels: + additionalProperties: + type: string + type: object + loadBalancerClass: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + serviceAnnotations: + additionalProperties: + type: string + type: object + serviceLabels: + additionalProperties: + type: string + type: object + type: + type: string + required: + - enabled + type: object + externalNodes: + items: + properties: + horizons: + additionalProperties: + type: string + type: object + host: + type: string + port: + type: integer + priority: + type: integer + tags: + additionalProperties: + type: string + type: object + votes: + type: integer + required: + - host + - priority + - votes + type: object + type: array + hidden: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + configuration: + type: string + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + enabled: + type: boolean + labels: + additionalProperties: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + startupDelaySeconds: + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + volumeSpec: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + persistentVolumeClaim: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + annotations: + additionalProperties: + type: string + type: object + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + labels: + additionalProperties: + type: string + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + required: + - enabled + - size + type: object + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + labels: + additionalProperties: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + startupDelaySeconds: + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + nonvoting: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + configuration: + type: string + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + enabled: + type: boolean + labels: + additionalProperties: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + startupDelaySeconds: + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + volumeSpec: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + persistentVolumeClaim: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + annotations: + additionalProperties: + type: string + type: object + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + labels: + additionalProperties: + type: string + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + required: + - enabled + - size + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + primaryPreferTagSelector: + additionalProperties: + type: string + type: object + priorityClassName: + type: string + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + replsetOverrides: + additionalProperties: + properties: + horizons: + additionalProperties: + type: string + type: object + host: + type: string + priority: + type: integer + tags: + additionalProperties: + type: string + type: object + type: object + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + splitHorizons: + additionalProperties: + additionalProperties: + type: string + type: object + type: object + storage: + properties: + directoryPerDB: + type: boolean + engine: + type: string + inMemory: + properties: + engineConfig: + properties: + inMemorySizeRatio: + type: number + type: object + type: object + mmapv1: + properties: + nsSize: + type: integer + smallfiles: + type: boolean + type: object + syncPeriodSecs: + type: integer + wiredTiger: + properties: + collectionConfig: + properties: + blockCompressor: + type: string + type: object + engineConfig: + properties: + cacheSizeRatio: + type: number + directoryForIndexes: + type: boolean + journalCompressor: + type: string + type: object + indexConfig: + properties: + prefixCompression: + type: boolean + type: object + type: object + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + volumeSpec: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + persistentVolumeClaim: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + annotations: + additionalProperties: + type: string + type: object + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + labels: + additionalProperties: + type: string + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + required: + - size + type: object + type: array + roles: + items: + properties: + authenticationRestrictions: + items: + properties: + clientSource: + items: + type: string + type: array + serverAddress: + items: + type: string + type: array + type: object + type: array + db: + type: string + privileges: + items: + properties: + actions: + items: + type: string + type: array + resource: + properties: + cluster: + type: boolean + collection: + type: string + db: + type: string + type: object + required: + - actions + type: object + type: array + role: + type: string + roles: + items: + properties: + db: + type: string + role: + type: string + required: + - db + - role + type: object + type: array + required: + - db + - privileges + - role + type: object + type: array + schedulerName: + type: string + secrets: + properties: + encryptionKey: + type: string + keyFile: + type: string + ldapSecret: + type: string + sse: + type: string + ssl: + type: string + sslInternal: + type: string + users: + type: string + vault: + type: string + type: object + sharding: + properties: + balancer: + properties: + enabled: + type: boolean + type: object + configsvrReplSet: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + arbiter: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + enabled: + type: boolean + labels: + additionalProperties: + type: string + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + priorityClassName: + type: string + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + required: + - enabled + - size + type: object + clusterRole: + type: string + configuration: + type: string + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + expose: + properties: + annotations: + additionalProperties: + type: string + type: object + enabled: + type: boolean + exposeType: + type: string + externalTrafficPolicy: + type: string + internalTrafficPolicy: + type: string + labels: + additionalProperties: + type: string + type: object + loadBalancerClass: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + serviceAnnotations: + additionalProperties: + type: string + type: object + serviceLabels: + additionalProperties: + type: string + type: object + type: + type: string + required: + - enabled + type: object + externalNodes: + items: + properties: + horizons: + additionalProperties: + type: string + type: object + host: + type: string + port: + type: integer + priority: + type: integer + tags: + additionalProperties: + type: string + type: object + votes: + type: integer + required: + - host + - priority + - votes + type: object + type: array + hidden: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + configuration: + type: string + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + enabled: + type: boolean + labels: + additionalProperties: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + startupDelaySeconds: + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + volumeSpec: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + persistentVolumeClaim: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + annotations: + additionalProperties: + type: string + type: object + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + labels: + additionalProperties: + type: string + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + required: + - enabled + - size + type: object + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + labels: + additionalProperties: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + startupDelaySeconds: + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + nonvoting: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + configuration: + type: string + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + enabled: + type: boolean + labels: + additionalProperties: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + startupDelaySeconds: + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + priorityClassName: + type: string + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + volumeSpec: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + persistentVolumeClaim: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + annotations: + additionalProperties: + type: string + type: object + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + labels: + additionalProperties: + type: string + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + required: + - enabled + - size + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + primaryPreferTagSelector: + additionalProperties: + type: string + type: object + priorityClassName: + type: string + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + replsetOverrides: + additionalProperties: + properties: + horizons: + additionalProperties: + type: string + type: object + host: + type: string + priority: + type: integer + tags: + additionalProperties: + type: string + type: object + type: object + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + splitHorizons: + additionalProperties: + additionalProperties: + type: string + type: object + type: object + storage: + properties: + directoryPerDB: + type: boolean + engine: + type: string + inMemory: + properties: + engineConfig: + properties: + inMemorySizeRatio: + type: number + type: object + type: object + mmapv1: + properties: + nsSize: + type: integer + smallfiles: + type: boolean + type: object + syncPeriodSecs: + type: integer + wiredTiger: + properties: + collectionConfig: + properties: + blockCompressor: + type: string + type: object + engineConfig: + properties: + cacheSizeRatio: + type: number + directoryForIndexes: + type: boolean + journalCompressor: + type: string + type: object + indexConfig: + properties: + prefixCompression: + type: boolean + type: object + type: object + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + volumeSpec: + properties: + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + persistentVolumeClaim: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + annotations: + additionalProperties: + type: string + type: object + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + labels: + additionalProperties: + type: string + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + type: object + required: + - size + type: object + enabled: + type: boolean + mongos: + properties: + affinity: + properties: + advanced: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + 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 + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + antiAffinityTopologyKey: + type: string + type: object + annotations: + additionalProperties: + type: string + type: object + configuration: + type: string + containerSecurityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + expose: + properties: + annotations: + additionalProperties: + type: string + type: object + exposeType: + type: string + externalTrafficPolicy: + type: string + internalTrafficPolicy: + type: string + labels: + additionalProperties: + type: string + type: object + loadBalancerClass: + type: string + loadBalancerSourceRanges: + items: + type: string + type: array + nodePort: + format: int32 + type: integer + serviceAnnotations: + additionalProperties: + type: string + type: object + serviceLabels: + additionalProperties: + type: string + type: object + servicePerPod: + type: boolean + type: + type: string + type: object + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + hostPort: + format: int32 + type: integer + labels: + additionalProperties: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + startupDelaySeconds: + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podDisruptionBudget: + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + type: object + podSecurityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + port: + format: int32 + type: integer + priorityClassName: + type: string + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + runtimeClassName: + type: string + serviceAccountName: + type: string + setParameter: + properties: + cursorTimeoutMillis: + type: integer + type: object + sidecarPVCs: + items: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + status: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + allocatedResourceStatuses: + additionalProperties: + type: string + 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 + 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 + type: object + conditions: + items: + properties: + lastProbeTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + currentVolumeAttributesClassName: + type: string + modifyVolumeStatus: + properties: + status: + type: string + targetVolumeAttributesClassName: + type: string + required: + - status + type: object + phase: + type: string + type: object + type: object + type: array + sidecarVolumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + 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 + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + 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 + 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 + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + sidecars: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + 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 + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + 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 + 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 + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + size: + format: int32 + type: integer + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + required: + - enabled + type: object + tls: + properties: + allowInvalidCertificates: + type: boolean + certValidityDuration: + type: string + issuerConf: + properties: + group: + type: string + kind: + type: string + name: + type: string + required: + - name + type: object + mode: + type: string + type: object + unmanaged: + type: boolean + unsafeFlags: + properties: + backupIfUnhealthy: + type: boolean + mongosSize: + type: boolean + replsetSize: + type: boolean + terminationGracePeriod: + type: boolean + tls: + type: boolean + type: object + updateStrategy: + type: string + upgradeOptions: + properties: + apply: + type: string + schedule: + type: string + setFCV: + type: boolean + versionServiceEndpoint: + type: string + type: object + users: + items: + properties: + db: + type: string + name: + type: string + passwordSecretRef: + properties: + key: + type: string + name: + type: string + required: + - name + type: object + roles: + items: + properties: + db: + type: string + name: + type: string + required: + - db + - name + type: object + type: array + required: + - name + - roles + type: object + type: array + required: + - image + type: object + status: + properties: + backupConfigHash: + type: string + backupImage: + type: string + backupVersion: + type: string + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + host: + type: string + message: + type: string + mongoImage: + type: string + mongoVersion: + type: string + mongos: + properties: + message: + type: string + ready: + type: integer + size: + type: integer + status: + type: string + required: + - ready + - size + type: object + observedGeneration: + format: int64 + type: integer + pmmStatus: + type: string + pmmVersion: + type: string + ready: + format: int32 + type: integer + replsets: + additionalProperties: + properties: + added_as_shard: + type: boolean + clusterRole: + type: string + initialized: + type: boolean + members: + additionalProperties: + properties: + name: + type: string + state: + type: integer + stateStr: + type: string + type: object + type: object + message: + type: string + ready: + format: int32 + type: integer + size: + format: int32 + type: integer + status: + type: string + required: + - ready + - size + type: object + type: object + size: + format: int32 + type: integer + state: + type: string + required: + - ready + - size + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/templates/NOTES.txt b/packages/system/mongodb-operator/charts/psmdb-operator/templates/NOTES.txt new file mode 100644 index 00000000..9276ae03 --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/templates/NOTES.txt @@ -0,0 +1,40 @@ +1. Percona Operator for MongoDB is deployed. + See if the operator Pod is running: + + kubectl get pods -l app.kubernetes.io/name=psmdb-operator --namespace {{ .Release.Namespace }} + + Check the operator logs if the Pod is not starting: + + export POD=$(kubectl get pods -l app.kubernetes.io/name=psmdb-operator --namespace {{ .Release.Namespace }} --output name) + kubectl logs $POD --namespace={{ .Release.Namespace }} + +2. Deploy the database cluster from psmdb-db chart: + + helm install my-db percona/psmdb-db --namespace={{ .Release.Namespace }} + +{{- if .Release.IsUpgrade }} + {{- $ctx := dict "upgradeCrd" false }} + {{- $crdNames := list "perconaservermongodbbackups.psmdb.percona.com" "perconaservermongodbrestores.psmdb.percona.com " "perconaservermongodbs.psmdb.percona.com" }} + {{- range $name := $crdNames }} + {{- $crd := lookup "apiextensions.k8s.io/v1" "CustomResourceDefinition" "" $name }} + {{- if $crd }} + {{- $crdLabels := (($crd).metadata).labels | default dict }} + {{- $crdVersion := index $crdLabels "app.kubernetes.io/version" }} + {{- if or (not $crdVersion) (semverCompare (printf "< %s" $.Chart.AppVersion) (trimPrefix "v" $crdVersion)) }} + {{- $_ := set $ctx "upgradeCrd" true }} + {{- end }} + {{- end }} + {{- end }} + {{- if $ctx.upgradeCrd }} + +** WARNING ** During Helm upgrade CRDs are not automatically upgraded. + +Consider upgrading to the latest version of the CRDs using the command below: + + kubectl apply --server-side --force-conflicts -f https://raw.githubusercontent.com/percona/percona-server-mongodb-operator/v{{ .Chart.AppVersion }}/deploy/crd.yaml + +Ensure all deprecated fields are reviewed as part of the upgrade process, especially when running multiple PSMDB Operator versions in the same cluster. Deprecated fields may be removed or unsupported in newer CRD versions. + {{- end }} +{{- end }} + +Read more in our documentation: https://docs.percona.com/percona-operator-for-mongodb/ diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/templates/_helpers.tpl b/packages/system/mongodb-operator/charts/psmdb-operator/templates/_helpers.tpl new file mode 100644 index 00000000..1bf81ed1 --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/templates/_helpers.tpl @@ -0,0 +1,45 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "psmdb-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 "psmdb-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 "psmdb-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "psmdb-operator.labels" -}} +app.kubernetes.io/name: {{ include "psmdb-operator.name" . }} +helm.sh/chart: {{ include "psmdb-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 }} +{{- end -}} diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/templates/deployment.yaml b/packages/system/mongodb-operator/charts/psmdb-operator/templates/deployment.yaml new file mode 100644 index 00000000..14e2eb89 --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/templates/deployment.yaml @@ -0,0 +1,112 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "psmdb-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "psmdb-operator.labels" . | nindent 4 }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "psmdb-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/name: {{ include "psmdb-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "psmdb-operator.fullname" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: 8080 + protocol: TCP + name: metrics + - containerPort: 8081 + protocol: TCP + name: health + command: + - percona-server-mongodb-operator + {{- if .Values.securityContext.readOnlyRootFilesystem }} + volumeMounts: + - name: tmpdir + mountPath: /tmp + {{- end }} + env: + - name: LOG_STRUCTURED + value: "{{ .Values.logStructured }}" + - name: LOG_LEVEL + value: "{{ .Values.logLevel }}" + - name: WATCH_NAMESPACE + {{- if .Values.watchAllNamespaces }} + value: "" + {{- else }} + value: "{{ default .Release.Namespace .Values.watchNamespace }}" + {{- end }} + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: {{ default "percona-server-mongodb-operator" .Values.operatorName }} + - name: RESYNC_PERIOD + value: "{{ .Values.env.resyncPeriod }}" + - name: DISABLE_TELEMETRY + value: "{{ .Values.disableTelemetry }}" + {{- if .Values.maxConcurrentReconciles }} + - name: MAX_CONCURRENT_RECONCILES + value: "{{ .Values.maxConcurrentReconciles }}" + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: health + readinessProbe: + httpGet: + path: /healthz + port: health + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.securityContext.readOnlyRootFilesystem }} + volumes: + - name: tmpdir + emptyDir: {} + {{- end }} diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/templates/namespace.yaml b/packages/system/mongodb-operator/charts/psmdb-operator/templates/namespace.yaml new file mode 100644 index 00000000..cfc96d4d --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/templates/namespace.yaml @@ -0,0 +1,11 @@ +{{ if and .Values.watchNamespace .Values.createNamespace }} +{{ range ( split "," .Values.watchNamespace ) }} +apiVersion: v1 +kind: Namespace +metadata: + name: {{ trim . }} + annotations: + helm.sh/resource-policy: keep +--- +{{ end }} +{{ end }} diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/templates/role-binding.yaml b/packages/system/mongodb-operator/charts/psmdb-operator/templates/role-binding.yaml new file mode 100644 index 00000000..a815869d --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/templates/role-binding.yaml @@ -0,0 +1,41 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "psmdb-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +--- +{{- end }} +{{- if .Values.rbac.create }} +{{- if or .Values.watchNamespace .Values.watchAllNamespaces }} +kind: ClusterRoleBinding +{{- else }} +kind: RoleBinding +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: service-account-{{ include "psmdb-operator.fullname" . }} +{{- if not (or .Values.watchNamespace .Values.watchAllNamespaces) }} + namespace: {{ .Release.Namespace }} +{{- end }} + labels: +{{ include "psmdb-operator.labels" . | indent 4 }} +subjects: +- kind: ServiceAccount + name: {{ include "psmdb-operator.fullname" . }} + {{- if or .Values.watchNamespace .Values.watchAllNamespaces }} + namespace: {{ .Release.Namespace }} + {{- end }} +roleRef: + {{- if or .Values.watchNamespace .Values.watchAllNamespaces }} + kind: ClusterRole + {{- else }} + kind: Role + {{- end }} + name: {{ include "psmdb-operator.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/templates/role.yaml b/packages/system/mongodb-operator/charts/psmdb-operator/templates/role.yaml new file mode 100644 index 00000000..4d65e6a7 --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/templates/role.yaml @@ -0,0 +1,167 @@ +{{- if .Values.rbac.create }} +{{- if or .Values.watchNamespace .Values.watchAllNamespaces }} +kind: ClusterRole +{{- else }} +kind: Role +{{- end }} +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "psmdb-operator.fullname" . }} +{{- if not (or .Values.watchNamespace .Values.watchAllNamespaces) }} + namespace: {{ .Release.Namespace }} +{{- end }} + labels: +{{ include "psmdb-operator.labels" . | indent 4 }} +rules: + - apiGroups: + - psmdb.percona.com + resources: + - perconaservermongodbs + - perconaservermongodbs/status + - perconaservermongodbs/finalizers + - perconaservermongodbbackups + - perconaservermongodbbackups/status + - perconaservermongodbbackups/finalizers + - perconaservermongodbrestores + - perconaservermongodbrestores/status + - perconaservermongodbrestores/finalizers + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +{{- if or .Values.watchNamespace .Values.watchAllNamespaces }} + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch +{{- end }} + - apiGroups: + - "" + resources: + - pods + - pods/exec + - services + - persistentvolumeclaims + - secrets + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - apps + resources: + - deployments + - replicasets + - statefulsets + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - batch + resources: + - cronjobs + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - events.k8s.io + - "" + resources: + - events + verbs: + - get + - list + - watch + - create + - patch + - apiGroups: + - certmanager.k8s.io + - cert-manager.io + resources: + - issuers + - certificates + - certificaterequests + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - deletecollection + - apiGroups: + - net.gke.io + - multicluster.x-k8s.io + resources: + - serviceexports + - serviceimports + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - deletecollection +{{- end }} diff --git a/packages/system/mongodb-operator/charts/psmdb-operator/values.yaml b/packages/system/mongodb-operator/charts/psmdb-operator/values.yaml new file mode 100644 index 00000000..cc5ece0b --- /dev/null +++ b/packages/system/mongodb-operator/charts/psmdb-operator/values.yaml @@ -0,0 +1,103 @@ +# Default values for psmdb-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: percona/percona-server-mongodb-operator + tag: 1.21.1 + pullPolicy: IfNotPresent + +# disableTelemetry: according to +# https://docs.percona.com/percona-operator-for-mongodb/telemetry.html +# this is how you can disable telemetry collection +# default is false which means telemetry will be collected +disableTelemetry: false + +# set if you want to specify a namespace to watch +# defaults to `.Release.namespace` if left blank +# multiple namespaces can be specified and separated by comma +# watchNamespace: +# set if you want that watched namespaces are created by helm +# createNamespace: false + +# set if operator should be deployed in cluster wide mode. defaults to false +watchAllNamespaces: false + +# rbac: settings for deployer RBAC creation +rbac: + # rbac.create: if false RBAC resources should be in place + create: true + +# serviceAccount: settings for Service Accounts used by the deployer +serviceAccount: + # serviceAccount.create: Whether to create the Service Accounts or not + create: true + # annotations to add to the service account + annotations: {} + +# annotations to add to the operator deployment +annotations: {} + +# labels to add to the operator deployment +labels: {} + +# annotations to add to the operator pod +podAnnotations: {} + # prometheus.io/scrape: "true" + # prometheus.io/port: "8080" + +# labels to the operator pod +podLabels: {} + +podSecurityContext: {} + # runAsNonRoot: true + # runAsUser: 2 + # runAsGroup: 2 + # fsGroup: 2 + # fsGroupChangePolicy: "OnRootMismatch" + +securityContext: {} + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - ALL + # seccompProfile: + # type: RuntimeDefault + +# set if you want to use a different operator name +# defaults to `percona-server-mongodb-operator` +# operatorName: + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + resyncPeriod: 5s + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +logStructured: false +logLevel: "INFO" + +# maxConcurrentReconciles controls the number of concurrent workers +# that can reconcile resources in Percona Server for MongoDB clusters in parallel. +maxConcurrentReconciles: "1" diff --git a/packages/system/mongodb-operator/values.yaml b/packages/system/mongodb-operator/values.yaml new file mode 100644 index 00000000..b51a4e1d --- /dev/null +++ b/packages/system/mongodb-operator/values.yaml @@ -0,0 +1,2 @@ +psmdb-operator: + watchAllNamespaces: true diff --git a/packages/system/mongodb-rd/Chart.yaml b/packages/system/mongodb-rd/Chart.yaml new file mode 100644 index 00000000..41aafc6d --- /dev/null +++ b/packages/system/mongodb-rd/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: mongodb-rd +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/mongodb-rd/Makefile b/packages/system/mongodb-rd/Makefile new file mode 100644 index 00000000..fa32b825 --- /dev/null +++ b/packages/system/mongodb-rd/Makefile @@ -0,0 +1,4 @@ +export NAME=mongodb-rd +export NAMESPACE=cozy-system + +include ../../../hack/package.mk diff --git a/packages/system/mongodb-rd/cozyrds/mongodb.yaml b/packages/system/mongodb-rd/cozyrds/mongodb.yaml new file mode 100644 index 00000000..54909131 --- /dev/null +++ b/packages/system/mongodb-rd/cozyrds/mongodb.yaml @@ -0,0 +1,40 @@ +apiVersion: cozystack.io/v1alpha1 +kind: ApplicationDefinition +metadata: + name: mongodb +spec: + application: + kind: MongoDB + singular: mongodb + plural: mongodbs + openAPISchema: |- + {"title":"Chart Values","type":"object","properties":{"backup":{"description":"Backup configuration.","type":"object","default":{},"required":["enabled"],"properties":{"destinationPath":{"description":"Destination path for backups (e.g. s3://bucket/path/).","type":"string","default":"s3://bucket/path/to/folder/"},"enabled":{"description":"Enable regular backups.","type":"boolean","default":false},"endpointURL":{"description":"S3 endpoint URL for uploads.","type":"string","default":"http://minio-gateway-service:9000"},"retentionPolicy":{"description":"Retention policy (e.g. \"30d\").","type":"string","default":"30d"},"s3AccessKey":{"description":"Access key for S3 authentication.","type":"string","default":""},"s3SecretKey":{"description":"Secret key for S3 authentication.","type":"string","default":""},"schedule":{"description":"Cron schedule for automated backups.","type":"string","default":"0 2 * * *"}}},"bootstrap":{"description":"Bootstrap configuration.","type":"object","default":{},"required":["backupName","enabled"],"properties":{"backupName":{"description":"Name of backup to restore from.","type":"string","default":""},"enabled":{"description":"Whether to restore from a backup.","type":"boolean","default":false},"recoveryTime":{"description":"Timestamp for point-in-time recovery; empty means latest.","type":"string","default":""}}},"databases":{"description":"Databases configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"roles":{"description":"Roles assigned to users.","type":"object","properties":{"admin":{"description":"List of users with admin privileges (readWrite + dbAdmin).","type":"array","items":{"type":"string"}},"readonly":{"description":"List of users with read-only privileges.","type":"array","items":{"type":"string"}}}}}}},"external":{"description":"Enable external access from outside the cluster.","type":"boolean","default":false},"replicas":{"description":"Number of MongoDB replicas in replica set.","type":"integer","default":3},"resources":{"description":"Explicit CPU and memory configuration for each MongoDB replica. When omitted, the preset defined in `resourcesPreset` is applied.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset used when `resources` is omitted.","type":"string","default":"small","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"sharding":{"description":"Enable sharded cluster mode. When disabled, deploys a replica set.","type":"boolean","default":false},"shardingConfig":{"description":"Configuration for sharded cluster mode.","type":"object","default":{},"required":["configServerSize","configServers","mongos"],"properties":{"configServerSize":{"description":"PVC size for config servers.","default":"3Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"configServers":{"description":"Number of config server replicas.","type":"integer","default":3},"mongos":{"description":"Number of mongos router replicas.","type":"integer","default":2},"shards":{"description":"List of shard configurations.","type":"array","default":[{"name":"rs0","replicas":3,"size":"10Gi"}],"items":{"type":"object","required":["name","replicas","size"],"properties":{"name":{"description":"Shard name.","type":"string"},"replicas":{"description":"Number of replicas in this shard.","type":"integer"},"size":{"description":"PVC size for this shard.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}}}}},"size":{"description":"Persistent Volume Claim size available for application data.","default":"10Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":""},"users":{"description":"Users configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"password":{"description":"Password for the user (auto-generated if omitted).","type":"string"}}}},"version":{"description":"MongoDB major version to deploy.","type":"string","default":"v8","enum":["v8","v7","v6"]}}} + release: + prefix: mongodb- + labels: + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-mongodb-application-default-mongodb + namespace: cozy-system + dashboard: + category: PaaS + singular: MongoDB + plural: MongoDB Instances + description: Managed MongoDB service + tags: + - database + icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl9tb25nb2RiKSIvPgo8cGF0aCBkPSJNNzIgMjRDNzIgMjQgNzIgMjQgNzIgMjRDNzIgMjQgNTggNDAgNTggNjJDNTggODQgNzIgMTIwIDcyIDEyMEM3MiAxMjAgODYgODQgODYgNjJDODYgNDAgNzIgMjQgNzIgMjRaIiBmaWxsPSIjMDBFRDY0Ii8+CjxwYXRoIGQ9Ik03MiAxMjBDNzIgMTIwIDg2IDg0IDg2IDYyQzg2IDQwIDcyIDI0IDcyIDI0IiBzdHJva2U9IiMwMDY4NEEiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik03MiAyNEM3MiAyNCA1OCA0MCA1OCA2MkM1OCA4NCA3MiAxMjAgNzIgMTIwIiBzdHJva2U9IiMwMDFFMkIiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxyZWN0IHg9IjY5IiB5PSIxMDgiIHdpZHRoPSI2IiBoZWlnaHQ9IjE2IiByeD0iMiIgZmlsbD0iIzAwNjg0QSIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyX21vbmdvZGIiIHgxPSIxNDAiIHkxPSIxMzAuNSIgeDI9IjQiIHkyPSI5LjQ5OTk5IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiMwMDFFMkIiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDIzNDMwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg== + keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "replicas"], ["spec", "resources"], ["spec", "resourcesPreset"], ["spec", "size"], ["spec", "storageClass"], ["spec", "external"], ["spec", "version"], ["spec", "sharding"], ["spec", "shardingConfig"], ["spec", "shardingConfig", "configServers"], ["spec", "shardingConfig", "configServerSize"], ["spec", "shardingConfig", "mongos"], ["spec", "shardingConfig", "shards"], ["spec", "users"], ["spec", "databases"], ["spec", "backup"], ["spec", "backup", "enabled"], ["spec", "backup", "schedule"], ["spec", "backup", "retentionPolicy"], ["spec", "backup", "destinationPath"], ["spec", "backup", "endpointURL"], ["spec", "backup", "s3AccessKey"], ["spec", "backup", "s3SecretKey"], ["spec", "bootstrap"], ["spec", "bootstrap", "enabled"], ["spec", "bootstrap", "recoveryTime"], ["spec", "bootstrap", "backupName"]] + secrets: + exclude: [] + include: + - resourceNames: + - mongodb-{{ .name }}-credentials + services: + exclude: [] + include: + - resourceNames: + - mongodb-{{ .name }}-rs0 + - mongodb-{{ .name }}-mongos + - mongodb-{{ .name }}-external diff --git a/packages/system/mongodb-rd/templates/cozyrd.yaml b/packages/system/mongodb-rd/templates/cozyrd.yaml new file mode 100644 index 00000000..e079ddcf --- /dev/null +++ b/packages/system/mongodb-rd/templates/cozyrd.yaml @@ -0,0 +1,4 @@ +{{- range $path, $_ := .Files.Glob "cozyrds/*" }} +--- +{{ $.Files.Get $path }} +{{- end }} diff --git a/packages/system/mongodb-rd/values.yaml b/packages/system/mongodb-rd/values.yaml new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/packages/system/mongodb-rd/values.yaml @@ -0,0 +1 @@ +{} diff --git a/packages/system/monitoring-agents/Makefile b/packages/system/monitoring-agents/Makefile index f324bfef..339b15a2 100644 --- a/packages/system/monitoring-agents/Makefile +++ b/packages/system/monitoring-agents/Makefile @@ -1,7 +1,7 @@ export NAME=monitoring-agents export NAMESPACE=cozy-monitoring -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/monitoring-agents/templates/vpa.yaml b/packages/system/monitoring-agents/templates/vpa.yaml index fa672d82..4da978e7 100644 --- a/packages/system/monitoring-agents/templates/vpa.yaml +++ b/packages/system/monitoring-agents/templates/vpa.yaml @@ -9,6 +9,7 @@ spec: name: vmagent updatePolicy: updateMode: Auto + minReplicas: 1 resourcePolicy: containerPolicies: - containerName: config-reloader diff --git a/packages/system/monitoring-rd/Makefile b/packages/system/monitoring-rd/Makefile index ecce61e3..5b0bf43b 100644 --- a/packages/system/monitoring-rd/Makefile +++ b/packages/system/monitoring-rd/Makefile @@ -1,4 +1,4 @@ export NAME=monitoring-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/monitoring-rd/cozyrds/monitoring.yaml b/packages/system/monitoring-rd/cozyrds/monitoring.yaml index e3f098e4..b79f1cf6 100644 --- a/packages/system/monitoring-rd/cozyrds/monitoring.yaml +++ b/packages/system/monitoring-rd/cozyrds/monitoring.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: monitoring spec: @@ -12,14 +12,12 @@ spec: release: prefix: "" labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" - chart: - name: monitoring - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public + chartRef: + kind: ExternalArtifact + name: cozystack-monitoring-application-default-monitoring + namespace: cozy-system dashboard: category: Administration singular: Monitoring diff --git a/packages/system/multus/Makefile b/packages/system/multus/Makefile index b7ae5bfc..9b34606d 100644 --- a/packages/system/multus/Makefile +++ b/packages/system/multus/Makefile @@ -1,8 +1,8 @@ export NAME=multus export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/packages/system/multus/patches/customize-deployment.patch b/packages/system/multus/patches/customize-deployment.patch index 7ea3aeeb..b62d57e7 100644 --- a/packages/system/multus/patches/customize-deployment.patch +++ b/packages/system/multus/patches/customize-deployment.patch @@ -34,7 +34,7 @@ labels: tier: node app: multus -@@ -159,10 +159,10 @@ spec: +@@ -159,10 +159,9 @@ spec: resources: requests: cpu: "100m" @@ -43,7 +43,6 @@ limits: cpu: "100m" - memory: "50Mi" -+ memory: "900Mi" securityContext: privileged: true terminationMessagePolicy: FallbackToLogsOnError diff --git a/packages/system/multus/templates/multus-daemonset-thick.yml b/packages/system/multus/templates/multus-daemonset-thick.yml index ba7eedfb..2f00de85 100644 --- a/packages/system/multus/templates/multus-daemonset-thick.yml +++ b/packages/system/multus/templates/multus-daemonset-thick.yml @@ -162,7 +162,6 @@ spec: memory: "100Mi" limits: cpu: "100m" - memory: "900Mi" securityContext: privileged: true terminationMessagePolicy: FallbackToLogsOnError diff --git a/packages/system/mysql-rd/Makefile b/packages/system/mysql-rd/Makefile index a2d28923..2a8af787 100644 --- a/packages/system/mysql-rd/Makefile +++ b/packages/system/mysql-rd/Makefile @@ -1,4 +1,4 @@ export NAME=mysql-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/mysql-rd/cozyrds/mysql.yaml b/packages/system/mysql-rd/cozyrds/mysql.yaml index ba8251b8..9c2d6d32 100644 --- a/packages/system/mysql-rd/cozyrds/mysql.yaml +++ b/packages/system/mysql-rd/cozyrds/mysql.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: mysql spec: @@ -12,13 +12,11 @@ spec: release: prefix: mysql- labels: - cozystack.io/ui: "true" - chart: - name: mysql - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-mysql-application-default-mysql + namespace: cozy-system dashboard: category: PaaS singular: MySQL diff --git a/packages/system/nats-rd/Makefile b/packages/system/nats-rd/Makefile index 2b5b232e..4a72284c 100644 --- a/packages/system/nats-rd/Makefile +++ b/packages/system/nats-rd/Makefile @@ -1,4 +1,4 @@ export NAME=nats-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/nats-rd/cozyrds/nats.yaml b/packages/system/nats-rd/cozyrds/nats.yaml index 258f8f40..61c590d3 100644 --- a/packages/system/nats-rd/cozyrds/nats.yaml +++ b/packages/system/nats-rd/cozyrds/nats.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: nats spec: @@ -12,13 +12,11 @@ spec: release: prefix: nats- labels: - cozystack.io/ui: "true" - chart: - name: nats - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-nats-application-default-nats + namespace: cozy-system dashboard: category: PaaS singular: NATS diff --git a/packages/system/nats/Makefile b/packages/system/nats/Makefile index 25657a89..88883ab0 100644 --- a/packages/system/nats/Makefile +++ b/packages/system/nats/Makefile @@ -1,4 +1,4 @@ -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/nfs-driver/Makefile b/packages/system/nfs-driver/Makefile index e3af6c03..2f14aa28 100644 --- a/packages/system/nfs-driver/Makefile +++ b/packages/system/nfs-driver/Makefile @@ -1,8 +1,8 @@ export NAME=nfs-driver export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/objectstorage-controller/Makefile b/packages/system/objectstorage-controller/Makefile index 54c195a0..dacc3353 100644 --- a/packages/system/objectstorage-controller/Makefile +++ b/packages/system/objectstorage-controller/Makefile @@ -1,8 +1,8 @@ export NAME=objectstorage-controller export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/packages/system/objectstorage-controller/values.yaml b/packages/system/objectstorage-controller/values.yaml index 7a5b5c22..aa3756ad 100644 --- a/packages/system/objectstorage-controller/values.yaml +++ b/packages/system/objectstorage-controller/values.yaml @@ -1,3 +1,3 @@ objectstorage: controller: - image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v0.38.2@sha256:7d37495cce46d30d4613ecfacaa7b7f140e7ea8f3dbcc3e8c976e271de6cc71b" + image: "ghcr.io/cozystack/cozystack/objectstorage-controller:v1.0.0-beta.2@sha256:1f35e09bae32cd11c6ce2268556cac76b8da68b448208aea3c13071306087534" diff --git a/packages/system/opencost/Makefile b/packages/system/opencost/Makefile index cfef2167..43ee7032 100644 --- a/packages/system/opencost/Makefile +++ b/packages/system/opencost/Makefile @@ -1,7 +1,7 @@ export NAME=opencost export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package-system.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/piraeus-operator/Makefile b/packages/system/piraeus-operator/Makefile index a10c7369..b46680f2 100644 --- a/packages/system/piraeus-operator/Makefile +++ b/packages/system/piraeus-operator/Makefile @@ -1,7 +1,7 @@ export NAME=piraeus-operator export NAMESPACE=cozy-linstor -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/postgres-operator/Makefile b/packages/system/postgres-operator/Makefile index f1a0bba0..f58f235f 100644 --- a/packages/system/postgres-operator/Makefile +++ b/packages/system/postgres-operator/Makefile @@ -1,7 +1,7 @@ export NAME=postgres-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/postgres-rd/Makefile b/packages/system/postgres-rd/Makefile index 0c8b1cb0..7da8103a 100644 --- a/packages/system/postgres-rd/Makefile +++ b/packages/system/postgres-rd/Makefile @@ -1,4 +1,4 @@ export NAME=postgres-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/postgres-rd/cozyrds/postgres.yaml b/packages/system/postgres-rd/cozyrds/postgres.yaml index c3d16cb7..b2980e8c 100644 --- a/packages/system/postgres-rd/cozyrds/postgres.yaml +++ b/packages/system/postgres-rd/cozyrds/postgres.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: postgres spec: @@ -12,13 +12,11 @@ spec: release: prefix: postgres- labels: - cozystack.io/ui: "true" - chart: - name: postgres - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-postgres-application-default-postgres + namespace: cozy-system dashboard: category: PaaS singular: PostgreSQL diff --git a/packages/system/prometheus-operator-crds/Makefile b/packages/system/prometheus-operator-crds/Makefile index 173da9c1..ed55f286 100644 --- a/packages/system/prometheus-operator-crds/Makefile +++ b/packages/system/prometheus-operator-crds/Makefile @@ -1,7 +1,7 @@ export NAME=prometheus-operator-crds export NAMESPACE=cozy-victoria-metrics-operator -include ../../../scripts/package.mk +include ../../../hack/package.mk update: helm repo add prometheus-community https://prometheus-community.github.io/helm-charts diff --git a/packages/system/rabbitmq-operator/Makefile b/packages/system/rabbitmq-operator/Makefile index 12eda697..a75e37cd 100644 --- a/packages/system/rabbitmq-operator/Makefile +++ b/packages/system/rabbitmq-operator/Makefile @@ -1,7 +1,7 @@ export NAME=rabbitmq-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf templates/cluster-operator.yml diff --git a/packages/system/rabbitmq-rd/Makefile b/packages/system/rabbitmq-rd/Makefile index 9c5be0d5..7db599d7 100644 --- a/packages/system/rabbitmq-rd/Makefile +++ b/packages/system/rabbitmq-rd/Makefile @@ -1,4 +1,4 @@ export NAME=rabbitmq-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/rabbitmq-rd/cozyrds/rabbitmq.yaml b/packages/system/rabbitmq-rd/cozyrds/rabbitmq.yaml index 092142ac..1bbed02d 100644 --- a/packages/system/rabbitmq-rd/cozyrds/rabbitmq.yaml +++ b/packages/system/rabbitmq-rd/cozyrds/rabbitmq.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: rabbitmq spec: @@ -12,13 +12,11 @@ spec: release: prefix: rabbitmq- labels: - cozystack.io/ui: "true" - chart: - name: rabbitmq - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-rabbitmq-application-default-rabbitmq + namespace: cozy-system dashboard: category: PaaS singular: RabbitMQ diff --git a/packages/system/redis-operator/Makefile b/packages/system/redis-operator/Makefile index 650cbc72..9e21b1b4 100644 --- a/packages/system/redis-operator/Makefile +++ b/packages/system/redis-operator/Makefile @@ -2,8 +2,8 @@ REDIS_OPERATOR_TAG=$(shell grep -F 'ARG VERSION=' images/redis-operator/Dockerfi export NAME=redis-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/redis-rd/Makefile b/packages/system/redis-rd/Makefile index bed18877..e6aca9de 100644 --- a/packages/system/redis-rd/Makefile +++ b/packages/system/redis-rd/Makefile @@ -1,4 +1,4 @@ export NAME=redis-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/redis-rd/cozyrds/redis.yaml b/packages/system/redis-rd/cozyrds/redis.yaml index d23f8d2c..0a9aa989 100644 --- a/packages/system/redis-rd/cozyrds/redis.yaml +++ b/packages/system/redis-rd/cozyrds/redis.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: redis spec: @@ -12,13 +12,11 @@ spec: release: prefix: redis- labels: - cozystack.io/ui: "true" - chart: - name: redis - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-redis-application-default-redis + namespace: cozy-system dashboard: category: PaaS singular: Redis diff --git a/packages/system/reloader/Makefile b/packages/system/reloader/Makefile index 378dc23c..6dc1f004 100644 --- a/packages/system/reloader/Makefile +++ b/packages/system/reloader/Makefile @@ -1,7 +1,7 @@ export NAME=reloader export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/seaweedfs-rd/Makefile b/packages/system/seaweedfs-rd/Makefile index 5be03dbb..b4c5a2da 100644 --- a/packages/system/seaweedfs-rd/Makefile +++ b/packages/system/seaweedfs-rd/Makefile @@ -1,4 +1,4 @@ export NAME=seaweedfs-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/seaweedfs-rd/cozyrds/seaweedfs.yaml b/packages/system/seaweedfs-rd/cozyrds/seaweedfs.yaml index 787b5448..898e9f96 100644 --- a/packages/system/seaweedfs-rd/cozyrds/seaweedfs.yaml +++ b/packages/system/seaweedfs-rd/cozyrds/seaweedfs.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: seaweedfs spec: @@ -12,14 +12,12 @@ spec: release: prefix: "" labels: - cozystack.io/ui: "true" + sharding.fluxcd.io/key: tenants internal.cozystack.io/tenantmodule: "true" - chart: - name: seaweedfs - sourceRef: - kind: HelmRepository - name: cozystack-extra - namespace: cozy-public + chartRef: + kind: ExternalArtifact + name: cozystack-seaweedfs-application-default-seaweedfs + namespace: cozy-system dashboard: category: Administration singular: SeaweedFS diff --git a/packages/system/seaweedfs/Makefile b/packages/system/seaweedfs/Makefile index d1f21a80..c3a2f777 100644 --- a/packages/system/seaweedfs/Makefile +++ b/packages/system/seaweedfs/Makefile @@ -1,7 +1,7 @@ export NAME=seaweedfs-system -include ../../../scripts/common-envs.mk -include ../../../scripts/package.mk +include ../../../hack/common-envs.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/seaweedfs/values.yaml b/packages/system/seaweedfs/values.yaml index 830c4faa..3a60c779 100644 --- a/packages/system/seaweedfs/values.yaml +++ b/packages/system/seaweedfs/values.yaml @@ -177,7 +177,7 @@ seaweedfs: bucketClassName: "seaweedfs" region: "" sidecar: - image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v0.38.2@sha256:ff3281fe53a97d2cd5cd94bd4c4d8ff08189508729869bb39b3f60c80da5f919" + image: "ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-beta.2@sha256:ea035d4eff4a05d9d83f487d00438504cc27a95c0ee78c534d6eed53f4b2f04e" certificates: commonName: "SeaweedFS CA" ipAddresses: [] diff --git a/packages/system/snapshot-controller/Makefile b/packages/system/snapshot-controller/Makefile index 65d37f1f..ca5d39e7 100644 --- a/packages/system/snapshot-controller/Makefile +++ b/packages/system/snapshot-controller/Makefile @@ -1,7 +1,7 @@ export NAME=snapshot-controller export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/tcp-balancer-rd/Makefile b/packages/system/tcp-balancer-rd/Makefile index 39a0495f..c85634a6 100644 --- a/packages/system/tcp-balancer-rd/Makefile +++ b/packages/system/tcp-balancer-rd/Makefile @@ -1,4 +1,4 @@ export NAME=tcp-balancer-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/tcp-balancer-rd/cozyrds/tcp-balancer.yaml b/packages/system/tcp-balancer-rd/cozyrds/tcp-balancer.yaml index 057bc922..4f87f888 100644 --- a/packages/system/tcp-balancer-rd/cozyrds/tcp-balancer.yaml +++ b/packages/system/tcp-balancer-rd/cozyrds/tcp-balancer.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: tcp-balancer spec: @@ -12,13 +12,11 @@ spec: release: prefix: tcp-balancer- labels: - cozystack.io/ui: "true" - chart: - name: tcp-balancer - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-tcp-balancer-application-default-tcp-balancer + namespace: cozy-system dashboard: category: NaaS singular: TCP Balancer diff --git a/packages/system/telepresence/Makefile b/packages/system/telepresence/Makefile index 1aec8917..d7f83e05 100644 --- a/packages/system/telepresence/Makefile +++ b/packages/system/telepresence/Makefile @@ -1,7 +1,7 @@ export NAME=traffic-manager export NAMESPACE=cozy-telepresence -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/tenant-rd/Makefile b/packages/system/tenant-rd/Makefile index 37852fe6..11db2069 100644 --- a/packages/system/tenant-rd/Makefile +++ b/packages/system/tenant-rd/Makefile @@ -1,4 +1,4 @@ export NAME=tenant-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/tenant-rd/cozyrds/tenant.yaml b/packages/system/tenant-rd/cozyrds/tenant.yaml index a5c497ac..9b09692c 100644 --- a/packages/system/tenant-rd/cozyrds/tenant.yaml +++ b/packages/system/tenant-rd/cozyrds/tenant.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: tenant spec: @@ -8,24 +8,22 @@ spec: singular: tenant plural: tenants openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"etcd":{"description":"Deploy own Etcd cluster.","type":"boolean","default":false},"host":{"description":"The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host).","type":"string","default":""},"ingress":{"description":"Deploy own Ingress Controller.","type":"boolean","default":false},"isolated":{"description":"Enforce tenant namespace with network policies (default: true).","type":"boolean","default":true},"monitoring":{"description":"Deploy own Monitoring Stack.","type":"boolean","default":false},"resourceQuotas":{"description":"Define resource quotas for the tenant.","type":"object","default":{},"additionalProperties":{"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}},"seaweedfs":{"description":"Deploy own SeaweedFS.","type":"boolean","default":false}}} + {"title":"Chart Values","type":"object","properties":{"etcd":{"description":"Deploy own Etcd cluster.","type":"boolean","default":false},"host":{"description":"The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host).","type":"string","default":""},"ingress":{"description":"Deploy own Ingress Controller.","type":"boolean","default":false},"monitoring":{"description":"Deploy own Monitoring Stack.","type":"boolean","default":false},"resourceQuotas":{"description":"Define resource quotas for the tenant.","type":"object","default":{},"additionalProperties":{"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}},"seaweedfs":{"description":"Deploy own SeaweedFS.","type":"boolean","default":false}}} release: prefix: tenant- labels: - cozystack.io/ui: "true" - chart: - name: tenant - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-tenant-application-default-tenant + namespace: cozy-system dashboard: category: Administration singular: Tenant plural: Tenants description: Separated tenant namespace icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl82ODdfMzQwMykiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzY4N18zNDAzKSI+CjxwYXRoIGQ9Ik03MiAyOUM2Ni4zOTI2IDI5IDYxLjAxNDggMzEuMjM4OCA1Ny4wNDk3IDM1LjIyNEM1My4wODQ3IDM5LjIwOTEgNTAuODU3MSA0NC42MTQxIDUwLjg1NzEgNTAuMjVDNTAuODU3MSA1NS44ODU5IDUzLjA4NDcgNjEuMjkwOSA1Ny4wNDk3IDY1LjI3NkM2MS4wMTQ4IDY5LjI2MTIgNjYuMzkyNiA3MS41IDcyIDcxLjVDNzcuNjA3NCA3MS41IDgyLjk4NTIgNjkuMjYxMiA4Ni45NTAzIDY1LjI3NkM5MC45MTUzIDYxLjI5MDkgOTMuMTQyOSA1NS44ODU5IDkzLjE0MjkgNTAuMjVDOTMuMTQyOSA0NC42MTQxIDkwLjkxNTMgMzkuMjA5MSA4Ni45NTAzIDM1LjIyNEM4Mi45ODUyIDMxLjIzODggNzcuNjA3NCAyOSA3MiAyOVpNNjAuOTgyNiA4My4zMDM3QzYwLjQ1NCA4Mi41ODk4IDU5LjU5NTEgODIuMTkxNCA1OC43MTk2IDgyLjI3NDRDNDUuMzg5NyA4My43MzU0IDM1IDk1LjEwNzQgMzUgMTA4LjkwM0MzNSAxMTEuNzI2IDM3LjI3OTUgMTE0IDQwLjA3MSAxMTRIMTAzLjkyOUMxMDYuNzM3IDExNCAxMDkgMTExLjcwOSAxMDkgMTA4LjkwM0MxMDkgOTUuMTA3NCA5OC42MTAzIDgzLjc1MiA4NS4yNjM4IDgyLjI5MUM4NC4zODg0IDgyLjE5MTQgODMuNTI5NSA4Mi42MDY0IDgzLjAwMDkgODMuMzIwM0w3NC4wOTc4IDk1LjI0MDJDNzMuMDQwNiA5Ni42NTE0IDcwLjkyNjMgOTYuNjUxNCA2OS44NjkyIDk1LjI0MDJMNjAuOTY2MSA4My4zMjAzTDYwLjk4MjYgODMuMzAzN1oiIGZpbGw9ImJsYWNrIi8+CjwvZz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl82ODdfMzQwMyIgeDE9IjcyIiB5MT0iMTQ0IiB4Mj0iLTEuMjgxN2UtMDUiIHkyPSI0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiNDMEQ2RkYiLz4KPHN0b3Agb2Zmc2V0PSIwLjMiIHN0b3AtY29sb3I9IiNDNERBRkYiLz4KPHN0b3Agb2Zmc2V0PSIwLjY1IiBzdG9wLWNvbG9yPSIjRDNFOUZGIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0U5RkZGRiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzY4N18zNDAzIj4KPHJlY3Qgd2lkdGg9Ijc0IiBoZWlnaHQ9Ijg1IiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzUgMjkpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg== - keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "host"], ["spec", "etcd"], ["spec", "monitoring"], ["spec", "ingress"], ["spec", "seaweedfs"], ["spec", "isolated"], ["spec", "resourceQuotas"]] + keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "host"], ["spec", "etcd"], ["spec", "monitoring"], ["spec", "ingress"], ["spec", "seaweedfs"], ["spec", "resourceQuotas"]] secrets: exclude: [] include: [] diff --git a/packages/system/velero/Makefile b/packages/system/velero/Makefile index ca4ebd5e..44eba951 100644 --- a/packages/system/velero/Makefile +++ b/packages/system/velero/Makefile @@ -1,7 +1,7 @@ export NAME=velero export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/velero/charts/velero/values.yaml b/packages/system/velero/charts/velero/values.yaml index 30eb7b5f..00ec9380 100644 --- a/packages/system/velero/charts/velero/values.yaml +++ b/packages/system/velero/charts/velero/values.yaml @@ -338,12 +338,12 @@ metrics: kubectl: image: - repository: docker.io/bitnamilegacy/kubectl + repository: alpine/k8s # Digest value example: sha256:d238835e151cec91c6a811fe3a89a66d3231d9f64d09e5f3c49552672d271f38. # If used, it will take precedence over the kubectl.image.tag. # digest: # kubectl image tag. If used, it will take precedence over the cluster Kubernetes version. - # tag: 1.16.15 + tag: "1.35.0" # Container Level Security Context for the 'kubectl' container of the crd jobs. Optional. # See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container containerSecurityContext: {} diff --git a/packages/system/velero/values.yaml b/packages/system/velero/values.yaml index 62f13c1f..4d503543 100644 --- a/packages/system/velero/values.yaml +++ b/packages/system/velero/values.yaml @@ -1,4 +1,7 @@ velero: + # Disable CRD upgrade job - CRDs are installed as part of helm chart + # The upgrade job has issues with kubectl image compatibility + upgradeCRDs: false initContainers: - name: velero-plugin-for-aws image: velero/velero-plugin-for-aws:v1.12.1 diff --git a/packages/system/vertical-pod-autoscaler-crds/Makefile b/packages/system/vertical-pod-autoscaler-crds/Makefile index 9290640e..52b84278 100644 --- a/packages/system/vertical-pod-autoscaler-crds/Makefile +++ b/packages/system/vertical-pod-autoscaler-crds/Makefile @@ -1,7 +1,7 @@ export NAME=vertical-pod-autoscaler export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: curl -o ./templates/vpa-v1-crd-gen.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml diff --git a/packages/system/vertical-pod-autoscaler/Makefile b/packages/system/vertical-pod-autoscaler/Makefile index 389f9c6e..1e5372e1 100644 --- a/packages/system/vertical-pod-autoscaler/Makefile +++ b/packages/system/vertical-pod-autoscaler/Makefile @@ -1,7 +1,7 @@ export NAME=vertical-pod-autoscaler export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/vertical-pod-autoscaler/templates/vpa-for-vpa.yaml b/packages/system/vertical-pod-autoscaler/templates/vpa-for-vpa.yaml index 5fb35fca..2df053b5 100644 --- a/packages/system/vertical-pod-autoscaler/templates/vpa-for-vpa.yaml +++ b/packages/system/vertical-pod-autoscaler/templates/vpa-for-vpa.yaml @@ -16,15 +16,10 @@ metadata: name: vpa-for-vpa namespace: cozy-vpa-for-vpa spec: - chart: - spec: - chart: cozy-vertical-pod-autoscaler - reconcileStrategy: Revision - sourceRef: - kind: HelmRepository - name: cozystack-system - namespace: cozy-system - version: '>= 0.0.0-0' + chartRef: + kind: ExternalArtifact + name: cozystack-vertical-pod-autoscaler-default-vpa-for-vpa + namespace: cozy-system dependsOn: - name: monitoring-agents namespace: cozy-monitoring diff --git a/packages/system/victoria-metrics-operator/Makefile b/packages/system/victoria-metrics-operator/Makefile index a78b7b76..981a1dbc 100644 --- a/packages/system/victoria-metrics-operator/Makefile +++ b/packages/system/victoria-metrics-operator/Makefile @@ -1,7 +1,7 @@ export NAME=victoria-metrics-operator export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf charts diff --git a/packages/system/virtual-machine-rd/Makefile b/packages/system/virtual-machine-rd/Makefile index 4d59946b..79142c9b 100644 --- a/packages/system/virtual-machine-rd/Makefile +++ b/packages/system/virtual-machine-rd/Makefile @@ -1,4 +1,4 @@ export NAME=virtual-machine-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/virtual-machine-rd/cozyrds/virtual-machine.yaml b/packages/system/virtual-machine-rd/cozyrds/virtual-machine.yaml index a1e384c4..5fdc8561 100644 --- a/packages/system/virtual-machine-rd/cozyrds/virtual-machine.yaml +++ b/packages/system/virtual-machine-rd/cozyrds/virtual-machine.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: virtual-machine spec: @@ -12,13 +12,11 @@ spec: release: prefix: virtual-machine- labels: - cozystack.io/ui: "true" - chart: - name: virtual-machine - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-virtual-machine-application-kubevirt-virtual-machine + namespace: cozy-system dashboard: category: IaaS singular: Virtual Machine diff --git a/packages/system/virtualprivatecloud-rd/Makefile b/packages/system/virtualprivatecloud-rd/Makefile index 9d9b6c50..013e96b1 100644 --- a/packages/system/virtualprivatecloud-rd/Makefile +++ b/packages/system/virtualprivatecloud-rd/Makefile @@ -1,4 +1,4 @@ export NAME=virtualprivatecloud-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/virtualprivatecloud-rd/cozyrds/virtualprivatecloud.yaml b/packages/system/virtualprivatecloud-rd/cozyrds/virtualprivatecloud.yaml index 8d05a5b6..3f53f984 100644 --- a/packages/system/virtualprivatecloud-rd/cozyrds/virtualprivatecloud.yaml +++ b/packages/system/virtualprivatecloud-rd/cozyrds/virtualprivatecloud.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: virtualprivatecloud spec: @@ -12,13 +12,11 @@ spec: release: prefix: "virtualprivatecloud-" labels: - cozystack.io/ui: "true" - chart: - name: virtualprivatecloud - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-virtualprivatecloud-application-kubevirt-virtualprivatecloud + namespace: cozy-system dashboard: category: IaaS singular: VPC diff --git a/packages/system/vm-disk-rd/Makefile b/packages/system/vm-disk-rd/Makefile index e6de276d..5b73fd4c 100644 --- a/packages/system/vm-disk-rd/Makefile +++ b/packages/system/vm-disk-rd/Makefile @@ -1,4 +1,4 @@ export NAME=vm-disk-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/vm-disk-rd/cozyrds/vm-disk.yaml b/packages/system/vm-disk-rd/cozyrds/vm-disk.yaml index c3c1b830..93f8956f 100644 --- a/packages/system/vm-disk-rd/cozyrds/vm-disk.yaml +++ b/packages/system/vm-disk-rd/cozyrds/vm-disk.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: vm-disk spec: @@ -12,13 +12,11 @@ spec: release: prefix: vm-disk- labels: - cozystack.io/ui: "true" - chart: - name: vm-disk - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-vm-disk-application-kubevirt-vm-disk + namespace: cozy-system dashboard: category: IaaS singular: VM Disk diff --git a/packages/system/vm-instance-rd/Makefile b/packages/system/vm-instance-rd/Makefile index badc4951..621d74bd 100644 --- a/packages/system/vm-instance-rd/Makefile +++ b/packages/system/vm-instance-rd/Makefile @@ -1,4 +1,4 @@ export NAME=vm-instance-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/vm-instance-rd/cozyrds/vm-instance.yaml b/packages/system/vm-instance-rd/cozyrds/vm-instance.yaml index 58eb5f9a..b03d82a0 100644 --- a/packages/system/vm-instance-rd/cozyrds/vm-instance.yaml +++ b/packages/system/vm-instance-rd/cozyrds/vm-instance.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: vm-instance spec: @@ -12,13 +12,11 @@ spec: release: prefix: vm-instance- labels: - cozystack.io/ui: "true" - chart: - name: vm-instance - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-vm-instance-application-kubevirt-vm-instance + namespace: cozy-system dashboard: category: IaaS singular: VM Instance diff --git a/packages/system/vpn-rd/Makefile b/packages/system/vpn-rd/Makefile index c6ee47bb..d37f46fc 100644 --- a/packages/system/vpn-rd/Makefile +++ b/packages/system/vpn-rd/Makefile @@ -1,4 +1,4 @@ export NAME=vpn-rd export NAMESPACE=cozy-system -include ../../../scripts/package.mk +include ../../../hack/package.mk diff --git a/packages/system/vpn-rd/cozyrds/vpn.yaml b/packages/system/vpn-rd/cozyrds/vpn.yaml index 59d940c0..1d3fe7fb 100644 --- a/packages/system/vpn-rd/cozyrds/vpn.yaml +++ b/packages/system/vpn-rd/cozyrds/vpn.yaml @@ -1,5 +1,5 @@ apiVersion: cozystack.io/v1alpha1 -kind: CozystackResourceDefinition +kind: ApplicationDefinition metadata: name: vpn spec: @@ -12,13 +12,11 @@ spec: release: prefix: vpn- labels: - cozystack.io/ui: "true" - chart: - name: vpn - sourceRef: - kind: HelmRepository - name: cozystack-apps - namespace: cozy-public + sharding.fluxcd.io/key: tenants + chartRef: + kind: ExternalArtifact + name: cozystack-vpn-application-default-vpn + namespace: cozy-system dashboard: category: NaaS singular: VPN diff --git a/packages/system/vsnap-crd/Makefile b/packages/system/vsnap-crd/Makefile index 57e5a290..005eefbd 100644 --- a/packages/system/vsnap-crd/Makefile +++ b/packages/system/vsnap-crd/Makefile @@ -1,7 +1,7 @@ export NAME=vsnap-crd export NAMESPACE=cozy-$(NAME) -include ../../../scripts/package.mk +include ../../../hack/package.mk update: rm -rf templates diff --git a/pkg/apis/apps/fuzzer/fuzzer.go b/pkg/apis/apps/fuzzer/fuzzer.go index fd744ed6..c92c5799 100644 --- a/pkg/apis/apps/fuzzer/fuzzer.go +++ b/pkg/apis/apps/fuzzer/fuzzer.go @@ -17,7 +17,7 @@ limitations under the License. package fuzzer import ( - "github.com/cozystack/cozystack/pkg/apis/apps" + "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1" fuzz "github.com/google/gofuzz" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" @@ -26,7 +26,7 @@ import ( // Funcs returns the fuzzer functions for the apps api group. var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ - func(s *apps.ApplicationSpec, c fuzz.Continue) { + func(s *v1alpha1.Application, c fuzz.Continue) { c.FuzzNoCustom(s) // fuzz self without calling this function again }, } diff --git a/pkg/apis/apps/v1alpha1/types.go b/pkg/apis/apps/v1alpha1/types.go index 0118b0de..51247efb 100644 --- a/pkg/apis/apps/v1alpha1/types.go +++ b/pkg/apis/apps/v1alpha1/types.go @@ -47,6 +47,9 @@ type ApplicationStatus struct { // Namespace holds the computed namespace for Tenant applications. // +optional Namespace string `json:"namespace,omitempty"` + // ExternalIPsCount holds the number of LoadBalancer services with assigned external IPs for Tenant applications. + // +optional + ExternalIPsCount int32 `json:"externalIPsCount,omitempty"` } // GetConditions returns the status conditions of the object. diff --git a/pkg/apis/apps/validation/validation.go b/pkg/apis/apps/validation/validation.go deleted file mode 100644 index 84c20c54..00000000 --- a/pkg/apis/apps/validation/validation.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2024 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package validation - -import ( - "github.com/cozystack/cozystack/pkg/apis/apps" - "k8s.io/apimachinery/pkg/util/validation/field" -) - -// ValidateApplication validates a Application. -func ValidateApplication(f *apps.Application) field.ErrorList { - allErrs := field.ErrorList{} - - allErrs = append(allErrs, ValidateApplicationSpec(&f.Spec, field.NewPath("spec"))...) - - return allErrs -} - -// ValidateApplicationSpec validates a ApplicationSpec. -func ValidateApplicationSpec(s *apps.ApplicationSpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - // TODO validation - - return allErrs -} diff --git a/pkg/apis/core/fuzzer/fuzzer.go b/pkg/apis/core/fuzzer/fuzzer.go index dbf3ca39..82a1b5ab 100644 --- a/pkg/apis/core/fuzzer/fuzzer.go +++ b/pkg/apis/core/fuzzer/fuzzer.go @@ -17,7 +17,7 @@ limitations under the License. package fuzzer import ( - "github.com/cozystack/cozystack/pkg/apis/core" + "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1" fuzz "github.com/google/gofuzz" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" @@ -26,7 +26,7 @@ import ( // Funcs returns the fuzzer functions for the core api group. var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ - func(s *core.TenantNamespaceSpec, c fuzz.Continue) { + func(s *v1alpha1.TenantNamespace, c fuzz.Continue) { c.FuzzNoCustom(s) // fuzz self without calling this function again }, } diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go deleted file mode 100644 index 060067de..00000000 --- a/pkg/apis/core/validation/validation.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2024 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package validation - -import ( - "github.com/cozystack/cozystack/pkg/apis/core" - "k8s.io/apimachinery/pkg/util/validation/field" -) - -// ValidateTenantNamespace validates a TenantNamespace. -func ValidateTenantNamespace(f *core.TenantNamespace) field.ErrorList { - allErrs := field.ErrorList{} - - allErrs = append(allErrs, ValidateTenantNamespaceSpec(&f.Spec, field.NewPath("spec"))...) - - return allErrs -} - -// ValidateTenantNamespaceSpec validates a TenantNamespaceSpec. -func ValidateTenantNamespaceSpec(s *core.TenantNamespaceSpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - // TODO validation - - return allErrs -} diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index fccbf9a9..bc2b4857 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -149,6 +149,17 @@ func (c completedConfig) New() (*CozyServer, error) { return nil, fmt.Errorf("failed to build manager: %w", err) } + if err := mgr.GetFieldIndexer().IndexField( + context.Background(), + &corev1.Service{}, + "spec.type", + func(rawObj client.Object) []string { + svc := rawObj.(*corev1.Service) + return []string{string(svc.Spec.Type)} + }); err != nil { + return nil, fmt.Errorf("failed to index service spec.type field: %w", err) + } + ctx := ctrl.SetupSignalHandler() if err = mustGetInformers(ctx, mgr, diff --git a/pkg/cmd/server/start.go b/pkg/cmd/server/start.go index 5da8254e..6ff8d2d1 100644 --- a/pkg/cmd/server/start.go +++ b/pkg/cmd/server/start.go @@ -124,7 +124,7 @@ func (o *CozyServerOptions) Complete() error { return fmt.Errorf("client initialization failed: %w", err) } - crdList := &v1alpha1.CozystackResourceDefinitionList{} + crdList := &v1alpha1.ApplicationDefinitionList{} // Retry with exponential backoff for at least 30 minutes const maxRetryDuration = 30 * time.Minute @@ -142,11 +142,11 @@ func (o *CozyServerOptions) Complete() error { // Check if we've exceeded the maximum retry duration if time.Since(startTime) >= maxRetryDuration { - return fmt.Errorf("failed to list CozystackResourceDefinitions after %v: %w", maxRetryDuration, err) + return fmt.Errorf("failed to list ApplicationDefinitions after %v: %w", maxRetryDuration, err) } // Log the error and wait before retrying - fmt.Printf("Failed to list CozystackResourceDefinitions (retrying in %v): %v\n", delay, err) + fmt.Printf("Failed to list ApplicationDefinitions (retrying in %v): %v\n", delay, err) time.Sleep(delay) delay = time.Duration(float64(delay) * 1.5) @@ -169,13 +169,10 @@ func (o *CozyServerOptions) Complete() error { Release: config.ReleaseConfig{ Prefix: crd.Spec.Release.Prefix, Labels: crd.Spec.Release.Labels, - Chart: config.ChartConfig{ - Name: crd.Spec.Release.Chart.Name, - SourceRef: config.SourceRefConfig{ - Kind: crd.Spec.Release.Chart.SourceRef.Kind, - Name: crd.Spec.Release.Chart.SourceRef.Name, - Namespace: crd.Spec.Release.Chart.SourceRef.Namespace, - }, + ChartRef: config.ChartRefConfig{ + Kind: crd.Spec.Release.ChartRef.Kind, + Name: crd.Spec.Release.ChartRef.Name, + Namespace: crd.Spec.Release.ChartRef.Namespace, }, }, } diff --git a/pkg/config/config.go b/pkg/config/config.go index 390918a6..1e123e2c 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -38,19 +38,13 @@ type ApplicationConfig struct { // ReleaseConfig contains the release settings. type ReleaseConfig struct { - Prefix string `yaml:"prefix"` - Labels map[string]string `yaml:"labels"` - Chart ChartConfig `yaml:"chart"` + Prefix string `yaml:"prefix"` + Labels map[string]string `yaml:"labels"` + ChartRef ChartRefConfig `yaml:"chartRef"` } -// ChartConfig contains the chart settings. -type ChartConfig struct { - Name string `yaml:"name"` - SourceRef SourceRefConfig `yaml:"sourceRef"` -} - -// SourceRefConfig contains the reference to the chart source. -type SourceRefConfig struct { +// ChartRefConfig references a Flux source artifact for the Helm chart. +type ChartRefConfig struct { Kind string `yaml:"kind"` Name string `yaml:"name"` Namespace string `yaml:"namespace"` diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 4202bbac..ba5ab71b 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -2714,6 +2714,13 @@ func schema_pkg_apis_meta_v1_DeleteOptions(ref common.ReferenceCallback) common. }, }, }, + "ignoreStoreReadErrorWithClusterBreakingPotential": { + SchemaProps: spec.SchemaProps{ + Description: "if set to true, it will trigger an unsafe deletion of the resource in case the normal deletion flow fails with a corrupt object error. A resource is considered corrupt if it can not be retrieved from the underlying storage successfully because of a) its data can not be transformed e.g. decryption failure, or b) it fails to decode into an object. NOTE: unsafe deletion ignores finalizer constraints, skips precondition checks, and removes the object from the storage. WARNING: This may potentially break the cluster if the workload associated with the resource being unsafe-deleted relies on normal deletion flow. Use only if you REALLY know what you are doing. The default value is false, and the user must opt in to enable it", + Type: []string{"boolean"}, + Format: "", + }, + }, }, }, }, @@ -4601,16 +4608,46 @@ func schema_k8sio_apimachinery_pkg_version_Info(ref common.ReferenceCallback) co Properties: map[string]spec.Schema{ "major": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Major is the major version of the binary version", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "minor": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Minor is the minor version of the binary version", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "emulationMajor": { + SchemaProps: spec.SchemaProps{ + Description: "EmulationMajor is the major version of the emulation version", + Type: []string{"string"}, + Format: "", + }, + }, + "emulationMinor": { + SchemaProps: spec.SchemaProps{ + Description: "EmulationMinor is the minor version of the emulation version", + Type: []string{"string"}, + Format: "", + }, + }, + "minCompatibilityMajor": { + SchemaProps: spec.SchemaProps{ + Description: "MinCompatibilityMajor is the major version of the minimum compatibility version", + Type: []string{"string"}, + Format: "", + }, + }, + "minCompatibilityMinor": { + SchemaProps: spec.SchemaProps{ + Description: "MinCompatibilityMinor is the minor version of the minimum compatibility version", + Type: []string{"string"}, + Format: "", }, }, "gitVersion": { diff --git a/pkg/lineage/lineage.go b/pkg/lineage/lineage.go index 867e1aab..94be77b7 100644 --- a/pkg/lineage/lineage.go +++ b/pkg/lineage/lineage.go @@ -22,6 +22,11 @@ const ( HRLabel = "helm.toolkit.fluxcd.io/name" ) +// AppMapper maps HelmRelease to application metadata. +type AppMapper interface { + Map(*helmv2.HelmRelease) (apiVersion, kind, prefix string, err error) +} + type ObjectID struct { APIVersion string Kind string diff --git a/pkg/lineage/lineage_test.go b/pkg/lineage/lineage_test.go index a705f26c..7da09dfc 100644 --- a/pkg/lineage/lineage_test.go +++ b/pkg/lineage/lineage_test.go @@ -4,8 +4,10 @@ import ( "context" "fmt" "os" + "strings" "testing" + helmv2 "github.com/fluxcd/helm-controller/api/v2" "github.com/go-logr/logr" "github.com/go-logr/zapr" "go.uber.org/zap" @@ -41,12 +43,41 @@ func init() { ctx = logr.NewContext(context.Background(), l) } +// labelsMapper implements AppMapper using HelmRelease labels. +type labelsMapper struct{} + +func (m *labelsMapper) Map(hr *helmv2.HelmRelease) (string, string, string, error) { + if hr.Labels == nil { + return "", "", "", fmt.Errorf("cannot map helm release %s/%s: labels are nil", hr.Namespace, hr.Name) + } + + appKind, ok := hr.Labels["apps.cozystack.io/application.kind"] + if !ok { + return "", "", "", fmt.Errorf("cannot map helm release %s/%s: missing application.kind label", hr.Namespace, hr.Name) + } + + appGroup, ok := hr.Labels["apps.cozystack.io/application.group"] + if !ok { + return "", "", "", fmt.Errorf("cannot map helm release %s/%s: missing application.group label", hr.Namespace, hr.Name) + } + + appName, ok := hr.Labels["apps.cozystack.io/application.name"] + if !ok { + return "", "", "", fmt.Errorf("cannot map helm release %s/%s: missing application.name label", hr.Namespace, hr.Name) + } + + apiVersion := fmt.Sprintf("%s/v1alpha1", appGroup) + prefix := strings.TrimSuffix(hr.Name, appName) + + return apiVersion, appKind, prefix, nil +} + func TestWalkingOwnershipGraph(t *testing.T) { obj, err := dynClient.Resource(schema.GroupVersionResource{"", "v1", "pods"}).Namespace(os.Args[1]).Get(ctx, os.Args[2], metav1.GetOptions{}) if err != nil { t.Fatal(err) } - nodes := WalkOwnershipGraph(ctx, dynClient, mapper, &stubMapper{}, obj) + nodes := WalkOwnershipGraph(ctx, dynClient, mapper, &labelsMapper{}, obj) for _, node := range nodes { fmt.Printf("%#v\n", node) } diff --git a/pkg/lineage/mapper.go b/pkg/lineage/mapper.go deleted file mode 100644 index c424b288..00000000 --- a/pkg/lineage/mapper.go +++ /dev/null @@ -1,49 +0,0 @@ -package lineage - -import ( - "fmt" - "strings" - - helmv2 "github.com/fluxcd/helm-controller/api/v2" -) - -type AppMapper interface { - Map(*helmv2.HelmRelease) (apiVersion, kind, prefix string, err error) -} - -type stubMapper struct{} - -var stubMapperMap = map[string]string{ - "cozystack-extra/bootbox": "apps.cozystack.io/v1alpha1/BootBox/", - "cozystack-apps/bucket": "apps.cozystack.io/v1alpha1/Bucket/bucket-", - "cozystack-apps/clickhouse": "apps.cozystack.io/v1alpha1/ClickHouse/clickhouse-", - "cozystack-extra/etcd": "apps.cozystack.io/v1alpha1/Etcd/", - "cozystack-apps/ferretdb": "apps.cozystack.io/v1alpha1/FerretDB/ferretdb-", - "cozystack-apps/http-cache": "apps.cozystack.io/v1alpha1/HTTPCache/http-cache-", - "cozystack-extra/info": "apps.cozystack.io/v1alpha1/Info/", - "cozystack-extra/ingress": "apps.cozystack.io/v1alpha1/Ingress/", - "cozystack-apps/kafka": "apps.cozystack.io/v1alpha1/Kafka/kafka-", - "cozystack-apps/kubernetes": "apps.cozystack.io/v1alpha1/Kubernetes/kubernetes-", - "cozystack-extra/monitoring": "apps.cozystack.io/v1alpha1/Monitoring/", - "cozystack-apps/mysql": "apps.cozystack.io/v1alpha1/MySQL/mysql-", - "cozystack-apps/nats": "apps.cozystack.io/v1alpha1/NATS/nats-", - "cozystack-apps/postgres": "apps.cozystack.io/v1alpha1/Postgres/postgres-", - "cozystack-apps/rabbitmq": "apps.cozystack.io/v1alpha1/RabbitMQ/rabbitmq-", - "cozystack-apps/redis": "apps.cozystack.io/v1alpha1/Redis/redis-", - "cozystack-extra/seaweedfs": "apps.cozystack.io/v1alpha1/SeaweedFS/", - "cozystack-apps/tcp-balancer": "apps.cozystack.io/v1alpha1/TCPBalancer/tcp-balancer-", - "cozystack-apps/tenant": "apps.cozystack.io/v1alpha1/Tenant/tenant-", - "cozystack-apps/virtual-machine": "apps.cozystack.io/v1alpha1/VirtualMachine/virtual-machine-", - "cozystack-apps/vm-disk": "apps.cozystack.io/v1alpha1/VMDisk/vm-disk-", - "cozystack-apps/vm-instance": "apps.cozystack.io/v1alpha1/VMInstance/vm-instance-", - "cozystack-apps/vpn": "apps.cozystack.io/v1alpha1/VPN/vpn-", -} - -func (s *stubMapper) Map(hr *helmv2.HelmRelease) (string, string, string, error) { - val, ok := stubMapperMap[hr.Spec.Chart.Spec.SourceRef.Name+"/"+hr.Spec.Chart.Spec.Chart] - if !ok { - return "", "", "", fmt.Errorf("cannot map helm release %s/%s to dynamic app", hr.Namespace, hr.Name) - } - split := strings.Split(val, "/") - return strings.Join(split[:2], "/"), split[2], split[3], nil -} diff --git a/pkg/registry/apps/application/rest.go b/pkg/registry/apps/application/rest.go index 9e8fb891..00d22486 100644 --- a/pkg/registry/apps/application/rest.go +++ b/pkg/registry/apps/application/rest.go @@ -21,14 +21,16 @@ import ( "encoding/json" "fmt" "net/http" + "strconv" "strings" "sync" "time" helmv2 "github.com/fluxcd/helm-controller/api/v2" + corev1 "k8s.io/api/core/v1" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - fields "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/fields" labels "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -42,6 +44,8 @@ import ( appsv1alpha1 "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1" "github.com/cozystack/cozystack/pkg/config" + "github.com/cozystack/cozystack/pkg/registry" + fieldfilter "github.com/cozystack/cozystack/pkg/registry/fields" "github.com/cozystack/cozystack/pkg/registry/sorting" internalapiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -183,7 +187,7 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation } // Convert the created HelmRelease back to Application - convertedApp, err := r.ConvertHelmReleaseToApplication(helmRelease) + convertedApp, err := r.ConvertHelmReleaseToApplication(ctx, helmRelease) if err != nil { klog.Errorf("Conversion error from HelmRelease to Application for resource %s: %v", helmRelease.GetName(), err) return nil, fmt.Errorf("conversion error: %v", err) @@ -230,7 +234,7 @@ func (r *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) } // Convert HelmRelease to Application - convertedApp, err := r.ConvertHelmReleaseToApplication(helmRelease) + convertedApp, err := r.ConvertHelmReleaseToApplication(ctx, helmRelease) if err != nil { klog.Errorf("Conversion error from HelmRelease to Application for resource %s: %v", name, err) return nil, fmt.Errorf("conversion error: %v", err) @@ -248,7 +252,7 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption return nil, err } - klog.V(6).Infof("Attempting to list HelmReleases in namespace %s with options: %v", namespace, options) + klog.V(6).Infof("List called for %s in namespace %q", r.kindName, namespace) // Get resource name from the request (if any) var resourceName string @@ -257,26 +261,32 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption } // Initialize variables for selector mapping - var helmFieldSelector string - var helmLabelSelector string + var helmLabelSelector labels.Selector - // Process field.selector - if options.FieldSelector != nil { - fs, err := fields.ParseSelector(options.FieldSelector.String()) - if err != nil { - klog.Errorf("Invalid field selector: %v", err) - return nil, fmt.Errorf("invalid field selector: %v", err) - } - // Check if selector is for metadata.name - if name, exists := fs.RequiresExactMatch("metadata.name"); exists { - // Convert Application name to HelmRelease name - mappedName := r.releaseConfig.Prefix + name - // Create new field.selector for HelmRelease - helmFieldSelector = fields.OneTermEqualSelector("metadata.name", mappedName).String() - } else { - // If field.selector contains other fields, map them directly - helmFieldSelector = fs.String() - } + // Parse field selector for manual filtering + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + fieldFilter, err := fieldfilter.ParseFieldSelector(options.FieldSelector) + if err != nil { + klog.Errorf("Error parsing field selector: %v", err) + return nil, err + } + + // If field selector specifies namespace different from context, return empty list + if fieldFilter.Namespace != "" && namespace != "" && namespace != fieldFilter.Namespace { + klog.V(6).Infof("Field selector namespace %s doesn't match context namespace %s, returning empty list", fieldFilter.Namespace, namespace) + return &appsv1alpha1.ApplicationList{ + TypeMeta: metav1.TypeMeta{ + APIVersion: appsv1alpha1.SchemeGroupVersion.String(), + Kind: r.kindName + "List", + }, + }, nil + } + + // Convert Application name to HelmRelease name for manual filtering + var filterByName string + if fieldFilter.Name != "" { + filterByName = r.releaseConfig.Prefix + fieldFilter.Name } // Process label.selector @@ -315,21 +325,16 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption labelRequirements = append(labelRequirements, prefixedReqs...) } } - helmLabelSelector = labels.NewSelector().Add(labelRequirements...).String() + helmLabelSelector = labels.NewSelector().Add(labelRequirements...) klog.V(6).Infof("Using label selector: %s for kind: %s, group: %s", helmLabelSelector, r.kindName, r.gvk.Group) - // Set ListOptions for HelmRelease with selector mapping - metaOptions := metav1.ListOptions{ - FieldSelector: helmFieldSelector, - LabelSelector: helmLabelSelector, - } - - // List HelmReleases with mapped selectors + // List HelmReleases with label selector only + // Field selectors are not supported by controller-runtime cache, so we filter manually below hrList := &helmv2.HelmReleaseList{} err = r.c.List(ctx, hrList, &client.ListOptions{ - Namespace: namespace, - Raw: &metaOptions, + Namespace: namespace, + LabelSelector: helmLabelSelector, }) if err != nil { klog.Errorf("Error listing HelmReleases: %v", err) @@ -346,7 +351,17 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption for i := range hrList.Items { hr := &hrList.Items[i] - app, err := r.ConvertHelmReleaseToApplication(hr) + // Apply manual field selector filtering (metadata.name and metadata.namespace) + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + if filterByName != "" && hr.Name != filterByName { + continue + } + if !fieldFilter.MatchesNamespace(hr.Namespace) { + continue + } + + app, err := r.ConvertHelmReleaseToApplication(ctx, hr) if err != nil { klog.Errorf("Error converting HelmRelease %s to Application: %v", hr.GetName(), err) continue @@ -390,12 +405,20 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption // Create ApplicationList with proper kind appList := r.NewList().(*appsv1alpha1.ApplicationList) - appList.SetResourceVersion(hrList.GetResourceVersion()) + + // Get ResourceVersion from list or compute from items + // controller-runtime cached client may not set ResourceVersion on the list itself + listRV := hrList.GetResourceVersion() + if listRV == "" { + listRV, _ = registry.MaxResourceVersion(hrList) + } + appList.SetResourceVersion(listRV) appList.Items = items sorting.ByNamespacedName[appsv1alpha1.Application, *appsv1alpha1.Application](appList.Items) - klog.V(6).Infof("Successfully listed %d Application resources in namespace %s", len(items), namespace) + klog.V(6).Infof("List returning %d items for %s in namespace %q, resourceVersion=%q", + len(items), r.kindName, namespace, appList.GetResourceVersion()) return appList, nil } @@ -492,7 +515,7 @@ func (r *REST) Update(ctx context.Context, name string, objInfo rest.UpdatedObje } // Convert the updated HelmRelease back to Application - convertedApp, err := r.ConvertHelmReleaseToApplication(helmRelease) + convertedApp, err := r.ConvertHelmReleaseToApplication(ctx, helmRelease) if err != nil { klog.Errorf("Conversion error from HelmRelease to Application for resource %s: %v", helmRelease.GetName(), err) return nil, false, fmt.Errorf("conversion error: %v", err) @@ -560,7 +583,8 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio return nil, err } - klog.V(6).Infof("Setting up watch for HelmReleases in namespace %s with options: %v", namespace, options) + klog.V(6).Infof("Watch called for %s in namespace %q, resourceVersion=%q", + r.kindName, namespace, options.ResourceVersion) // Get request information, including resource name if specified var resourceName string @@ -569,27 +593,21 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio } // Initialize variables for selector mapping - var helmFieldSelector string - var helmLabelSelector string + var helmLabelSelector labels.Selector - // Process field.selector - if options.FieldSelector != nil { - fs, err := fields.ParseSelector(options.FieldSelector.String()) - if err != nil { - klog.Errorf("Invalid field selector: %v", err) - return nil, fmt.Errorf("invalid field selector: %v", err) - } + // Parse field selector for manual filtering + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + fieldFilter, err := fieldfilter.ParseFieldSelector(options.FieldSelector) + if err != nil { + klog.Errorf("Error parsing field selector: %v", err) + return nil, err + } - // Check if selector is for metadata.name - if name, exists := fs.RequiresExactMatch("metadata.name"); exists { - // Convert Application name to HelmRelease name - mappedName := r.releaseConfig.Prefix + name - // Create new field.selector for HelmRelease - helmFieldSelector = fields.OneTermEqualSelector("metadata.name", mappedName).String() - } else { - // If field.selector contains other fields, map them directly - helmFieldSelector = fs.String() - } + // Convert Application name to HelmRelease name for manual filtering + var filterByName string + if fieldFilter.Name != "" { + filterByName = r.releaseConfig.Prefix + fieldFilter.Name } // Process label.selector @@ -628,47 +646,129 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio labelRequirements = append(labelRequirements, prefixedReqs...) } } - helmLabelSelector = labels.NewSelector().Add(labelRequirements...).String() + helmLabelSelector = labels.NewSelector().Add(labelRequirements...) - // Set ListOptions for HelmRelease with selector mapping - metaOptions := metav1.ListOptions{ - Watch: true, - ResourceVersion: options.ResourceVersion, - FieldSelector: helmFieldSelector, - LabelSelector: helmLabelSelector, - } - - // Start watch on HelmRelease with mapped selectors - hrList := &helmv2.HelmReleaseList{} - helmWatcher, err := r.w.Watch(ctx, hrList, &client.ListOptions{ - Namespace: namespace, - Raw: &metaOptions, - }) - if err != nil { - klog.Errorf("Error setting up watch for HelmReleases: %v", err) - return nil, err - } + // Handle SendInitialEvents for WatchList feature (Kubernetes 1.27+) + // When sendInitialEvents=true, the client expects: + // 1. All existing resources as ADDED events + // 2. A Bookmark event with "k8s.io/initial-events-end": "true" annotation + // controller-runtime cache already sends ADDED events for all cached objects, + // so we just need to send the bookmark after those initial events + sendInitialEvents := options.SendInitialEvents != nil && *options.SendInitialEvents // Create a custom watcher to transform events customW := &customWatcher{ resultChan: make(chan watch.Event), stopChan: make(chan struct{}), - underlying: helmWatcher, } + // Start watch on HelmRelease with label selector only + // Field selectors are not supported by controller-runtime cache + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + hrList := &helmv2.HelmReleaseList{} + helmWatcher, err := r.w.Watch(ctx, hrList, &client.ListOptions{ + Namespace: namespace, + LabelSelector: helmLabelSelector, + }) + if err != nil { + klog.Errorf("Error setting up watch for HelmReleases: %v", err) + return nil, err + } + customW.underlying = helmWatcher + go func() { defer close(customW.resultChan) defer customW.underlying.Stop() + + // Track whether we've sent the initial-events-end bookmark + initialEventsEndSent := !sendInitialEvents // If not sendInitialEvents, consider it already sent + var lastResourceVersion string + + // Get the starting resourceVersion from options + // If client provides resourceVersion (e.g., from a previous List), we should skip + // objects with resourceVersion <= startingRV (client already has them) + var startingRV uint64 + if options.ResourceVersion != "" { + if rv, err := strconv.ParseUint(options.ResourceVersion, 10, 64); err == nil { + startingRV = rv + } + } + + // Helper function to send initial-events-end bookmark + sendInitialEventsEndBookmark := func() { + if initialEventsEndSent { + return + } + initialEventsEndSent = true + + bookmarkApp := &appsv1alpha1.Application{} + bookmarkApp.SetResourceVersion(lastResourceVersion) + bookmarkApp.TypeMeta = metav1.TypeMeta{ + APIVersion: appsv1alpha1.SchemeGroupVersion.String(), + Kind: r.kindName, + } + bookmarkApp.SetAnnotations(map[string]string{ + "k8s.io/initial-events-end": "true", + }) + bookmarkEvent := watch.Event{ + Type: watch.Bookmark, + Object: bookmarkApp, + } + klog.V(6).Infof("Sending initial-events-end bookmark with RV=%s", lastResourceVersion) + select { + case customW.resultChan <- bookmarkEvent: + case <-customW.stopChan: + case <-ctx.Done(): + } + } + + // Process watch events for { select { case event, ok := <-customW.underlying.ResultChan(): if !ok { - // The watcher has been closed, attempt to re-establish the watch - klog.Warning("HelmRelease watcher closed, attempting to re-establish") - // Implement retry logic or exit based on your requirements + // The watcher has been closed + klog.Warning("HelmRelease watcher closed") + // Send initial-events-end bookmark before closing if not yet sent + sendInitialEventsEndBookmark() return } + // Handle bookmark events - these are critical for informer sync + if event.Type == watch.Bookmark { + if hr, ok := event.Object.(*helmv2.HelmRelease); ok { + lastResourceVersion = hr.GetResourceVersion() + + // If sendInitialEvents and we haven't sent initial-events-end yet, + // add the annotation to this bookmark + bookmarkApp := &appsv1alpha1.Application{} + bookmarkApp.SetResourceVersion(lastResourceVersion) + bookmarkApp.TypeMeta = metav1.TypeMeta{ + APIVersion: appsv1alpha1.SchemeGroupVersion.String(), + Kind: r.kindName, + } + if !initialEventsEndSent { + initialEventsEndSent = true + bookmarkApp.SetAnnotations(map[string]string{ + "k8s.io/initial-events-end": "true", + }) + klog.V(6).Infof("Sending initial-events-end bookmark with RV=%s", lastResourceVersion) + } + bookmarkEvent := watch.Event{ + Type: watch.Bookmark, + Object: bookmarkApp, + } + select { + case customW.resultChan <- bookmarkEvent: + case <-customW.stopChan: + return + case <-ctx.Done(): + return + } + } + continue + } + // Check if the object is a *v1.Status if status, ok := event.Object.(*metav1.Status); ok { klog.V(4).Infof("Received Status object in HelmRelease watch: %v", status.Message) @@ -682,9 +782,22 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio continue } + // Update lastResourceVersion for bookmark + lastResourceVersion = hr.GetResourceVersion() + + // Apply manual field selector filtering (metadata.name and metadata.namespace) + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + if filterByName != "" && hr.Name != filterByName { + continue + } + if !fieldFilter.MatchesNamespace(hr.Namespace) { + continue + } + // Note: All HelmReleases already match the required labels due to server-side label selector filtering // Convert HelmRelease to Application - app, err := r.ConvertHelmReleaseToApplication(hr) + app, err := r.ConvertHelmReleaseToApplication(ctx, hr) if err != nil { klog.Errorf("Error converting HelmRelease to Application: %v", err) continue @@ -707,6 +820,23 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio } } + // If this is not an ADDED event and we haven't sent initial-events-end, send it now + if event.Type != watch.Added && !initialEventsEndSent { + sendInitialEventsEndBookmark() + } + + // Skip ADDED events based on resourceVersion comparison + if event.Type == watch.Added && startingRV > 0 { + objRV, parseErr := strconv.ParseUint(app.ResourceVersion, 10, 64) + // Skip objects client already has (objRV <= startingRV) + if parseErr == nil && objRV <= startingRV { + klog.V(6).Infof("Skipping ADDED event for %s/%s (objRV=%d <= startingRV=%d)", + app.Namespace, app.Name, objRV, startingRV) + continue + } + } + // When startingRV == 0, always send ADDED events (client wants full state) + // Create watch event with Application object appEvent := watch.Event{ Type: event.Type, @@ -838,11 +968,11 @@ func filterPrefixedMap(original map[string]string, prefix string) map[string]str } // ConvertHelmReleaseToApplication converts a HelmRelease to an Application -func (r *REST) ConvertHelmReleaseToApplication(hr *helmv2.HelmRelease) (appsv1alpha1.Application, error) { +func (r *REST) ConvertHelmReleaseToApplication(ctx context.Context, hr *helmv2.HelmRelease) (appsv1alpha1.Application, error) { klog.V(6).Infof("Converting HelmRelease to Application for resource %s", hr.GetName()) // Convert HelmRelease struct to Application struct - app, err := r.convertHelmReleaseToApplication(hr) + app, err := r.convertHelmReleaseToApplication(ctx, hr) if err != nil { klog.Errorf("Error converting from HelmRelease to Application: %v", err) return appsv1alpha1.Application{}, err @@ -900,7 +1030,7 @@ func validateNoInternalKeys(values *apiextv1.JSON) error { } // convertHelmReleaseToApplication implements the actual conversion logic -func (r *REST) convertHelmReleaseToApplication(hr *helmv2.HelmRelease) (appsv1alpha1.Application, error) { +func (r *REST) convertHelmReleaseToApplication(ctx context.Context, hr *helmv2.HelmRelease) (appsv1alpha1.Application, error) { // Filter out internal keys (starting with "_") from spec filteredSpec := filterInternalKeys(hr.Spec.Values) @@ -942,6 +1072,12 @@ func (r *REST) convertHelmReleaseToApplication(hr *helmv2.HelmRelease) (appsv1al // Add namespace field for Tenant applications if r.kindName == "Tenant" { app.Status.Namespace = r.computeTenantNamespace(hr.Namespace, app.Name) + externalIPsCount, err := r.countTenantExternalIPs(ctx, app.Status.Namespace) + if err != nil { + klog.Warningf("Failed to count external IPs for tenant %s/%s: %v", hr.Namespace, app.Name, err) + } else { + app.Status.ExternalIPsCount = externalIPsCount + } } return app, nil @@ -963,17 +1099,10 @@ func (r *REST) convertApplicationToHelmRelease(app *appsv1alpha1.Application) (* UID: app.UID, }, Spec: helmv2.HelmReleaseSpec{ - Chart: &helmv2.HelmChartTemplate{ - Spec: helmv2.HelmChartTemplateSpec{ - Chart: r.releaseConfig.Chart.Name, - Version: ">= 0.0.0-0", - ReconcileStrategy: "Revision", - SourceRef: helmv2.CrossNamespaceObjectReference{ - Kind: r.releaseConfig.Chart.SourceRef.Kind, - Name: r.releaseConfig.Chart.SourceRef.Name, - Namespace: r.releaseConfig.Chart.SourceRef.Namespace, - }, - }, + ChartRef: &helmv2.CrossNamespaceSourceReference{ + Kind: r.releaseConfig.ChartRef.Kind, + Name: r.releaseConfig.ChartRef.Name, + Namespace: r.releaseConfig.ChartRef.Namespace, }, Interval: metav1.Duration{Duration: 5 * time.Minute}, Install: &helmv2.Install{ @@ -1085,11 +1214,19 @@ func (r *REST) buildTableFromApplication(app appsv1alpha1.Application) metav1.Ta return table } -// getVersion returns the application version or a placeholder if unknown +// getVersion extracts and returns only the revision from the version string +// If version is in format "0.1.4+abcdef", returns "abcdef" +// Otherwise returns the original string or "" if empty func getVersion(version string) string { if version == "" { return "" } + // Check if version contains "+" separator + if idx := strings.LastIndex(version, "+"); idx >= 0 && idx < len(version)-1 { + // Return only the part after "+" + return version[idx+1:] + } + // If no "+" found, return original version return version } @@ -1135,6 +1272,35 @@ func (r *REST) computeTenantNamespace(currentNamespace, tenantName string) strin } } +func (r *REST) countTenantExternalIPs(ctx context.Context, namespace string) (int32, error) { + if namespace == "" { + return 0, nil + } + + var services corev1.ServiceList + if err := r.c.List( + ctx, + &services, + client.InNamespace(namespace), + client.MatchingFields{"spec.type": string(corev1.ServiceTypeLoadBalancer)}, + ); err != nil { + return 0, err + } + + var count int32 + for i := range services.Items { + svc := &services.Items[i] + for _, ingress := range svc.Status.LoadBalancer.Ingress { + if ingress.IP != "" { + count++ + break + } + } + } + + return count, nil +} + // Destroy releases resources associated with REST func (r *REST) Destroy() { // No additional actions needed to release resources. diff --git a/pkg/registry/core/tenantmodule/rest.go b/pkg/registry/core/tenantmodule/rest.go index 12da0e0d..888d4414 100644 --- a/pkg/registry/core/tenantmodule/rest.go +++ b/pkg/registry/core/tenantmodule/rest.go @@ -20,6 +20,8 @@ import ( "context" "fmt" "net/http" + "strconv" + "strings" "sync" "time" @@ -40,6 +42,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1" + "github.com/cozystack/cozystack/pkg/registry" + fieldfilter "github.com/cozystack/cozystack/pkg/registry/fields" "github.com/cozystack/cozystack/pkg/registry/sorting" apierrors "k8s.io/apimachinery/pkg/api/errors" ) @@ -161,24 +165,26 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption } // Initialize variables for selector mapping - var helmFieldSelector string - var helmLabelSelector string + var helmLabelSelector labels.Selector - // Process field.selector - if options.FieldSelector != nil { - fs, err := fields.ParseSelector(options.FieldSelector.String()) - if err != nil { - klog.Errorf("Invalid field selector: %v", err) - return nil, fmt.Errorf("invalid field selector: %v", err) - } - // Check if selector is for metadata.name - if name, exists := fs.RequiresExactMatch("metadata.name"); exists { - // Create new field.selector for HelmRelease - helmFieldSelector = fields.OneTermEqualSelector("metadata.name", name).String() - } else { - // If field.selector contains other fields, map them directly - helmFieldSelector = fs.String() - } + // Parse field selector for manual filtering + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + fieldFilter, err := fieldfilter.ParseFieldSelector(options.FieldSelector) + if err != nil { + klog.Errorf("Error parsing field selector: %v", err) + return nil, err + } + + // If field selector specifies namespace different from context, return empty list + if fieldFilter.Namespace != "" && namespace != "" && namespace != fieldFilter.Namespace { + klog.V(6).Infof("Field selector namespace %s doesn't match context namespace %s, returning empty list", fieldFilter.Namespace, namespace) + return &corev1alpha1.TenantModuleList{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1alpha1.SchemeGroupVersion.String(), + Kind: "TenantModuleList", + }, + }, nil } // Process label.selector - add the tenant module label requirement @@ -202,19 +208,15 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption } } - helmLabelSelector = labels.NewSelector().Add(labelRequirements...).String() + helmLabelSelector = labels.NewSelector().Add(labelRequirements...) - // Set ListOptions for HelmRelease with selector mapping - metaOptions := metav1.ListOptions{ - FieldSelector: helmFieldSelector, - LabelSelector: helmLabelSelector, - } - - // List HelmReleases with mapped selectors + // List HelmReleases with label selector only + // Field selectors are not supported by controller-runtime cache + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 hrList := &helmv2.HelmReleaseList{} err = r.c.List(ctx, hrList, &client.ListOptions{ - Namespace: namespace, - Raw: &metaOptions, + Namespace: namespace, + LabelSelector: helmLabelSelector, }) if err != nil { klog.Errorf("Error listing HelmReleases: %v", err) @@ -226,6 +228,16 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption // Iterate over HelmReleases and convert to TenantModules for i := range hrList.Items { + // Apply manual field selector filtering (metadata.name and metadata.namespace) + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + if !fieldFilter.MatchesName(hrList.Items[i].Name) { + continue + } + if !fieldFilter.MatchesNamespace(hrList.Items[i].Namespace) { + continue + } + // Double-check the label requirement if !r.hasTenantModuleLabel(&hrList.Items[i]) { continue @@ -279,7 +291,14 @@ func (r *REST) List(ctx context.Context, options *metainternalversion.ListOption APIVersion: "core.cozystack.io/v1alpha1", Kind: r.kindName + "List", } - moduleList.SetResourceVersion(hrList.GetResourceVersion()) + + // Get ResourceVersion from list or compute from items + // controller-runtime cached client may not set ResourceVersion on the list itself + listRV := hrList.GetResourceVersion() + if listRV == "" { + listRV, _ = registry.MaxResourceVersion(hrList) + } + moduleList.SetResourceVersion(listRV) moduleList.Items = items sorting.ByNamespacedName[corev1alpha1.TenantModule, *corev1alpha1.TenantModule](moduleList.Items) @@ -305,25 +324,15 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio } // Initialize variables for selector mapping - var helmFieldSelector string - var helmLabelSelector string + var helmLabelSelector labels.Selector - // Process field.selector - if options.FieldSelector != nil { - fs, err := fields.ParseSelector(options.FieldSelector.String()) - if err != nil { - klog.Errorf("Invalid field selector: %v", err) - return nil, fmt.Errorf("invalid field selector: %v", err) - } - - // Check if selector is for metadata.name - if name, exists := fs.RequiresExactMatch("metadata.name"); exists { - // Create new field.selector for HelmRelease - helmFieldSelector = fields.OneTermEqualSelector("metadata.name", name).String() - } else { - // If field.selector contains other fields, map them directly - helmFieldSelector = fs.String() - } + // Parse field selector for manual filtering + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + fieldFilter, err := fieldfilter.ParseFieldSelector(options.FieldSelector) + if err != nil { + klog.Errorf("Error parsing field selector: %v", err) + return nil, err } // Process label.selector - add the tenant module label requirement @@ -347,21 +356,23 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio } } - helmLabelSelector = labels.NewSelector().Add(labelRequirements...).String() + helmLabelSelector = labels.NewSelector().Add(labelRequirements...) - // Set ListOptions for HelmRelease with selector mapping - metaOptions := metav1.ListOptions{ - Watch: true, - ResourceVersion: options.ResourceVersion, - FieldSelector: helmFieldSelector, - LabelSelector: helmLabelSelector, + // Get starting resourceVersion from options + var startingRV uint64 + if options.ResourceVersion != "" { + if rv, err := strconv.ParseUint(options.ResourceVersion, 10, 64); err == nil { + startingRV = rv + } } - // Start watch on HelmRelease with mapped selectors + // Start watch on HelmRelease with label selector only + // Field selectors are not supported by controller-runtime cache + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 hrList := &helmv2.HelmReleaseList{} helmWatcher, err := r.w.Watch(ctx, hrList, &client.ListOptions{ - Namespace: namespace, - Raw: &metaOptions, + Namespace: namespace, + LabelSelector: helmLabelSelector, }) if err != nil { klog.Errorf("Error setting up watch for HelmReleases: %v", err) @@ -378,20 +389,43 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio go func() { defer close(customW.resultChan) defer customW.underlying.Stop() + for { select { case event, ok := <-customW.underlying.ResultChan(): if !ok { - // The watcher has been closed, attempt to re-establish the watch - klog.Warning("HelmRelease watcher closed, attempting to re-establish") - // Implement retry logic or exit based on your requirements + klog.Warning("HelmRelease watcher closed") return } + // Handle bookmark events + if event.Type == watch.Bookmark { + if hr, ok := event.Object.(*helmv2.HelmRelease); ok { + bookmarkModule := &corev1alpha1.TenantModule{} + bookmarkModule.SetResourceVersion(hr.GetResourceVersion()) + bookmarkModule.TypeMeta = metav1.TypeMeta{ + APIVersion: corev1alpha1.SchemeGroupVersion.String(), + Kind: r.kindName, + } + bookmarkEvent := watch.Event{ + Type: watch.Bookmark, + Object: bookmarkModule, + } + select { + case customW.resultChan <- bookmarkEvent: + case <-customW.stopChan: + return + case <-ctx.Done(): + return + } + } + continue + } + // Check if the object is a *v1.Status if status, ok := event.Object.(*metav1.Status); ok { klog.V(4).Infof("Received Status object in HelmRelease watch: %v", status.Message) - continue // Skip processing this event + continue } // Proceed with processing HelmRelease objects @@ -401,6 +435,14 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio continue } + // Apply manual field selector filtering + if !fieldFilter.MatchesName(hr.Name) { + continue + } + if !fieldFilter.MatchesNamespace(hr.Namespace) { + continue + } + if !r.hasTenantModuleLabel(hr) { continue } @@ -412,6 +454,17 @@ func (r *REST) Watch(ctx context.Context, options *metainternalversion.ListOptio continue } + // Skip ADDED events based on resourceVersion comparison + // Only skip when client provided resourceVersion (they already have objects from List) + if event.Type == watch.Added && startingRV > 0 { + objRV, parseErr := strconv.ParseUint(module.ResourceVersion, 10, 64) + // Skip objects client already has (objRV <= startingRV) + if parseErr == nil && objRV <= startingRV { + continue + } + } + // When startingRV == 0, always send ADDED events (client wants full state) + // Apply field.selector by name if specified if resourceName != "" && module.Name != resourceName { continue @@ -666,11 +719,19 @@ func (r *REST) buildTableFromTenantModule(module corev1alpha1.TenantModule) meta return table } -// getVersion returns the module version or a placeholder if unknown +// getVersion extracts and returns only the revision from the version string +// If version is in format "0.1.4+abcdef", returns "abcdef" +// Otherwise returns the original string or "" if empty func getVersion(version string) string { if version == "" { return "" } + // Check if version contains "+" separator + if idx := strings.LastIndex(version, "+"); idx >= 0 && idx < len(version)-1 { + // Return only the part after "+" + return version[idx+1:] + } + // If no "+" found, return original version return version } diff --git a/pkg/registry/core/tenantnamespace/rest.go b/pkg/registry/core/tenantnamespace/rest.go index 90d5920d..f1ed3fab 100644 --- a/pkg/registry/core/tenantnamespace/rest.go +++ b/pkg/registry/core/tenantnamespace/rest.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "net/http" + "strconv" "strings" "time" @@ -26,6 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1" + "github.com/cozystack/cozystack/pkg/registry" "github.com/cozystack/cozystack/pkg/registry/sorting" ) @@ -150,16 +152,43 @@ func (r *REST) Watch(ctx context.Context, opts *metainternal.ListOptions) (watch return nil, err } + // Get starting resourceVersion from options + var startingRV uint64 + if opts.ResourceVersion != "" { + if rv, err := strconv.ParseUint(opts.ResourceVersion, 10, 64); err == nil { + startingRV = rv + } + } + events := make(chan watch.Event) pw := watch.NewProxyWatcher(events) go func() { defer pw.Stop() + for ev := range nsWatch.ResultChan() { + // Handle bookmark events + if ev.Type == watch.Bookmark { + if ns, ok := ev.Object.(*corev1.Namespace); ok { + out := &corev1alpha1.TenantNamespace{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1alpha1.SchemeGroupVersion.String(), + Kind: "TenantNamespace", + }, + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: ns.ResourceVersion, + }, + } + events <- watch.Event{Type: watch.Bookmark, Object: out} + } + continue + } + ns, ok := ev.Object.(*corev1.Namespace) if !ok || !strings.HasPrefix(ns.Name, prefix) { continue } + out := &corev1alpha1.TenantNamespace{ TypeMeta: metav1.TypeMeta{ APIVersion: corev1alpha1.SchemeGroupVersion.String(), @@ -174,6 +203,18 @@ func (r *REST) Watch(ctx context.Context, opts *metainternal.ListOptions) (watch Annotations: ns.Annotations, }, } + + // Skip ADDED events based on resourceVersion comparison + // Only skip when client provided resourceVersion (they already have objects from List) + if ev.Type == watch.Added && startingRV > 0 { + objRV, parseErr := strconv.ParseUint(out.ResourceVersion, 10, 64) + // Skip objects client already has (objRV <= startingRV) + if parseErr == nil && objRV <= startingRV { + continue + } + } + // When startingRV == 0, always send ADDED events (client wants full state) + events <- watch.Event{Type: ev.Type, Object: out} } }() @@ -227,12 +268,19 @@ func (r *REST) makeList(src *corev1.NamespaceList, allowed []string) *corev1alph set[n] = struct{}{} } + // Get ResourceVersion from list or compute from items + // controller-runtime cached client may not set ResourceVersion on the list itself + listRV := src.ResourceVersion + if listRV == "" { + listRV, _ = registry.MaxResourceVersion(src) + } + out := &corev1alpha1.TenantNamespaceList{ TypeMeta: metav1.TypeMeta{ APIVersion: corev1alpha1.SchemeGroupVersion.String(), Kind: "TenantNamespaceList", }, - ListMeta: metav1.ListMeta{ResourceVersion: src.ResourceVersion}, + ListMeta: metav1.ListMeta{ResourceVersion: listRV}, } for i := range src.Items { diff --git a/pkg/registry/core/tenantsecret/rest.go b/pkg/registry/core/tenantsecret/rest.go index e5dbf9dd..1f95c397 100644 --- a/pkg/registry/core/tenantsecret/rest.go +++ b/pkg/registry/core/tenantsecret/rest.go @@ -9,6 +9,7 @@ import ( "encoding/base64" "fmt" "net/http" + "strconv" "time" corev1 "k8s.io/api/core/v1" @@ -27,6 +28,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1" + "github.com/cozystack/cozystack/pkg/registry" + fieldfilter "github.com/cozystack/cozystack/pkg/registry/fields" "github.com/cozystack/cozystack/pkg/registry/sorting" ) @@ -248,9 +251,22 @@ func (r *REST) List(ctx context.Context, opts *metainternal.ListOptions) (runtim } } - fieldSel := "" - if opts.FieldSelector != nil { - fieldSel = opts.FieldSelector.String() + // Parse field selector for manual filtering + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + fieldFilter, err := fieldfilter.ParseFieldSelector(opts.FieldSelector) + if err != nil { + return nil, err + } + + // If field selector specifies namespace different from context, return empty list + if fieldFilter.Namespace != "" && ns != "" && ns != fieldFilter.Namespace { + return &corev1alpha1.TenantSecretList{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1alpha1.SchemeGroupVersion.String(), + Kind: kindTenantSecretList, + }, + }, nil } list := &corev1.SecretList{} @@ -258,24 +274,36 @@ func (r *REST) List(ctx context.Context, opts *metainternal.ListOptions) (runtim &client.ListOptions{ Namespace: ns, LabelSelector: ls, - Raw: &metav1.ListOptions{ - LabelSelector: ls.String(), - FieldSelector: fieldSel, - }, }) if err != nil { return nil, err } + // Get ResourceVersion from list or compute from items + // controller-runtime cached client may not set ResourceVersion on the list itself + listRV := list.ResourceVersion + if listRV == "" { + listRV, _ = registry.MaxResourceVersion(list) + } + out := &corev1alpha1.TenantSecretList{ TypeMeta: metav1.TypeMeta{ APIVersion: corev1alpha1.SchemeGroupVersion.String(), Kind: kindTenantSecretList, }, - ListMeta: list.ListMeta, + ListMeta: metav1.ListMeta{ResourceVersion: listRV}, } for i := range list.Items { + // Apply manual field selector filtering (metadata.name and metadata.namespace) + // controller-runtime cache doesn't support field selectors + // See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + if !fieldFilter.MatchesName(list.Items[i].Name) { + continue + } + if !fieldFilter.MatchesNamespace(list.Items[i].Namespace) { + continue + } out.Items = append(out.Items, *secretToTenant(&list.Items[i])) } sorting.ByNamespacedName[corev1alpha1.TenantSecret, *corev1alpha1.TenantSecret](out.Items) @@ -415,7 +443,6 @@ func (r *REST) Watch(ctx context.Context, opts *metainternal.ListOptions) (watch LabelSelector: ls, Raw: &metav1.ListOptions{ Watch: true, - LabelSelector: ls.String(), ResourceVersion: opts.ResourceVersion, }, }) @@ -423,17 +450,56 @@ func (r *REST) Watch(ctx context.Context, opts *metainternal.ListOptions) (watch return nil, err } + // Get starting resourceVersion from options + var startingRV uint64 + if opts.ResourceVersion != "" { + if rv, err := strconv.ParseUint(opts.ResourceVersion, 10, 64); err == nil { + startingRV = rv + } + } + ch := make(chan watch.Event) proxy := watch.NewProxyWatcher(ch) go func() { defer proxy.Stop() + for ev := range base.ResultChan() { + // Handle bookmark events + if ev.Type == watch.Bookmark { + if sec, ok := ev.Object.(*corev1.Secret); ok { + out := &corev1alpha1.TenantSecret{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1alpha1.SchemeGroupVersion.String(), + Kind: kindTenantSecret, + }, + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: sec.ResourceVersion, + }, + } + ch <- watch.Event{Type: watch.Bookmark, Object: out} + } + continue + } + sec, ok := ev.Object.(*corev1.Secret) if !ok || sec == nil { continue } + tenant := secretToTenant(sec) + + // Skip ADDED events based on resourceVersion comparison + // Only skip when client provided resourceVersion (they already have objects from List) + if ev.Type == watch.Added && startingRV > 0 { + objRV, parseErr := strconv.ParseUint(tenant.ResourceVersion, 10, 64) + // Skip objects client already has (objRV <= startingRV) + if parseErr == nil && objRV <= startingRV { + continue + } + } + // When startingRV == 0, always send ADDED events (client wants full state) + ch <- watch.Event{ Type: ev.Type, Object: tenant, diff --git a/pkg/registry/fields/filter.go b/pkg/registry/fields/filter.go new file mode 100644 index 00000000..9b1fc246 --- /dev/null +++ b/pkg/registry/fields/filter.go @@ -0,0 +1,70 @@ +// Copyright 2024 The Cozystack Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fields + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/fields" +) + +// Filter holds field selector filters extracted from a field selector string. +type Filter struct { + // Name is the value from metadata.name field selector, empty if not specified + Name string + // Namespace is the value from metadata.namespace field selector, empty if not specified + Namespace string +} + +// ParseFieldSelector parses a field selector and extracts metadata.name and metadata.namespace values. +// Other field selectors are silently ignored as controller-runtime cache doesn't support them. +// See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 +func ParseFieldSelector(fieldSelector fields.Selector) (*Filter, error) { + if fieldSelector == nil { + return &Filter{}, nil + } + + fs, err := fields.ParseSelector(fieldSelector.String()) + if err != nil { + return nil, fmt.Errorf("invalid field selector: %v", err) + } + + filter := &Filter{} + + // Check if selector is for metadata.name + if name, exists := fs.RequiresExactMatch("metadata.name"); exists { + filter.Name = name + } + + // Check if selector is for metadata.namespace + if namespace, exists := fs.RequiresExactMatch("metadata.namespace"); exists { + filter.Namespace = namespace + } + + // Note: Other field selectors are silently ignored as controller-runtime cache + // doesn't support them. See: https://github.com/kubernetes-sigs/controller-runtime/issues/612 + + return filter, nil +} + +// MatchesName returns true if the filter has no name constraint or if the name matches. +func (f *Filter) MatchesName(name string) bool { + return f.Name == "" || f.Name == name +} + +// MatchesNamespace returns true if the filter has no namespace constraint or if the namespace matches. +func (f *Filter) MatchesNamespace(namespace string) bool { + return f.Namespace == "" || f.Namespace == namespace +} diff --git a/pkg/registry/utils.go b/pkg/registry/utils.go new file mode 100644 index 00000000..c5deb422 --- /dev/null +++ b/pkg/registry/utils.go @@ -0,0 +1,57 @@ +/* +Copyright 2024 The Cozystack Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package registry + +import ( + "strconv" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" +) + +// MaxResourceVersion returns the maximum resourceVersion from all items in a list. +// This is useful when the list's ResourceVersion is empty (e.g., from controller-runtime cache). +func MaxResourceVersion(list runtime.Object) (string, error) { + var max uint64 + + err := meta.EachListItem(list, func(obj runtime.Object) error { + accessor, err := meta.Accessor(obj) + if err != nil { + return err + } + + rvStr := accessor.GetResourceVersion() + if rvStr == "" { + return nil + } + + rv, err := strconv.ParseUint(rvStr, 10, 64) + if err != nil { + return err + } + + if rv > max { + max = rv + } + return nil + }) + if err != nil { + return "", err + } + + return strconv.FormatUint(max, 10), nil +} diff --git a/pkg/version/version.go b/pkg/version/version.go new file mode 100644 index 00000000..0a571525 --- /dev/null +++ b/pkg/version/version.go @@ -0,0 +1,24 @@ +/* +Copyright 2025 The Cozystack Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package version provides the version information for cozystack components. +// Version is set at build time via -ldflags: +// +// go build -ldflags "-X github.com/cozystack/cozystack/pkg/version.Version=v1.0.0" +package version + +// Version is set at build time via -ldflags. +var Version = "dev" diff --git a/scripts/installer.sh b/scripts/installer.sh deleted file mode 100755 index 042e895a..00000000 --- a/scripts/installer.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh -set -o pipefail -set -e - -BUNDLE=$(set -x; kubectl get configmap -n cozy-system cozystack -o 'go-template={{index .data "bundle-name"}}') -VERSION=$(find scripts/migrations -mindepth 1 -maxdepth 1 -type f | sort -V | awk -F/ 'END {print $NF+1}') - -run_migrations() { - if ! kubectl get configmap -n cozy-system cozystack-version; then - kubectl create configmap -n cozy-system cozystack-version --from-literal=version="$VERSION" --dry-run=client -o yaml | kubectl create -f- - return - fi - current_version=$(kubectl get configmap -n cozy-system cozystack-version -o jsonpath='{.data.version}') || true - until [ "$current_version" = "$VERSION" ]; do - echo "run migration: $current_version --> $VERSION" - chmod +x scripts/migrations/$current_version - scripts/migrations/$current_version - current_version=$(kubectl get configmap -n cozy-system cozystack-version -o jsonpath='{.data.version}') - done -} - -install_flux() { - if [ "$INSTALL_FLUX" != "true" ]; then - return - fi - make -C packages/core/flux-aio apply - wait_for_crds helmreleases.helm.toolkit.fluxcd.io helmrepositories.source.toolkit.fluxcd.io -} - -wait_for_crds() { - timeout 60 sh -c "until kubectl get crd $*; do sleep 1; done" -} - -cd "$(dirname "$0")/.." - -# Run migrations -run_migrations - -# Install namespaces -make -C packages/core/platform namespaces-apply - -# Install fluxcd -install_flux - -# Install fluxcd certificates -./scripts/issue-flux-certificates.sh - -# Install platform chart -make -C packages/core/platform reconcile - -# Reconcile Helm repositories -kubectl annotate helmrepositories.source.toolkit.fluxcd.io -A -l cozystack.io/repository reconcile.fluxcd.io/requestedAt=$(date +"%Y-%m-%dT%H:%M:%SZ") --overwrite - -# Unsuspend all Cozystack managed charts -kubectl get hr -A -o go-template='{{ range .items }}{{ if .spec.suspend }}{{ .spec.chart.spec.sourceRef.namespace }}/{{ .spec.chart.spec.sourceRef.name }} {{ .metadata.namespace }} {{ .metadata.name }}{{ "\n" }}{{ end }}{{ end }}' | while read repo namespace name; do - case "$repo" in - cozy-system/cozystack-system|cozy-public/cozystack-extra|cozy-public/cozystack-apps) - kubectl patch hr -n "$namespace" "$name" -p '{"spec": {"suspend": null}}' --type=merge --field-manager=flux-client-side-apply - ;; - esac -done - -# Update all Cozystack managed charts to latest version -kubectl get hr -A -l cozystack.io/ui=true --no-headers | awk '{print "kubectl patch helmrelease -n " $1 " " $2 " --type=merge -p '\''{\"spec\":{\"chart\":{\"spec\":{\"version\":\">= 0.0.0-0\"}}}}'\'' "}' | sh -x - -# Reconcile platform chart -trap 'exit' INT TERM -while true; do - sleep 60 & wait - make -C packages/core/platform reconcile -done diff --git a/scripts/issue-flux-certificates.sh b/scripts/issue-flux-certificates.sh deleted file mode 100755 index 825447e2..00000000 --- a/scripts/issue-flux-certificates.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -set -e - -if kubectl get secret -n cozy-system cozystack-assets-tls >/dev/null 2>&1 && kubectl get secret -n cozy-public cozystack-assets-tls >/dev/null 2>&1; then - echo "Secret cozystack-assets-tls already exists in both cozy-system and cozy-public namespaces. Exiting." - exit 0 -fi - -USER_CN="cozystack-assets-reader" -CSR_NAME="csr-${USER_CN}-$(date +%s)" - -# make temp directory and cleanup handler -TMPDIR=$(mktemp -d) -trap 'rm -rf "$TMPDIR"' EXIT - -# move into tmpdir -cd "$TMPDIR" - -openssl genrsa -out tls.key 2048 -openssl req -new -key tls.key -subj "/CN=${USER_CN}" -out tls.csr - -CSR_B64=$(base64 < tls.csr | tr -d '\n') - -cat < tls.crt - -kubectl get -n kube-public configmap kube-root-ca.crt \ - -o jsonpath='{.data.ca\.crt}' > ca.crt - -kubectl create secret generic "cozystack-assets-tls" \ - --namespace='cozy-system' \ - --type='kubernetes.io/tls' \ - --from-file=tls.crt \ - --from-file=tls.key \ - --from-file=ca.crt \ - --dry-run=client -o yaml | kubectl apply -f - - -kubectl create secret generic "cozystack-assets-tls" \ - --namespace='cozy-public' \ - --type='kubernetes.io/tls' \ - --from-file=tls.crt \ - --from-file=tls.key \ - --from-file=ca.crt \ - --dry-run=client -o yaml | kubectl apply -f - diff --git a/scripts/migrations/21 b/scripts/migrations/21 deleted file mode 100755 index 7a367668..00000000 --- a/scripts/migrations/21 +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# Migration 21 --> 22 - -set -euo pipefail - -kubectl delete hr -n cozy-fluxcd fluxcd --ignore-not-found - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=22 --dry-run=client -o yaml | kubectl apply -f-