mirror of
https://github.com/outbackdingo/cozystack.git
synced 2026-02-05 00:15:51 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
015c893efe | ||
|
|
d177e475da | ||
|
|
280fd1f685 | ||
|
|
9ec5863a75 | ||
|
|
50f3089f14 | ||
|
|
1aadefef75 | ||
|
|
81a412517c | ||
|
|
23a7281fbf | ||
|
|
f32c6426a9 | ||
|
|
91583a4e1a | ||
|
|
f628e7d9c7 | ||
|
|
68d1646ae7 | ||
|
|
8fde834e39 | ||
|
|
e99d238647 | ||
|
|
e9435c2d3d | ||
|
|
da3ee5d0ea | ||
|
|
411a465b14 | ||
|
|
cad57cd922 | ||
|
|
fe1776b4c8 | ||
|
|
d9779d55ea | ||
|
|
74d3c89235 | ||
|
|
c831f53444 | ||
|
|
2c68eee9f8 | ||
|
|
e6ffb4f4e5 | ||
|
|
e63cc1890e | ||
|
|
1079472a2a | ||
|
|
1609931e3f | ||
|
|
699d38d8b9 | ||
|
|
acd4663aee | ||
|
|
f251cba363 | ||
|
|
91a07dcda6 | ||
|
|
99552bf792 | ||
|
|
45031055f8 | ||
|
|
d200017f74 | ||
|
|
f6eaca3843 | ||
|
|
8d3324f958 |
1
.github/workflows/tags.yaml
vendored
1
.github/workflows/tags.yaml
vendored
@@ -118,6 +118,7 @@ jobs:
|
|||||||
git config user.name "cozystack-bot"
|
git config user.name "cozystack-bot"
|
||||||
git config user.email "217169706+cozystack-bot@users.noreply.github.com"
|
git config user.email "217169706+cozystack-bot@users.noreply.github.com"
|
||||||
git remote set-url origin https://cozystack-bot:${GH_PAT}@github.com/${GITHUB_REPOSITORY}
|
git remote set-url origin https://cozystack-bot:${GH_PAT}@github.com/${GITHUB_REPOSITORY}
|
||||||
|
git config --unset-all http.https://github.com/.extraheader || true
|
||||||
git add .
|
git add .
|
||||||
git commit -m "Prepare release ${GITHUB_REF#refs/tags/}" -s || echo "No changes to commit"
|
git commit -m "Prepare release ${GITHUB_REF#refs/tags/}" -s || echo "No changes to commit"
|
||||||
git push origin HEAD || true
|
git push origin HEAD || true
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@@ -15,6 +16,10 @@ import (
|
|||||||
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
deletionRequeueDelay = 30 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
// WorkloadMonitorReconciler reconciles a WorkloadMonitor object
|
// WorkloadMonitorReconciler reconciles a WorkloadMonitor object
|
||||||
type WorkloadReconciler struct {
|
type WorkloadReconciler struct {
|
||||||
client.Client
|
client.Client
|
||||||
@@ -52,6 +57,9 @@ func (r *WorkloadReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
|
|||||||
|
|
||||||
// found object, nothing to do
|
// found object, nothing to do
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if !t.GetDeletionTimestamp().IsZero() {
|
||||||
|
return ctrl.Result{RequeueAfter: deletionRequeueDelay}, nil
|
||||||
|
}
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,6 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|||||||
@@ -62,6 +62,6 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ghcr.io/cozystack/cozystack/nginx-cache:0.6.0@sha256:b7633717cd7449c0042ae92d8ca9b36e4d69566561f5c7d44e21058e7d05c6d5
|
ghcr.io/cozystack/cozystack/nginx-cache:0.6.0@sha256:50ac1581e3100bd6c477a71161cb455a341ffaf9e5e2f6086802e4e25271e8af
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 0.25.0
|
version: 0.25.2
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# 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
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ image-kubevirt-csi-driver:
|
|||||||
--load=$(LOAD)
|
--load=$(LOAD)
|
||||||
echo "$(REGISTRY)/kubevirt-csi-driver:$(call settag,$(KUBERNETES_PKG_TAG))@$$(yq e '."containerimage.digest"' images/kubevirt-csi-driver.json -o json -r)" \
|
echo "$(REGISTRY)/kubevirt-csi-driver:$(call settag,$(KUBERNETES_PKG_TAG))@$$(yq e '."containerimage.digest"' images/kubevirt-csi-driver.json -o json -r)" \
|
||||||
> images/kubevirt-csi-driver.tag
|
> images/kubevirt-csi-driver.tag
|
||||||
|
IMAGE=$$(cat images/kubevirt-csi-driver.tag) \
|
||||||
|
yq -i '.csiDriver.image = strenv(IMAGE)' ../../system/kubevirt-csi-node/values.yaml
|
||||||
rm -f images/kubevirt-csi-driver.json
|
rm -f images/kubevirt-csi-driver.json
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.25.0@sha256:3a8170433e1632e5cc2b6d9db34d0605e8e6c63c158282c38450415e700e932e
|
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.25.2@sha256:3a8170433e1632e5cc2b6d9db34d0605e8e6c63c158282c38450415e700e932e
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.25.0@sha256:412ed2b3c77249bd1b973e6dc9c87976d31863717fb66ba74ccda573af737eb1
|
ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.25.2@sha256:71f9afa218693a890f827cb5cda98ba327302bd9f58afde767740557538e07d9
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.25.0@sha256:445c2727b04ac68595b43c988ff17b3d69a7b22b0644fde3b10c65b47a7bc036
|
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.25.2@sha256:761e7235ff9cb7f6f223f00954943e6a5af32ed6624ee592a8610122f96febb0
|
||||||
|
|||||||
@@ -13,11 +13,17 @@ rules:
|
|||||||
resources: ["datavolumes"]
|
resources: ["datavolumes"]
|
||||||
verbs: ["get", "create", "delete"]
|
verbs: ["get", "create", "delete"]
|
||||||
- apiGroups: ["kubevirt.io"]
|
- apiGroups: ["kubevirt.io"]
|
||||||
resources: ["virtualmachineinstances"]
|
resources: ["virtualmachineinstances", "virtualmachines"]
|
||||||
verbs: ["list", "get"]
|
verbs: ["list", "get"]
|
||||||
- apiGroups: ["subresources.kubevirt.io"]
|
- apiGroups: ["subresources.kubevirt.io"]
|
||||||
resources: ["virtualmachineinstances/addvolume", "virtualmachineinstances/removevolume"]
|
resources: ["virtualmachines/addvolume", "virtualmachines/removevolume"]
|
||||||
verbs: ["update"]
|
verbs: ["update"]
|
||||||
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
|
resources: ["volumesnapshots"]
|
||||||
|
verbs: ["get", "create", "delete"]
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["persistentvolumeclaims"]
|
||||||
|
verbs: ["get", "patch"]
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ spec:
|
|||||||
{{ .Release.Name }}-fluxcd-operator
|
{{ .Release.Name }}-fluxcd-operator
|
||||||
{{ .Release.Name }}-fluxcd
|
{{ .Release.Name }}-fluxcd
|
||||||
{{ .Release.Name }}-gpu-operator
|
{{ .Release.Name }}-gpu-operator
|
||||||
|
{{ .Release.Name }}-velero
|
||||||
-p '{"spec": {"suspend": true}}'
|
-p '{"spec": {"suspend": true}}'
|
||||||
--type=merge --field-manager=flux-client-side-apply || true
|
--type=merge --field-manager=flux-client-side-apply || true
|
||||||
---
|
---
|
||||||
@@ -79,6 +80,8 @@ rules:
|
|||||||
- {{ .Release.Name }}-fluxcd-operator
|
- {{ .Release.Name }}-fluxcd-operator
|
||||||
- {{ .Release.Name }}-fluxcd
|
- {{ .Release.Name }}-fluxcd
|
||||||
- {{ .Release.Name }}-gpu-operator
|
- {{ .Release.Name }}-gpu-operator
|
||||||
|
- {{ .Release.Name }}-velero
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ghcr.io/cozystack/cozystack/mariadb-backup:0.9.0@sha256:cfd1c37d8ad24e10681d82d6e6ce8a641b4602c1b0ffa8516ae15b4958bb12d4
|
ghcr.io/cozystack/cozystack/mariadb-backup:0.9.0@sha256:a3789db9e9e065ff60cbac70771b4a8aa1460db3194307cf5ca5d4fe1b412b6b
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 0.16.0
|
version: 0.17.1
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# 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
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
|
|||||||
@@ -11,7 +11,50 @@ This managed service is controlled by the CloudNativePG operator, ensuring effic
|
|||||||
- Docs: <https://cloudnative-pg.io/docs/>
|
- Docs: <https://cloudnative-pg.io/docs/>
|
||||||
- Github: <https://github.com/cloudnative-pg/cloudnative-pg>
|
- Github: <https://github.com/cloudnative-pg/cloudnative-pg>
|
||||||
|
|
||||||
## HowTos
|
## Operations
|
||||||
|
|
||||||
|
### How to enable backups
|
||||||
|
|
||||||
|
To back up a PostgreSQL application, an external S3-compatible storage is required.
|
||||||
|
|
||||||
|
To start regular backups, update the application, setting `backup.enabled` to `true`, and fill in the path and credentials to an `backup.*`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
## @param backup.enabled Enable regular backups
|
||||||
|
## @param backup.schedule Cron schedule for automated backups
|
||||||
|
## @param backup.retentionPolicy Retention policy
|
||||||
|
## @param backup.destinationPath Path to store the backup (i.e. s3://bucket/path/to/folder)
|
||||||
|
## @param backup.endpointURL S3 Endpoint used to upload data to the cloud
|
||||||
|
## @param backup.s3AccessKey Access key for S3, used for authentication
|
||||||
|
## @param backup.s3SecretKey Secret key for S3, used for authentication
|
||||||
|
backup:
|
||||||
|
enabled: false
|
||||||
|
retentionPolicy: 30d
|
||||||
|
destinationPath: s3://bucket/path/to/folder/
|
||||||
|
endpointURL: http://minio-gateway-service:9000
|
||||||
|
schedule: "0 2 * * * *"
|
||||||
|
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||||
|
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to recover a backup
|
||||||
|
|
||||||
|
CloudNativePG supports point-in-time-recovery.
|
||||||
|
Recovering a backup is done by creating a new database instance and restoring the data in it.
|
||||||
|
|
||||||
|
Create a new PostgreSQL application with a different name, but identical configuration.
|
||||||
|
Set `bootstrap.enabled` to `true` and fill in the name of the database instance to recover from and the recovery time:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
## @param bootstrap.enabled Restore database cluster from a backup
|
||||||
|
## @param bootstrap.recoveryTime Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest
|
||||||
|
## @param bootstrap.oldName Name of database cluster before deleting
|
||||||
|
##
|
||||||
|
bootstrap:
|
||||||
|
enabled: false
|
||||||
|
recoveryTime: "" # leave empty for latest or exact timestamp; example: 2020-11-26 15:22:00.00000+00
|
||||||
|
oldName: "<previous-postgres-instance>"
|
||||||
|
```
|
||||||
|
|
||||||
### How to switch primary/secondary replica
|
### How to switch primary/secondary replica
|
||||||
|
|
||||||
@@ -19,24 +62,6 @@ See:
|
|||||||
|
|
||||||
- <https://cloudnative-pg.io/documentation/1.15/rolling_update/#manual-updates-supervised>
|
- <https://cloudnative-pg.io/documentation/1.15/rolling_update/#manual-updates-supervised>
|
||||||
|
|
||||||
### How to restore backup
|
|
||||||
|
|
||||||
find snapshot:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
restic -r s3:s3.example.org/postgres-backups/database_name snapshots
|
|
||||||
```
|
|
||||||
|
|
||||||
restore:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
restic -r s3:s3.example.org/postgres-backups/database_name restore latest --target /tmp/
|
|
||||||
```
|
|
||||||
|
|
||||||
more details:
|
|
||||||
|
|
||||||
- <https://blog.aenix.io/restic-effective-backup-from-stdin-4bc1e8f083c1>
|
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
### Common parameters
|
### Common parameters
|
||||||
@@ -60,23 +85,23 @@ more details:
|
|||||||
|
|
||||||
### Backup parameters
|
### Backup parameters
|
||||||
|
|
||||||
| Name | Description | Value |
|
| Name | Description | Value |
|
||||||
| ------------------------ | -------------------------------------------------------------------- | ----------------------------------- |
|
| ------------------------ | ---------------------------------------------------------- | ----------------------------------- |
|
||||||
| `backup.enabled` | Enable pereiodic backups | `false` |
|
| `backup.enabled` | Enable regular backups | `false` |
|
||||||
| `backup.schedule` | Cron schedule for automated backups | `0 2 * * * *` |
|
| `backup.schedule` | Cron schedule for automated backups | `0 2 * * * *` |
|
||||||
| `backup.retentionPolicy` | The retention policy | `30d` |
|
| `backup.retentionPolicy` | Retention policy | `30d` |
|
||||||
| `backup.destinationPath` | The path where to store the backup (i.e. s3://bucket/path/to/folder) | `s3://BUCKET_NAME/` |
|
| `backup.destinationPath` | Path to store the backup (i.e. s3://bucket/path/to/folder) | `s3://bucket/path/to/folder/` |
|
||||||
| `backup.endpointURL` | Endpoint to be used to upload data to the cloud | `http://minio-gateway-service:9000` |
|
| `backup.endpointURL` | S3 Endpoint used to upload data to the cloud | `http://minio-gateway-service:9000` |
|
||||||
| `backup.s3AccessKey` | The access key for S3, used for authentication | `oobaiRus9pah8PhohL1ThaeTa4UVa7gu` |
|
| `backup.s3AccessKey` | Access key for S3, used for authentication | `oobaiRus9pah8PhohL1ThaeTa4UVa7gu` |
|
||||||
| `backup.s3SecretKey` | The secret key for S3, used for authentication | `ju3eum4dekeich9ahM1te8waeGai0oog` |
|
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `ju3eum4dekeich9ahM1te8waeGai0oog` |
|
||||||
|
|
||||||
### Bootstrap parameters
|
### Bootstrap parameters
|
||||||
|
|
||||||
| Name | Description | Value |
|
| Name | Description | Value |
|
||||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||||
| `bootstrap.enabled` | Restore cluster from backup | `false` |
|
| `bootstrap.enabled` | Restore database cluster from a backup | `false` |
|
||||||
| `bootstrap.recoveryTime` | Time stamp up to which recovery will proceed, expressed in RFC 3339 format, if empty, will restore latest | `""` |
|
| `bootstrap.recoveryTime` | Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest | `""` |
|
||||||
| `bootstrap.oldName` | Name of cluster before deleting | `""` |
|
| `bootstrap.oldName` | Name of database cluster before deleting | `""` |
|
||||||
| `resources` | Explicit CPU and memory configuration for each PostgreSQL replica. When left empty, the preset defined in `resourcesPreset` is applied. | `{}` |
|
| `resources` | Explicit CPU and memory configuration for each PostgreSQL replica. When left empty, the preset defined in `resourcesPreset` is applied. | `{}` |
|
||||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge. | `micro` |
|
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge. | `micro` |
|
||||||
|
|
||||||
@@ -103,7 +128,7 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ stringData:
|
|||||||
until pg_isready ; do sleep 5; done
|
until pg_isready ; do sleep 5; done
|
||||||
|
|
||||||
echo "== create users"
|
echo "== create users"
|
||||||
{{- if .Values.users }}
|
{{- if and .Values.users (not (hasKey .Values.users "postgres")) }}
|
||||||
psql -v ON_ERROR_STOP=1 <<\EOT
|
psql -v ON_ERROR_STOP=1 <<\EOT
|
||||||
{{- range $user, $u := .Values.users }}
|
{{- range $user, $u := .Values.users }}
|
||||||
SELECT 'CREATE ROLE "{{ $user }}" LOGIN INHERIT;'
|
SELECT 'CREATE ROLE "{{ $user }}" LOGIN INHERIT;'
|
||||||
@@ -47,6 +47,8 @@ stringData:
|
|||||||
COMMENT ON ROLE "{{ $user }}" IS 'user managed by helm';
|
COMMENT ON ROLE "{{ $user }}" IS 'user managed by helm';
|
||||||
{{- end }}
|
{{- end }}
|
||||||
EOT
|
EOT
|
||||||
|
{{- else if and .Values.users (hasKey .Values.users "postgres") }}
|
||||||
|
{{- fail "`users.postgres` is forbidden by policy. Use a different username." }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
echo "== delete users"
|
echo "== delete users"
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"enabled": {
|
"enabled": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Enable pereiodic backups",
|
"description": "Enable regular backups",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"schedule": {
|
"schedule": {
|
||||||
@@ -72,27 +72,27 @@
|
|||||||
},
|
},
|
||||||
"retentionPolicy": {
|
"retentionPolicy": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The retention policy",
|
"description": "Retention policy",
|
||||||
"default": "30d"
|
"default": "30d"
|
||||||
},
|
},
|
||||||
"destinationPath": {
|
"destinationPath": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The path where to store the backup (i.e. s3://bucket/path/to/folder)",
|
"description": "Path to store the backup (i.e. s3://bucket/path/to/folder)",
|
||||||
"default": "s3://BUCKET_NAME/"
|
"default": "s3://bucket/path/to/folder/"
|
||||||
},
|
},
|
||||||
"endpointURL": {
|
"endpointURL": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Endpoint to be used to upload data to the cloud",
|
"description": "S3 Endpoint used to upload data to the cloud",
|
||||||
"default": "http://minio-gateway-service:9000"
|
"default": "http://minio-gateway-service:9000"
|
||||||
},
|
},
|
||||||
"s3AccessKey": {
|
"s3AccessKey": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The access key for S3, used for authentication",
|
"description": "Access key for S3, used for authentication",
|
||||||
"default": "oobaiRus9pah8PhohL1ThaeTa4UVa7gu"
|
"default": "oobaiRus9pah8PhohL1ThaeTa4UVa7gu"
|
||||||
},
|
},
|
||||||
"s3SecretKey": {
|
"s3SecretKey": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The secret key for S3, used for authentication",
|
"description": "Secret key for S3, used for authentication",
|
||||||
"default": "ju3eum4dekeich9ahM1te8waeGai0oog"
|
"default": "ju3eum4dekeich9ahM1te8waeGai0oog"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,17 +102,17 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"enabled": {
|
"enabled": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Restore cluster from backup",
|
"description": "Restore database cluster from a backup",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"recoveryTime": {
|
"recoveryTime": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Time stamp up to which recovery will proceed, expressed in RFC 3339 format, if empty, will restore latest",
|
"description": "Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest",
|
||||||
"default": ""
|
"default": ""
|
||||||
},
|
},
|
||||||
"oldName": {
|
"oldName": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Name of cluster before deleting",
|
"description": "Name of database cluster before deleting",
|
||||||
"default": ""
|
"default": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,17 +59,17 @@ databases: {}
|
|||||||
|
|
||||||
## @section Backup parameters
|
## @section Backup parameters
|
||||||
|
|
||||||
## @param backup.enabled Enable pereiodic backups
|
## @param backup.enabled Enable regular backups
|
||||||
## @param backup.schedule Cron schedule for automated backups
|
## @param backup.schedule Cron schedule for automated backups
|
||||||
## @param backup.retentionPolicy The retention policy
|
## @param backup.retentionPolicy Retention policy
|
||||||
## @param backup.destinationPath The path where to store the backup (i.e. s3://bucket/path/to/folder)
|
## @param backup.destinationPath Path to store the backup (i.e. s3://bucket/path/to/folder)
|
||||||
## @param backup.endpointURL Endpoint to be used to upload data to the cloud
|
## @param backup.endpointURL S3 Endpoint used to upload data to the cloud
|
||||||
## @param backup.s3AccessKey The access key for S3, used for authentication
|
## @param backup.s3AccessKey Access key for S3, used for authentication
|
||||||
## @param backup.s3SecretKey The secret key for S3, used for authentication
|
## @param backup.s3SecretKey Secret key for S3, used for authentication
|
||||||
backup:
|
backup:
|
||||||
enabled: false
|
enabled: false
|
||||||
retentionPolicy: 30d
|
retentionPolicy: 30d
|
||||||
destinationPath: s3://BUCKET_NAME/
|
destinationPath: s3://bucket/path/to/folder/
|
||||||
endpointURL: http://minio-gateway-service:9000
|
endpointURL: http://minio-gateway-service:9000
|
||||||
schedule: "0 2 * * * *"
|
schedule: "0 2 * * * *"
|
||||||
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||||
@@ -77,9 +77,9 @@ backup:
|
|||||||
|
|
||||||
## @section Bootstrap parameters
|
## @section Bootstrap parameters
|
||||||
|
|
||||||
## @param bootstrap.enabled Restore cluster from backup
|
## @param bootstrap.enabled Restore database cluster from a backup
|
||||||
## @param bootstrap.recoveryTime Time stamp up to which recovery will proceed, expressed in RFC 3339 format, if empty, will restore latest
|
## @param bootstrap.recoveryTime Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest
|
||||||
## @param bootstrap.oldName Name of cluster before deleting
|
## @param bootstrap.oldName Name of database cluster before deleting
|
||||||
##
|
##
|
||||||
bootstrap:
|
bootstrap:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|||||||
@@ -45,6 +45,6 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|||||||
@@ -52,6 +52,6 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ kafka 0.7.0 6358fd7a
|
|||||||
kafka 0.7.1 4369b031
|
kafka 0.7.1 4369b031
|
||||||
kafka 0.8.0 HEAD
|
kafka 0.8.0 HEAD
|
||||||
kubernetes 0.24.0 62cb694d
|
kubernetes 0.24.0 62cb694d
|
||||||
kubernetes 0.25.0 HEAD
|
kubernetes 0.25.0 70f82667
|
||||||
|
kubernetes 0.25.1 acd4663a
|
||||||
|
kubernetes 0.25.2 HEAD
|
||||||
mysql 0.1.0 263e47be
|
mysql 0.1.0 263e47be
|
||||||
mysql 0.2.0 c24a103f
|
mysql 0.2.0 c24a103f
|
||||||
mysql 0.3.0 53f2365e
|
mysql 0.3.0 53f2365e
|
||||||
@@ -101,7 +103,9 @@ postgres 0.12.0 6130f43d
|
|||||||
postgres 0.12.1 632224a3
|
postgres 0.12.1 632224a3
|
||||||
postgres 0.14.0 62cb694d
|
postgres 0.14.0 62cb694d
|
||||||
postgres 0.15.1 4369b031
|
postgres 0.15.1 4369b031
|
||||||
postgres 0.16.0 HEAD
|
postgres 0.16.0 70f82667
|
||||||
|
postgres 0.17.0 acd4663a
|
||||||
|
postgres 0.17.1 HEAD
|
||||||
rabbitmq 0.1.0 263e47be
|
rabbitmq 0.1.0 263e47be
|
||||||
rabbitmq 0.2.0 53f2365e
|
rabbitmq 0.2.0 53f2365e
|
||||||
rabbitmq 0.3.0 6c5cf5bf
|
rabbitmq 0.3.0 6c5cf5bf
|
||||||
@@ -153,7 +157,8 @@ virtual-machine 0.9.1 93bdf411
|
|||||||
virtual-machine 0.10.0 6130f43d
|
virtual-machine 0.10.0 6130f43d
|
||||||
virtual-machine 0.10.2 632224a3
|
virtual-machine 0.10.2 632224a3
|
||||||
virtual-machine 0.11.0 4369b031
|
virtual-machine 0.11.0 4369b031
|
||||||
virtual-machine 0.12.0 HEAD
|
virtual-machine 0.12.0 70f82667
|
||||||
|
virtual-machine 0.12.1 HEAD
|
||||||
vm-disk 0.1.0 d971f2ff
|
vm-disk 0.1.0 d971f2ff
|
||||||
vm-disk 0.1.1 6130f43d
|
vm-disk 0.1.1 6130f43d
|
||||||
vm-disk 0.1.2 632224a3
|
vm-disk 0.1.2 632224a3
|
||||||
@@ -170,7 +175,8 @@ vm-instance 0.6.0 721c12a7
|
|||||||
vm-instance 0.7.0 6130f43d
|
vm-instance 0.7.0 6130f43d
|
||||||
vm-instance 0.7.2 632224a3
|
vm-instance 0.7.2 632224a3
|
||||||
vm-instance 0.8.0 4369b031
|
vm-instance 0.8.0 4369b031
|
||||||
vm-instance 0.9.0 HEAD
|
vm-instance 0.9.0 70f82667
|
||||||
|
vm-instance 0.10.0 HEAD
|
||||||
vpn 0.1.0 263e47be
|
vpn 0.1.0 263e47be
|
||||||
vpn 0.2.0 53f2365e
|
vpn 0.2.0 53f2365e
|
||||||
vpn 0.3.0 6c5cf5bf
|
vpn 0.3.0 6c5cf5bf
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 0.12.0
|
version: 0.12.1
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# 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
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ kind: Role
|
|||||||
metadata:
|
metadata:
|
||||||
name: {{ .Release.Name }}-dashboard-resources
|
name: {{ .Release.Name }}-dashboard-resources
|
||||||
rules:
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
resourceNames:
|
||||||
|
- {{ include "virtual-machine.fullname" . }}
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- cozystack.io
|
- cozystack.io
|
||||||
resources:
|
resources:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ stringData:
|
|||||||
key{{ $k }}: {{ quote $v }}
|
key{{ $k }}: {{ quote $v }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.cloudInit }}
|
{{- if or .Values.cloudInit .Values.sshKeys }}
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
@@ -17,5 +17,17 @@ metadata:
|
|||||||
name: {{ include "virtual-machine.fullname" . }}-cloud-init
|
name: {{ include "virtual-machine.fullname" . }}-cloud-init
|
||||||
stringData:
|
stringData:
|
||||||
userdata: |
|
userdata: |
|
||||||
{{- .Values.cloudInit | nindent 4 }}
|
{{- if .Values.cloudInit }}
|
||||||
|
{{- .Values.cloudInit | nindent 4 }}
|
||||||
|
{{- else if and (.Values.sshKeys) (not .Values.cloudInit) }}
|
||||||
|
{{- /*
|
||||||
|
We usually provide ssh keys in cloud-init metadata, because userdata it not typed and can be used for any purpose.
|
||||||
|
However, if user provides ssh keys but not cloud-init, we still need to provide a minimal cloud-init config to avoid errors.
|
||||||
|
*/}}
|
||||||
|
#cloud-config
|
||||||
|
ssh_authorized_keys:
|
||||||
|
{{- range .Values.sshKeys }}
|
||||||
|
- {{ quote . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ spec:
|
|||||||
- disk:
|
- disk:
|
||||||
bus: scsi
|
bus: scsi
|
||||||
name: systemdisk
|
name: systemdisk
|
||||||
{{- if .Values.sshKeys }}
|
{{- if or .Values.cloudInit .Values.sshKeys }}
|
||||||
- disk:
|
- disk:
|
||||||
bus: virtio
|
bus: virtio
|
||||||
name: cloudinitdisk
|
name: cloudinitdisk
|
||||||
@@ -122,28 +122,11 @@ spec:
|
|||||||
- name: systemdisk
|
- name: systemdisk
|
||||||
dataVolume:
|
dataVolume:
|
||||||
name: {{ include "virtual-machine.fullname" . }}
|
name: {{ include "virtual-machine.fullname" . }}
|
||||||
|
{{- if or .Values.cloudInit .Values.sshKeys }}
|
||||||
{{- if and .Values.sshKeys .Values.cloudInit }}
|
|
||||||
- name: cloudinitdisk
|
- name: cloudinitdisk
|
||||||
cloudInitNoCloud:
|
cloudInitNoCloud:
|
||||||
secretRef:
|
secretRef:
|
||||||
name: {{ include "virtual-machine.fullname" . }}-cloud-init
|
name: {{ include "virtual-machine.fullname" . }}-cloud-init
|
||||||
{{- else if .Values.sshKeys }}
|
|
||||||
- name: cloudinitdisk
|
|
||||||
cloudInitNoCloud:
|
|
||||||
userData: |
|
|
||||||
{{ printf "%s" "#cloud-config" }}
|
|
||||||
ssh_authorized_keys:
|
|
||||||
{{- range .Values.sshKeys }}
|
|
||||||
- {{ . }}
|
|
||||||
{{- end }}
|
|
||||||
chpasswd:
|
|
||||||
expire: false
|
|
||||||
{{- else }}
|
|
||||||
- name: cloudinitdisk
|
|
||||||
cloudInitNoCloud:
|
|
||||||
userData: |
|
|
||||||
{{ printf "%s" "#cloud-config" }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 0.9.0
|
version: 0.10.0
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# 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
|
# 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.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
# It is recommended to use it with quotes.
|
# It is recommended to use it with quotes.
|
||||||
appVersion: 0.8.0
|
appVersion: 0.10.0
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ kind: Role
|
|||||||
metadata:
|
metadata:
|
||||||
name: {{ .Release.Name }}-dashboard-resources
|
name: {{ .Release.Name }}-dashboard-resources
|
||||||
rules:
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
resourceNames:
|
||||||
|
- {{ include "virtual-machine.fullname" . }}
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- cozystack.io
|
- cozystack.io
|
||||||
resources:
|
resources:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ stringData:
|
|||||||
key{{ $k }}: {{ quote $v }}
|
key{{ $k }}: {{ quote $v }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.cloudInit }}
|
{{- if or .Values.cloudInit .Values.sshKeys }}
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
@@ -17,5 +17,17 @@ metadata:
|
|||||||
name: {{ include "virtual-machine.fullname" . }}-cloud-init
|
name: {{ include "virtual-machine.fullname" . }}-cloud-init
|
||||||
stringData:
|
stringData:
|
||||||
userdata: |
|
userdata: |
|
||||||
{{- .Values.cloudInit | nindent 4 }}
|
{{- if .Values.cloudInit }}
|
||||||
|
{{- .Values.cloudInit | nindent 4 }}
|
||||||
|
{{- else if and (.Values.sshKeys) (not .Values.cloudInit) }}
|
||||||
|
{{- /*
|
||||||
|
We usually provide ssh keys in cloud-init metadata, because userdata it not typed and can be used for any purpose.
|
||||||
|
However, if user provides ssh keys but not cloud-init, we still need to provide a minimal cloud-init config to avoid errors.
|
||||||
|
*/}}
|
||||||
|
#cloud-config
|
||||||
|
ssh_authorized_keys:
|
||||||
|
{{- range .Values.sshKeys }}
|
||||||
|
- {{ quote . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -54,24 +54,24 @@ spec:
|
|||||||
disks:
|
disks:
|
||||||
{{- range $i, $disk := .Values.disks }}
|
{{- range $i, $disk := .Values.disks }}
|
||||||
- name: disk-{{ $disk.name }}
|
- name: disk-{{ $disk.name }}
|
||||||
{{- $disk := lookup "cdi.kubevirt.io/v1beta1" "DataVolume" $.Release.Namespace (printf "vm-disk-%s" $disk.name) }}
|
{{- $dv := lookup "cdi.kubevirt.io/v1beta1" "DataVolume" $.Release.Namespace (printf "vm-disk-%s" $disk.name) }}
|
||||||
{{- if $disk }}
|
{{- if $dv }}
|
||||||
{{- if and (hasKey $disk.metadata.annotations "vm-disk.cozystack.io/optical") (eq (index $disk.metadata.annotations "vm-disk.cozystack.io/optical") "true") }}
|
{{- if and (hasKey $dv.metadata.annotations "vm-disk.cozystack.io/optical") (eq (index $dv.metadata.annotations "vm-disk.cozystack.io/optical") "true") }}
|
||||||
cdrom: {}
|
cdrom:
|
||||||
{{- else }}
|
{{- else }}
|
||||||
disk: {}
|
disk:
|
||||||
{{- end }}
|
|
||||||
{{- if eq $i 0 }}
|
|
||||||
bootOrder: 1
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- with $disk.bus }}
|
||||||
|
bus: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
bootOrder: {{ add $i 1 }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
{{- fail (printf "Specified disk not exists in cluster: %s" .name) }}
|
{{- fail (printf "Specified disk not exists in cluster: %s" .name) }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if or .Values.sshKeys .Values.cloudInit }}
|
{{- if or .Values.cloudInit .Values.sshKeys }}
|
||||||
- name: cloudinitdisk
|
- name: cloudinitdisk
|
||||||
disk:
|
disk: {}
|
||||||
bus: virtio
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
interfaces:
|
interfaces:
|
||||||
- name: default
|
- name: default
|
||||||
@@ -95,27 +95,11 @@ spec:
|
|||||||
dataVolume:
|
dataVolume:
|
||||||
name: vm-disk-{{ .name }}
|
name: vm-disk-{{ .name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if and .Values.sshKeys .Values.cloudInit }}
|
{{- if or .Values.cloudInit .Values.sshKeys }}
|
||||||
- name: cloudinitdisk
|
- name: cloudinitdisk
|
||||||
cloudInitNoCloud:
|
cloudInitNoCloud:
|
||||||
secretRef:
|
secretRef:
|
||||||
name: {{ include "virtual-machine.fullname" . }}-cloud-init
|
name: {{ include "virtual-machine.fullname" . }}-cloud-init
|
||||||
{{- else if .Values.sshKeys }}
|
|
||||||
- name: cloudinitdisk
|
|
||||||
cloudInitNoCloud:
|
|
||||||
userData: |
|
|
||||||
{{ printf "%s" "#cloud-config" }}
|
|
||||||
ssh_authorized_keys:
|
|
||||||
{{- range .Values.sshKeys }}
|
|
||||||
- {{ . }}
|
|
||||||
{{- end }}
|
|
||||||
chpasswd:
|
|
||||||
expire: false
|
|
||||||
{{- else }}
|
|
||||||
- name: cloudinitdisk
|
|
||||||
cloudInitNoCloud:
|
|
||||||
userData: |
|
|
||||||
{{ printf "%s" "#cloud-config" }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
networks:
|
networks:
|
||||||
- name: default
|
- name: default
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ instanceProfile: ubuntu
|
|||||||
## disks:
|
## disks:
|
||||||
## - name: example-system
|
## - name: example-system
|
||||||
## - name: example-data
|
## - name: example-data
|
||||||
|
## bus: sata
|
||||||
disks: []
|
disks: []
|
||||||
|
|
||||||
## @param gpus [array] List of GPUs to attach
|
## @param gpus [array] List of GPUs to attach
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ This setting is ignored if the corresponding `resources` value is set.
|
|||||||
| `micro` | `500m` | `256Mi` |
|
| `micro` | `500m` | `256Mi` |
|
||||||
| `small` | `1` | `512Mi` |
|
| `small` | `1` | `512Mi` |
|
||||||
| `medium` | `1` | `1Gi` |
|
| `medium` | `1` | `1Gi` |
|
||||||
| `large` | `3` | `2Gi` |
|
| `large` | `2` | `2Gi` |
|
||||||
| `xlarge` | `4` | `4Gi` |
|
| `xlarge` | `4` | `4Gi` |
|
||||||
| `2xlarge` | `8` | `8Gi` |
|
| `2xlarge` | `8` | `8Gi` |
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
cozystack:
|
cozystack:
|
||||||
image: ghcr.io/cozystack/cozystack/installer:v0.33.0@sha256:6cdc5d9062b536929152214e8a6a6b8096b64a17592e04a3633f58d21ff43a63
|
image: ghcr.io/cozystack/cozystack/installer:v0.33.3@sha256:cee50a80af792af7427c5e1e32d6841f62b9eed1a857b41729372ba79bd18e68
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
e2e:
|
e2e:
|
||||||
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.33.0@sha256:fd169ae7ee7b0b10ee34f02353ae96c182ca7b6cede771c8fc6539894416104f
|
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.33.3@sha256:9baa3c1465133b968e775f29f74c8b569fea29c7e5b490551f0a5baf8b6f1270
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ghcr.io/cozystack/cozystack/matchbox:v0.33.0@sha256:adc133234a48f3496441334348aeab400ee29b8514129c110b892fa1e0dff1d8
|
ghcr.io/cozystack/cozystack/matchbox:v0.33.3@sha256:2e71760570c40d18b29f74f989f120563acefc77c25c477a1d6722f50794a588
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:2759763d35ba35144ba10ba4d2b9effd875f4f0d01d9694b010f491ba6eb6d46
|
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:208d8ea43b4b493ee0bea80606f6b3041a02460be79c52ed12aecccd35ec2a02
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
cozystackAPI:
|
cozystackAPI:
|
||||||
image: ghcr.io/cozystack/cozystack/cozystack-api:v0.33.0@sha256:d9bee0e9f73a950784e43d907552c21044d01eed728e1185455308e49d00c00d
|
image: ghcr.io/cozystack/cozystack/cozystack-api:v0.33.3@sha256:c9d123823e2cfd8900d485401f8ac7b805be248a1a40715e746495739165787b
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cozystackController:
|
cozystackController:
|
||||||
image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.33.0@sha256:a1fceb277007846bc85ceee0afd1f5d1122496174203c718c1275a1038cb07f6
|
image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.33.3@sha256:3b589fc8a102344d66407d814bdcc807a1a97a42163336bc3b5d0c44b086c128
|
||||||
debug: false
|
debug: false
|
||||||
disableTelemetry: false
|
disableTelemetry: false
|
||||||
cozystackVersion: "v0.33.0"
|
cozystackVersion: "v0.33.3"
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ data:
|
|||||||
"kubeappsNamespace": {{ .Release.Namespace | quote }},
|
"kubeappsNamespace": {{ .Release.Namespace | quote }},
|
||||||
"helmGlobalNamespace": {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }},
|
"helmGlobalNamespace": {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }},
|
||||||
"carvelGlobalNamespace": {{ .Values.kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace | quote }},
|
"carvelGlobalNamespace": {{ .Values.kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace | quote }},
|
||||||
"appVersion": "v0.33.0",
|
"appVersion": "v0.33.3",
|
||||||
"authProxyEnabled": {{ .Values.authProxy.enabled }},
|
"authProxyEnabled": {{ .Values.authProxy.enabled }},
|
||||||
"oauthLoginURI": {{ .Values.authProxy.oauthLoginURI | quote }},
|
"oauthLoginURI": {{ .Values.authProxy.oauthLoginURI | quote }},
|
||||||
"oauthLogoutURI": {{ .Values.authProxy.oauthLogoutURI | quote }},
|
"oauthLogoutURI": {{ .Values.authProxy.oauthLogoutURI | quote }},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM bitnami/node:20.15.1 AS build
|
FROM bitnami/node:20.15.1 AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ARG COMMIT_REF=6856b66f9244ef1b2703a2f30899366e0ba040de
|
ARG COMMIT_REF=e1382f51c6db1bca0a8ecd454407c8e282fe0243
|
||||||
RUN wget -O- https://github.com/cozystack/kubeapps/archive/${COMMIT_REF}.tar.gz | tar xzf - --strip-components=2 kubeapps-${COMMIT_REF}/dashboard
|
RUN wget -O- https://github.com/cozystack/kubeapps/archive/${COMMIT_REF}.tar.gz | tar xzf - --strip-components=2 kubeapps-${COMMIT_REF}/dashboard
|
||||||
|
|
||||||
RUN yarn install --frozen-lockfile
|
RUN yarn install --frozen-lockfile
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# syntax = docker/dockerfile:1
|
# syntax = docker/dockerfile:1
|
||||||
|
|
||||||
FROM alpine AS source
|
FROM alpine AS source
|
||||||
ARG COMMIT_REF=6856b66f9244ef1b2703a2f30899366e0ba040de
|
ARG COMMIT_REF=e1382f51c6db1bca0a8ecd454407c8e282fe0243
|
||||||
RUN apk add --no-cache patch
|
RUN apk add --no-cache patch
|
||||||
WORKDIR /source
|
WORKDIR /source
|
||||||
RUN wget -O- https://github.com/cozystack/kubeapps/archive/${COMMIT_REF}.tar.gz | tar xzf - --strip-components=1
|
RUN wget -O- https://github.com/cozystack/kubeapps/archive/${COMMIT_REF}.tar.gz | tar xzf - --strip-components=1
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ kubeapps:
|
|||||||
image:
|
image:
|
||||||
registry: ghcr.io/cozystack/cozystack
|
registry: ghcr.io/cozystack/cozystack
|
||||||
repository: dashboard
|
repository: dashboard
|
||||||
tag: v0.33.0
|
tag: v0.33.3
|
||||||
digest: "sha256:5e514516bd3dc0c693bb346ddeb9740e0439a59deb2a56b87317286e3ce79ac9"
|
digest: "sha256:ac2b5348d85fe37ad70a4cc159881c4eaded9175a4b586cfa09a52b0fbe5e1e5"
|
||||||
redis:
|
redis:
|
||||||
master:
|
master:
|
||||||
resourcesPreset: "none"
|
resourcesPreset: "none"
|
||||||
@@ -37,8 +37,8 @@ kubeapps:
|
|||||||
image:
|
image:
|
||||||
registry: ghcr.io/cozystack/cozystack
|
registry: ghcr.io/cozystack/cozystack
|
||||||
repository: kubeapps-apis
|
repository: kubeapps-apis
|
||||||
tag: v0.33.0
|
tag: v0.33.3
|
||||||
digest: "sha256:8c60134b9216e0cd8ffc044c14c872b76c1a95879b4cf7887541980ade9e8c65"
|
digest: "sha256:be25afff8d0f8ae8d2e42a824856e9776db0cee285f6f41514803a4e85e17371"
|
||||||
pluginConfig:
|
pluginConfig:
|
||||||
flux:
|
flux:
|
||||||
packages:
|
packages:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ kamaji:
|
|||||||
deploy: false
|
deploy: false
|
||||||
image:
|
image:
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
tag: v0.33.0@sha256:afaf5f003eb990377c21623d17bb00e7a95a1021e1c36b318cb451b80c8d37a2
|
tag: v0.33.3@sha256:09465ae8285b4ae43203581e443409cd4e1e119dde62a5c14d63ce064fb840b0
|
||||||
repository: ghcr.io/cozystack/cozystack/kamaji
|
repository: ghcr.io/cozystack/cozystack/kamaji
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
portSecurity: true
|
portSecurity: true
|
||||||
routes: ""
|
routes: ""
|
||||||
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.33.0@sha256:926fa45edd2149e4bc4bb54710832c8fb7aa46c85cf6adb7cd486e0b956cdbfa
|
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.33.3@sha256:c7f42022280a565da8b3091ed2f4fe2768fcd392327d23172a532c24794787c6
|
||||||
|
|||||||
@@ -64,4 +64,4 @@ global:
|
|||||||
images:
|
images:
|
||||||
kubeovn:
|
kubeovn:
|
||||||
repository: kubeovn
|
repository: kubeovn
|
||||||
tag: v1.13.13@sha256:6315d11876b78f3c24e54a73063d05c63137c4210dcd7620bd983db5fedf469a
|
tag: v1.13.13@sha256:f8edb9f98fe64daf5e3634b8844cea7747e197f3a345d6fe8be6f1d336154cfb
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ spec:
|
|||||||
privileged: true
|
privileged: true
|
||||||
allowPrivilegeEscalation: true
|
allowPrivilegeEscalation: true
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
image: ghcr.io/kvaps/test:kubevirt-csi-driver
|
image: {{ .Values.csiDriver.image }}
|
||||||
args:
|
args:
|
||||||
- "--endpoint=unix:/csi/csi.sock"
|
- "--endpoint=unix:/csi/csi.sock"
|
||||||
- "--node-name=$(KUBE_NODE_NAME)"
|
- "--node-name=$(KUBE_NODE_NAME)"
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
storageClass: replicated
|
storageClass: replicated
|
||||||
|
csiDriver:
|
||||||
|
image: ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.25.2@sha256:761e7235ff9cb7f6f223f00954943e6a5af32ed6624ee592a8610122f96febb0
|
||||||
|
|||||||
221
pkg/cmd/server/openapi.go
Normal file
221
pkg/cmd/server/openapi.go
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/kube-openapi/pkg/spec3"
|
||||||
|
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// shared helpers
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
baseRef = "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Application"
|
||||||
|
baseListRef = baseRef + "List"
|
||||||
|
smp = "application/strategic-merge-patch+json"
|
||||||
|
)
|
||||||
|
|
||||||
|
func deepCopySchema(in *spec.Schema) *spec.Schema {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(in)
|
||||||
|
if err != nil {
|
||||||
|
// Log error or panic since this is unexpected
|
||||||
|
panic(fmt.Sprintf("failed to marshal schema: %v", err))
|
||||||
|
}
|
||||||
|
var out spec.Schema
|
||||||
|
if err := json.Unmarshal(b, &out); err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to unmarshal schema: %v", err))
|
||||||
|
}
|
||||||
|
return &out
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the object that already owns ".spec"
|
||||||
|
func findSpecContainer(s *spec.Schema) *spec.Schema {
|
||||||
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(s.Type) > 0 && s.Type.Contains("object") && s.Properties != nil {
|
||||||
|
if _, ok := s.Properties["spec"]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, branch := range [][]spec.Schema{s.AllOf, s.OneOf, s.AnyOf} {
|
||||||
|
for i := range branch {
|
||||||
|
if res := findSpecContainer(&branch[i]); res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply user-supplied schema; when raw == "" turn the field into a schemaless object
|
||||||
|
func patchSpec(target *spec.Schema, raw string) error {
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// 1) schema not provided → make ".spec" a fully open object
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
if strings.TrimSpace(raw) == "" {
|
||||||
|
if target.Properties == nil {
|
||||||
|
target.Properties = map[string]spec.Schema{}
|
||||||
|
}
|
||||||
|
prop := target.Properties["spec"]
|
||||||
|
prop.AdditionalProperties = &spec.SchemaOrBool{
|
||||||
|
Allows: true,
|
||||||
|
Schema: &spec.Schema{},
|
||||||
|
}
|
||||||
|
target.Properties["spec"] = prop
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// 2) custom schema provided → keep / inject additionalProperties
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
var custom spec.Schema
|
||||||
|
if err := json.Unmarshal([]byte(raw), &custom); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// if user didn't specify additionalProperties, add a permissive one
|
||||||
|
if custom.AdditionalProperties == nil {
|
||||||
|
custom.AdditionalProperties = &spec.SchemaOrBool{
|
||||||
|
Allows: true,
|
||||||
|
Schema: &spec.Schema{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.Properties == nil {
|
||||||
|
target.Properties = map[string]spec.Schema{}
|
||||||
|
}
|
||||||
|
target.Properties["spec"] = custom
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// OpenAPI **v3** post-processor
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
func buildPostProcessV3(kindSchemas map[string]string) func(*spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||||
|
|
||||||
|
return func(doc *spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||||
|
|
||||||
|
// Replace the basic "Application" schema with the user-supplied kinds.
|
||||||
|
if doc.Components == nil {
|
||||||
|
doc.Components = &spec3.Components{}
|
||||||
|
}
|
||||||
|
if doc.Components.Schemas == nil {
|
||||||
|
doc.Components.Schemas = map[string]*spec.Schema{}
|
||||||
|
}
|
||||||
|
base, ok := doc.Components.Schemas[baseRef]
|
||||||
|
if !ok {
|
||||||
|
return doc, fmt.Errorf("base schema %q not found", baseRef)
|
||||||
|
}
|
||||||
|
for kind, raw := range kindSchemas {
|
||||||
|
ref := fmt.Sprintf("%s.%s", "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1", kind)
|
||||||
|
s := doc.Components.Schemas[ref]
|
||||||
|
if s == nil { // first time – clone "Application"
|
||||||
|
s = deepCopySchema(base)
|
||||||
|
s.Extensions = map[string]interface{}{
|
||||||
|
"x-kubernetes-group-version-kind": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"group": "apps.cozystack.io", "version": "v1alpha1", "kind": kind,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
doc.Components.Schemas[ref] = s
|
||||||
|
}
|
||||||
|
container := findSpecContainer(s)
|
||||||
|
if container == nil { // fallback: use the root
|
||||||
|
container = s
|
||||||
|
}
|
||||||
|
if err := patchSpec(container, raw); err != nil {
|
||||||
|
return nil, fmt.Errorf("kind %s: %w", kind, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(doc.Components.Schemas, baseRef)
|
||||||
|
delete(doc.Components.Schemas, baseListRef)
|
||||||
|
|
||||||
|
// Disable strategic-merge-patch+json support in all PATCH operations
|
||||||
|
for p, pi := range doc.Paths.Paths {
|
||||||
|
if pi == nil || pi.Patch == nil || pi.Patch.RequestBody == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(pi.Patch.RequestBody.Content, smp)
|
||||||
|
|
||||||
|
doc.Paths.Paths[p] = pi
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// OpenAPI **v2** (swagger) post-processor
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
func buildPostProcessV2(kindSchemas map[string]string) func(*spec.Swagger) (*spec.Swagger, error) {
|
||||||
|
|
||||||
|
return func(sw *spec.Swagger) (*spec.Swagger, error) {
|
||||||
|
|
||||||
|
// Replace the basic "Application" schema with the user-supplied kinds.
|
||||||
|
defs := sw.Definitions
|
||||||
|
base, ok := defs[baseRef]
|
||||||
|
if !ok {
|
||||||
|
return sw, fmt.Errorf("base schema %q not found", baseRef)
|
||||||
|
}
|
||||||
|
for kind, raw := range kindSchemas {
|
||||||
|
ref := fmt.Sprintf("%s.%s", "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1", kind)
|
||||||
|
s := deepCopySchema(&base)
|
||||||
|
s.Extensions = map[string]interface{}{
|
||||||
|
"x-kubernetes-group-version-kind": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"group": "apps.cozystack.io", "version": "v1alpha1", "kind": kind,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := patchSpec(s, raw); err != nil {
|
||||||
|
return nil, fmt.Errorf("kind %s: %w", kind, err)
|
||||||
|
}
|
||||||
|
defs[ref] = *s
|
||||||
|
// clone the List variant
|
||||||
|
listName := ref + "List"
|
||||||
|
listSrc := defs[baseListRef]
|
||||||
|
listCopy := deepCopySchema(&listSrc)
|
||||||
|
listCopy.Extensions = map[string]interface{}{
|
||||||
|
"x-kubernetes-group-version-kind": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"group": "apps.cozystack.io",
|
||||||
|
"version": "v1alpha1",
|
||||||
|
"kind": kind + "List",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if items := listCopy.Properties["items"]; items.Items != nil && items.Items.Schema != nil {
|
||||||
|
items.Items.Schema.Ref = spec.MustCreateRef("#/definitions/" + ref)
|
||||||
|
listCopy.Properties["items"] = items
|
||||||
|
}
|
||||||
|
defs[listName] = *listCopy
|
||||||
|
}
|
||||||
|
delete(defs, baseRef)
|
||||||
|
delete(defs, baseListRef)
|
||||||
|
|
||||||
|
// Disable strategic-merge-patch+json support in all PATCH operations
|
||||||
|
for p, op := range sw.Paths.Paths {
|
||||||
|
if op.Patch != nil && len(op.Patch.Consumes) > 0 {
|
||||||
|
var out []string
|
||||||
|
for _, c := range op.Patch.Consumes {
|
||||||
|
if c != smp {
|
||||||
|
out = append(out, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
op.Patch.Consumes = out
|
||||||
|
sw.Paths.Paths[p] = op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sw, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,8 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -38,8 +40,6 @@ import (
|
|||||||
utilversionpkg "k8s.io/apiserver/pkg/util/version"
|
utilversionpkg "k8s.io/apiserver/pkg/util/version"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
baseversion "k8s.io/component-base/version"
|
baseversion "k8s.io/component-base/version"
|
||||||
"k8s.io/klog/v2"
|
|
||||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -159,22 +159,6 @@ func (o AppsServerOptions) Validate(args []string) error {
|
|||||||
return utilerrors.NewAggregate(allErrors)
|
return utilerrors.NewAggregate(allErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopySchema делает глубокую копию структуры spec.Schema
|
|
||||||
func DeepCopySchema(schema *spec.Schema) (*spec.Schema, error) {
|
|
||||||
data, err := json.Marshal(schema)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to marshal schema: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var newSchema spec.Schema
|
|
||||||
err = json.Unmarshal(data, &newSchema)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to unmarshal schema: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &newSchema, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config returns the configuration for the API server based on AppsServerOptions
|
// Config returns the configuration for the API server based on AppsServerOptions
|
||||||
func (o *AppsServerOptions) Config() (*apiserver.Config, error) {
|
func (o *AppsServerOptions) Config() (*apiserver.Config, error) {
|
||||||
// TODO: set the "real" external address
|
// TODO: set the "real" external address
|
||||||
@@ -195,98 +179,34 @@ func (o *AppsServerOptions) Config() (*apiserver.Config, error) {
|
|||||||
serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(
|
serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(
|
||||||
sampleopenapi.GetOpenAPIDefinitions, openapi.NewDefinitionNamer(apiserver.Scheme),
|
sampleopenapi.GetOpenAPIDefinitions, openapi.NewDefinitionNamer(apiserver.Scheme),
|
||||||
)
|
)
|
||||||
serverConfig.OpenAPIConfig.Info.Title = "Apps"
|
|
||||||
serverConfig.OpenAPIConfig.Info.Version = "0.1"
|
|
||||||
|
|
||||||
serverConfig.OpenAPIConfig.PostProcessSpec = func(swagger *spec.Swagger) (*spec.Swagger, error) {
|
version := "0.1"
|
||||||
defs := swagger.Definitions
|
if o.ResourceConfig != nil {
|
||||||
|
raw, err := json.Marshal(o.ResourceConfig)
|
||||||
// Verify the presence of the base Application/ApplicationList definitions
|
if err != nil {
|
||||||
appDef, exists := defs["com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Application"]
|
return nil, fmt.Errorf("failed to marshal resource config: %v", err)
|
||||||
if !exists {
|
|
||||||
return swagger, fmt.Errorf("Application definition not found")
|
|
||||||
}
|
}
|
||||||
|
sum := sha256.Sum256(raw)
|
||||||
listDef, exists := defs["com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.ApplicationList"]
|
version = "0.1-" + hex.EncodeToString(sum[:8])
|
||||||
if !exists {
|
|
||||||
return swagger, fmt.Errorf("ApplicationList definition not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over all registered GVKs (e.g., Bucket, Database, etc.)
|
|
||||||
for _, gvk := range v1alpha1.RegisteredGVKs {
|
|
||||||
// This will be something like:
|
|
||||||
// "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Bucket"
|
|
||||||
resourceName := fmt.Sprintf("com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.%s", gvk.Kind)
|
|
||||||
|
|
||||||
// 1. Create a copy of the base Application definition for the new resource
|
|
||||||
newDef, err := DeepCopySchema(&appDef)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to deepcopy schema for %s: %w", gvk.Kind, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Update x-kubernetes-group-version-kind to match the new resource
|
|
||||||
if newDef.Extensions == nil {
|
|
||||||
newDef.Extensions = map[string]interface{}{}
|
|
||||||
}
|
|
||||||
newDef.Extensions["x-kubernetes-group-version-kind"] = []map[string]interface{}{
|
|
||||||
{
|
|
||||||
"group": gvk.Group,
|
|
||||||
"version": gvk.Version,
|
|
||||||
"kind": gvk.Kind,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Save the new resource definition under the correct name
|
|
||||||
defs[resourceName] = *newDef
|
|
||||||
klog.V(6).Infof("PostProcessSpec: Added OpenAPI definition for %s\n", resourceName)
|
|
||||||
|
|
||||||
// 4. Now handle the corresponding List type (e.g., BucketList).
|
|
||||||
// We'll start by copying the ApplicationList definition.
|
|
||||||
listResourceName := fmt.Sprintf("com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.%sList", gvk.Kind)
|
|
||||||
newListDef, err := DeepCopySchema(&listDef)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to deepcopy schema for %sList: %w", gvk.Kind, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Update x-kubernetes-group-version-kind for the List definition
|
|
||||||
if newListDef.Extensions == nil {
|
|
||||||
newListDef.Extensions = map[string]interface{}{}
|
|
||||||
}
|
|
||||||
newListDef.Extensions["x-kubernetes-group-version-kind"] = []map[string]interface{}{
|
|
||||||
{
|
|
||||||
"group": gvk.Group,
|
|
||||||
"version": gvk.Version,
|
|
||||||
"kind": fmt.Sprintf("%sList", gvk.Kind),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. IMPORTANT: Fix the "items" reference so it points to the new resource
|
|
||||||
// rather than to "Application".
|
|
||||||
if itemsProp, found := newListDef.Properties["items"]; found {
|
|
||||||
if itemsProp.Items != nil && itemsProp.Items.Schema != nil {
|
|
||||||
itemsProp.Items.Schema.Ref = spec.MustCreateRef("#/definitions/" + resourceName)
|
|
||||||
newListDef.Properties["items"] = itemsProp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. Finally, save the new List definition
|
|
||||||
defs[listResourceName] = *newListDef
|
|
||||||
klog.V(6).Infof("PostProcessSpec: Added OpenAPI definition for %s\n", listResourceName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the original Application/ApplicationList from the definitions
|
|
||||||
delete(defs, "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Application")
|
|
||||||
delete(defs, "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.ApplicationList")
|
|
||||||
|
|
||||||
swagger.Definitions = defs
|
|
||||||
return swagger, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// capture schemas from config once for fast lookup inside the closure
|
||||||
|
kindSchemas := map[string]string{}
|
||||||
|
for _, r := range o.ResourceConfig.Resources {
|
||||||
|
kindSchemas[r.Application.Kind] = r.Application.OpenAPISchema
|
||||||
|
}
|
||||||
|
|
||||||
|
serverConfig.OpenAPIConfig.Info.Title = "Apps"
|
||||||
|
serverConfig.OpenAPIConfig.Info.Version = version
|
||||||
|
serverConfig.OpenAPIConfig.PostProcessSpec = buildPostProcessV2(kindSchemas)
|
||||||
|
|
||||||
serverConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(
|
serverConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(
|
||||||
sampleopenapi.GetOpenAPIDefinitions, openapi.NewDefinitionNamer(apiserver.Scheme),
|
sampleopenapi.GetOpenAPIDefinitions, openapi.NewDefinitionNamer(apiserver.Scheme),
|
||||||
)
|
)
|
||||||
serverConfig.OpenAPIV3Config.Info.Title = "Apps"
|
serverConfig.OpenAPIV3Config.Info.Title = "Apps"
|
||||||
serverConfig.OpenAPIV3Config.Info.Version = "0.1"
|
serverConfig.OpenAPIV3Config.Info.Version = version
|
||||||
|
|
||||||
|
serverConfig.OpenAPIV3Config.PostProcessSpec = buildPostProcessV3(kindSchemas)
|
||||||
|
|
||||||
serverConfig.FeatureGate = utilversionpkg.DefaultComponentGlobalsRegistry.FeatureGateFor(
|
serverConfig.FeatureGate = utilversionpkg.DefaultComponentGlobalsRegistry.FeatureGateFor(
|
||||||
utilversionpkg.DefaultKubeComponent,
|
utilversionpkg.DefaultKubeComponent,
|
||||||
|
|||||||
@@ -36,10 +36,11 @@ type Resource struct {
|
|||||||
|
|
||||||
// ApplicationConfig contains the application settings.
|
// ApplicationConfig contains the application settings.
|
||||||
type ApplicationConfig struct {
|
type ApplicationConfig struct {
|
||||||
Kind string `yaml:"kind"`
|
Kind string `yaml:"kind"`
|
||||||
Singular string `yaml:"singular"`
|
Singular string `yaml:"singular"`
|
||||||
Plural string `yaml:"plural"`
|
Plural string `yaml:"plural"`
|
||||||
ShortNames []string `yaml:"shortNames"`
|
ShortNames []string `yaml:"shortNames"`
|
||||||
|
OpenAPISchema string `yaml:"openAPISchema"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReleaseConfig contains the release settings.
|
// ReleaseConfig contains the release settings.
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ type REST struct {
|
|||||||
gvr schema.GroupVersionResource
|
gvr schema.GroupVersionResource
|
||||||
gvk schema.GroupVersionKind
|
gvk schema.GroupVersionKind
|
||||||
kindName string
|
kindName string
|
||||||
|
singularName string
|
||||||
releaseConfig config.ReleaseConfig
|
releaseConfig config.ReleaseConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +94,7 @@ func NewREST(dynamicClient dynamic.Interface, config *config.Resource) *REST {
|
|||||||
Version: "v1alpha1",
|
Version: "v1alpha1",
|
||||||
}.WithKind(config.Application.Kind),
|
}.WithKind(config.Application.Kind),
|
||||||
kindName: config.Application.Kind,
|
kindName: config.Application.Kind,
|
||||||
|
singularName: config.Application.Singular,
|
||||||
releaseConfig: config.Release,
|
releaseConfig: config.Release,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +106,7 @@ func (r *REST) NamespaceScoped() bool {
|
|||||||
|
|
||||||
// GetSingularName returns the singular name of the resource
|
// GetSingularName returns the singular name of the resource
|
||||||
func (r *REST) GetSingularName() string {
|
func (r *REST) GetSingularName() string {
|
||||||
return r.gvr.Resource
|
return r.singularName
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create handles the creation of a new Application by converting it to a HelmRelease
|
// Create handles the creation of a new Application by converting it to a HelmRelease
|
||||||
@@ -423,6 +425,15 @@ func (r *REST) Update(ctx context.Context, name string, objInfo rest.UpdatedObje
|
|||||||
return nil, false, fmt.Errorf("conversion error: %v", err)
|
return nil, false, fmt.Errorf("conversion error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure ResourceVersion
|
||||||
|
if helmRelease.ResourceVersion == "" {
|
||||||
|
cur, err := r.dynamicClient.Resource(helmReleaseGVR).Namespace(helmRelease.Namespace).Get(ctx, helmRelease.Name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, fmt.Errorf("failed to fetch current HelmRelease: %w", err)
|
||||||
|
}
|
||||||
|
helmRelease.SetResourceVersion(cur.GetResourceVersion())
|
||||||
|
}
|
||||||
|
|
||||||
// Merge system labels (from config) directly
|
// Merge system labels (from config) directly
|
||||||
helmRelease.Labels = mergeMaps(r.releaseConfig.Labels, helmRelease.Labels)
|
helmRelease.Labels = mergeMaps(r.releaseConfig.Labels, helmRelease.Labels)
|
||||||
// Merge user labels with prefix
|
// Merge user labels with prefix
|
||||||
|
|||||||
Reference in New Issue
Block a user