mirror of
https://github.com/cozystack/cozystack.git
synced 2026-03-16 20:08:54 +00:00
Compare commits
362 Commits
bugfix-fix
...
openapi-al
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
759d64c738 | ||
|
|
79a9c11430 | ||
|
|
55d8e46345 | ||
|
|
330103cc2b | ||
|
|
8b1e55dec2 | ||
|
|
da3f133d89 | ||
|
|
19baa7b14f | ||
|
|
502d31fe8d | ||
|
|
5359c6d991 | ||
|
|
8d4a12e14f | ||
|
|
771fbc817f | ||
|
|
bc22b22341 | ||
|
|
cffff6c49e | ||
|
|
39adc16015 | ||
|
|
896209a004 | ||
|
|
d48b5cfa2f | ||
|
|
c6bceff54b | ||
|
|
ff3305f43c | ||
|
|
58def95f67 | ||
|
|
9bc3b636a2 | ||
|
|
895597eecb | ||
|
|
a91e829cc9 | ||
|
|
be31370540 | ||
|
|
b26dc63b01 | ||
|
|
fafa859660 | ||
|
|
6e119ba940 | ||
|
|
754d5a976d | ||
|
|
c4a2bef4c9 | ||
|
|
cd80a73446 | ||
|
|
299d006d20 | ||
|
|
85063cf624 | ||
|
|
c74df866e6 | ||
|
|
080289fa00 | ||
|
|
98f86269f3 | ||
|
|
44fabd4abc | ||
|
|
8ddbe32ea1 | ||
|
|
432ddf6abc | ||
|
|
9d184a098f | ||
|
|
1c2cc0fa28 | ||
|
|
24807cb679 | ||
|
|
cd8e8bee0a | ||
|
|
856720004f | ||
|
|
d1ad5ff222 | ||
|
|
c81c9d255a | ||
|
|
f057d92a4d | ||
|
|
1ab63187c9 | ||
|
|
2fa56fc1e1 | ||
|
|
36ccfb9509 | ||
|
|
cb3cb99d06 | ||
|
|
8704767ac5 | ||
|
|
03c4bf904f | ||
|
|
dca2eb7ae8 | ||
|
|
1d9465d662 | ||
|
|
53241efe63 | ||
|
|
940b0b18b0 | ||
|
|
824c72318a | ||
|
|
0d7e856186 | ||
|
|
2897813dda | ||
|
|
e3a61b23af | ||
|
|
7918e282bf | ||
|
|
0e428810fd | ||
|
|
fa4fff2292 | ||
|
|
0e875b17d1 | ||
|
|
efb2c632e2 | ||
|
|
8951bc13d7 | ||
|
|
830ec252b9 | ||
|
|
730584bd15 | ||
|
|
0e47e1e8ac | ||
|
|
9617071ada | ||
|
|
3b32bfe149 | ||
|
|
d9a5e9d628 | ||
|
|
0feeaadb9c | ||
|
|
8fac3bfcb1 | ||
|
|
b1e4ebeafc | ||
|
|
2f61798fa8 | ||
|
|
02436f312f | ||
|
|
68a47097c1 | ||
|
|
917a6f354d | ||
|
|
847a834920 | ||
|
|
3088e987e3 | ||
|
|
fddeea03f0 | ||
|
|
2fefafd061 | ||
|
|
084be87618 | ||
|
|
6598213b58 | ||
|
|
4079a69335 | ||
|
|
553c2d5482 | ||
|
|
0c9ab17a12 | ||
|
|
5e8f6e0503 | ||
|
|
f04cd55f2a | ||
|
|
53d9cf365d | ||
|
|
94e2fd0ff9 | ||
|
|
0618446b95 | ||
|
|
640d0f10ac | ||
|
|
a03530a72f | ||
|
|
3612bbd8ca | ||
|
|
028bb365ff | ||
|
|
65e3b74dda | ||
|
|
2e1a7a00c3 | ||
|
|
feae1b8317 | ||
|
|
da3f233f87 | ||
|
|
ee5a724374 | ||
|
|
46662fe6bd | ||
|
|
315c36db3e | ||
|
|
25f1cb6cd7 | ||
|
|
269761fcd0 | ||
|
|
4e87e9e37b | ||
|
|
657662461f | ||
|
|
71f7a88b45 | ||
|
|
61929fe2c8 | ||
|
|
28c9fcd61c | ||
|
|
a010fde4b0 | ||
|
|
379e0da6d2 | ||
|
|
a60dff1215 | ||
|
|
a5896be36a | ||
|
|
9022b8bda8 | ||
|
|
190f94c485 | ||
|
|
72e7b5e0b5 | ||
|
|
def5a612c6 | ||
|
|
725f94f347 | ||
|
|
a0b1914972 | ||
|
|
bb907e5e7d | ||
|
|
909208baec | ||
|
|
7abca1bdf5 | ||
|
|
4728127253 | ||
|
|
d919dcc05a | ||
|
|
8a1929038b | ||
|
|
1d6b9a025a | ||
|
|
3475cdb17a | ||
|
|
181e8dce28 | ||
|
|
38f76f6ad0 | ||
|
|
2c2b44e8fd | ||
|
|
5199021b8d | ||
|
|
f2a8c3d0d1 | ||
|
|
5b6ebbc796 | ||
|
|
7b87d555e4 | ||
|
|
e5cde60311 | ||
|
|
d0fba985e2 | ||
|
|
7d5ab78b84 | ||
|
|
493ad821c1 | ||
|
|
c01462d3f9 | ||
|
|
bccf6113cc | ||
|
|
a862d41aa4 | ||
|
|
096227d025 | ||
|
|
4d62961c89 | ||
|
|
2466a0ae6c | ||
|
|
8042c85bca | ||
|
|
79f7300474 | ||
|
|
7a74936d6b | ||
|
|
c5d3fe9aaa | ||
|
|
d201e03d5e | ||
|
|
168a9ae7f4 | ||
|
|
c664d4550f | ||
|
|
19b79b7ca4 | ||
|
|
0de9a0a262 | ||
|
|
edc9995832 | ||
|
|
6023dffd6d | ||
|
|
6fdde29723 | ||
|
|
d63aac727c | ||
|
|
7b9a19c94b | ||
|
|
f78ab1c867 | ||
|
|
7c918125e5 | ||
|
|
d3f1dca1ad | ||
|
|
259a2f5cab | ||
|
|
c7376ef3c9 | ||
|
|
7a619d8b04 | ||
|
|
c58aa798a4 | ||
|
|
378e6e018e | ||
|
|
55cfdb3a38 | ||
|
|
83e0ab3adf | ||
|
|
cc2b36fbe0 | ||
|
|
76c8de7f4d | ||
|
|
c1a4a58500 | ||
|
|
1faf40cd81 | ||
|
|
1b7a597f1c | ||
|
|
aa84b1c054 | ||
|
|
8b0fc77202 | ||
|
|
6e96dd0a33 | ||
|
|
adc2c17c38 | ||
|
|
56f230391d | ||
|
|
08cb7c0f28 | ||
|
|
ef30e69245 | ||
|
|
847980f03d | ||
|
|
999faa7f66 | ||
|
|
0ecb8585bc | ||
|
|
32aea4254b | ||
|
|
e49918745e | ||
|
|
220c347cc5 | ||
|
|
a4ec46a941 | ||
|
|
2c126786b3 | ||
|
|
784f1454ba | ||
|
|
9d9226b575 | ||
|
|
9ec5863a75 | ||
|
|
50f3089f14 | ||
|
|
1aadefef75 | ||
|
|
5727110542 | ||
|
|
f2fffb03e4 | ||
|
|
ab5eae3fbc | ||
|
|
38cf5fd58c | ||
|
|
cda554b58c | ||
|
|
a73794d751 | ||
|
|
81a412517c | ||
|
|
23a7281fbf | ||
|
|
f32c6426a9 | ||
|
|
91583a4e1a | ||
|
|
f628e7d9c7 | ||
|
|
68d1646ae7 | ||
|
|
8fde834e39 | ||
|
|
e99d238647 | ||
|
|
e9435c2d3d | ||
|
|
da3ee5d0ea | ||
|
|
411a465b14 | ||
|
|
cad57cd922 | ||
|
|
fe1776b4c8 | ||
|
|
d9779d55ea | ||
|
|
74d3c89235 | ||
|
|
9af6ce25bc | ||
|
|
c831f53444 | ||
|
|
2c68eee9f8 | ||
|
|
e6ffb4f4e5 | ||
|
|
e63cc1890e | ||
|
|
1079472a2a | ||
|
|
e70dfdec31 | ||
|
|
08c0eecbc5 | ||
|
|
1609931e3f | ||
|
|
699d38d8b9 | ||
|
|
acd4663aee | ||
|
|
f251cba363 | ||
|
|
91a07dcda6 | ||
|
|
99552bf792 | ||
|
|
45031055f8 | ||
|
|
d200017f74 | ||
|
|
f6eaca3843 | ||
|
|
8d3324f958 | ||
|
|
dd16b8f27f | ||
|
|
70f8266767 | ||
|
|
a9674d2ae7 | ||
|
|
cb6a55bc4a | ||
|
|
3ecbaf23a4 | ||
|
|
946fad8bb8 | ||
|
|
f1d86e5045 | ||
|
|
9adcd48c44 | ||
|
|
fb82bfae11 | ||
|
|
bd9e283d3b | ||
|
|
d2126b6703 | ||
|
|
73fe621da1 | ||
|
|
0b7bbb1ba9 | ||
|
|
bb46aa4b7d | ||
|
|
6256e40169 | ||
|
|
22cda073b9 | ||
|
|
0d46393e8c | ||
|
|
193f43d7bb | ||
|
|
8ec882ca5f | ||
|
|
c596805b60 | ||
|
|
f891d0bee6 | ||
|
|
1f748d563f | ||
|
|
210f3c7b6b | ||
|
|
433bfe7b6c | ||
|
|
fa6442998a | ||
|
|
6d06d3b1fb | ||
|
|
4c347cc026 | ||
|
|
986de717f1 | ||
|
|
d38c8aa5ab | ||
|
|
7f9f850b47 | ||
|
|
ca772fae2e | ||
|
|
fb831c05c0 | ||
|
|
f7f8020b9b | ||
|
|
98194a7414 | ||
|
|
70c7978306 | ||
|
|
d5521df9bd | ||
|
|
6ed1243f86 | ||
|
|
d1275ecd08 | ||
|
|
6c9d8bb47f | ||
|
|
1f240387f9 | ||
|
|
1d3964352e | ||
|
|
512277fa93 | ||
|
|
cd7fec68fc | ||
|
|
d12d07fd5c | ||
|
|
00bd212886 | ||
|
|
d19d6b58d0 | ||
|
|
f953db50da | ||
|
|
55e11fcc7b | ||
|
|
12184bc2b9 | ||
|
|
39daa3a38a | ||
|
|
a5ff9bf65b | ||
|
|
036fa6f888 | ||
|
|
792f6b4af8 | ||
|
|
52714f5cce | ||
|
|
bc54bd7bb0 | ||
|
|
0b85a52bee | ||
|
|
b3a2bc85e3 | ||
|
|
d097433266 | ||
|
|
2d294f0546 | ||
|
|
78b4d06b25 | ||
|
|
ae90969b7e | ||
|
|
6732205b24 | ||
|
|
60dee45a61 | ||
|
|
70cd3ce3e7 | ||
|
|
9dc21c6c2d | ||
|
|
4648c7b4c1 | ||
|
|
6a080fbf5d | ||
|
|
72f40f32ad | ||
|
|
cfc8c269f3 | ||
|
|
1da45ff039 | ||
|
|
c6ee006d6b | ||
|
|
848abc4bd1 | ||
|
|
4369b03141 | ||
|
|
baefc78bfe | ||
|
|
1db08d0b73 | ||
|
|
b2ed7525cd | ||
|
|
4f11814551 | ||
|
|
307b5617f0 | ||
|
|
7cf0ce1abf | ||
|
|
5602e9753f | ||
|
|
ab20502b37 | ||
|
|
8369fcddbf | ||
|
|
9f9ca50dd9 | ||
|
|
e7681debe2 | ||
|
|
36b10341ca | ||
|
|
0c234e400b | ||
|
|
c0b7f4e938 | ||
|
|
654778a0c7 | ||
|
|
86fdb51236 | ||
|
|
e8b83fbbda | ||
|
|
29f26f4dd0 | ||
|
|
a0526be17d | ||
|
|
4e41c133b4 | ||
|
|
587904e8cc | ||
|
|
6358fd7a45 | ||
|
|
af595f34dc | ||
|
|
2832058036 | ||
|
|
b9d3b43c3e | ||
|
|
bd0bc64c2a | ||
|
|
2dd62f052e | ||
|
|
778577e0d5 | ||
|
|
8568b9925f | ||
|
|
46ad1b1cd8 | ||
|
|
066ed77918 | ||
|
|
c7be1a5572 | ||
|
|
439e927f6b | ||
|
|
c354d5adc6 | ||
|
|
5ffe11dfc6 | ||
|
|
37a8bfaa06 | ||
|
|
0b03768482 | ||
|
|
620d626887 | ||
|
|
4e2a081c8b | ||
|
|
fa09845ef9 | ||
|
|
a2a79cb5d9 | ||
|
|
7f7cb019e6 | ||
|
|
ba74f397f5 | ||
|
|
7c45335abb | ||
|
|
ae13b58d5f | ||
|
|
3c7f7d1127 | ||
|
|
f0fc3238ca | ||
|
|
b3380d8365 | ||
|
|
d97d6cb81d | ||
|
|
b2a697f98d | ||
|
|
6e6a05d11e | ||
|
|
5d76294ff0 | ||
|
|
62a6da0063 | ||
|
|
6a8530a00a | ||
|
|
b3b40dcf9c | ||
|
|
e848dde422 |
24
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
24
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<!-- Thank you for making a contribution! Here are some tips for you:
|
||||
- Start the PR title with the [label] of Cozystack component:
|
||||
- For system components: [platform], [system], [linstor], [cilium], [kube-ovn], [dashboard], [cluster-api], etc.
|
||||
- For managed apps: [apps], [tenant], [kubernetes], [postgres], [virtual-machine] etc.
|
||||
- For development and maintenance: [tests], [ci], [docs], [maintenance].
|
||||
- If it's a work in progress, consider creating this PR as a draft.
|
||||
- Don't hesistate to ask for opinion and review in the community chats, even if it's still a draft.
|
||||
- Add the label `backport` if it's a bugfix that needs to be backported to a previous version.
|
||||
-->
|
||||
|
||||
## What this PR does
|
||||
|
||||
|
||||
### Release note
|
||||
|
||||
<!-- Write a release note:
|
||||
- Explain what has changed internally and for users.
|
||||
- Start with the same [label] as in the PR title
|
||||
- Follow the guidelines at https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
|
||||
-->
|
||||
|
||||
```release-note
|
||||
[]
|
||||
```
|
||||
13
.github/workflows/pre-commit.yml
vendored
13
.github/workflows/pre-commit.yml
vendored
@@ -2,7 +2,7 @@ name: Pre-Commit Checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled, opened, synchronize, reopened]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
concurrency:
|
||||
group: pre-commit-${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
@@ -28,16 +28,7 @@ jobs:
|
||||
|
||||
- name: Install generate
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install curl -y
|
||||
sudo apt install nodejs -y
|
||||
sudo apt install npm -y
|
||||
|
||||
git clone --branch 2.7.0 --depth 1 https://github.com/bitnami/readme-generator-for-helm.git
|
||||
cd ./readme-generator-for-helm
|
||||
npm install
|
||||
npm install -g @yao-pkg/pkg
|
||||
pkg . -o /usr/local/bin/readme-generator
|
||||
curl -sSL https://github.com/cozystack/cozyvalues-gen/releases/download/v0.8.4/cozyvalues-gen-linux-amd64.tar.gz | tar -xzvf- -C /usr/local/bin/ cozyvalues-gen
|
||||
|
||||
- name: Run pre-commit hooks
|
||||
run: |
|
||||
|
||||
95
.github/workflows/pull-requests-release.yaml
vendored
95
.github/workflows/pull-requests-release.yaml
vendored
@@ -1,100 +1,17 @@
|
||||
name: Releasing PR
|
||||
name: "Releasing PR"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled, opened, synchronize, reopened, closed]
|
||||
types: [closed]
|
||||
paths-ignore:
|
||||
- 'docs/**/*'
|
||||
|
||||
# Cancel in‑flight runs for the same PR when a new push arrives.
|
||||
concurrency:
|
||||
group: pull-requests-release-${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
group: pr-${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
name: Test Release
|
||||
runs-on: [self-hosted]
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
if: |
|
||||
contains(github.event.pull_request.labels.*.name, 'release') &&
|
||||
github.event.action != 'closed'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
registry: ghcr.io
|
||||
|
||||
- name: Extract tag from PR branch
|
||||
id: get_tag
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const branch = context.payload.pull_request.head.ref;
|
||||
const m = branch.match(/^release-(\d+\.\d+\.\d+(?:[-\w\.]+)?)$/);
|
||||
if (!m) {
|
||||
core.setFailed(`❌ Branch '${branch}' does not match 'release-X.Y.Z[-suffix]'`);
|
||||
return;
|
||||
}
|
||||
const tag = `v${m[1]}`;
|
||||
core.setOutput('tag', tag);
|
||||
|
||||
- name: Find draft release and get asset IDs
|
||||
id: fetch_assets
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GH_PAT }}
|
||||
script: |
|
||||
const tag = '${{ steps.get_tag.outputs.tag }}';
|
||||
const releases = await github.rest.repos.listReleases({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 100
|
||||
});
|
||||
const draft = releases.data.find(r => r.tag_name === tag && r.draft);
|
||||
if (!draft) {
|
||||
core.setFailed(`Draft release '${tag}' not found`);
|
||||
return;
|
||||
}
|
||||
const findAssetId = (name) =>
|
||||
draft.assets.find(a => a.name === name)?.id;
|
||||
const installerId = findAssetId("cozystack-installer.yaml");
|
||||
const diskId = findAssetId("nocloud-amd64.raw.xz");
|
||||
if (!installerId || !diskId) {
|
||||
core.setFailed("Missing required assets");
|
||||
return;
|
||||
}
|
||||
core.setOutput("installer_id", installerId);
|
||||
core.setOutput("disk_id", diskId);
|
||||
|
||||
- name: Download assets from GitHub API
|
||||
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/${{ steps.fetch_assets.outputs.installer_id }}"
|
||||
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/${{ steps.fetch_assets.outputs.disk_id }}"
|
||||
env:
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
|
||||
- name: Run tests
|
||||
run: make test
|
||||
|
||||
finalize:
|
||||
name: Finalize Release
|
||||
runs-on: [self-hosted]
|
||||
|
||||
299
.github/workflows/pull-requests.yaml
vendored
299
.github/workflows/pull-requests.yaml
vendored
@@ -1,11 +1,16 @@
|
||||
name: Pull Request
|
||||
|
||||
env:
|
||||
REGISTRY: ${{ secrets.OCIR_REPO }}
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled, opened, synchronize, reopened]
|
||||
types: [opened, synchronize, reopened]
|
||||
paths-ignore:
|
||||
- 'docs/**/*'
|
||||
|
||||
# Cancel in‑flight runs for the same PR when a new push arrives.
|
||||
concurrency:
|
||||
group: pull-requests-${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
group: pr-${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -30,9 +35,9 @@ jobs:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
registry: ghcr.io
|
||||
username: ${{ secrets.OCIR_USER}}
|
||||
password: ${{ secrets.OCIR_TOKEN }}
|
||||
registry: iad.ocir.io
|
||||
env:
|
||||
DOCKER_CONFIG: ${{ runner.temp }}/.docker
|
||||
|
||||
@@ -43,6 +48,17 @@ jobs:
|
||||
|
||||
- name: Build Talos image
|
||||
run: make -C packages/core/installer talos-nocloud
|
||||
|
||||
- name: Save git diff as patch
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'release')"
|
||||
run: git diff HEAD > _out/assets/pr.patch
|
||||
|
||||
- name: Upload git diff patch
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'release')"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr-patch
|
||||
path: _out/assets/pr.patch
|
||||
|
||||
- name: Upload installer
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -55,93 +71,267 @@ jobs:
|
||||
with:
|
||||
name: talos-image
|
||||
path: _out/assets/nocloud-amd64.raw.xz
|
||||
|
||||
prepare_env:
|
||||
name: Prepare environment
|
||||
runs-on: [self-hosted]
|
||||
needs: build
|
||||
|
||||
# Never run when the PR carries the "release" label.
|
||||
if: |
|
||||
!contains(github.event.pull_request.labels.*.name, 'release')
|
||||
resolve_assets:
|
||||
name: "Resolve assets"
|
||||
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 }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
if: contains(github.event.pull_request.labels.*.name, 'release')
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Download installer
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Extract tag from PR branch (release PR)
|
||||
if: contains(github.event.pull_request.labels.*.name, 'release')
|
||||
id: get_tag
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
name: cozystack-installer
|
||||
path: _out/assets/
|
||||
script: |
|
||||
const branch = context.payload.pull_request.head.ref;
|
||||
const m = branch.match(/^release-(\d+\.\d+\.\d+(?:[-\w\.]+)?)$/);
|
||||
if (!m) {
|
||||
core.setFailed(`❌ Branch '${branch}' does not match 'release-X.Y.Z[-suffix]'`);
|
||||
return;
|
||||
}
|
||||
core.setOutput('tag', `v${m[1]}`);
|
||||
|
||||
- name: Download Talos image
|
||||
- name: Find draft release & asset IDs (release PR)
|
||||
if: contains(github.event.pull_request.labels.*.name, 'release')
|
||||
id: fetch_assets
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GH_PAT }}
|
||||
script: |
|
||||
const tag = '${{ steps.get_tag.outputs.tag }}';
|
||||
const releases = await github.rest.repos.listReleases({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 100
|
||||
});
|
||||
const draft = releases.data.find(r => r.tag_name === tag && r.draft);
|
||||
if (!draft) {
|
||||
core.setFailed(`Draft release '${tag}' not found`);
|
||||
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) {
|
||||
core.setFailed('Required assets missing in draft release');
|
||||
return;
|
||||
}
|
||||
core.setOutput('installer_id', installerId);
|
||||
core.setOutput('disk_id', diskId);
|
||||
|
||||
|
||||
prepare_env:
|
||||
name: "Prepare environment"
|
||||
runs-on: [self-hosted]
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
needs: ["build", "resolve_assets"]
|
||||
if: ${{ always() && (needs.build.result == 'success' || needs.resolve_assets.result == 'success') }}
|
||||
|
||||
steps:
|
||||
# ▸ Checkout and prepare the codebase
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# ▸ Regular PR path – download artefacts produced by the *build* job
|
||||
- name: "Download Talos image (regular PR)"
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'release')"
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: talos-image
|
||||
path: _out/assets/
|
||||
path: _out/assets
|
||||
|
||||
- name: Download PR patch
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'release')"
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pr-patch
|
||||
path: _out/assets
|
||||
|
||||
- name: Apply patch
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'release')"
|
||||
run: |
|
||||
git apply _out/assets/pr.patch
|
||||
|
||||
# ▸ 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/nocloud-amd64.raw.xz \
|
||||
"https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/assets/${{ needs.resolve_assets.outputs.disk_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
|
||||
- name: Prepare workspace
|
||||
run: |
|
||||
rm -rf /tmp/$SANDBOX_NAME
|
||||
cp -r ${{ github.workspace }} /tmp/$SANDBOX_NAME
|
||||
|
||||
- name: Prepare environment
|
||||
run: make SANDBOX_NAME=$SANDBOX_NAME prepare-env
|
||||
run: |
|
||||
cd /tmp/$SANDBOX_NAME
|
||||
attempt=0
|
||||
until make SANDBOX_NAME=$SANDBOX_NAME prepare-env; do
|
||||
attempt=$((attempt + 1))
|
||||
if [ $attempt -ge 3 ]; then
|
||||
echo "❌ Attempt $attempt failed, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
echo "❌ Attempt $attempt failed, retrying..."
|
||||
done
|
||||
echo "✅ The task completed successfully after $attempt attempts"
|
||||
|
||||
install_cozystack:
|
||||
name: Install Cozystack
|
||||
name: "Install Cozystack"
|
||||
runs-on: [self-hosted]
|
||||
needs: prepare_env
|
||||
|
||||
# Never run when the PR carries the "release" label.
|
||||
if: |
|
||||
!contains(github.event.pull_request.labels.*.name, 'release')
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
needs: ["prepare_env", "resolve_assets"]
|
||||
if: ${{ always() && needs.prepare_env.result == 'success' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
- 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: Install Cozystack
|
||||
run: make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME install-cozystack
|
||||
- name: Sync _out/assets directory
|
||||
run: |
|
||||
mkdir -p /tmp/$SANDBOX_NAME/_out/assets
|
||||
mv _out/assets/* /tmp/$SANDBOX_NAME/_out/assets/
|
||||
|
||||
test_apps:
|
||||
name: Test applications
|
||||
runs-on: [self-hosted]
|
||||
needs: install_cozystack
|
||||
- name: Install Cozystack into sandbox
|
||||
run: |
|
||||
cd /tmp/$SANDBOX_NAME
|
||||
attempt=0
|
||||
until make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME install-cozystack; do
|
||||
attempt=$((attempt + 1))
|
||||
if [ $attempt -ge 3 ]; then
|
||||
echo "❌ Attempt $attempt failed, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
echo "❌ Attempt $attempt failed, retrying..."
|
||||
done
|
||||
echo "✅ The task completed successfully after $attempt attempts."
|
||||
|
||||
# Never run when the PR carries the "release" label.
|
||||
if: |
|
||||
!contains(github.event.pull_request.labels.*.name, 'release')
|
||||
detect_test_matrix:
|
||||
name: "Detect e2e test matrix"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.set.outputs.matrix }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
- 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:
|
||||
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: make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME test-apps
|
||||
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
|
||||
fi
|
||||
echo "❌ Attempt $attempt failed, retrying..."
|
||||
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
|
||||
|
||||
- name: Collect report
|
||||
run: |
|
||||
cd /tmp/$SANDBOX_NAME
|
||||
make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME collect-report
|
||||
|
||||
- name: Upload cozyreport.tgz
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cozyreport
|
||||
path: /tmp/${{ env.SANDBOX_NAME }}/_out/cozyreport.tgz
|
||||
|
||||
- name: Collect images list
|
||||
run: |
|
||||
cd /tmp/$SANDBOX_NAME
|
||||
make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME collect-images
|
||||
|
||||
- name: Upload image list
|
||||
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: test_apps
|
||||
|
||||
# Never run when the PR carries the "release" label.
|
||||
if: |
|
||||
!contains(github.event.pull_request.labels.*.name, 'release')
|
||||
needs: [collect_debug_information]
|
||||
if: ${{ always() && needs.test_apps.result == 'success' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -153,5 +343,10 @@ jobs:
|
||||
- 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
|
||||
- name: Tear down sandbox
|
||||
run: make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME delete
|
||||
|
||||
- name: Remove workspace
|
||||
run: rm -rf /tmp/$SANDBOX_NAME
|
||||
|
||||
|
||||
|
||||
37
.github/workflows/tags.yaml
vendored
37
.github/workflows/tags.yaml
vendored
@@ -112,9 +112,13 @@ jobs:
|
||||
# Commit built artifacts
|
||||
- name: Commit release artifacts
|
||||
if: steps.check_release.outputs.skip == 'false'
|
||||
env:
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
run: |
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
git config user.name "cozystack-bot"
|
||||
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 config --unset-all http.https://github.com/.extraheader || true
|
||||
git add .
|
||||
git commit -m "Prepare release ${GITHUB_REF#refs/tags/}" -s || echo "No changes to commit"
|
||||
git push origin HEAD || true
|
||||
@@ -145,36 +149,35 @@ jobs:
|
||||
version: ${{ steps.tag.outputs.tag }} # A
|
||||
compare-to: ${{ steps.latest_release.outputs.tag }} # B
|
||||
|
||||
# Create or reuse DRAFT GitHub Release
|
||||
# Create or reuse draft release
|
||||
- name: Create / reuse draft release
|
||||
if: steps.check_release.outputs.skip == 'false'
|
||||
id: release
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const tag = '${{ steps.tag.outputs.tag }}';
|
||||
const isRc = ${{ steps.tag.outputs.is_rc }};
|
||||
const outdated = '${{ steps.semver.outputs.comparison-result }}' === '<';
|
||||
const makeLatest = outdated ? false : 'legacy';
|
||||
const releases = await github.rest.repos.listReleases({
|
||||
const tag = '${{ steps.tag.outputs.tag }}';
|
||||
const isRc = ${{ steps.tag.outputs.is_rc }};
|
||||
const releases = await github.rest.repos.listReleases({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
let rel = releases.data.find(r => r.tag_name === tag);
|
||||
|
||||
let rel = releases.data.find(r => r.tag_name === tag);
|
||||
if (!rel) {
|
||||
rel = await github.rest.repos.createRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
tag_name: tag,
|
||||
name: tag,
|
||||
draft: true,
|
||||
prerelease: isRc,
|
||||
make_latest: makeLatest
|
||||
tag_name: tag,
|
||||
name: tag,
|
||||
draft: true,
|
||||
prerelease: isRc // no make_latest for drafts
|
||||
});
|
||||
console.log(`Draft release created for ${tag}`);
|
||||
} else {
|
||||
console.log(`Re-using existing release ${tag}`);
|
||||
}
|
||||
|
||||
core.setOutput('upload_url', rel.upload_url);
|
||||
|
||||
# Build + upload assets (optional)
|
||||
@@ -189,7 +192,12 @@ jobs:
|
||||
# Create release-X.Y.Z branch and push (force-update)
|
||||
- name: Create release branch
|
||||
if: steps.check_release.outputs.skip == 'false'
|
||||
env:
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
run: |
|
||||
git config user.name "cozystack-bot"
|
||||
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}
|
||||
BRANCH="release-${GITHUB_REF#refs/tags/v}"
|
||||
git branch -f "$BRANCH"
|
||||
git push -f origin "$BRANCH"
|
||||
@@ -199,6 +207,7 @@ jobs:
|
||||
if: steps.check_release.outputs.skip == 'false'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GH_PAT }}
|
||||
script: |
|
||||
const version = context.ref.replace('refs/tags/v', '');
|
||||
const base = '${{ steps.get_base.outputs.branch }}';
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -77,3 +77,5 @@ fabric.properties
|
||||
|
||||
.DS_Store
|
||||
**/.DS_Store
|
||||
|
||||
tmp/
|
||||
|
||||
@@ -11,14 +11,14 @@ repos:
|
||||
- id: run-make-generate
|
||||
name: Run 'make generate' in all app directories
|
||||
entry: |
|
||||
/bin/bash -c '
|
||||
for dir in ./packages/apps/*/; do
|
||||
flock -x .git/pre-commit.lock sh -c '
|
||||
for dir in ./packages/apps/*/ ./packages/extra/*/ ./packages/system/cozystack-api/; do
|
||||
if [ -d "$dir" ]; then
|
||||
echo "Running make generate in $dir"
|
||||
(cd "$dir" && make generate)
|
||||
make generate -C "$dir" || exit $?
|
||||
fi
|
||||
done
|
||||
git diff --color=always | cat
|
||||
'
|
||||
language: script
|
||||
language: system
|
||||
files: ^.*$
|
||||
|
||||
2
Makefile
2
Makefile
@@ -9,7 +9,6 @@ build-deps:
|
||||
|
||||
build: build-deps
|
||||
make -C packages/apps/http-cache image
|
||||
make -C packages/apps/postgres image
|
||||
make -C packages/apps/mysql image
|
||||
make -C packages/apps/clickhouse image
|
||||
make -C packages/apps/kubernetes image
|
||||
@@ -23,6 +22,7 @@ build: build-deps
|
||||
make -C packages/system/metallb image
|
||||
make -C packages/system/kamaji image
|
||||
make -C packages/system/bucket image
|
||||
make -C packages/system/objectstorage-controller image
|
||||
make -C packages/core/testing image
|
||||
make -C packages/core/installer image
|
||||
make manifests
|
||||
|
||||
89
api/v1alpha1/cozystackresourcedefinitions_types.go
Normal file
89
api/v1alpha1/cozystackresourcedefinitions_types.go
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
// CozystackResourceDefinition is the Schema for the cozystackresourcedefinitions API
|
||||
type CozystackResourceDefinition struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec CozystackResourceDefinitionSpec `json:"spec,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
// CozystackResourceDefinitionList contains a list of CozystackResourceDefinition
|
||||
type CozystackResourceDefinitionList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []CozystackResourceDefinition `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&CozystackResourceDefinition{}, &CozystackResourceDefinitionList{})
|
||||
}
|
||||
|
||||
type CozystackResourceDefinitionSpec struct {
|
||||
// Application configuration
|
||||
Application CozystackResourceDefinitionApplication `json:"application"`
|
||||
// Release configuration
|
||||
Release CozystackResourceDefinitionRelease `json:"release"`
|
||||
}
|
||||
|
||||
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 {
|
||||
// Kind of the application, used for UI and API
|
||||
Kind string `json:"kind"`
|
||||
// OpenAPI schema for the application, used for API validation
|
||||
OpenAPISchema string `json:"openAPISchema"`
|
||||
// Plural name of the application, used for UI and API
|
||||
Plural string `json:"plural"`
|
||||
// Singular name of the application, used for UI and API
|
||||
Singular string `json:"singular"`
|
||||
}
|
||||
|
||||
type CozystackResourceDefinitionRelease struct {
|
||||
// Helm chart configuration
|
||||
Chart CozystackResourceDefinitionChart `json:"chart"`
|
||||
// Labels for the release
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
// Prefix for the release name
|
||||
Prefix string `json:"prefix"`
|
||||
}
|
||||
@@ -25,6 +25,135 @@ import (
|
||||
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 *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 *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 *CozystackResourceDefinitionSpec) DeepCopyInto(out *CozystackResourceDefinitionSpec) {
|
||||
*out = *in
|
||||
out.Application = in.Application
|
||||
in.Release.DeepCopyInto(&out.Release)
|
||||
}
|
||||
|
||||
// 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 Selector) DeepCopyInto(out *Selector) {
|
||||
{
|
||||
@@ -46,6 +175,21 @@ 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 *Workload) DeepCopyInto(out *Workload) {
|
||||
*out = *in
|
||||
|
||||
@@ -206,6 +206,14 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err = (&controller.CozystackResourceDefinitionReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
}).SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "CozystackResourceDefinitionReconciler")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// +kubebuilder:scaffold:builder
|
||||
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
|
||||
3359
dashboards/seaweedfs/seaweedfs.json
Normal file
3359
dashboards/seaweedfs/seaweedfs.json
Normal file
File diff suppressed because it is too large
Load Diff
11
docs/changelogs/template.md
Normal file
11
docs/changelogs/template.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## Major Features and Improvements
|
||||
|
||||
## Security
|
||||
|
||||
## Fixes
|
||||
|
||||
## Dependencies
|
||||
|
||||
## Documentation
|
||||
|
||||
## Development, Testing, and CI/CD
|
||||
8
docs/changelogs/v0.31.1.md
Normal file
8
docs/changelogs/v0.31.1.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Fixes
|
||||
|
||||
* [build] Update Talos Linux v1.10.3 and fix assets. (@kvaps in https://github.com/cozystack/cozystack/pull/1006)
|
||||
* [ci] Fix uploading released artifacts to GitHub. (@kvaps in https://github.com/cozystack/cozystack/pull/1009)
|
||||
* [ci] Separate build and testing jobs. (@kvaps in https://github.com/cozystack/cozystack/pull/1005)
|
||||
* [docs] Write a full release post for v0.31.1. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/999)
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.31.0...v0.31.1
|
||||
12
docs/changelogs/v0.31.2.md
Normal file
12
docs/changelogs/v0.31.2.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## Security
|
||||
|
||||
* Resolve a security problem that allowed a tenant administrator to gain enhanced privileges outside the tenant. (@kvaps in https://github.com/cozystack/cozystack/pull/1062, backported in https://github.com/cozystack/cozystack/pull/1066)
|
||||
|
||||
## Fixes
|
||||
|
||||
* [platform] Fix dependencies in `distro-full` bundle. (@klinch0 in https://github.com/cozystack/cozystack/pull/1056, backported in https://github.com/cozystack/cozystack/pull/1064)
|
||||
* [platform] Fix RBAC for annotating namespaces. (@kvaps in https://github.com/cozystack/cozystack/pull/1031, backported in https://github.com/cozystack/cozystack/pull/1037)
|
||||
* [platform] Reduce system resource consumption by using smaller resource presets for VerticalPodAutoscaler, SeaweedFS, and KubeOVN. (@klinch0 in https://github.com/cozystack/cozystack/pull/1054, backported in https://github.com/cozystack/cozystack/pull/1058)
|
||||
* [dashboard] Fix a number of issues in the Cozystack Dashboard (@kvaps in https://github.com/cozystack/cozystack/pull/1042, backported in https://github.com/cozystack/cozystack/pull/1066)
|
||||
* [apps] Specify minimal working resource presets. (@kvaps in https://github.com/cozystack/cozystack/pull/1040, backported in https://github.com/cozystack/cozystack/pull/1041)
|
||||
* [apps] Update built-in documentation and configuration reference for managed Clickhouse application. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/1059, backported in https://github.com/cozystack/cozystack/pull/1065)
|
||||
71
docs/changelogs/v0.32.0.md
Normal file
71
docs/changelogs/v0.32.0.md
Normal file
@@ -0,0 +1,71 @@
|
||||
Cozystack v0.32.0 is a significant release that brings new features, key fixes, and updates to underlying components.
|
||||
|
||||
## Major Features and Improvements
|
||||
|
||||
* [platform] Use `cozypkg` instead of Helm (@kvaps in https://github.com/cozystack/cozystack/pull/1057)
|
||||
* [platform] Introduce the HelmRelease reconciler for system components. (@kvaps in https://github.com/cozystack/cozystack/pull/1033)
|
||||
* [kubernetes] Enable using container registry mirrors by tenant Kubernetes clusters. Configure containerd for tenant Kubernetes clusters. (@klinch0 in https://github.com/cozystack/cozystack/pull/979, patched by @lllamnyp in https://github.com/cozystack/cozystack/pull/1032)
|
||||
* [platform] Allow users to specify CPU requests in VCPUs. Use a library chart for resource management. (@lllamnyp in https://github.com/cozystack/cozystack/pull/972 and https://github.com/cozystack/cozystack/pull/1025)
|
||||
* [platform] Annotate all child objects of apps with uniform labels for tracking by WorkloadMonitors. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1018 and https://github.com/cozystack/cozystack/pull/1024)
|
||||
* [platform] Introduce `cluster-domain` option and un-hardcode `cozy.local`. (@kvaps in https://github.com/cozystack/cozystack/pull/1039)
|
||||
* [platform] Get instance type when reconciling WorkloadMonitor (https://github.com/cozystack/cozystack/pull/1030)
|
||||
* [virtual-machine] Add RBAC rules to allow port forwarding in KubeVirt for SSH via `virtctl`. (@mattia-eleuteri in https://github.com/cozystack/cozystack/pull/1027, patched by @klinch0 in https://github.com/cozystack/cozystack/pull/1028)
|
||||
* [monitoring] Add events and audit inputs (@kevin880202 in https://github.com/cozystack/cozystack/pull/948)
|
||||
|
||||
## Security
|
||||
|
||||
* Resolve a security problem that allowed tenant administrator to gain enhanced privileges outside the tenant. (@kvaps in https://github.com/cozystack/cozystack/pull/1062)
|
||||
|
||||
## Fixes
|
||||
|
||||
* [dashboard] Fix a number of issues in the Cozystack Dashboard (@kvaps in https://github.com/cozystack/cozystack/pull/1042)
|
||||
* [kafka] Specify minimal working resource presets. (@kvaps in https://github.com/cozystack/cozystack/pull/1040)
|
||||
* [cilium] Fixed Gateway API manifest. (@zdenekjanda in https://github.com/cozystack/cozystack/pull/1016)
|
||||
* [platform] Fix RBAC for annotating namespaces. (@kvaps in https://github.com/cozystack/cozystack/pull/1031)
|
||||
* [platform] Fix dependencies for paas-hosted bundle. (@kvaps in https://github.com/cozystack/cozystack/pull/1034)
|
||||
* [platform] Reduce system resource consumption by using lesser resource presets for VerticalPodAutoscaler, SeaweedFS, and KubeOVN. (@klinch0 in https://github.com/cozystack/cozystack/pull/1054)
|
||||
* [virtual-machine] Fix handling of cloudinit and ssh-key input for `virtual-machine` and `vm-instance` applications. (@gwynbleidd2106 in https://github.com/cozystack/cozystack/pull/1019 and https://github.com/cozystack/cozystack/pull/1020)
|
||||
* [apps] Fix Clickhouse version parsing. (@kvaps in https://github.com/cozystack/cozystack/commit/28302e776e9d2bb8f424cf467619fa61d71ac49a)
|
||||
* [apps] Add resource quotas for PostgreSQL jobs and fix application readme generation check in CI. (@klinch0 in https://github.com/cozystack/cozystack/pull/1051)
|
||||
* [kube-ovn] Enable database health check. (@kvaps in https://github.com/cozystack/cozystack/pull/1047)
|
||||
* [kubernetes] Fix upstream issue by updating Kubevirt-CCM. (@kvaps in https://github.com/cozystack/cozystack/pull/1052)
|
||||
* [kubernetes] Fix resources and introduce a migration when upgrading tenant Kubernetes to v0.32.4. (@kvaps in https://github.com/cozystack/cozystack/pull/1073)
|
||||
* [cluster-api] Add a missing migration for `capi-providers`. (@kvaps in https://github.com/cozystack/cozystack/pull/1072)
|
||||
|
||||
## Dependencies
|
||||
|
||||
* Introduce cozykpg, update to v1.1.0. (@kvaps in https://github.com/cozystack/cozystack/pull/1057 and https://github.com/cozystack/cozystack/pull/1063)
|
||||
* Update flux-operator to 0.22.0, Flux to 2.6.x. (@kingdonb in https://github.com/cozystack/cozystack/pull/1035)
|
||||
* Update Talos Linux to v1.10.3. (@kvaps in https://github.com/cozystack/cozystack/pull/1006)
|
||||
* Update Cilium to v1.17.4. (@kvaps in https://github.com/cozystack/cozystack/pull/1046)
|
||||
* Update MetalLB to v0.15.2. (@kvaps in https://github.com/cozystack/cozystack/pull/1045)
|
||||
* Update Kube-OVN to v1.13.13. (@kvaps in https://github.com/cozystack/cozystack/pull/1047)
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Oracle Cloud Infrastructure installation guide](https://cozystack.io/docs/operations/talos/installation/oracle-cloud/). (@kvaps, @lllamnyp, and @NickVolynkin in https://github.com/cozystack/website/pull/168)
|
||||
* [Cluster configuration with `talosctl`](https://cozystack.io/docs/operations/talos/configuration/talosctl/). (@NickVolynkin in https://github.com/cozystack/website/pull/211)
|
||||
* [Configuring container registry mirrors for tenant Kubernetes clusters](https://cozystack.io/docs/operations/talos/configuration/air-gapped/#5-configure-container-registry-mirrors-for-tenant-kubernetes). (@klinch0 in https://github.com/cozystack/website/pull/210)
|
||||
* [Explain application management strategies and available versions for managed applications.](https://cozystack.io/docs/guides/applications/). (@NickVolynkin in https://github.com/cozystack/website/pull/219)
|
||||
* [How to clean up etcd state](https://cozystack.io/docs/operations/faq/#how-to-clean-up-etcd-state). (@gwynbleidd2106 in https://github.com/cozystack/website/pull/214)
|
||||
* [State that Cozystack is a CNCF Sandbox project](https://github.com/cozystack/cozystack?tab=readme-ov-file#cozystack). (@NickVolynkin in https://github.com/cozystack/cozystack/pull/1055)
|
||||
|
||||
## Development, Testing, and CI/CD
|
||||
|
||||
* [tests] Add tests for applications `virtual-machine`, `vm-disk`, `vm-instance`, `postgresql`, `mysql`, and `clickhouse`. (@gwynbleidd2106 in https://github.com/cozystack/cozystack/pull/1048, patched by @kvaps in https://github.com/cozystack/cozystack/pull/1074)
|
||||
* [tests] Fix concurrency for the `docker login` action. (@kvaps in https://github.com/cozystack/cozystack/pull/1014)
|
||||
* [tests] Increase QEMU system disk size in tests. (@kvaps in https://github.com/cozystack/cozystack/pull/1011)
|
||||
* [tests] Increase the waiting timeout for VMs in tests. (@kvaps in https://github.com/cozystack/cozystack/pull/1038)
|
||||
* [ci] Separate build and testing jobs in CI. (@kvaps in https://github.com/cozystack/cozystack/pull/1005 and https://github.com/cozystack/cozystack/pull/1010)
|
||||
* [ci] Fix the release assets. (@kvaps in https://github.com/cozystack/cozystack/pull/1006 and https://github.com/cozystack/cozystack/pull/1009)
|
||||
|
||||
## New Contributors
|
||||
|
||||
* @kevin880202 made their first contribution in https://github.com/cozystack/cozystack/pull/948
|
||||
* @mattia-eleuteri made their first contribution in https://github.com/cozystack/cozystack/pull/1027
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.31.0...v0.32.0
|
||||
|
||||
<!--
|
||||
HEAD https://github.com/cozystack/cozystack/commit/3ce6dbe8
|
||||
-->
|
||||
38
docs/changelogs/v0.32.1.md
Normal file
38
docs/changelogs/v0.32.1.md
Normal file
@@ -0,0 +1,38 @@
|
||||
## Major Features and Improvements
|
||||
|
||||
* [postgres] Introduce new functionality for backup and restore in PostgreSQL. (@klinch0 in https://github.com/cozystack/cozystack/pull/1086)
|
||||
* [apps] Refactor resources in managed applications. (@kvaps in https://github.com/cozystack/cozystack/pull/1106)
|
||||
* [system] Make VMAgent's `extraArgs` tunable. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1091)
|
||||
|
||||
## Fixes
|
||||
|
||||
* [postgres] Escape users and database names. (@kvaps in https://github.com/cozystack/cozystack/pull/1087)
|
||||
* [tenant] Fix monitoring agents HelmReleases for tenant clusters. (@klinch0 in https://github.com/cozystack/cozystack/pull/1079)
|
||||
* [kubernetes] Wrap cert-manager CRDs in a conditional. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1076)
|
||||
* [kubernetes] Remove `useCustomSecretForPatchContainerd` option and enable it by default. (@kvaps in https://github.com/cozystack/cozystack/pull/1104)
|
||||
* [apps] Increase default resource presets for Clickhouse and Kafka from `nano` to `small`. Update OpenAPI specs and readme's. (@kvaps in https://github.com/cozystack/cozystack/pull/1103 and https://github.com/cozystack/cozystack/pull/1105)
|
||||
* [linstor] Add configurable DRBD network options for connection and timeout settings, replacing scripted logic for detecting devices that lost connection. (@kvaps in https://github.com/cozystack/cozystack/pull/1094)
|
||||
|
||||
## Dependencies
|
||||
|
||||
* Update cozy-proxy to v0.2.0 (@kvaps in https://github.com/cozystack/cozystack/pull/1081)
|
||||
* Update Kafka Operator to 0.45.1-rc1 (@kvaps in https://github.com/cozystack/cozystack/pull/1082 and https://github.com/cozystack/cozystack/pull/1102)
|
||||
* Update Flux Operator to 0.23.0 (@kingdonb in https://github.com/cozystack/cozystack/pull/1078)
|
||||
|
||||
## Documentation
|
||||
|
||||
* [docs] Release notes for v0.32.0 and two beta-versions. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/1043)
|
||||
|
||||
## Development, Testing, and CI/CD
|
||||
|
||||
* [tests] Add Kafka, Redis. (@gwynbleidd2106 in https://github.com/cozystack/cozystack/pull/1077)
|
||||
* [tests] Increase disk space for VMs in tests. (@kvaps in https://github.com/cozystack/cozystack/pull/1097)
|
||||
* [tests] Upd Kubernetes v1.33. (@kvaps in https://github.com/cozystack/cozystack/pull/1083)
|
||||
* [tests] increase postgres timeouts. (@kvaps in https://github.com/cozystack/cozystack/pull/1108)
|
||||
* [tests] don't wait for postgres ro service. (@kvaps in https://github.com/cozystack/cozystack/pull/1109)
|
||||
* [ci] Setup systemd timer to tear down sandbox. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1092)
|
||||
* [ci] Split testing job into several. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1075)
|
||||
* [ci] Run E2E tests as separate parallel jobs. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1093)
|
||||
* [ci] Refactor GitHub workflows. (@kvaps in https://github.com/cozystack/cozystack/pull/1107)
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.32.0...v0.32.1
|
||||
91
docs/changelogs/v0.33.0.md
Normal file
91
docs/changelogs/v0.33.0.md
Normal file
@@ -0,0 +1,91 @@
|
||||
> [!WARNING]
|
||||
> A patch release [0.33.2](github.com/cozystack/cozystack/releases/tag/v0.33.2) fixing a regression in 0.33.0 has been released.
|
||||
> It is recommended to skip this version and upgrade to [0.33.2](github.com/cozystack/cozystack/releases/tag/v0.33.2) instead.
|
||||
|
||||
## Feature Highlights
|
||||
|
||||
### Unified CPU and Memory Allocation Management
|
||||
|
||||
Since version 0.31.0, Cozystack introduced a single-point-of-truth configuration variable `cpu-allocation-ratio`,
|
||||
making CPU resource requests and limits uniform in Virtual Machines managed by KubeVirt.
|
||||
The new release 0.33.0 introduces `memory-allocation-ratio` and expands both variables to all managed applications and tenant resource quotas.
|
||||
|
||||
Resource presets also respect the allocation ratios and behave in the same way as explicit resource definitions.
|
||||
The new resource definition format is concise and simple for platform users.
|
||||
|
||||
```yaml
|
||||
# resource definition in the configuration
|
||||
resources:
|
||||
cpu: <defined cpu value>
|
||||
memory: <defined memory value>
|
||||
```
|
||||
|
||||
It results in Kubernetes resource requests and limits, based on defined values and the universal allocation ratios:
|
||||
|
||||
```yaml
|
||||
# actual requests and limits, provided to the application
|
||||
resources:
|
||||
limits:
|
||||
cpu: <defined cpu value>
|
||||
memory: <defined memory value>
|
||||
requests:
|
||||
cpu: <defined cpu value / cpu-allocation-ratio>
|
||||
memory: <defined memory value / memory-allocation-ratio>
|
||||
```
|
||||
|
||||
When updating from earlier Cozystack versions, resource configuration in managed applications will be automatically migrated to the new format.
|
||||
|
||||
### Backing up and Restoring Data in Tenant Kubernetes
|
||||
|
||||
One of the main features of the release is backup capability for PVCs in tenant Kubernetes clusters.
|
||||
It enables platform and tenant administrators to back up and restore data used by services in the tenant clusters.
|
||||
|
||||
This new functionality in Cozystack is powered by [Velero](https://velero.io/) and needs an external S3-compatible storage.
|
||||
|
||||
## Support for NFS Storage
|
||||
|
||||
Cozystack now supports using NFS shared storage with a new optional system module.
|
||||
See the documentation: https://cozystack.io/docs/operations/storage/nfs/.
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
* [kubernetes] Enable PVC backups in tenant Kubernetes clusters, powered by [Velero](https://velero.io/). (@klinch0 in https://github.com/cozystack/cozystack/pull/1132)
|
||||
* [nfs-driver] Enable NFS support by introducing a new optional system module `nfs-driver`. (@kvaps in https://github.com/cozystack/cozystack/pull/1133)
|
||||
* [virtual-machine] Configure CPU sockets available to VMs with the `resources.cpu.sockets` configuration value. (@klinch0 in https://github.com/cozystack/cozystack/pull/1131)
|
||||
* [virtual-machine] Add support for using pre-imported "golden image" disks for virtual machines, enabling faster provisioning by referencing existing images instead of downloading via HTTP. (@gwynbleidd2106 in https://github.com/cozystack/cozystack/pull/1112)
|
||||
* [kubernetes] Add an option to expose the Ingress-NGINX controller in tenant Kubernetes cluster via LoadBalancer. New configuration value `exposeMethod` offers a choice of `Proxied` and `LoadBalancer`. (@kvaps in https://github.com/cozystack/cozystack/pull/1114)
|
||||
* [apps] When updating from earlier Cozystack versions, automatically migrate to the new resource definition format: from `resources.requests.[cpu,memory]` and `resources.limits.[cpu,memory]` to `resources.[cpu,memory]`. (@kvaps in https://github.com/cozystack/cozystack/pull/1127)
|
||||
* [apps] Give examples of new resource definitions in the managed app README's. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/1120)
|
||||
* [tenant] Respect `cpu-allocation-ratio` in tenant's `resourceQuotas`.(@kvaps in https://github.com/cozystack/cozystack/pull/1119)
|
||||
* [cozy-lib] Introduce helper function to calculate Java heap params based on memory requests and limits. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1157)
|
||||
|
||||
## Security
|
||||
|
||||
* [monitoring] Disable sign up in Alerta. (@klinch0 in https://github.com/cozystack/cozystack/pull/1129)
|
||||
|
||||
## Fixes
|
||||
|
||||
* [platform] Always set resources for managed apps . (@lllamnyp in https://github.com/cozystack/cozystack/pull/1156)
|
||||
* [platform] Remove the memory limit for Keycloak deployment. (@klinch0 in https://github.com/cozystack/cozystack/pull/1122)
|
||||
* [kubernetes] Fix a condition in the ingress template for tenant Kubernetes. (@kvaps in https://github.com/cozystack/cozystack/pull/1143)
|
||||
* [kubernetes] Fix a deadlock on reattaching a KubeVirt-CSI volume. (@kvaps in https://github.com/cozystack/cozystack/pull/1135)
|
||||
* [mysql] MySQL applications with a single replica now correctly create a `LoadBalancer` service. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1113)
|
||||
* [etcd] Fix resources and headless services in the etcd application. (@kvaps in https://github.com/cozystack/cozystack/pull/1128)
|
||||
* [apps] Enable selecting `resourcePreset` from a drop-down list for all applications by adding enum of allowed values in the config scheme. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/1117)
|
||||
* [apps] Refactor resource presets provided to managed apps by `cozy-lib`. (@kvaps in https://github.com/cozystack/cozystack/pull/1155)
|
||||
* [keycloak] Calculate and pass Java heap parameters explicitly to prevent OOM errors. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1157)
|
||||
|
||||
|
||||
## Development, Testing, and CI/CD
|
||||
|
||||
* [dx] Introduce cozyreport tool and gather reports in CI. (@kvaps in https://github.com/cozystack/cozystack/pull/1139)
|
||||
* [ci] Use Nexus as a pull-through cache for CI. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1124)
|
||||
* [ci] Save a list of observed images after each workflow run. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1089)
|
||||
* [ci] Skip Cozystack tests on PRs that only change the docs. Don't restart CI when a PR is labeled. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/1136)
|
||||
* [dx] Fix Makefile variables for `capi-providers`. (@kvaps in https://github.com/cozystack/cozystack/pull/1115)
|
||||
* [tests] Introduce self-destructing testing environments. (@kvaps in https://github.com/cozystack/cozystack/pull/1138, https://github.com/cozystack/cozystack/pull/1140, https://github.com/cozystack/cozystack/pull/1141, https://github.com/cozystack/cozystack/pull/1142)
|
||||
* [e2e] Retry flaky application tests to improve total test time. (@kvaps in https://github.com/cozystack/cozystack/pull/1123)
|
||||
* [maintenance] Add a PR template. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/1121)
|
||||
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.32.1...v0.33.0
|
||||
3
docs/changelogs/v0.33.1.md
Normal file
3
docs/changelogs/v0.33.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## Fixes
|
||||
|
||||
* [kubevirt-csi] Fix a regression by updating the role of the CSI controller. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1165)
|
||||
19
docs/changelogs/v0.33.2.md
Normal file
19
docs/changelogs/v0.33.2.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## Features and Improvements
|
||||
|
||||
* [vm-instance] Enable running [Windows](https://cozystack.io/docs/operations/virtualization/windows/) and [MikroTik RouterOS](https://cozystack.io/docs/operations/virtualization/mikrotik/) in Cozystack. Add `bus` option and always specify `bootOrder` for all disks. (@kvaps in https://github.com/cozystack/cozystack/pull/1168)
|
||||
* [cozystack-api] Refactor OpenAPI Schema and support reading it from config. (@kvaps in https://github.com/cozystack/cozystack/pull/1173)
|
||||
* [cozystack-api] Enable using singular resource names in Cozystack API. For example, `kubectl get tenant` is now a valid command, in addition to `kubectl get tenants`. (@kvaps in https://github.com/cozystack/cozystack/pull/1169)
|
||||
* [postgres] Explain how to back up and restore PostgreSQL using Velero backups. (@klinch0 and @NickVolynkin in https://github.com/cozystack/cozystack/pull/1141)
|
||||
|
||||
## Fixes
|
||||
|
||||
* [virtual-machine,vm-instance] Adjusted RBAC role to let users read the service associated with the VMs they create. Consequently, users can now see details of the service in the dashboard and therefore read the IP address of the VM. (@klinch0 in https://github.com/cozystack/cozystack/pull/1161)
|
||||
* [cozystack-api] Fix an error with `resourceVersion` which resulted in message 'failed to update HelmRelease: helmreleases.helm.toolkit.fluxcd.io "xxx" is invalid...'. (@kvaps in https://github.com/cozystack/cozystack/pull/1170)
|
||||
* [cozystack-api] Fix an error in updating lists in Cozystack objects, which resulted in message "Warning: resource ... is missing the kubectl.kubernetes.io/last-applied-configuration annotation". (@kvaps in https://github.com/cozystack/cozystack/pull/1171)
|
||||
* [cozystack-api] Disable `startegic-json-patch` support. (@kvaps in https://github.com/cozystack/cozystack/pull/1179)
|
||||
* [dashboard] Fix the code for removing dashboard comments which used to mistakenly remove shebang from cloudInit scripts. (@kvaps in https://github.com/cozystack/cozystack/pull/1175).
|
||||
* [virtual-machine] Fix cloudInit and sshKeys processing. (@kvaps in https://github.com/cozystack/cozystack/pull/1175 and https://github.com/cozystack/cozystack/commit/da3ee5d0ea9e87529c8adc4fcccffabe8782292e)
|
||||
* [applications] Fix a typo in preset resource tables in the built-in documentation of managed applications. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/1172)
|
||||
* [kubernetes] Enable deleting Velero component from a tenant Kubernetes cluster. (@klinch0 in https://github.com/cozystack/cozystack/pull/1176)
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.33.1...v0.33.2
|
||||
32
hack/cdi_golden_image_create.sh
Normal file
32
hack/cdi_golden_image_create.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
name="$1"
|
||||
url="$2"
|
||||
|
||||
if [ -z "$name" ] || [ -z "$url" ]; then
|
||||
echo "Usage: <name> <url>"
|
||||
echo "Example: 'ubuntu' 'https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#### create DV ubuntu source for CDI image cloning
|
||||
kubectl create -f - <<EOF
|
||||
apiVersion: cdi.kubevirt.io/v1beta1
|
||||
kind: DataVolume
|
||||
metadata:
|
||||
name: "vm-image-$name"
|
||||
namespace: cozy-public
|
||||
annotations:
|
||||
cdi.kubevirt.io/storage.bind.immediate.requested: "true"
|
||||
spec:
|
||||
source:
|
||||
http:
|
||||
url: "$url"
|
||||
storage:
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
storageClassName: replicated
|
||||
EOF
|
||||
8
hack/collect-images.sh
Executable file
8
hack/collect-images.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
for node in 11 12 13; do
|
||||
talosctl -n 192.168.123.${node} -e 192.168.123.${node} images ls >> images.tmp
|
||||
talosctl -n 192.168.123.${node} -e 192.168.123.${node} images --namespace system ls >> images.tmp
|
||||
done
|
||||
|
||||
while read _ name sha _ ; do echo $sha $name ; done < images.tmp | sort -u > images.txt
|
||||
147
hack/cozyreport.sh
Executable file
147
hack/cozyreport.sh
Executable file
@@ -0,0 +1,147 @@
|
||||
#!/bin/sh
|
||||
REPORT_DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
REPORT_NAME=${1:-cozyreport-$REPORT_DATE}
|
||||
REPORT_PDIR=$(mktemp -d)
|
||||
REPORT_DIR=$REPORT_PDIR/$REPORT_NAME
|
||||
|
||||
# -- check dependencies
|
||||
command -V kubectl >/dev/null || exit $?
|
||||
command -V tar >/dev/null || exit $?
|
||||
|
||||
# -- cozystack module
|
||||
|
||||
echo "Collecting Cozystack information..."
|
||||
mkdir -p $REPORT_DIR/cozystack
|
||||
kubectl get deploy -n cozy-system cozystack -o jsonpath='{.spec.template.spec.containers[0].image}' > $REPORT_DIR/cozystack/image.txt 2>&1
|
||||
kubectl get cm -n cozy-system --no-headers | awk '$1 ~ /^cozystack/' |
|
||||
while read NAME _; do
|
||||
DIR=$REPORT_DIR/cozystack/configs
|
||||
mkdir -p $DIR
|
||||
kubectl get cm -n cozy-system $NAME -o yaml > $DIR/$NAME.yaml 2>&1
|
||||
done
|
||||
|
||||
# -- kubernetes module
|
||||
|
||||
echo "Collecting Kubernetes information..."
|
||||
mkdir -p $REPORT_DIR/kubernetes
|
||||
kubectl version > $REPORT_DIR/kubernetes/version.txt 2>&1
|
||||
|
||||
echo "Collecting nodes..."
|
||||
kubectl get nodes -o wide > $REPORT_DIR/kubernetes/nodes.txt 2>&1
|
||||
kubectl get nodes --no-headers | awk '$2 != "Ready"' |
|
||||
while read NAME _; do
|
||||
DIR=$REPORT_DIR/kubernetes/nodes/$NAME
|
||||
mkdir -p $DIR
|
||||
kubectl get node $NAME -o yaml > $DIR/node.yaml 2>&1
|
||||
kubectl describe node $NAME > $DIR/describe.txt 2>&1
|
||||
done
|
||||
|
||||
echo "Collecting namespaces..."
|
||||
kubectl get ns -o wide > $REPORT_DIR/kubernetes/namespaces.txt 2>&1
|
||||
kubectl get ns --no-headers | awk '$2 != "Active"' |
|
||||
while read NAME _; do
|
||||
DIR=$REPORT_DIR/kubernetes/namespaces/$NAME
|
||||
mkdir -p $DIR
|
||||
kubectl get ns $NAME -o yaml > $DIR/namespace.yaml 2>&1
|
||||
kubectl describe ns $NAME > $DIR/describe.txt 2>&1
|
||||
done
|
||||
|
||||
echo "Collecting helmreleases..."
|
||||
kubectl get hr -A > $REPORT_DIR/kubernetes/helmreleases.txt 2>&1
|
||||
kubectl get hr -A | awk '$4 != "True"' | \
|
||||
while read NAMESPACE NAME _; do
|
||||
DIR=$REPORT_DIR/kubernetes/helmreleases/$NAMESPACE/$NAME
|
||||
mkdir -p $DIR
|
||||
kubectl get hr -n $NAMESPACE $NAME -o yaml > $DIR/hr.yaml 2>&1
|
||||
kubectl describe hr -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/' |
|
||||
while read NAMESPACE NAME _ STATE _; do
|
||||
DIR=$REPORT_DIR/kubernetes/pods/$NAMESPACE/$NAME
|
||||
mkdir -p $DIR
|
||||
CONTAINERS=$(kubectl get pod -o jsonpath='{.spec.containers[*].name}' -n $NAMESPACE $NAME)
|
||||
kubectl get pod -n $NAMESPACE $NAME -o yaml > $DIR/pod.yaml 2>&1
|
||||
kubectl describe pod -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1
|
||||
if [ "$STATE" != "Pending" ]; then
|
||||
for CONTAINER in $CONTAINERS; do
|
||||
kubectl logs -n $NAMESPACE $NAME $CONTAINER > $DIR/logs-$CONTAINER.txt 2>&1
|
||||
kubectl logs -n $NAMESPACE $NAME $CONTAINER --previous > $DIR/logs-$CONTAINER-previous.txt 2>&1
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Collecting virtualmachines..."
|
||||
kubectl get vm -A > $REPORT_DIR/kubernetes/vms.txt 2>&1
|
||||
kubectl get vm -A --no-headers | awk '$5 != "True"' |
|
||||
while read NAMESPACE NAME _; do
|
||||
DIR=$REPORT_DIR/kubernetes/vm/$NAMESPACE/$NAME
|
||||
mkdir -p $DIR
|
||||
kubectl get vm -n $NAMESPACE $NAME -o yaml > $DIR/vm.yaml 2>&1
|
||||
kubectl describe vm -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1
|
||||
done
|
||||
|
||||
echo "Collecting virtualmachine instances..."
|
||||
kubectl get vmi -A > $REPORT_DIR/kubernetes/vmis.txt 2>&1
|
||||
kubectl get vmi -A --no-headers | awk '$4 != "Running"' |
|
||||
while read NAMESPACE NAME _; do
|
||||
DIR=$REPORT_DIR/kubernetes/vmi/$NAMESPACE/$NAME
|
||||
mkdir -p $DIR
|
||||
kubectl get vmi -n $NAMESPACE $NAME -o yaml > $DIR/vmi.yaml 2>&1
|
||||
kubectl describe vmi -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1
|
||||
done
|
||||
|
||||
echo "Collecting services..."
|
||||
kubectl get svc -A > $REPORT_DIR/kubernetes/services.txt 2>&1
|
||||
kubectl get svc -A --no-headers | awk '$4 == "<pending>"' |
|
||||
while read NAMESPACE NAME _; do
|
||||
DIR=$REPORT_DIR/kubernetes/services/$NAMESPACE/$NAME
|
||||
mkdir -p $DIR
|
||||
kubectl get svc -n $NAMESPACE $NAME -o yaml > $DIR/service.yaml 2>&1
|
||||
kubectl describe svc -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1
|
||||
done
|
||||
|
||||
echo "Collecting pvcs..."
|
||||
kubectl get pvc -A > $REPORT_DIR/kubernetes/pvcs.txt 2>&1
|
||||
kubectl get pvc -A | awk '$3 != "Bound"' |
|
||||
while read NAMESPACE NAME _; do
|
||||
DIR=$REPORT_DIR/kubernetes/pvc/$NAMESPACE/$NAME
|
||||
mkdir -p $DIR
|
||||
kubectl get pvc -n $NAMESPACE $NAME -o yaml > $DIR/pvc.yaml 2>&1
|
||||
kubectl describe pvc -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1
|
||||
done
|
||||
|
||||
# -- kamaji module
|
||||
|
||||
if kubectl get deploy -n cozy-linstor linstor-controller >/dev/null 2>&1; then
|
||||
echo "Collecting kamaji resources..."
|
||||
DIR=$REPORT_DIR/kamaji
|
||||
mkdir -p $DIR
|
||||
kubectl logs -n cozy-kamaji deployment/kamaji > $DIR/kamaji-controller.log 2>&1
|
||||
kubectl get kamajicontrolplanes.controlplane.cluster.x-k8s.io -A > $DIR/kamajicontrolplanes.txt 2>&1
|
||||
kubectl get kamajicontrolplanes.controlplane.cluster.x-k8s.io -A -o yaml > $DIR/kamajicontrolplanes.yaml 2>&1
|
||||
kubectl get tenantcontrolplanes.kamaji.clastix.io -A > $DIR/tenantcontrolplanes.txt 2>&1
|
||||
kubectl get tenantcontrolplanes.kamaji.clastix.io -A -o yaml > $DIR/tenantcontrolplanes.yaml 2>&1
|
||||
fi
|
||||
|
||||
# -- linstor module
|
||||
|
||||
if kubectl get deploy -n cozy-linstor linstor-controller >/dev/null 2>&1; then
|
||||
echo "Collecting linstor resources..."
|
||||
DIR=$REPORT_DIR/linstor
|
||||
mkdir -p $DIR
|
||||
kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor --no-color n l > $DIR/nodes.txt 2>&1
|
||||
kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor --no-color sp l > $DIR/storage-pools.txt 2>&1
|
||||
kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor --no-color r l > $DIR/resources.txt 2>&1
|
||||
fi
|
||||
|
||||
# -- finalization
|
||||
|
||||
echo "Creating archive..."
|
||||
tar -czf $REPORT_NAME.tgz -C $REPORT_PDIR .
|
||||
echo "Report created: $REPORT_NAME.tgz"
|
||||
|
||||
echo "Cleaning up..."
|
||||
rm -rf $REPORT_PDIR
|
||||
@@ -81,6 +81,7 @@ modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//main/capacity-p
|
||||
modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//flux/flux-control-plane.json
|
||||
modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//flux/flux-stats.json
|
||||
modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//kafka/strimzi-kafka.json
|
||||
modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//seaweedfs/seaweedfs.json
|
||||
modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//goldpinger/goldpinger.json
|
||||
EOT
|
||||
|
||||
|
||||
@@ -1,353 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Cozystack end‑to‑end provisioning test (Bats)
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
@test "Create tenant with isolated mode enabled" {
|
||||
kubectl -n tenant-root get tenants.apps.cozystack.io test ||
|
||||
kubectl create -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Tenant
|
||||
metadata:
|
||||
name: test
|
||||
namespace: tenant-root
|
||||
spec:
|
||||
etcd: false
|
||||
host: ""
|
||||
ingress: false
|
||||
isolated: true
|
||||
monitoring: false
|
||||
resourceQuotas: {}
|
||||
seaweedfs: false
|
||||
EOF
|
||||
kubectl wait hr/tenant-test -n tenant-root --timeout=1m --for=condition=ready
|
||||
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
|
||||
}
|
||||
|
||||
@test "Create a tenant Kubernetes control plane" {
|
||||
kubectl -n tenant-test get kuberneteses.apps.cozystack.io test ||
|
||||
kubectl create -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Kubernetes
|
||||
metadata:
|
||||
name: test
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
addons:
|
||||
certManager:
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
cilium:
|
||||
valuesOverride: {}
|
||||
fluxcd:
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
gatewayAPI:
|
||||
enabled: false
|
||||
gpuOperator:
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
ingressNginx:
|
||||
enabled: true
|
||||
hosts: []
|
||||
valuesOverride: {}
|
||||
monitoringAgents:
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
verticalPodAutoscaler:
|
||||
valuesOverride: {}
|
||||
controlPlane:
|
||||
apiServer:
|
||||
resources: {}
|
||||
resourcesPreset: small
|
||||
controllerManager:
|
||||
resources: {}
|
||||
resourcesPreset: micro
|
||||
konnectivity:
|
||||
server:
|
||||
resources: {}
|
||||
resourcesPreset: micro
|
||||
replicas: 2
|
||||
scheduler:
|
||||
resources: {}
|
||||
resourcesPreset: micro
|
||||
host: ""
|
||||
nodeGroups:
|
||||
md0:
|
||||
ephemeralStorage: 20Gi
|
||||
gpus: []
|
||||
instanceType: u1.medium
|
||||
maxReplicas: 10
|
||||
minReplicas: 0
|
||||
resources:
|
||||
cpu: ""
|
||||
memory: ""
|
||||
roles:
|
||||
- ingress-nginx
|
||||
storageClass: replicated
|
||||
EOF
|
||||
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
|
||||
timeout 10 sh -ec 'until kubectl get kamajicontrolplane -n tenant-test kubernetes-test; do sleep 1; done'
|
||||
kubectl wait --for=condition=TenantControlPlaneCreated kamajicontrolplane -n tenant-test kubernetes-test --timeout=4m
|
||||
kubectl wait tcp -n tenant-test kubernetes-test --timeout=2m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready
|
||||
kubectl wait deploy --timeout=4m --for=condition=available -n tenant-test kubernetes-test kubernetes-test-cluster-autoscaler kubernetes-test-kccm kubernetes-test-kcsi-controller
|
||||
kubectl wait machinedeployment kubernetes-test-md0 -n tenant-test --timeout=1m --for=jsonpath='{.status.replicas}'=2
|
||||
kubectl wait machinedeployment kubernetes-test-md0 -n tenant-test --timeout=10m --for=jsonpath='{.status.v1beta2.readyReplicas}'=2
|
||||
kubectl -n tenant-test delete kuberneteses.apps.cozystack.io test
|
||||
}
|
||||
|
||||
@test "Create a VM Disk" {
|
||||
name='test'
|
||||
kubectl -n tenant-test get vmdisks.apps.cozystack.io $name ||
|
||||
kubectl create -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: VMDisk
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
source:
|
||||
http:
|
||||
url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
|
||||
optical: false
|
||||
storage: 5Gi
|
||||
storageClass: replicated
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr vm-disk-$name --timeout=5s --for=condition=ready
|
||||
kubectl -n tenant-test wait dv vm-disk-$name --timeout=150s --for=condition=ready
|
||||
kubectl -n tenant-test wait pvc vm-disk-$name --timeout=100s --for=jsonpath='{.status.phase}'=Bound
|
||||
}
|
||||
|
||||
@test "Create a VM Instance" {
|
||||
diskName='test'
|
||||
name='test'
|
||||
kubectl -n tenant-test get vminstances.apps.cozystack.io $name ||
|
||||
kubectl create -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: VMInstance
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
externalMethod: PortList
|
||||
externalPorts:
|
||||
- 22
|
||||
running: true
|
||||
instanceType: "u1.medium"
|
||||
instanceProfile: ubuntu
|
||||
disks:
|
||||
- name: $diskName
|
||||
gpus: []
|
||||
resources:
|
||||
cpu: ""
|
||||
memory: ""
|
||||
sshKeys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPht0dPk5qQ+54g1hSX7A6AUxXJW5T6n/3d7Ga2F8gTF
|
||||
test@test
|
||||
cloudInit: |
|
||||
#cloud-config
|
||||
users:
|
||||
- name: test
|
||||
shell: /bin/bash
|
||||
sudo: ['ALL=(ALL) NOPASSWD: ALL']
|
||||
groups: sudo
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPht0dPk5qQ+54g1hSX7A6AUxXJW5T6n/3d7Ga2F8gTF test@test
|
||||
cloudInitSeed: ""
|
||||
EOF
|
||||
sleep 5
|
||||
timeout 20 sh -ec "until kubectl -n tenant-test get vmi vm-instance-$name -o jsonpath='{.status.interfaces[0].ipAddress}' | grep -q '[0-9]'; do sleep 5; done"
|
||||
kubectl -n tenant-test wait hr vm-instance-$name --timeout=5s --for=condition=ready
|
||||
kubectl -n tenant-test wait vm vm-instance-$name --timeout=20s --for=condition=ready
|
||||
kubectl -n tenant-test delete vminstances.apps.cozystack.io $name
|
||||
kubectl -n tenant-test delete vmdisks.apps.cozystack.io $diskName
|
||||
}
|
||||
|
||||
@test "Create a Virtual Machine" {
|
||||
name='test'
|
||||
kubectl -n tenant-test get virtualmachines.apps.cozystack.io $name ||
|
||||
kubectl create -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: VirtualMachine
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
externalMethod: PortList
|
||||
externalPorts:
|
||||
- 22
|
||||
instanceType: "u1.medium"
|
||||
instanceProfile: ubuntu
|
||||
systemDisk:
|
||||
image: ubuntu
|
||||
storage: 5Gi
|
||||
storageClass: replicated
|
||||
gpus: []
|
||||
resources:
|
||||
cpu: ""
|
||||
memory: ""
|
||||
sshKeys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPht0dPk5qQ+54g1hSX7A6AUxXJW5T6n/3d7Ga2F8gTF
|
||||
test@test
|
||||
cloudInit: |
|
||||
#cloud-config
|
||||
users:
|
||||
- name: test
|
||||
shell: /bin/bash
|
||||
sudo: ['ALL=(ALL) NOPASSWD: ALL']
|
||||
groups: sudo
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPht0dPk5qQ+54g1hSX7A6AUxXJW5T6n/3d7Ga2F8gTF test@test
|
||||
cloudInitSeed: ""
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr virtual-machine-$name --timeout=10s --for=condition=ready
|
||||
kubectl -n tenant-test wait dv virtual-machine-$name --timeout=150s --for=condition=ready
|
||||
kubectl -n tenant-test wait pvc virtual-machine-$name --timeout=100s --for=jsonpath='{.status.phase}'=Bound
|
||||
kubectl -n tenant-test wait vm virtual-machine-$name --timeout=100s --for=condition=ready
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get vmi virtual-machine-$name -o jsonpath='{.status.interfaces[0].ipAddress}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test delete virtualmachines.apps.cozystack.io $name
|
||||
}
|
||||
|
||||
@test "Create DB PostgreSQL" {
|
||||
name='test'
|
||||
kubectl -n tenant-test get postgreses.apps.cozystack.io $name ||
|
||||
kubectl create -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Postgres
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
size: 10Gi
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
postgresql:
|
||||
parameters:
|
||||
max_connections: 100
|
||||
quorum:
|
||||
minSyncReplicas: 0
|
||||
maxSyncReplicas: 0
|
||||
users:
|
||||
testuser:
|
||||
password: xai7Wepo
|
||||
databases:
|
||||
testdb:
|
||||
roles:
|
||||
admin:
|
||||
- testuser
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
s3Bucket: s3.example.org/postgres-backups
|
||||
schedule: "0 2 * * *"
|
||||
cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||
resticPassword: ChaXoveekoh6eigh4siesheeda2quai0
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr postgres-$name --timeout=100s --for=condition=ready
|
||||
kubectl -n tenant-test wait job.batch postgres-$name-init-job --timeout=50s --for=condition=Complete
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc postgres-$name-r -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc postgres-$name-ro -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc postgres-$name-rw -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get endpoints postgres-$name-r -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get endpoints postgres-$name-ro -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get endpoints postgres-$name-rw -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test delete postgreses.apps.cozystack.io $name
|
||||
}
|
||||
|
||||
@test "Create DB MySQL" {
|
||||
name='test'
|
||||
kubectl -n tenant-test get mysqls.apps.cozystack.io $name ||
|
||||
kubectl create -f- <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: MySQL
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
size: 10Gi
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
users:
|
||||
testuser:
|
||||
maxUserConnections: 1000
|
||||
password: xai7Wepo
|
||||
databases:
|
||||
testdb:
|
||||
roles:
|
||||
admin:
|
||||
- testuser
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
s3Bucket: s3.example.org/postgres-backups
|
||||
schedule: "0 2 * * *"
|
||||
cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||
resticPassword: ChaXoveekoh6eigh4siesheeda2quai0
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr mysql-$name --timeout=30s --for=condition=ready
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get svc mysql-$name -o jsonpath='{.spec.ports[0].port}' | grep -q '3306'; do sleep 10; done"
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get endpoints mysql-$name -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test wait statefulset.apps/mysql-$name --timeout=110s --for=jsonpath='{.status.replicas}'=2
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get svc mysql-$name-metrics -o jsonpath='{.spec.ports[0].port}' | grep -q '9104'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get endpoints mysql-$name-metrics -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test wait deployment.apps/mysql-$name-metrics --timeout=90s --for=jsonpath='{.status.replicas}'=1
|
||||
kubectl -n tenant-test delete mysqls.apps.cozystack.io $name
|
||||
}
|
||||
|
||||
@test "Create DB ClickHouse" {
|
||||
name='test'
|
||||
kubectl -n tenant-test get clickhouses.apps.cozystack.io $name ||
|
||||
kubectl create -f- <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: ClickHouse
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
size: 10Gi
|
||||
logStorageSize: 2Gi
|
||||
shards: 1
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
logTTL: 15
|
||||
users:
|
||||
testuser:
|
||||
password: xai7Wepo
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
s3Bucket: s3.example.org/clickhouse-backups
|
||||
schedule: "0 2 * * *"
|
||||
cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||
resticPassword: ChaXoveekoh6eigh4siesheeda2quai0
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr clickhouse-$name --timeout=20s --for=condition=ready
|
||||
timeout 180 sh -ec "until kubectl -n tenant-test get svc chendpoint-clickhouse-$name -o jsonpath='{.spec.ports[*].port}' | grep -q '8123 9000'; do sleep 10; done"
|
||||
kubectl -n tenant-test wait statefulset.apps/chi-clickhouse-$name-clickhouse-0-0 --timeout=120s --for=jsonpath='{.status.replicas}'=1
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get endpoints chi-clickhouse-$name-clickhouse-0-0 -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
timeout 100 sh -ec "until kubectl -n tenant-test get svc chi-clickhouse-$name-clickhouse-0-0 -o jsonpath='{.spec.ports[*].port}' | grep -q '9000 8123 9009'; do sleep 10; done"
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get sts chi-clickhouse-$name-clickhouse-0-1 ; do sleep 10; done"
|
||||
kubectl -n tenant-test wait statefulset.apps/chi-clickhouse-$name-clickhouse-0-1 --timeout=140s --for=jsonpath='{.status.replicas}'=1
|
||||
}
|
||||
47
hack/e2e-apps/bucket.bats
Normal file
47
hack/e2e-apps/bucket.bats
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create and Verify Seeweedfs Bucket" {
|
||||
# Create the bucket resource
|
||||
name='test'
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: ${name}
|
||||
namespace: tenant-test
|
||||
spec: {}
|
||||
EOF
|
||||
|
||||
# Wait for the bucket to be ready
|
||||
kubectl -n tenant-test wait hr bucket-${name} --timeout=100s --for=condition=ready
|
||||
kubectl -n tenant-test wait bucketclaims.objectstorage.k8s.io bucket-${name} --timeout=300s --for=jsonpath='{.status.bucketReady}'
|
||||
kubectl -n tenant-test wait bucketaccesses.objectstorage.k8s.io bucket-${name} --timeout=300s --for=jsonpath='{.status.accessGranted}'
|
||||
|
||||
# Get and decode credentials
|
||||
kubectl -n tenant-test get secret bucket-${name} -ojsonpath='{.data.BucketInfo}' | base64 -d > bucket-test-credentials.json
|
||||
|
||||
# Get credentials from the secret
|
||||
ACCESS_KEY=$(jq -r '.spec.secretS3.accessKeyID' bucket-test-credentials.json)
|
||||
SECRET_KEY=$(jq -r '.spec.secretS3.accessSecretKey' bucket-test-credentials.json)
|
||||
BUCKET_NAME=$(jq -r '.spec.bucketName' bucket-test-credentials.json)
|
||||
|
||||
# Start port-forwarding
|
||||
bash -c 'timeout 100s kubectl port-forward service/seaweedfs-s3 -n tenant-root 8333:8333 > /dev/null 2>&1 &'
|
||||
|
||||
# Wait for port-forward to be ready
|
||||
timeout 30 sh -ec 'until nc -z localhost 8333; do sleep 1; done'
|
||||
|
||||
# Set up MinIO alias with error handling
|
||||
mc alias set local https://localhost:8333 $ACCESS_KEY $SECRET_KEY --insecure
|
||||
|
||||
# Upload file to bucket
|
||||
mc cp bucket-test-credentials.json $BUCKET_NAME/bucket-test-credentials.json
|
||||
|
||||
# Verify file was uploaded
|
||||
mc ls $BUCKET_NAME/bucket-test-credentials.json
|
||||
|
||||
# Clean up uploaded file
|
||||
mc rm $BUCKET_NAME/bucket-test-credentials.json
|
||||
|
||||
kubectl -n tenant-test delete bucket.apps.cozystack.io ${name}
|
||||
}
|
||||
46
hack/e2e-apps/clickhouse.bats
Normal file
46
hack/e2e-apps/clickhouse.bats
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create DB ClickHouse" {
|
||||
name='test'
|
||||
kubectl apply -f- <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: ClickHouse
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
size: 10Gi
|
||||
logStorageSize: 2Gi
|
||||
shards: 1
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
logTTL: 15
|
||||
users:
|
||||
testuser:
|
||||
password: xai7Wepo
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
s3Bucket: s3.example.org/clickhouse-backups
|
||||
schedule: "0 2 * * *"
|
||||
cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||
resticPassword: ChaXoveekoh6eigh4siesheeda2quai0
|
||||
clickhouseKeeper:
|
||||
enabled: true
|
||||
resourcesPreset: "micro"
|
||||
size: "1Gi"
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr clickhouse-$name --timeout=20s --for=condition=ready
|
||||
timeout 180 sh -ec "until kubectl -n tenant-test get svc chendpoint-clickhouse-$name -o jsonpath='{.spec.ports[*].port}' | grep -q '8123 9000'; do sleep 10; done"
|
||||
kubectl -n tenant-test wait statefulset.apps/chi-clickhouse-$name-clickhouse-0-0 --timeout=120s --for=jsonpath='{.status.replicas}'=1
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get endpoints chi-clickhouse-$name-clickhouse-0-0 -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
timeout 100 sh -ec "until kubectl -n tenant-test get svc chi-clickhouse-$name-clickhouse-0-0 -o jsonpath='{.spec.ports[*].port}' | grep -q '9000 8123 9009'; do sleep 10; done"
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get sts chi-clickhouse-$name-clickhouse-0-1 ; do sleep 10; done"
|
||||
kubectl -n tenant-test wait statefulset.apps/chi-clickhouse-$name-clickhouse-0-1 --timeout=140s --for=jsonpath='{.status.replicas}'=1
|
||||
kubectl -n tenant-test delete clickhouse $name
|
||||
}
|
||||
51
hack/e2e-apps/kafka.bats
Normal file
51
hack/e2e-apps/kafka.bats
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create Kafka" {
|
||||
name='test'
|
||||
kubectl apply -f- <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Kafka
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
kafka:
|
||||
size: 10Gi
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
zookeeper:
|
||||
size: 5Gi
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
resources:
|
||||
resourcesPreset: "nano"
|
||||
topics:
|
||||
- name: testResults
|
||||
partitions: 1
|
||||
replicas: 2
|
||||
config:
|
||||
min.insync.replicas: 2
|
||||
- name: testOrders
|
||||
config:
|
||||
cleanup.policy: compact
|
||||
segment.ms: 3600000
|
||||
max.compaction.lag.ms: 5400000
|
||||
min.insync.replicas: 2
|
||||
partitions: 1
|
||||
replicas: 2
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr kafka-$name --timeout=30s --for=condition=ready
|
||||
kubectl wait kafkas -n tenant-test test --timeout=60s --for=condition=ready
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get pvc data-kafka-$name-zookeeper-0; do sleep 10; done"
|
||||
kubectl -n tenant-test wait pvc data-kafka-$name-zookeeper-0 --timeout=50s --for=jsonpath='{.status.phase}'=Bound
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc kafka-$name-zookeeper-client -o jsonpath='{.spec.ports[0].port}' | grep -q '2181'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc kafka-$name-zookeeper-nodes -o jsonpath='{.spec.ports[*].port}' | grep -q '2181 2888 3888'; do sleep 10; done"
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get endpoints kafka-$name-zookeeper-nodes -o jsonpath='{.subsets[*].addresses[0].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test delete kafka.apps.cozystack.io $name
|
||||
kubectl -n tenant-test delete pvc data-kafka-$name-zookeeper-0
|
||||
kubectl -n tenant-test delete pvc data-kafka-$name-zookeeper-1
|
||||
}
|
||||
6
hack/e2e-apps/kubernetes-latest.bats
Normal file
6
hack/e2e-apps/kubernetes-latest.bats
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create a tenant Kubernetes control plane with latest version" {
|
||||
. hack/e2e-apps/run-kubernetes.sh
|
||||
run_kubernetes_test 'keys | sort_by(.) | .[-1]' 'test-latest-version' '59991'
|
||||
}
|
||||
6
hack/e2e-apps/kubernetes-previous.bats
Normal file
6
hack/e2e-apps/kubernetes-previous.bats
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create a tenant Kubernetes control plane with previous version" {
|
||||
. hack/e2e-apps/run-kubernetes.sh
|
||||
run_kubernetes_test 'keys | sort_by(.) | .[-2]' 'test-previous-version' '59992'
|
||||
}
|
||||
46
hack/e2e-apps/mysql.bats
Normal file
46
hack/e2e-apps/mysql.bats
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create DB MySQL" {
|
||||
name='test'
|
||||
kubectl apply -f- <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: MySQL
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
size: 10Gi
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
users:
|
||||
testuser:
|
||||
maxUserConnections: 1000
|
||||
password: xai7Wepo
|
||||
databases:
|
||||
testdb:
|
||||
roles:
|
||||
admin:
|
||||
- testuser
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
s3Bucket: s3.example.org/postgres-backups
|
||||
schedule: "0 2 * * *"
|
||||
cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||
resticPassword: ChaXoveekoh6eigh4siesheeda2quai0
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr mysql-$name --timeout=30s --for=condition=ready
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get svc mysql-$name -o jsonpath='{.spec.ports[0].port}' | grep -q '3306'; do sleep 10; done"
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get endpoints mysql-$name -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test wait statefulset.apps/mysql-$name --timeout=110s --for=jsonpath='{.status.replicas}'=2
|
||||
timeout 80 sh -ec "until kubectl -n tenant-test get svc mysql-$name-metrics -o jsonpath='{.spec.ports[0].port}' | grep -q '9104'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get endpoints mysql-$name-metrics -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test wait deployment.apps/mysql-$name-metrics --timeout=90s --for=jsonpath='{.status.replicas}'=1
|
||||
kubectl -n tenant-test delete mysqls.apps.cozystack.io $name
|
||||
}
|
||||
54
hack/e2e-apps/postgres.bats
Normal file
54
hack/e2e-apps/postgres.bats
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create DB PostgreSQL" {
|
||||
name='test'
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Postgres
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
size: 10Gi
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
postgresql:
|
||||
parameters:
|
||||
max_connections: 100
|
||||
quorum:
|
||||
minSyncReplicas: 0
|
||||
maxSyncReplicas: 0
|
||||
users:
|
||||
testuser:
|
||||
password: xai7Wepo
|
||||
databases:
|
||||
testdb:
|
||||
roles:
|
||||
admin:
|
||||
- testuser
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
s3Bucket: s3.example.org/postgres-backups
|
||||
schedule: "0 2 * * *"
|
||||
cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||
resticPassword: ChaXoveekoh6eigh4siesheeda2quai0
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr postgres-$name --timeout=100s --for=condition=ready
|
||||
kubectl -n tenant-test wait job.batch postgres-$name-init-job --timeout=50s --for=condition=Complete
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc postgres-$name-r -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc postgres-$name-ro -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc postgres-$name-rw -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get endpoints postgres-$name-r -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
# for some reason it takes longer for the read-only endpoint to be ready
|
||||
#timeout 120 sh -ec "until kubectl -n tenant-test get endpoints postgres-$name-ro -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get endpoints postgres-$name-rw -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test delete postgreses.apps.cozystack.io $name
|
||||
kubectl -n tenant-test delete job.batch/postgres-$name-init-job
|
||||
}
|
||||
26
hack/e2e-apps/redis.bats
Normal file
26
hack/e2e-apps/redis.bats
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create Redis" {
|
||||
name='test'
|
||||
kubectl apply -f- <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Redis
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
size: 1Gi
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
authEnabled: true
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr redis-$name --timeout=20s --for=condition=ready
|
||||
kubectl -n tenant-test wait pvc redisfailover-persistent-data-rfr-redis-$name-0 --timeout=50s --for=jsonpath='{.status.phase}'=Bound
|
||||
kubectl -n tenant-test wait deploy rfs-redis-$name --timeout=90s --for=condition=available
|
||||
kubectl -n tenant-test wait sts rfr-redis-$name --timeout=90s --for=jsonpath='{.status.replicas}'=2
|
||||
kubectl -n tenant-test delete redis.apps.cozystack.io $name
|
||||
}
|
||||
101
hack/e2e-apps/run-kubernetes.sh
Normal file
101
hack/e2e-apps/run-kubernetes.sh
Normal file
@@ -0,0 +1,101 @@
|
||||
run_kubernetes_test() {
|
||||
local version_expr="$1"
|
||||
local test_name="$2"
|
||||
local port="$3"
|
||||
local k8s_version=$(yq "$version_expr" packages/apps/kubernetes/files/versions.yaml)
|
||||
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Kubernetes
|
||||
metadata:
|
||||
name: "${test_name}"
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
addons:
|
||||
certManager:
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
cilium:
|
||||
valuesOverride: {}
|
||||
fluxcd:
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
gatewayAPI:
|
||||
enabled: false
|
||||
gpuOperator:
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
ingressNginx:
|
||||
enabled: true
|
||||
hosts: []
|
||||
valuesOverride: {}
|
||||
monitoringAgents:
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
verticalPodAutoscaler:
|
||||
valuesOverride: {}
|
||||
controlPlane:
|
||||
apiServer:
|
||||
resources: {}
|
||||
resourcesPreset: small
|
||||
controllerManager:
|
||||
resources: {}
|
||||
resourcesPreset: micro
|
||||
konnectivity:
|
||||
server:
|
||||
resources: {}
|
||||
resourcesPreset: micro
|
||||
replicas: 2
|
||||
scheduler:
|
||||
resources: {}
|
||||
resourcesPreset: micro
|
||||
host: ""
|
||||
nodeGroups:
|
||||
md0:
|
||||
ephemeralStorage: 20Gi
|
||||
gpus: []
|
||||
instanceType: u1.medium
|
||||
maxReplicas: 10
|
||||
minReplicas: 0
|
||||
roles:
|
||||
- ingress-nginx
|
||||
storageClass: replicated
|
||||
version: "${k8s_version}"
|
||||
EOF
|
||||
# Wait for the tenant-test namespace to be active
|
||||
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
|
||||
|
||||
# Wait for the Kamaji control plane to be created (retry for up to 10 seconds)
|
||||
timeout 10 sh -ec 'until kubectl get kamajicontrolplane -n tenant-test kubernetes-'"${test_name}"'; do sleep 1; done'
|
||||
|
||||
# Wait for the tenant control plane to be fully created (timeout after 4 minutes)
|
||||
kubectl wait --for=condition=TenantControlPlaneCreated kamajicontrolplane -n tenant-test kubernetes-${test_name} --timeout=4m
|
||||
|
||||
# Wait for Kubernetes resources to be ready (timeout after 2 minutes)
|
||||
kubectl wait tcp -n tenant-test kubernetes-${test_name} --timeout=2m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready
|
||||
|
||||
# Wait for all required deployments to be available (timeout after 4 minutes)
|
||||
kubectl wait deploy --timeout=4m --for=condition=available -n tenant-test kubernetes-${test_name} kubernetes-${test_name}-cluster-autoscaler kubernetes-${test_name}-kccm kubernetes-${test_name}-kcsi-controller
|
||||
|
||||
# Wait for the machine deployment to scale to 2 replicas (timeout after 1 minute)
|
||||
kubectl wait machinedeployment kubernetes-${test_name}-md0 -n tenant-test --timeout=1m --for=jsonpath='{.status.replicas}'=2
|
||||
|
||||
# Get the admin kubeconfig and save it to a file
|
||||
kubectl get secret kubernetes-${test_name}-admin-kubeconfig -ojsonpath='{.data.super-admin\.conf}' -n tenant-test | base64 -d > tenantkubeconfig
|
||||
|
||||
# Update the kubeconfig to use localhost for the API server
|
||||
yq -i ".clusters[0].cluster.server = \"https://localhost:${port}\"" tenantkubeconfig
|
||||
|
||||
# Set up port forwarding to the Kubernetes API server for a 40 second timeout
|
||||
bash -c 'timeout 40s kubectl port-forward service/kubernetes-'"${test_name}"' -n tenant-test '"${port}"':6443 > /dev/null 2>&1 &'
|
||||
|
||||
# Verify the Kubernetes version matches what we expect (retry for up to 20 seconds)
|
||||
timeout 20 sh -ec 'until kubectl --kubeconfig tenantkubeconfig version 2>/dev/null | grep -Fq "Server Version: ${k8s_version}"; do sleep 5; done'
|
||||
|
||||
# Wait for all machine deployment replicas to be ready (timeout after 10 minutes)
|
||||
kubectl wait machinedeployment kubernetes-${test_name}-md0 -n tenant-test --timeout=10m --for=jsonpath='{.status.v1beta2.readyReplicas}'=2
|
||||
|
||||
# Clean up by deleting the Kubernetes resource
|
||||
kubectl -n tenant-test delete kuberneteses.apps.cozystack.io $test_name
|
||||
|
||||
}
|
||||
45
hack/e2e-apps/virtualmachine.bats
Normal file
45
hack/e2e-apps/virtualmachine.bats
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create a Virtual Machine" {
|
||||
name='test'
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: VirtualMachine
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
externalMethod: PortList
|
||||
externalPorts:
|
||||
- 22
|
||||
instanceType: "u1.medium"
|
||||
instanceProfile: ubuntu
|
||||
systemDisk:
|
||||
image: ubuntu
|
||||
storage: 5Gi
|
||||
storageClass: replicated
|
||||
gpus: []
|
||||
resources: {}
|
||||
sshKeys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPht0dPk5qQ+54g1hSX7A6AUxXJW5T6n/3d7Ga2F8gTF
|
||||
test@test
|
||||
cloudInit: |
|
||||
#cloud-config
|
||||
users:
|
||||
- name: test
|
||||
shell: /bin/bash
|
||||
sudo: ['ALL=(ALL) NOPASSWD: ALL']
|
||||
groups: sudo
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPht0dPk5qQ+54g1hSX7A6AUxXJW5T6n/3d7Ga2F8gTF test@test
|
||||
cloudInitSeed: ""
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr virtual-machine-$name --timeout=10s --for=condition=ready
|
||||
kubectl -n tenant-test wait dv virtual-machine-$name --timeout=150s --for=condition=ready
|
||||
kubectl -n tenant-test wait pvc virtual-machine-$name --timeout=100s --for=jsonpath='{.status.phase}'=Bound
|
||||
kubectl -n tenant-test wait vm virtual-machine-$name --timeout=100s --for=condition=ready
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get vmi virtual-machine-$name -o jsonpath='{.status.interfaces[0].ipAddress}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test delete virtualmachines.apps.cozystack.io $name
|
||||
}
|
||||
68
hack/e2e-apps/vminstance.bats
Normal file
68
hack/e2e-apps/vminstance.bats
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create a VM Disk" {
|
||||
name='test'
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: VMDisk
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
source:
|
||||
http:
|
||||
url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
|
||||
optical: false
|
||||
storage: 5Gi
|
||||
storageClass: replicated
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr vm-disk-$name --timeout=5s --for=condition=ready
|
||||
kubectl -n tenant-test wait dv vm-disk-$name --timeout=150s --for=condition=ready
|
||||
kubectl -n tenant-test wait pvc vm-disk-$name --timeout=100s --for=jsonpath='{.status.phase}'=Bound
|
||||
}
|
||||
|
||||
@test "Create a VM Instance" {
|
||||
diskName='test'
|
||||
name='test'
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: VMInstance
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
external: false
|
||||
externalMethod: PortList
|
||||
externalPorts:
|
||||
- 22
|
||||
running: true
|
||||
instanceType: "u1.medium"
|
||||
instanceProfile: ubuntu
|
||||
disks:
|
||||
- name: $diskName
|
||||
gpus: []
|
||||
resources:
|
||||
cpu: ""
|
||||
memory: ""
|
||||
sshKeys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPht0dPk5qQ+54g1hSX7A6AUxXJW5T6n/3d7Ga2F8gTF
|
||||
test@test
|
||||
cloudInit: |
|
||||
#cloud-config
|
||||
users:
|
||||
- name: test
|
||||
shell: /bin/bash
|
||||
sudo: ['ALL=(ALL) NOPASSWD: ALL']
|
||||
groups: sudo
|
||||
ssh_authorized_keys:
|
||||
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPht0dPk5qQ+54g1hSX7A6AUxXJW5T6n/3d7Ga2F8gTF test@test
|
||||
cloudInitSeed: ""
|
||||
EOF
|
||||
sleep 5
|
||||
timeout 20 sh -ec "until kubectl -n tenant-test get vmi vm-instance-$name -o jsonpath='{.status.interfaces[0].ipAddress}' | grep -q '[0-9]'; do sleep 5; done"
|
||||
kubectl -n tenant-test wait hr vm-instance-$name --timeout=5s --for=condition=ready
|
||||
kubectl -n tenant-test wait vm vm-instance-$name --timeout=20s --for=condition=ready
|
||||
kubectl -n tenant-test delete vminstances.apps.cozystack.io $name
|
||||
kubectl -n tenant-test delete vmdisks.apps.cozystack.io $diskName
|
||||
}
|
||||
@@ -1,391 +0,0 @@
|
||||
#!/usr/bin/env bats
|
||||
# -----------------------------------------------------------------------------
|
||||
# Cozystack end‑to‑end provisioning test (Bats)
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
@test "Required installer assets exist" {
|
||||
if [ ! -f _out/assets/cozystack-installer.yaml ]; then
|
||||
echo "Missing: _out/assets/cozystack-installer.yaml" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f _out/assets/nocloud-amd64.raw.xz ]; then
|
||||
echo "Missing: _out/assets/nocloud-amd64.raw.xz" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@test "IPv4 forwarding is enabled" {
|
||||
if [ "$(cat /proc/sys/net/ipv4/ip_forward)" != 1 ]; then
|
||||
echo "IPv4 forwarding is disabled!" >&2
|
||||
echo >&2
|
||||
echo "Enable it with:" >&2
|
||||
echo " echo 1 > /proc/sys/net/ipv4/ip_forward" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@test "Clean previous VMs" {
|
||||
kill $(cat srv1/qemu.pid srv2/qemu.pid srv3/qemu.pid 2>/dev/null) 2>/dev/null || true
|
||||
rm -rf srv1 srv2 srv3
|
||||
}
|
||||
|
||||
@test "Prepare networking and masquerading" {
|
||||
ip link del cozy-br0 2>/dev/null || true
|
||||
ip link add cozy-br0 type bridge
|
||||
ip link set cozy-br0 up
|
||||
ip address add 192.168.123.1/24 dev cozy-br0
|
||||
|
||||
# Masquerading rule – idempotent (delete first, then add)
|
||||
iptables -t nat -D POSTROUTING -s 192.168.123.0/24 ! -d 192.168.123.0/24 -j MASQUERADE 2>/dev/null || true
|
||||
iptables -t nat -A POSTROUTING -s 192.168.123.0/24 ! -d 192.168.123.0/24 -j MASQUERADE
|
||||
}
|
||||
|
||||
@test "Prepare cloud‑init drive for VMs" {
|
||||
mkdir -p srv1 srv2 srv3
|
||||
|
||||
# Generate cloud‑init ISOs
|
||||
for i in 1 2 3; do
|
||||
echo "hostname: srv${i}" > "srv${i}/meta-data"
|
||||
|
||||
cat > "srv${i}/user-data" <<'EOF'
|
||||
#cloud-config
|
||||
EOF
|
||||
|
||||
cat > "srv${i}/network-config" <<EOF
|
||||
version: 2
|
||||
ethernets:
|
||||
eth0:
|
||||
dhcp4: false
|
||||
addresses:
|
||||
- "192.168.123.1${i}/26"
|
||||
gateway4: "192.168.123.1"
|
||||
nameservers:
|
||||
search: [cluster.local]
|
||||
addresses: [8.8.8.8]
|
||||
EOF
|
||||
|
||||
( cd "srv${i}" && genisoimage \
|
||||
-output seed.img \
|
||||
-volid cidata -rational-rock -joliet \
|
||||
user-data meta-data network-config )
|
||||
done
|
||||
}
|
||||
|
||||
@test "Use Talos NoCloud image from assets" {
|
||||
if [ ! -f _out/assets/nocloud-amd64.raw.xz ]; then
|
||||
echo "Missing _out/assets/nocloud-amd64.raw.xz" 2>&1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f nocloud-amd64.raw
|
||||
cp _out/assets/nocloud-amd64.raw.xz .
|
||||
xz --decompress nocloud-amd64.raw.xz
|
||||
}
|
||||
|
||||
@test "Prepare VM disks" {
|
||||
for i in 1 2 3; do
|
||||
cp nocloud-amd64.raw srv${i}/system.img
|
||||
qemu-img resize srv${i}/system.img 50G
|
||||
qemu-img create srv${i}/data.img 100G
|
||||
done
|
||||
}
|
||||
|
||||
@test "Create tap devices" {
|
||||
for i in 1 2 3; do
|
||||
ip link del cozy-srv${i} 2>/dev/null || true
|
||||
ip tuntap add dev cozy-srv${i} mode tap
|
||||
ip link set cozy-srv${i} up
|
||||
ip link set cozy-srv${i} master cozy-br0
|
||||
done
|
||||
}
|
||||
|
||||
@test "Boot QEMU VMs" {
|
||||
for i in 1 2 3; do
|
||||
qemu-system-x86_64 -machine type=pc,accel=kvm -cpu host -smp 8 -m 24576 \
|
||||
-device virtio-net,netdev=net0,mac=52:54:00:12:34:5${i} \
|
||||
-netdev tap,id=net0,ifname=cozy-srv${i},script=no,downscript=no \
|
||||
-drive file=srv${i}/system.img,if=virtio,format=raw \
|
||||
-drive file=srv${i}/seed.img,if=virtio,format=raw \
|
||||
-drive file=srv${i}/data.img,if=virtio,format=raw \
|
||||
-display none -daemonize -pidfile srv${i}/qemu.pid
|
||||
done
|
||||
|
||||
# Give qemu a few seconds to start up networking
|
||||
sleep 5
|
||||
}
|
||||
|
||||
@test "Wait until Talos API port 50000 is reachable on all machines" {
|
||||
timeout 60 sh -ec 'until nc -nz 192.168.123.11 50000 && nc -nz 192.168.123.12 50000 && nc -nz 192.168.123.13 50000; do sleep 1; done'
|
||||
}
|
||||
|
||||
@test "Generate Talos cluster configuration" {
|
||||
# Cluster‑wide patches
|
||||
cat > patch.yaml <<'EOF'
|
||||
machine:
|
||||
kubelet:
|
||||
nodeIP:
|
||||
validSubnets:
|
||||
- 192.168.123.0/24
|
||||
extraConfig:
|
||||
maxPods: 512
|
||||
kernel:
|
||||
modules:
|
||||
- name: openvswitch
|
||||
- name: drbd
|
||||
parameters:
|
||||
- usermode_helper=disabled
|
||||
- name: zfs
|
||||
- name: spl
|
||||
registries:
|
||||
mirrors:
|
||||
docker.io:
|
||||
endpoints:
|
||||
- https://mirror.gcr.io
|
||||
files:
|
||||
- content: |
|
||||
[plugins]
|
||||
[plugins."io.containerd.cri.v1.runtime"]
|
||||
device_ownership_from_security_context = true
|
||||
path: /etc/cri/conf.d/20-customization.part
|
||||
op: create
|
||||
|
||||
cluster:
|
||||
apiServer:
|
||||
extraArgs:
|
||||
oidc-issuer-url: "https://keycloak.example.org/realms/cozy"
|
||||
oidc-client-id: "kubernetes"
|
||||
oidc-username-claim: "preferred_username"
|
||||
oidc-groups-claim: "groups"
|
||||
network:
|
||||
cni:
|
||||
name: none
|
||||
dnsDomain: cozy.local
|
||||
podSubnets:
|
||||
- 10.244.0.0/16
|
||||
serviceSubnets:
|
||||
- 10.96.0.0/16
|
||||
EOF
|
||||
|
||||
# Control‑plane‑only patches
|
||||
cat > patch-controlplane.yaml <<'EOF'
|
||||
machine:
|
||||
nodeLabels:
|
||||
node.kubernetes.io/exclude-from-external-load-balancers:
|
||||
$patch: delete
|
||||
network:
|
||||
interfaces:
|
||||
- interface: eth0
|
||||
vip:
|
||||
ip: 192.168.123.10
|
||||
cluster:
|
||||
allowSchedulingOnControlPlanes: true
|
||||
controllerManager:
|
||||
extraArgs:
|
||||
bind-address: 0.0.0.0
|
||||
scheduler:
|
||||
extraArgs:
|
||||
bind-address: 0.0.0.0
|
||||
apiServer:
|
||||
certSANs:
|
||||
- 127.0.0.1
|
||||
proxy:
|
||||
disabled: true
|
||||
discovery:
|
||||
enabled: false
|
||||
etcd:
|
||||
advertisedSubnets:
|
||||
- 192.168.123.0/24
|
||||
EOF
|
||||
|
||||
# Generate secrets once
|
||||
if [ ! -f secrets.yaml ]; then
|
||||
talosctl gen secrets
|
||||
fi
|
||||
|
||||
rm -f controlplane.yaml worker.yaml talosconfig kubeconfig
|
||||
talosctl gen config --with-secrets secrets.yaml cozystack https://192.168.123.10:6443 \
|
||||
--config-patch=@patch.yaml --config-patch-control-plane @patch-controlplane.yaml
|
||||
}
|
||||
|
||||
@test "Apply Talos configuration to the node" {
|
||||
# Apply the configuration to all three nodes
|
||||
for node in 11 12 13; do
|
||||
talosctl apply -f controlplane.yaml -n 192.168.123.${node} -e 192.168.123.${node} -i
|
||||
done
|
||||
|
||||
# Wait for Talos services to come up again
|
||||
timeout 60 sh -ec 'until nc -nz 192.168.123.11 50000 && nc -nz 192.168.123.12 50000 && nc -nz 192.168.123.13 50000; do sleep 1; done'
|
||||
}
|
||||
|
||||
@test "Bootstrap Talos cluster" {
|
||||
# Bootstrap etcd on the first node
|
||||
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'
|
||||
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
|
||||
rm -f kubeconfig
|
||||
talosctl kubeconfig kubeconfig -e 192.168.123.10 -n 192.168.123.10
|
||||
|
||||
# Wait until all three nodes register in Kubernetes
|
||||
timeout 60 sh -ec 'until [ $(kubectl get node --no-headers | wc -l) -eq 3 ]; do sleep 1; done'
|
||||
}
|
||||
|
||||
@test "Install Cozystack" {
|
||||
# Create namespace & configmap required by installer
|
||||
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
|
||||
|
||||
# Wait for the installer deployment to become available
|
||||
kubectl wait deployment/cozystack -n cozy-system --timeout=1m --for=condition=Available
|
||||
|
||||
# Wait until HelmReleases appear & reconcile them
|
||||
timeout 60 sh -ec 'until kubectl get hr -A | grep -q cozys; do sleep 1; done'
|
||||
sleep 5
|
||||
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
|
||||
kubectl get hr -A
|
||||
fail "Some HelmReleases failed to reconcile"
|
||||
fi
|
||||
}
|
||||
|
||||
@test "Wait for Cluster‑API provider deployments" {
|
||||
# Wait for Cluster‑API provider deployments
|
||||
timeout 60 sh -ec 'until kubectl get deploy -n cozy-cluster-api capi-controller-manager capi-kamaji-controller-manager capi-kubeadm-bootstrap-controller-manager capi-operator-cluster-api-operator capk-controller-manager >/dev/null 2>&1; do sleep 1; done'
|
||||
kubectl wait deployment/capi-controller-manager deployment/capi-kamaji-controller-manager deployment/capi-kubeadm-bootstrap-controller-manager deployment/capi-operator-cluster-api-operator deployment/capk-controller-manager -n cozy-cluster-api --timeout=1m --for=condition=available
|
||||
}
|
||||
|
||||
@test "Wait for LINSTOR and configure storage" {
|
||||
# Linstor controller and nodes
|
||||
kubectl wait deployment/linstor-controller -n cozy-linstor --timeout=5m --for=condition=available
|
||||
timeout 60 sh -ec 'until [ $(kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor node list | grep -c Online) -eq 3 ]; do sleep 1; done'
|
||||
|
||||
for node in srv1 srv2 srv3; do
|
||||
kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data
|
||||
done
|
||||
|
||||
# Storage classes
|
||||
kubectl apply -f - <<'EOF'
|
||||
---
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: local
|
||||
annotations:
|
||||
storageclass.kubernetes.io/is-default-class: "true"
|
||||
provisioner: linstor.csi.linbit.com
|
||||
parameters:
|
||||
linstor.csi.linbit.com/storagePool: "data"
|
||||
linstor.csi.linbit.com/layerList: "storage"
|
||||
linstor.csi.linbit.com/allowRemoteVolumeAccess: "false"
|
||||
volumeBindingMode: WaitForFirstConsumer
|
||||
allowVolumeExpansion: true
|
||||
---
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: replicated
|
||||
provisioner: linstor.csi.linbit.com
|
||||
parameters:
|
||||
linstor.csi.linbit.com/storagePool: "data"
|
||||
linstor.csi.linbit.com/autoPlace: "3"
|
||||
linstor.csi.linbit.com/layerList: "drbd storage"
|
||||
linstor.csi.linbit.com/allowRemoteVolumeAccess: "true"
|
||||
property.linstor.csi.linbit.com/DrbdOptions/auto-quorum: suspend-io
|
||||
property.linstor.csi.linbit.com/DrbdOptions/Resource/on-no-data-accessible: suspend-io
|
||||
property.linstor.csi.linbit.com/DrbdOptions/Resource/on-suspended-primary-outdated: force-secondary
|
||||
property.linstor.csi.linbit.com/DrbdOptions/Net/rr-conflict: retry-connect
|
||||
volumeBindingMode: WaitForFirstConsumer
|
||||
allowVolumeExpansion: true
|
||||
EOF
|
||||
}
|
||||
|
||||
@test "Wait for MetalLB and configure address pool" {
|
||||
# MetalLB address pool
|
||||
kubectl apply -f - <<'EOF'
|
||||
---
|
||||
apiVersion: metallb.io/v1beta1
|
||||
kind: L2Advertisement
|
||||
metadata:
|
||||
name: cozystack
|
||||
namespace: cozy-metallb
|
||||
spec:
|
||||
ipAddressPools: [cozystack]
|
||||
---
|
||||
apiVersion: metallb.io/v1beta1
|
||||
kind: IPAddressPool
|
||||
metadata:
|
||||
name: cozystack
|
||||
namespace: cozy-metallb
|
||||
spec:
|
||||
addresses: [192.168.123.200-192.168.123.250]
|
||||
autoAssign: true
|
||||
avoidBuggyIPs: false
|
||||
EOF
|
||||
}
|
||||
|
||||
@test "Check Cozystack API service" {
|
||||
kubectl wait --for=condition=Available apiservices/v1alpha1.apps.cozystack.io --timeout=2m
|
||||
}
|
||||
|
||||
@test "Configure Tenant and wait for applications" {
|
||||
# Patch root tenant and wait for its releases
|
||||
kubectl patch tenants/root -n tenant-root --type merge -p '{"spec":{"host":"example.org","ingress":true,"monitoring":true,"etcd":true,"isolated":true}}'
|
||||
|
||||
timeout 60 sh -ec 'until kubectl get hr -n tenant-root etcd ingress monitoring tenant-root >/dev/null 2>&1; do sleep 1; done'
|
||||
kubectl wait hr/etcd hr/ingress hr/tenant-root -n tenant-root --timeout=2m --for=condition=ready
|
||||
|
||||
if ! kubectl wait hr/monitoring -n tenant-root --timeout=2m --for=condition=ready; then
|
||||
flux reconcile hr monitoring -n tenant-root --force
|
||||
kubectl wait hr/monitoring -n tenant-root --timeout=2m --for=condition=ready
|
||||
fi
|
||||
|
||||
# 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"}}'
|
||||
|
||||
# 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'
|
||||
kubectl wait deploy/root-ingress-controller -n tenant-root --timeout=5m --for=condition=available
|
||||
|
||||
# etcd statefulset
|
||||
kubectl wait sts/etcd -n tenant-root --for=jsonpath='{.status.readyReplicas}'=3 --timeout=5m
|
||||
|
||||
# VictoriaMetrics components
|
||||
kubectl wait vmalert/vmalert-shortterm vmalertmanager/alertmanager -n tenant-root --for=jsonpath='{.status.updateStatus}'=operational --timeout=5m
|
||||
kubectl wait vlogs/generic -n tenant-root --for=jsonpath='{.status.updateStatus}'=operational --timeout=5m
|
||||
kubectl wait vmcluster/shortterm vmcluster/longterm -n tenant-root --for=jsonpath='{.status.clusterStatus}'=operational --timeout=5m
|
||||
|
||||
# Grafana
|
||||
kubectl wait clusters.postgresql.cnpg.io/grafana-db -n tenant-root --for=condition=ready --timeout=5m
|
||||
kubectl wait deploy/grafana-deployment -n tenant-root --for=condition=available --timeout=5m
|
||||
|
||||
# Verify Grafana via ingress
|
||||
ingress_ip=$(kubectl get svc root-ingress-controller -n tenant-root -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
if ! curl -sS -k "https://${ingress_ip}" -H 'Host: grafana.example.org' --max-time 30 | grep -q Found; then
|
||||
echo "Failed to access Grafana via ingress at ${ingress_ip}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@test "Keycloak OIDC stack is healthy" {
|
||||
kubectl patch configmap/cozystack -n cozy-system --type merge -p '{"data":{"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
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Required installer assets exist" {
|
||||
if [ ! -f _out/assets/cozystack-installer.yaml ]; then
|
||||
echo "Missing: _out/assets/cozystack-installer.yaml" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@test "Install Cozystack" {
|
||||
# Create namespace & configmap required by installer
|
||||
kubectl create namespace cozy-system --dry-run=client -o yaml | kubectl apply -f -
|
||||
@@ -20,14 +27,14 @@
|
||||
kubectl wait deployment/cozystack -n cozy-system --timeout=1m --for=condition=Available
|
||||
|
||||
# Wait until HelmReleases appear & reconcile them
|
||||
timeout 60 sh -ec 'until kubectl get hr -A | grep -q cozys; do sleep 1; done'
|
||||
timeout 60 sh -ec 'until kubectl get hr -A -l cozystack.io/system-app=true | grep -q cozys; do sleep 1; done'
|
||||
sleep 5
|
||||
kubectl get hr -A | awk 'NR>1 {print "kubectl wait --timeout=15m --for=condition=ready -n "$1" hr/"$2" &"} END {print "wait"}' | sh -ex
|
||||
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
|
||||
|
||||
# Fail the test if any HelmRelease is not Ready
|
||||
if kubectl get hr -A | grep -v " True " | grep -v NAME; then
|
||||
kubectl get hr -A
|
||||
fail "Some HelmReleases failed to reconcile"
|
||||
echo "Some HelmReleases failed to reconcile" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -42,7 +49,11 @@
|
||||
kubectl wait deployment/linstor-controller -n cozy-linstor --timeout=5m --for=condition=available
|
||||
timeout 60 sh -ec 'until [ $(kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor node list | grep -c Online) -eq 3 ]; do sleep 1; done'
|
||||
|
||||
created_pools=$(kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor sp l -s data --pastable | awk '$2 == "data" {printf " " $4} END{printf " "}')
|
||||
for node in srv1 srv2 srv3; do
|
||||
case $created_pools in
|
||||
*" $node "*) echo "Storage pool 'data' already exists on node $node"; continue;;
|
||||
esac
|
||||
kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data
|
||||
done
|
||||
|
||||
@@ -112,10 +123,10 @@ EOF
|
||||
|
||||
@test "Configure Tenant and wait for applications" {
|
||||
# Patch root tenant and wait for its releases
|
||||
kubectl patch tenants/root -n tenant-root --type merge -p '{"spec":{"host":"example.org","ingress":true,"monitoring":true,"etcd":true,"isolated":true}}'
|
||||
kubectl patch tenants/root -n tenant-root --type merge -p '{"spec":{"host":"example.org","ingress":true,"monitoring":true,"etcd":true,"isolated":true, "seaweedfs": true}}'
|
||||
|
||||
timeout 60 sh -ec 'until kubectl get hr -n tenant-root etcd ingress monitoring tenant-root >/dev/null 2>&1; do sleep 1; done'
|
||||
kubectl wait hr/etcd hr/ingress hr/tenant-root -n tenant-root --timeout=2m --for=condition=ready
|
||||
timeout 60 sh -ec 'until kubectl get hr -n tenant-root etcd ingress monitoring seaweedfs tenant-root >/dev/null 2>&1; do sleep 1; done'
|
||||
kubectl wait hr/etcd hr/ingress hr/tenant-root hr/seaweedfs -n tenant-root --timeout=4m --for=condition=ready
|
||||
|
||||
if ! kubectl wait hr/monitoring -n tenant-root --timeout=2m --for=condition=ready; then
|
||||
flux reconcile hr monitoring -n tenant-root --force
|
||||
@@ -155,3 +166,24 @@ EOF
|
||||
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
|
||||
}
|
||||
|
||||
@test "Create tenant with isolated mode enabled" {
|
||||
kubectl -n tenant-root get tenants.apps.cozystack.io test ||
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: Tenant
|
||||
metadata:
|
||||
name: test
|
||||
namespace: tenant-root
|
||||
spec:
|
||||
etcd: false
|
||||
host: ""
|
||||
ingress: false
|
||||
isolated: true
|
||||
monitoring: false
|
||||
resourceQuotas: {}
|
||||
seaweedfs: false
|
||||
EOF
|
||||
kubectl wait hr/tenant-test -n tenant-root --timeout=1m --for=condition=ready
|
||||
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
|
||||
}
|
||||
|
||||
@@ -4,11 +4,6 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
@test "Required installer assets exist" {
|
||||
if [ ! -f _out/assets/cozystack-installer.yaml ]; then
|
||||
echo "Missing: _out/assets/cozystack-installer.yaml" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f _out/assets/nocloud-amd64.raw.xz ]; then
|
||||
echo "Missing: _out/assets/nocloud-amd64.raw.xz" >&2
|
||||
exit 1
|
||||
@@ -141,7 +136,25 @@ machine:
|
||||
mirrors:
|
||||
docker.io:
|
||||
endpoints:
|
||||
- https://mirror.gcr.io
|
||||
- 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]
|
||||
|
||||
@@ -32,6 +32,10 @@ kube::codegen::gen_helpers \
|
||||
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \
|
||||
"${SCRIPT_ROOT}/pkg/apis"
|
||||
|
||||
kube::codegen::gen_helpers \
|
||||
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \
|
||||
"${SCRIPT_ROOT}/api"
|
||||
|
||||
if [[ -n "${API_KNOWN_VIOLATIONS_DIR:-}" ]]; then
|
||||
report_filename="${API_KNOWN_VIOLATIONS_DIR}/cozystack_api_violation_exceptions.list"
|
||||
if [[ "${UPDATE_API_KNOWN_VIOLATIONS:-}" == "true" ]]; then
|
||||
|
||||
117
internal/controller/cozystackresource_controller.go
Normal file
117
internal/controller/cozystackresource_controller.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
type CozystackResourceDefinitionReconciler struct {
|
||||
client.Client
|
||||
Scheme *runtime.Scheme
|
||||
|
||||
// Configurable debounce duration
|
||||
Debounce time.Duration
|
||||
|
||||
// Internal state for debouncing
|
||||
mu sync.Mutex
|
||||
lastEvent time.Time // Time of last CRUD event on CozystackResourceDefinition
|
||||
lastHandled time.Time // Last time the Deployment was actually restarted
|
||||
}
|
||||
|
||||
// Reconcile handles the logic to restart the target Deployment only once,
|
||||
// even if multiple events occur close together
|
||||
func (r *CozystackResourceDefinitionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
log := log.FromContext(ctx)
|
||||
|
||||
// Only respond to our target deployment
|
||||
if req.Namespace != "cozy-system" || req.Name != "cozystack-api" {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
r.mu.Lock()
|
||||
le := r.lastEvent
|
||||
lh := r.lastHandled
|
||||
debounce := r.Debounce
|
||||
r.mu.Unlock()
|
||||
|
||||
if debounce <= 0 {
|
||||
debounce = 5 * time.Second
|
||||
}
|
||||
|
||||
// No events received yet — nothing to do
|
||||
if le.IsZero() {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// Wait until the debounce duration has passed since the last event
|
||||
if d := time.Since(le); d < debounce {
|
||||
return ctrl.Result{RequeueAfter: debounce - d}, nil
|
||||
}
|
||||
|
||||
// Already handled this event — skip restart
|
||||
if !lh.Before(le) {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// Perform the restart by patching the deployment annotation
|
||||
deploy := &appsv1.Deployment{}
|
||||
if err := r.Get(ctx, types.NamespacedName{Namespace: "cozy-system", Name: "cozystack-api"}, deploy); err != nil {
|
||||
log.Error(err, "Failed to get Deployment cozy-system/cozystack-api")
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
||||
patch := client.MergeFrom(deploy.DeepCopy())
|
||||
if deploy.Spec.Template.Annotations == nil {
|
||||
deploy.Spec.Template.Annotations = make(map[string]string)
|
||||
}
|
||||
deploy.Spec.Template.Annotations["kubectl.kubernetes.io/restartedAt"] = time.Now().Format(time.RFC3339)
|
||||
|
||||
if err := r.Patch(ctx, deploy, patch); err != nil {
|
||||
log.Error(err, "Failed to patch Deployment annotation")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
// Mark this event as handled
|
||||
r.mu.Lock()
|
||||
r.lastHandled = le
|
||||
r.mu.Unlock()
|
||||
|
||||
log.Info("Deployment cozy-system/cozystack-api successfully restarted")
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// SetupWithManager configures how the controller listens to events
|
||||
func (r *CozystackResourceDefinitionReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
if r.Debounce == 0 {
|
||||
r.Debounce = 5 * time.Second
|
||||
}
|
||||
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
Named("cozystack-restart-controller").
|
||||
Watches(
|
||||
&cozyv1alpha1.CozystackResourceDefinition{},
|
||||
handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request {
|
||||
r.mu.Lock()
|
||||
r.lastEvent = time.Now()
|
||||
r.mu.Unlock()
|
||||
return []reconcile.Request{{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Namespace: "cozy-system",
|
||||
Name: "cozystack-api",
|
||||
},
|
||||
}}
|
||||
}),
|
||||
).
|
||||
Complete(r)
|
||||
}
|
||||
@@ -54,6 +54,7 @@ func (r *CozystackConfigReconciler) Reconcile(ctx context.Context, _ ctrl.Reques
|
||||
if !isSystemApp && !isTenantRoot {
|
||||
continue
|
||||
}
|
||||
patchTarget := hr.DeepCopy()
|
||||
|
||||
if hr.Annotations == nil {
|
||||
hr.Annotations = map[string]string{}
|
||||
@@ -62,13 +63,12 @@ func (r *CozystackConfigReconciler) Reconcile(ctx context.Context, _ ctrl.Reques
|
||||
if hr.Annotations[digestAnnotation] == digest {
|
||||
continue
|
||||
}
|
||||
patchTarget.Annotations[digestAnnotation] = digest
|
||||
patchTarget.Annotations[forceReconcileKey] = now
|
||||
patchTarget.Annotations[requestedAt] = now
|
||||
|
||||
patch := client.MergeFrom(hr.DeepCopy())
|
||||
hr.Annotations[digestAnnotation] = digest
|
||||
hr.Annotations[forceReconcileKey] = now
|
||||
hr.Annotations[requestedAt] = now
|
||||
|
||||
if err := r.Patch(ctx, &hr, patch); err != nil {
|
||||
if err := r.Patch(ctx, patchTarget, patch); err != nil {
|
||||
log.Error(err, "failed to patch HelmRelease", "name", hr.Name, "namespace", hr.Namespace)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ package controller
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"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"
|
||||
@@ -15,63 +15,50 @@ import (
|
||||
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
deletionRequeueDelay = 30 * time.Second
|
||||
)
|
||||
|
||||
// WorkloadMonitorReconciler reconciles a WorkloadMonitor object
|
||||
type WorkloadReconciler struct {
|
||||
client.Client
|
||||
Scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
// workload_controller.go
|
||||
func (r *WorkloadReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
logger := log.FromContext(ctx)
|
||||
log := log.FromContext(ctx)
|
||||
|
||||
w := &cozyv1alpha1.Workload{}
|
||||
err := r.Get(ctx, req.NamespacedName, w)
|
||||
if err != nil {
|
||||
if err := r.Get(ctx, req.NamespacedName, w); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
logger.Error(err, "Unable to fetch Workload")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
// it's being deleted, nothing to handle
|
||||
if w.DeletionTimestamp != nil {
|
||||
return ctrl.Result{}, nil
|
||||
// If my monitor is gone, delete me.
|
||||
monName, has := w.Labels["workloads.cozystack.io/monitor"]
|
||||
if !has {
|
||||
return ctrl.Result{}, client.IgnoreNotFound(r.Delete(ctx, w))
|
||||
}
|
||||
|
||||
t := getMonitoredObject(w)
|
||||
|
||||
if t == nil {
|
||||
err = r.Delete(ctx, w)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to delete workload")
|
||||
}
|
||||
monitor := &cozyv1alpha1.WorkloadMonitor{}
|
||||
if err := r.Get(ctx, client.ObjectKey{Namespace: w.Namespace, Name: monName}, monitor); apierrors.IsNotFound(err) {
|
||||
// Monitor is gone → delete the Workload. Ignore NotFound here, too.
|
||||
return ctrl.Result{}, client.IgnoreNotFound(r.Delete(ctx, w))
|
||||
} else if err != nil {
|
||||
// Some other error fetching the monitor
|
||||
log.Error(err, "failed to get WorkloadMonitor", "monitor", monName)
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
err = r.Get(ctx, types.NamespacedName{Name: t.GetName(), Namespace: t.GetNamespace()}, t)
|
||||
|
||||
// found object, nothing to do
|
||||
if err == nil {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// error getting object but not 404 -- requeue
|
||||
if !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "failed to get dependent object", "kind", t.GetObjectKind(), "dependent-object-name", t.GetName())
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
err = r.Delete(ctx, w)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to delete workload")
|
||||
}
|
||||
return ctrl.Result{}, err
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// SetupWithManager registers our controller with the Manager and sets up watches.
|
||||
func (r *WorkloadReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
// Watch WorkloadMonitor objects
|
||||
// Watch Workload objects
|
||||
For(&cozyv1alpha1.Workload{}).
|
||||
Complete(r)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
func TestUnprefixedMonitoredObjectReturnsNil(t *testing.T) {
|
||||
@@ -24,3 +31,83 @@ func TestPodMonitoredObject(t *testing.T) {
|
||||
t.Errorf(`getMonitoredObject(&Workload{Name: "%s"}) == %v, want &Pod{Name: "mypod"}`, w.Name, obj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkloadReconciler_DeletesOnMissingMonitor(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
_ = cozyv1alpha1.AddToScheme(scheme)
|
||||
_ = corev1.AddToScheme(scheme)
|
||||
|
||||
// Workload with a non-existent monitor
|
||||
w := &cozyv1alpha1.Workload{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod-foo",
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"workloadmonitor.cozystack.io/name": "missing-monitor",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fakeClient := fake.NewClientBuilder().
|
||||
WithScheme(scheme).
|
||||
WithObjects(w).
|
||||
Build()
|
||||
reconciler := &WorkloadReconciler{Client: fakeClient}
|
||||
req := reconcile.Request{NamespacedName: types.NamespacedName{Name: "pod-foo", Namespace: "default"}}
|
||||
|
||||
if _, err := reconciler.Reconcile(context.TODO(), req); err != nil {
|
||||
t.Fatalf("Reconcile returned error: %v", err)
|
||||
}
|
||||
|
||||
// Expect workload to be deleted
|
||||
err := fakeClient.Get(context.TODO(), req.NamespacedName, &cozyv1alpha1.Workload{})
|
||||
if !apierrors.IsNotFound(err) {
|
||||
t.Errorf("expected workload to be deleted, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkloadReconciler_KeepsWhenAllExist(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
_ = cozyv1alpha1.AddToScheme(scheme)
|
||||
_ = corev1.AddToScheme(scheme)
|
||||
|
||||
// Create a monitor and its backing Pod
|
||||
monitor := &cozyv1alpha1.WorkloadMonitor{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mon",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
pod := &corev1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: "default",
|
||||
},
|
||||
}
|
||||
w := &cozyv1alpha1.Workload{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod-foo",
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"workloadmonitor.cozystack.io/name": "mon",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fakeClient := fake.NewClientBuilder().
|
||||
WithScheme(scheme).
|
||||
WithObjects(monitor, pod, w).
|
||||
Build()
|
||||
reconciler := &WorkloadReconciler{Client: fakeClient}
|
||||
req := reconcile.Request{NamespacedName: types.NamespacedName{Name: "pod-foo", Namespace: "default"}}
|
||||
|
||||
if _, err := reconciler.Reconcile(context.TODO(), req); err != nil {
|
||||
t.Fatalf("Reconcile returned error: %v", err)
|
||||
}
|
||||
|
||||
// Expect workload to remain
|
||||
err := fakeClient.Get(context.TODO(), req.NamespacedName, &cozyv1alpha1.Workload{})
|
||||
if err != nil {
|
||||
t.Errorf("expected workload to persist, got error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/util/retry"
|
||||
"k8s.io/utils/pointer"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -111,6 +112,7 @@ func (r *WorkloadMonitorReconciler) reconcileServiceForMonitor(
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("svc-%s", svc.Name),
|
||||
Namespace: svc.Namespace,
|
||||
Labels: make(map[string]string, len(svc.Labels)),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -137,9 +139,12 @@ func (r *WorkloadMonitorReconciler) reconcileServiceForMonitor(
|
||||
|
||||
_, err := ctrl.CreateOrUpdate(ctx, r.Client, workload, func() error {
|
||||
// Update owner references with the new monitor
|
||||
updateOwnerReferences(workload.GetObjectMeta(), monitor)
|
||||
updateOwnerReferences(workload.GetObjectMeta(), &svc)
|
||||
|
||||
workload.Labels = svc.Labels
|
||||
for k, v := range svc.Labels {
|
||||
workload.Labels[k] = v
|
||||
}
|
||||
workload.Labels["workloads.cozystack.io/monitor"] = monitor.Name
|
||||
|
||||
// Fill Workload status fields:
|
||||
workload.Status.Kind = monitor.Spec.Kind
|
||||
@@ -168,6 +173,7 @@ func (r *WorkloadMonitorReconciler) reconcilePVCForMonitor(
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("pvc-%s", pvc.Name),
|
||||
Namespace: pvc.Namespace,
|
||||
Labels: make(map[string]string, len(pvc.Labels)),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -184,9 +190,12 @@ func (r *WorkloadMonitorReconciler) reconcilePVCForMonitor(
|
||||
|
||||
_, err := ctrl.CreateOrUpdate(ctx, r.Client, workload, func() error {
|
||||
// Update owner references with the new monitor
|
||||
updateOwnerReferences(workload.GetObjectMeta(), monitor)
|
||||
updateOwnerReferences(workload.GetObjectMeta(), &pvc)
|
||||
|
||||
workload.Labels = pvc.Labels
|
||||
for k, v := range pvc.Labels {
|
||||
workload.Labels[k] = v
|
||||
}
|
||||
workload.Labels["workloads.cozystack.io/monitor"] = monitor.Name
|
||||
|
||||
// Fill Workload status fields:
|
||||
workload.Status.Kind = monitor.Spec.Kind
|
||||
@@ -248,19 +257,19 @@ func (r *WorkloadMonitorReconciler) reconcilePodForMonitor(
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("pod-%s", pod.Name),
|
||||
Namespace: pod.Namespace,
|
||||
Labels: map[string]string{},
|
||||
Labels: make(map[string]string, len(pod.Labels)),
|
||||
},
|
||||
}
|
||||
|
||||
metaLabels := r.getWorkloadMetadata(&pod)
|
||||
_, err := ctrl.CreateOrUpdate(ctx, r.Client, workload, func() error {
|
||||
// Update owner references with the new monitor
|
||||
updateOwnerReferences(workload.GetObjectMeta(), monitor)
|
||||
updateOwnerReferences(workload.GetObjectMeta(), &pod)
|
||||
|
||||
// Copy labels from the Pod if needed
|
||||
for k, v := range pod.Labels {
|
||||
workload.Labels[k] = v
|
||||
}
|
||||
workload.Labels["workloads.cozystack.io/monitor"] = monitor.Name
|
||||
|
||||
// Add workload meta to labels
|
||||
for k, v := range metaLabels {
|
||||
@@ -370,15 +379,24 @@ func (r *WorkloadMonitorReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
monitor.Status.ObservedReplicas = observedReplicas
|
||||
monitor.Status.AvailableReplicas = availableReplicas
|
||||
|
||||
// Default to operational = true, but check MinReplicas if set
|
||||
monitor.Status.Operational = pointer.Bool(true)
|
||||
if monitor.Spec.MinReplicas != nil && availableReplicas < *monitor.Spec.MinReplicas {
|
||||
monitor.Status.Operational = pointer.Bool(false)
|
||||
}
|
||||
|
||||
// Update the WorkloadMonitor status in the cluster
|
||||
if err := r.Status().Update(ctx, monitor); err != nil {
|
||||
logger.Error(err, "Unable to update WorkloadMonitor status", "monitor", monitor.Name)
|
||||
err = retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
||||
fresh := &cozyv1alpha1.WorkloadMonitor{}
|
||||
if err := r.Get(ctx, req.NamespacedName, fresh); err != nil {
|
||||
return err
|
||||
}
|
||||
fresh.Status.ObservedReplicas = observedReplicas
|
||||
fresh.Status.AvailableReplicas = availableReplicas
|
||||
|
||||
// Default to operational = true, but check MinReplicas if set
|
||||
monitor.Status.Operational = pointer.Bool(true)
|
||||
if monitor.Spec.MinReplicas != nil && availableReplicas < *monitor.Spec.MinReplicas {
|
||||
monitor.Status.Operational = pointer.Bool(false)
|
||||
}
|
||||
return r.Status().Update(ctx, fresh)
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error(err, "unable to update WorkloadMonitor status after retries")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,5 @@
|
||||
cd packages/core/installer
|
||||
make image-cozystack REGISTRY=YOUR_CUSTOM_REGISTRY
|
||||
make apply
|
||||
kubectl delete pod dashboard-redis-master-0 -n cozy-dashboard
|
||||
kubectl delete po -l app=source-controller -n cozy-fluxcd
|
||||
```
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
include ../../../scripts/package.mk
|
||||
|
||||
generate:
|
||||
readme-generator -v values.yaml -s values.schema.json -r README.md
|
||||
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
|
||||
yq -o json -i '.properties = {}' values.schema.json
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.10.0
|
||||
version: 0.12.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
|
||||
@@ -4,7 +4,7 @@ include ../../../scripts/common-envs.mk
|
||||
include ../../../scripts/package.mk
|
||||
|
||||
generate:
|
||||
readme-generator -v values.yaml -s values.schema.json -r README.md
|
||||
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
|
||||
|
||||
image:
|
||||
docker buildx build images/clickhouse-backup \
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
# Managed Clickhouse Service
|
||||
# Managed ClickHouse Service
|
||||
|
||||
ClickHouse is an open source high-performance and column-oriented SQL database management system (DBMS).
|
||||
It is used for online analytical processing (OLAP).
|
||||
Cozystack platform uses Altinity operator to provide ClickHouse.
|
||||
|
||||
### How to restore backup:
|
||||
### How to restore backup from S3
|
||||
|
||||
1. Find a snapshot:
|
||||
```
|
||||
1. Find the snapshot:
|
||||
|
||||
```bash
|
||||
restic -r s3:s3.example.org/clickhouse-backups/table_name snapshots
|
||||
```
|
||||
|
||||
2. Restore it:
|
||||
```
|
||||
|
||||
```bash
|
||||
restic -r s3:s3.example.org/clickhouse-backups/table_name restore latest --target /tmp/
|
||||
```
|
||||
|
||||
@@ -22,49 +23,93 @@ For more details, read [Restic: Effective Backup from Stdin](https://blog.aenix.
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ---------------- | -------------------------------------------------------- | ------ |
|
||||
| `size` | Size of Persistent Volume for data | `10Gi` |
|
||||
| `logStorageSize` | Size of Persistent Volume for logs | `2Gi` |
|
||||
| `shards` | Number of Clickhouse shards | `1` |
|
||||
| `replicas` | Number of Clickhouse replicas | `2` |
|
||||
| `storageClass` | StorageClass used to store the data | `""` |
|
||||
| `logTTL` | TTL (expiration time) for query_log and query_thread_log | `15` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of Clickhouse replicas | `int` | `2` |
|
||||
| `shards` | Number of Clickhouse shards | `int` | `1` |
|
||||
| `resources` | Explicit CPU and memory configuration for each Clickhouse replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `{}` |
|
||||
| `resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `small` |
|
||||
| `size` | Persistent Volume Claim size, available for application data | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
|
||||
### Configuration parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------- | ------------------- | ----- |
|
||||
| `users` | Users configuration | `{}` |
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------- | ------------------------------------------------------------ | ------------------- | ------- |
|
||||
| `logStorageSize` | Size of Persistent Volume for logs | `quantity` | `2Gi` |
|
||||
| `logTTL` | TTL (expiration time) for `query_log` and `query_thread_log` | `int` | `15` |
|
||||
| `users` | Users configuration | `map[string]object` | `{...}` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
| `users[name].readonly` | User is `readonly`, default is `false`. | `*bool` | `null` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
| `users[name].readonly` | User is `readonly`, default is `false`. | `*bool` | `null` |
|
||||
|
||||
|
||||
### Backup parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------ | --------------------------------------------------------------------------- | ------------------------------------------------------ |
|
||||
| `backup.enabled` | Enable periodic backups | `false` |
|
||||
| `backup.s3Region` | AWS S3 region where backups are stored | `us-east-1` |
|
||||
| `backup.s3Bucket` | S3 bucket used for storing backups | `s3.example.org/clickhouse-backups` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `0 2 * * *` |
|
||||
| `backup.cleanupStrategy` | Retention strategy for cleaning up old backups | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `oobaiRus9pah8PhohL1ThaeTa4UVa7gu` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `ju3eum4dekeich9ahM1te8waeGai0oog` |
|
||||
| `backup.resticPassword` | Password for Restic backup encryption | `ChaXoveekoh6eigh4siesheeda2quai0` |
|
||||
| `resources` | Explicit CPU/memory resource requests and limits for the Clickhouse service | `{}` |
|
||||
| `resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `nano` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ---------------------------------------------- | -------- | ------------------------------------------------------ |
|
||||
| `backup` | Backup configuration | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups, default is `false` | `bool` | `false` |
|
||||
| `backup.s3Region` | AWS S3 region where backups are stored | `string` | `us-east-1` |
|
||||
| `backup.s3Bucket` | S3 bucket used for storing backups | `string` | `s3.example.org/clickhouse-backups` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `string` | `0 2 * * *` |
|
||||
| `backup.cleanupStrategy` | Retention strategy for cleaning up old backups | `string` | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `string` | `oobaiRus9pah8PhohL1ThaeTa4UVa7gu` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `string` | `ju3eum4dekeich9ahM1te8waeGai0oog` |
|
||||
| `backup.resticPassword` | Password for Restic backup encryption | `string` | `ChaXoveekoh6eigh4siesheeda2quai0` |
|
||||
| `backup.enabled` | Enable regular backups, default is `false` | `bool` | `false` |
|
||||
| `backup.s3Region` | AWS S3 region where backups are stored | `string` | `us-east-1` |
|
||||
| `backup.s3Bucket` | S3 bucket used for storing backups | `string` | `s3.example.org/clickhouse-backups` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `string` | `0 2 * * *` |
|
||||
| `backup.cleanupStrategy` | Retention strategy for cleaning up old backups | `string` | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `string` | `oobaiRus9pah8PhohL1ThaeTa4UVa7gu` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `string` | `ju3eum4dekeich9ahM1te8waeGai0oog` |
|
||||
| `backup.resticPassword` | Password for Restic backup encryption | `string` | `ChaXoveekoh6eigh4siesheeda2quai0` |
|
||||
|
||||
|
||||
In production environments, it's recommended to set `resources` explicitly.
|
||||
Example of `resources`:
|
||||
### Clickhouse Keeper parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `clickhouseKeeper` | Clickhouse Keeper configuration | `*object` | `{}` |
|
||||
| `clickhouseKeeper.enabled` | Deploy ClickHouse Keeper for cluster coordination | `*bool` | `true` |
|
||||
| `clickhouseKeeper.size` | Persistent Volume Claim size, available for application data | `*quantity` | `1Gi` |
|
||||
| `clickhouseKeeper.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `clickhouseKeeper.replicas` | Number of keeper replicas | `*int` | `3` |
|
||||
| `clickhouseKeeper.enabled` | Deploy ClickHouse Keeper for cluster coordination | `*bool` | `true` |
|
||||
| `clickhouseKeeper.size` | Persistent Volume Claim size, available for application data | `*quantity` | `1Gi` |
|
||||
| `clickhouseKeeper.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `clickhouseKeeper.replicas` | Number of keeper replicas | `*int` | `3` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
### resources and resourcesPreset
|
||||
|
||||
`resources` sets explicit CPU and memory configurations for each replica.
|
||||
When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
limits:
|
||||
cpu: 4000m
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 512Mi
|
||||
cpu: 4000m
|
||||
memory: 4Gi
|
||||
```
|
||||
|
||||
Allowed values for `resourcesPreset` are `none`, `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
This value is ignored if `resources` value is set.
|
||||
`resourcesPreset` sets named CPU and memory configurations for each replica.
|
||||
This setting is ignored if the corresponding `resources` value is set.
|
||||
|
||||
| Preset name | CPU | memory |
|
||||
|-------------|--------|---------|
|
||||
| `nano` | `250m` | `128Mi` |
|
||||
| `micro` | `500m` | `256Mi` |
|
||||
| `small` | `1` | `512Mi` |
|
||||
| `medium` | `1` | `1Gi` |
|
||||
| `large` | `2` | `2Gi` |
|
||||
| `xlarge` | `4` | `4Gi` |
|
||||
| `2xlarge` | `8` | `8Gi` |
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/clickhouse-backup:0.10.0@sha256:3faf7a4cebf390b9053763107482de175aa0fdb88c1e77424fd81100b1c3a205
|
||||
ghcr.io/cozystack/cozystack/clickhouse-backup:0.11.1@sha256:3faf7a4cebf390b9053763107482de175aa0fdb88c1e77424fd81100b1c3a205
|
||||
|
||||
96
packages/apps/clickhouse/templates/chkeeper.yaml
Normal file
96
packages/apps/clickhouse/templates/chkeeper.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }}
|
||||
{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }}
|
||||
|
||||
{{- if .Values.clickhouseKeeper.enabled }}
|
||||
apiVersion: "clickhouse-keeper.altinity.com/v1"
|
||||
kind: "ClickHouseKeeperInstallation"
|
||||
metadata:
|
||||
name: "{{ .Release.Name }}-keeper"
|
||||
annotations:
|
||||
prometheus.io/port: "7000"
|
||||
prometheus.io/scrape: "true"
|
||||
spec:
|
||||
namespaceDomainPattern: "%s.svc.{{ $clusterDomain }}"
|
||||
configuration:
|
||||
clusters:
|
||||
- name: "cluster1"
|
||||
layout:
|
||||
replicasCount: {{ .Values.clickhouseKeeper.replicas }}
|
||||
settings:
|
||||
logger/level: "trace"
|
||||
logger/console: "true"
|
||||
listen_host: "0.0.0.0"
|
||||
keeper_server/four_letter_word_white_list: "*"
|
||||
keeper_server/coordination_settings/raft_logs_level: "information"
|
||||
prometheus/endpoint: "/metrics"
|
||||
prometheus/port: "7000"
|
||||
prometheus/metrics: "true"
|
||||
prometheus/events: "true"
|
||||
prometheus/asynchronous_metrics: "true"
|
||||
prometheus/status_info: "false"
|
||||
|
||||
defaults:
|
||||
templates:
|
||||
# Templates are specified as default for all clusters
|
||||
podTemplate: default
|
||||
dataVolumeClaimTemplate: default
|
||||
|
||||
templates:
|
||||
podTemplates:
|
||||
- name: default
|
||||
metadata:
|
||||
labels:
|
||||
app: "{{ .Release.Name }}-keeper"
|
||||
annotations:
|
||||
prometheus.io/port: "7000"
|
||||
prometheus.io/scrape: "true"
|
||||
spec:
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchExpressions:
|
||||
- key: "app"
|
||||
operator: In
|
||||
values:
|
||||
- "{{ .Release.Name }}-keeper"
|
||||
topologyKey: "kubernetes.io/hostname"
|
||||
containers:
|
||||
- name: clickhouse-keeper
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: clickhouse/clickhouse-keeper:24.9.2.42
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.clickhouseKeeper.resourcesPreset .Values.resources $) | nindent 20 }}
|
||||
securityContext:
|
||||
fsGroup: 101
|
||||
|
||||
volumeClaimTemplates:
|
||||
- name: default
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: "{{ .Values.clickhouseKeeper.size }}"
|
||||
---
|
||||
apiVersion: operator.victoriametrics.com/v1beta1
|
||||
kind: VMPodScrape
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-keeper
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ .Release.Name }}-keeper
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace }}
|
||||
podMetricsEndpoints:
|
||||
- port: metrics
|
||||
path: /metrics
|
||||
interval: 30s
|
||||
scheme: http
|
||||
relabelConfigs:
|
||||
- action: replace
|
||||
sourceLabels: [__meta_kubernetes_pod_node_name]
|
||||
targetLabel: instance
|
||||
{{- end }}
|
||||
@@ -91,6 +91,18 @@ spec:
|
||||
layout:
|
||||
shardsCount: {{ .Values.shards }}
|
||||
replicasCount: {{ .Values.replicas }}
|
||||
{{- if .Values.clickhouseKeeper.enabled }}
|
||||
zookeeper:
|
||||
nodes:
|
||||
{{- $replicas := int .Values.clickhouseKeeper.replicas }}
|
||||
{{- $release := .Release.Name }}
|
||||
{{- $namespace := .Release.Namespace }}
|
||||
{{- $clusterDomain := .Values.clusterDomain }}
|
||||
{{- range $i := until $replicas }}
|
||||
- host: "chk-{{ $release }}-keeper-cluster1-0-{{ $i }}.{{ $namespace }}.svc.{{ $clusterDomain }}"
|
||||
port: 2181
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
templates:
|
||||
volumeClaimTemplates:
|
||||
- name: data-volume-template
|
||||
@@ -132,11 +144,7 @@ spec:
|
||||
containers:
|
||||
- name: clickhouse
|
||||
image: clickhouse/clickhouse-server:24.9.2.42
|
||||
{{- if .Values.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.resources $) | nindent 16 }}
|
||||
{{- else if ne .Values.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.resourcesPreset $) | nindent 16 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 16 }}
|
||||
volumeMounts:
|
||||
- name: data-volume-template
|
||||
mountPath: /var/lib/clickhouse
|
||||
|
||||
@@ -23,6 +23,9 @@ rules:
|
||||
- workloadmonitors
|
||||
resourceNames:
|
||||
- {{ .Release.Name }}
|
||||
{{- if .Values.clickhouseKeeper.enabled }}
|
||||
- {{ .Release.Name }}-keeper
|
||||
{{- end }}
|
||||
verbs: ["get", "list", "watch"]
|
||||
---
|
||||
kind: RoleBinding
|
||||
|
||||
@@ -11,3 +11,18 @@ spec:
|
||||
selector:
|
||||
app.kubernetes.io/instance: {{ $.Release.Name }}
|
||||
version: {{ $.Chart.Version }}
|
||||
{{- if .Values.clickhouseKeeper.enabled }}
|
||||
---
|
||||
apiVersion: cozystack.io/v1alpha1
|
||||
kind: WorkloadMonitor
|
||||
metadata:
|
||||
name: {{ $.Release.Name }}-keeper
|
||||
spec:
|
||||
replicas: {{ .Values.clickhouseKeeper.replicas }}
|
||||
minReplicas: 1
|
||||
kind: clickhouse
|
||||
type: clickhouse
|
||||
selector:
|
||||
app: {{ $.Release.Name }}-keeper
|
||||
version: {{ $.Chart.Version }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,91 +1,237 @@
|
||||
{
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "string",
|
||||
"description": "Size of Persistent Volume for data",
|
||||
"default": "10Gi"
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup": {
|
||||
"description": "Backup configuration",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"cleanupStrategy": "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m",
|
||||
"enabled": false,
|
||||
"resticPassword": "ChaXoveekoh6eigh4siesheeda2quai0",
|
||||
"s3AccessKey": "oobaiRus9pah8PhohL1ThaeTa4UVa7gu",
|
||||
"s3Bucket": "s3.example.org/clickhouse-backups",
|
||||
"s3Region": "us-east-1",
|
||||
"s3SecretKey": "ju3eum4dekeich9ahM1te8waeGai0oog",
|
||||
"schedule": "0 2 * * *"
|
||||
},
|
||||
"required": [
|
||||
"cleanupStrategy",
|
||||
"enabled",
|
||||
"resticPassword",
|
||||
"s3AccessKey",
|
||||
"s3Bucket",
|
||||
"s3Region",
|
||||
"s3SecretKey",
|
||||
"schedule"
|
||||
],
|
||||
"properties": {
|
||||
"cleanupStrategy": {
|
||||
"description": "Retention strategy for cleaning up old backups",
|
||||
"type": "string",
|
||||
"default": "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
},
|
||||
"logStorageSize": {
|
||||
"type": "string",
|
||||
"description": "Size of Persistent Volume for logs",
|
||||
"default": "2Gi"
|
||||
"enabled": {
|
||||
"description": "Enable regular backups, default is `false`",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"shards": {
|
||||
"type": "number",
|
||||
"description": "Number of Clickhouse shards",
|
||||
"default": 1
|
||||
"resticPassword": {
|
||||
"description": "Password for Restic backup encryption",
|
||||
"type": "string",
|
||||
"default": "ChaXoveekoh6eigh4siesheeda2quai0"
|
||||
},
|
||||
"s3AccessKey": {
|
||||
"description": "Access key for S3, used for authentication",
|
||||
"type": "string",
|
||||
"default": "oobaiRus9pah8PhohL1ThaeTa4UVa7gu"
|
||||
},
|
||||
"s3Bucket": {
|
||||
"description": "S3 bucket used for storing backups",
|
||||
"type": "string",
|
||||
"default": "s3.example.org/clickhouse-backups"
|
||||
},
|
||||
"s3Region": {
|
||||
"description": "AWS S3 region where backups are stored",
|
||||
"type": "string",
|
||||
"default": "us-east-1"
|
||||
},
|
||||
"s3SecretKey": {
|
||||
"description": "Secret key for S3, used for authentication",
|
||||
"type": "string",
|
||||
"default": "ju3eum4dekeich9ahM1te8waeGai0oog"
|
||||
},
|
||||
"schedule": {
|
||||
"description": "Cron schedule for automated backups",
|
||||
"type": "string",
|
||||
"default": "0 2 * * *"
|
||||
}
|
||||
}
|
||||
},
|
||||
"clickhouseKeeper": {
|
||||
"description": "Clickhouse Keeper configuration",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"enabled": true,
|
||||
"replicas": 3,
|
||||
"resourcesPreset": "micro",
|
||||
"size": "1Gi"
|
||||
},
|
||||
"required": [
|
||||
"resourcesPreset"
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Deploy ClickHouse Keeper for cluster coordination",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"replicas": {
|
||||
"type": "number",
|
||||
"description": "Number of Clickhouse replicas",
|
||||
"default": 2
|
||||
},
|
||||
"storageClass": {
|
||||
"type": "string",
|
||||
"description": "StorageClass used to store the data",
|
||||
"default": ""
|
||||
},
|
||||
"logTTL": {
|
||||
"type": "number",
|
||||
"description": "TTL (expiration time) for query_log and query_thread_log",
|
||||
"default": 15
|
||||
},
|
||||
"backup": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Enable periodic backups",
|
||||
"default": false
|
||||
},
|
||||
"s3Region": {
|
||||
"type": "string",
|
||||
"description": "AWS S3 region where backups are stored",
|
||||
"default": "us-east-1"
|
||||
},
|
||||
"s3Bucket": {
|
||||
"type": "string",
|
||||
"description": "S3 bucket used for storing backups",
|
||||
"default": "s3.example.org/clickhouse-backups"
|
||||
},
|
||||
"schedule": {
|
||||
"type": "string",
|
||||
"description": "Cron schedule for automated backups",
|
||||
"default": "0 2 * * *"
|
||||
},
|
||||
"cleanupStrategy": {
|
||||
"type": "string",
|
||||
"description": "Retention strategy for cleaning up old backups",
|
||||
"default": "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
},
|
||||
"s3AccessKey": {
|
||||
"type": "string",
|
||||
"description": "Access key for S3, used for authentication",
|
||||
"default": "oobaiRus9pah8PhohL1ThaeTa4UVa7gu"
|
||||
},
|
||||
"s3SecretKey": {
|
||||
"type": "string",
|
||||
"description": "Secret key for S3, used for authentication",
|
||||
"default": "ju3eum4dekeich9ahM1te8waeGai0oog"
|
||||
},
|
||||
"resticPassword": {
|
||||
"type": "string",
|
||||
"description": "Password for Restic backup encryption",
|
||||
"default": "ChaXoveekoh6eigh4siesheeda2quai0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"description": "Explicit CPU/memory resource requests and limits for the Clickhouse service",
|
||||
"default": {}
|
||||
"description": "Number of keeper replicas",
|
||||
"type": "integer",
|
||||
"default": 3
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"type": "string",
|
||||
"description": "Use a common resources preset when `resources` is not set explicitly.",
|
||||
"default": "nano"
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge.",
|
||||
"type": "string",
|
||||
"default": "micro",
|
||||
"enum": [
|
||||
"nano",
|
||||
"micro",
|
||||
"small",
|
||||
"medium",
|
||||
"large",
|
||||
"xlarge",
|
||||
"2xlarge"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"default": "1Gi",
|
||||
"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
|
||||
}
|
||||
}
|
||||
},
|
||||
"logStorageSize": {
|
||||
"description": "Size of Persistent Volume for logs",
|
||||
"default": "2Gi",
|
||||
"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
|
||||
},
|
||||
"logTTL": {
|
||||
"description": "TTL (expiration time) for `query_log` and `query_thread_log`",
|
||||
"type": "integer",
|
||||
"default": 15
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of Clickhouse replicas",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each Clickhouse replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU",
|
||||
"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",
|
||||
"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. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"type": "string",
|
||||
"default": "small",
|
||||
"enum": [
|
||||
"nano",
|
||||
"micro",
|
||||
"small",
|
||||
"medium",
|
||||
"large",
|
||||
"xlarge",
|
||||
"2xlarge"
|
||||
]
|
||||
},
|
||||
"shards": {
|
||||
"description": "Number of Clickhouse shards",
|
||||
"type": "integer",
|
||||
"default": 1
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"users": {
|
||||
"description": "Users configuration",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"description": "Password for the user",
|
||||
"type": "string"
|
||||
},
|
||||
"readonly": {
|
||||
"description": "User is `readonly`, default is `false`.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,36 @@
|
||||
## @section Common parameters
|
||||
|
||||
## @param size Size of Persistent Volume for data
|
||||
## @param logStorageSize Size of Persistent Volume for logs
|
||||
## @param shards Number of Clickhouse shards
|
||||
## @param replicas Number of Clickhouse replicas
|
||||
## @param storageClass StorageClass used to store the data
|
||||
## @param logTTL TTL (expiration time) for query_log and query_thread_log
|
||||
##
|
||||
size: 10Gi
|
||||
logStorageSize: 2Gi
|
||||
shards: 1
|
||||
## @param replicas {int} Number of Clickhouse replicas
|
||||
replicas: 2
|
||||
## @param shards {int} Number of Clickhouse shards
|
||||
shards: 1
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each Clickhouse replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU
|
||||
## @field resources.memory {*quantity} Memory
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
resources: {}
|
||||
|
||||
|
||||
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "small"
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
storageClass: ""
|
||||
|
||||
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param logStorageSize {quantity} Size of Persistent Volume for logs
|
||||
logStorageSize: 2Gi
|
||||
## @param logTTL {int} TTL (expiration time) for `query_log` and `query_thread_log`
|
||||
logTTL: 15
|
||||
|
||||
## @section Configuration parameters
|
||||
|
||||
## @param users [object] Users configuration
|
||||
## @param users {map[string]user} Users configuration
|
||||
## @field user.password {*string} Password for the user
|
||||
## @field user.readonly {*bool} User is `readonly`, default is `false`.
|
||||
## Example:
|
||||
## users:
|
||||
## user1:
|
||||
@@ -27,16 +41,18 @@ logTTL: 15
|
||||
##
|
||||
users: {}
|
||||
|
||||
|
||||
## @section Backup parameters
|
||||
|
||||
## @param backup.enabled Enable periodic backups
|
||||
## @param backup.s3Region AWS S3 region where backups are stored
|
||||
## @param backup.s3Bucket S3 bucket used for storing backups
|
||||
## @param backup.schedule Cron schedule for automated backups
|
||||
## @param backup.cleanupStrategy Retention strategy for cleaning up old backups
|
||||
## @param backup.s3AccessKey Access key for S3, used for authentication
|
||||
## @param backup.s3SecretKey Secret key for S3, used for authentication
|
||||
## @param backup.resticPassword Password for Restic backup encryption
|
||||
## @param backup {backup} Backup configuration
|
||||
## @field backup.enabled {bool} Enable regular backups, default is `false`
|
||||
## @field backup.s3Region {string} AWS S3 region where backups are stored
|
||||
## @field backup.s3Bucket {string} S3 bucket used for storing backups
|
||||
## @field backup.schedule {string} Cron schedule for automated backups
|
||||
## @field backup.cleanupStrategy {string} Retention strategy for cleaning up old backups
|
||||
## @field backup.s3AccessKey {string} Access key for S3, used for authentication
|
||||
## @field backup.s3SecretKey {string} Secret key for S3, used for authentication
|
||||
## @field backup.resticPassword {string} Password for Restic backup encryption
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
@@ -47,15 +63,15 @@ backup:
|
||||
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||
resticPassword: ChaXoveekoh6eigh4siesheeda2quai0
|
||||
|
||||
## @param resources Explicit CPU/memory resource requests and limits for the Clickhouse service
|
||||
resources: {}
|
||||
# resources:
|
||||
# limits:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 512Mi
|
||||
|
||||
## @param resourcesPreset Use a common resources preset when `resources` is not set explicitly.
|
||||
resourcesPreset: "nano"
|
||||
## @section Clickhouse Keeper parameters
|
||||
## @param clickhouseKeeper {*clickhouseKeeper} Clickhouse Keeper configuration
|
||||
## @field clickhouseKeeper.enabled {*bool} Deploy ClickHouse Keeper for cluster coordination
|
||||
## @field clickhouseKeeper.size {*quantity} Persistent Volume Claim size, available for application data
|
||||
## @field clickhouseKeeper.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge.
|
||||
## @field clickhouseKeeper.replicas {*int} Number of keeper replicas
|
||||
clickhouseKeeper:
|
||||
enabled: true
|
||||
size: 1Gi
|
||||
resourcesPreset: micro
|
||||
replicas: 3
|
||||
|
||||
@@ -16,10 +16,10 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.7.0
|
||||
version: 1.0.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.24.0"
|
||||
appVersion: 2.4.0
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
include ../../../scripts/package.mk
|
||||
|
||||
generate:
|
||||
readme-generator -v values.yaml -s values.schema.json -r README.md
|
||||
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
|
||||
|
||||
update:
|
||||
tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/FerretDB/FerretDB | awk -F'[/^]' '{sub("^v", "", $$3)} END{print $$3}') && \
|
||||
pgtag=$$(skopeo list-tags docker://ghcr.io/ferretdb/postgres-documentdb | jq -r --arg tag "$$tag" '.Tags[] | select(endswith("ferretdb-" + $$tag))' | sort -V | tail -n1) && \
|
||||
sed -i "s|\(imageName: ghcr.io/ferretdb/postgres-documentdb:\).*|\1$$pgtag|" templates/postgres.yaml && \
|
||||
sed -i "s|\(image: ghcr.io/ferretdb/ferretdb:\).*|\1$$tag|" templates/ferretdb.yaml && \
|
||||
sed -i "s|\(appVersion: \).*|\1$$tag|" Chart.yaml
|
||||
|
||||
@@ -1,37 +1,97 @@
|
||||
# Managed FerretDB Service
|
||||
|
||||
FerretDB is an open source MongoDB alternative.
|
||||
It translates MongoDB wire protocol queries to SQL and can be used as a direct replacement for MongoDB 5.0+.
|
||||
Internally, FerretDB service is backed by Postgres.
|
||||
|
||||
## Parameters
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `external` | Enable external access from outside the cluster | `false` |
|
||||
| `size` | Persistent Volume size | `10Gi` |
|
||||
| `replicas` | Number of Postgres replicas | `2` |
|
||||
| `storageClass` | StorageClass used to store the data | `""` |
|
||||
| `quorum.minSyncReplicas` | Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed. | `0` |
|
||||
| `quorum.maxSyncReplicas` | Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the number of instances). | `0` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of replicas | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each FerretDB replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `{}` |
|
||||
| `resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `micro` |
|
||||
| `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` |
|
||||
|
||||
### Configuration parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------- | ------------------- | ----- |
|
||||
| `users` | Users configuration | `{}` |
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------- |
|
||||
| `quorum` | Configuration for the quorum-based synchronous replication | `object` | `{}` |
|
||||
| `quorum.minSyncReplicas` | Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed | `int` | `0` |
|
||||
| `quorum.maxSyncReplicas` | Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the total number of replicas) | `int` | `0` |
|
||||
| `quorum.minSyncReplicas` | Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed | `int` | `0` |
|
||||
| `quorum.maxSyncReplicas` | Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the total number of replicas) | `int` | `0` |
|
||||
| `users` | Users configuration | `map[string]object` | `{...}` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
|
||||
|
||||
### Backup parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
|
||||
| `backup.enabled` | Enable pereiodic backups | `false` |
|
||||
| `backup.s3Region` | The AWS S3 region where backups are stored | `us-east-1` |
|
||||
| `backup.s3Bucket` | The S3 bucket used for storing backups | `s3.example.org/postgres-backups` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `0 2 * * *` |
|
||||
| `backup.cleanupStrategy` | The strategy for cleaning up old backups | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` |
|
||||
| `backup.s3AccessKey` | The access key for S3, used for authentication | `oobaiRus9pah8PhohL1ThaeTa4UVa7gu` |
|
||||
| `backup.s3SecretKey` | The secret key for S3, used for authentication | `ju3eum4dekeich9ahM1te8waeGai0oog` |
|
||||
| `backup.resticPassword` | The password for Restic backup encryption | `ChaXoveekoh6eigh4siesheeda2quai0` |
|
||||
| `resources` | Resources | `{}` |
|
||||
| `resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `nano` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ---------------------------------------------------------- | -------- | ----------------------------------- |
|
||||
| `backup` | Backup configuration | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups, default is `false`. | `bool` | `false` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `string` | `0 2 * * * *` |
|
||||
| `backup.retentionPolicy` | Retention policy | `string` | `30d` |
|
||||
| `backup.endpointURL` | S3 Endpoint used to upload data to the cloud | `string` | `http://minio-gateway-service:9000` |
|
||||
| `backup.destinationPath` | Path to store the backup (i.e. s3://bucket/path/to/folder) | `string` | `s3://bucket/path/to/folder/` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `string` | `oobaiRus9pah8PhohL1ThaeTa4UVa7gu` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `string` | `ju3eum4dekeich9ahM1te8waeGai0oog` |
|
||||
| `backup.enabled` | Enable regular backups, default is `false`. | `bool` | `false` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `string` | `0 2 * * * *` |
|
||||
| `backup.retentionPolicy` | Retention policy | `string` | `30d` |
|
||||
| `backup.endpointURL` | S3 Endpoint used to upload data to the cloud | `string` | `http://minio-gateway-service:9000` |
|
||||
| `backup.destinationPath` | Path to store the backup (i.e. s3://bucket/path/to/folder) | `string` | `s3://bucket/path/to/folder/` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `string` | `oobaiRus9pah8PhohL1ThaeTa4UVa7gu` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `string` | `ju3eum4dekeich9ahM1te8waeGai0oog` |
|
||||
|
||||
|
||||
### Bootstrap (recovery) parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
|
||||
| `bootstrap` | Bootstrap (recovery) configuration | `object` | `{}` |
|
||||
| `bootstrap.enabled` | Restore database cluster from a backup | `*bool` | `false` |
|
||||
| `bootstrap.recoveryTime` | Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest. | `*string` | `""` |
|
||||
| `bootstrap.oldName` | Name of database cluster before deleting | `*string` | `""` |
|
||||
| `bootstrap.enabled` | Restore database cluster from a backup | `*bool` | `false` |
|
||||
| `bootstrap.recoveryTime` | Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest. | `*string` | `""` |
|
||||
| `bootstrap.oldName` | Name of database cluster before deleting | `*string` | `""` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
### resources and resourcesPreset
|
||||
|
||||
`resources` sets explicit CPU and memory configurations for each replica.
|
||||
When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
cpu: 4000m
|
||||
memory: 4Gi
|
||||
```
|
||||
|
||||
`resourcesPreset` sets named CPU and memory configurations for each replica.
|
||||
This setting is ignored if the corresponding `resources` value is set.
|
||||
|
||||
| Preset name | CPU | memory |
|
||||
|-------------|--------|---------|
|
||||
| `nano` | `250m` | `128Mi` |
|
||||
| `micro` | `500m` | `256Mi` |
|
||||
| `small` | `1` | `512Mi` |
|
||||
| `medium` | `1` | `1Gi` |
|
||||
| `large` | `2` | `2Gi` |
|
||||
| `xlarge` | `4` | `4Gi` |
|
||||
| `2xlarge` | `8` | `8Gi` |
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
ghcr.io/cozystack/cozystack/postgres-backup:0.14.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f
|
||||
@@ -1,99 +0,0 @@
|
||||
{{- if .Values.backup.enabled }}
|
||||
{{ $image := .Files.Get "images/backup.json" | fromJson }}
|
||||
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-backup
|
||||
spec:
|
||||
schedule: "{{ .Values.backup.schedule }}"
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 3
|
||||
jobTemplate:
|
||||
spec:
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/backup-script.yaml") . | sha256sum }}
|
||||
checksum/secret: {{ include (print $.Template.BasePath "/backup-secret.yaml") . | sha256sum }}
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: pgdump
|
||||
image: "{{ $.Files.Get "images/postgres-backup.tag" | trim }}"
|
||||
command:
|
||||
- /bin/sh
|
||||
- /scripts/backup.sh
|
||||
env:
|
||||
- name: REPO_PREFIX
|
||||
value: {{ required "s3Bucket is not specified!" .Values.backup.s3Bucket | quote }}
|
||||
- name: CLEANUP_STRATEGY
|
||||
value: {{ required "cleanupStrategy is not specified!" .Values.backup.cleanupStrategy | quote }}
|
||||
- name: PGUSER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-postgres-superuser
|
||||
key: username
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-postgres-superuser
|
||||
key: password
|
||||
- name: PGHOST
|
||||
value: {{ .Release.Name }}-postgres-rw
|
||||
- name: PGPORT
|
||||
value: "5432"
|
||||
- name: PGDATABASE
|
||||
value: postgres
|
||||
- name: AWS_ACCESS_KEY_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-backup
|
||||
key: s3AccessKey
|
||||
- name: AWS_SECRET_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-backup
|
||||
key: s3SecretKey
|
||||
- name: AWS_DEFAULT_REGION
|
||||
value: {{ .Values.backup.s3Region }}
|
||||
- name: RESTIC_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-backup
|
||||
key: resticPassword
|
||||
volumeMounts:
|
||||
- mountPath: /scripts
|
||||
name: scripts
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /.cache
|
||||
name: cache
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
volumes:
|
||||
- name: scripts
|
||||
secret:
|
||||
secretName: {{ .Release.Name }}-backup-script
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: cache
|
||||
emptyDir: {}
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 9000
|
||||
runAsGroup: 9000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
{{- end }}
|
||||
@@ -1,50 +0,0 @@
|
||||
{{- if .Values.backup.enabled }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-backup-script
|
||||
stringData:
|
||||
backup.sh: |
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
JOB_ID="job-$(uuidgen|cut -f1 -d-)"
|
||||
DB_LIST=$(psql -Atq -c 'SELECT datname FROM pg_catalog.pg_database;' | grep -v '^\(postgres\|app\|template.*\)$')
|
||||
echo DB_LIST=$(echo "$DB_LIST" | shuf) # shuffle list
|
||||
echo "Job ID: $JOB_ID"
|
||||
echo "Target repo: $REPO_PREFIX"
|
||||
echo "Cleanup strategy: $CLEANUP_STRATEGY"
|
||||
echo "Start backup for:"
|
||||
echo "$DB_LIST"
|
||||
echo
|
||||
echo "Backup started at `date +%Y-%m-%d\ %H:%M:%S`"
|
||||
for db in $DB_LIST; do
|
||||
(
|
||||
set -x
|
||||
restic -r "s3:${REPO_PREFIX}/$db" cat config >/dev/null 2>&1 || \
|
||||
restic -r "s3:${REPO_PREFIX}/$db" init --repository-version 2
|
||||
restic -r "s3:${REPO_PREFIX}/$db" unlock --remove-all >/dev/null 2>&1 || true # no locks, k8s takes care of it
|
||||
pg_dump -Z0 -Ft -d "$db" | \
|
||||
restic -r "s3:${REPO_PREFIX}/$db" backup --tag "$JOB_ID" --stdin --stdin-filename dump.tar
|
||||
restic -r "s3:${REPO_PREFIX}/$db" tag --tag "$JOB_ID" --set "completed"
|
||||
)
|
||||
done
|
||||
echo "Backup finished at `date +%Y-%m-%d\ %H:%M:%S`"
|
||||
|
||||
echo
|
||||
echo "Run cleanup:"
|
||||
echo
|
||||
|
||||
echo "Cleanup started at `date +%Y-%m-%d\ %H:%M:%S`"
|
||||
for db in $DB_LIST; do
|
||||
(
|
||||
set -x
|
||||
restic forget -r "s3:${REPO_PREFIX}/$db" --group-by=tags --keep-tag "completed" # keep completed snapshots only
|
||||
restic forget -r "s3:${REPO_PREFIX}/$db" --group-by=tags $CLEANUP_STRATEGY
|
||||
restic prune -r "s3:${REPO_PREFIX}/$db"
|
||||
)
|
||||
done
|
||||
echo "Cleanup finished at `date +%Y-%m-%d\ %H:%M:%S`"
|
||||
{{- end }}
|
||||
@@ -1,11 +0,0 @@
|
||||
{{- if .Values.backup.enabled }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-backup
|
||||
stringData:
|
||||
s3AccessKey: {{ required "s3AccessKey is not specified!" .Values.backup.s3AccessKey }}
|
||||
s3SecretKey: {{ required "s3SecretKey is not specified!" .Values.backup.s3SecretKey }}
|
||||
resticPassword: {{ required "resticPassword is not specified!" .Values.backup.resticPassword }}
|
||||
{{- end }}
|
||||
12
packages/apps/ferretdb/templates/backup.yaml
Normal file
12
packages/apps/ferretdb/templates/backup.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
{{- if .Values.backup.enabled }}
|
||||
---
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: ScheduledBackup
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-postgres
|
||||
spec:
|
||||
schedule: {{ .Values.backup.schedule | quote }}
|
||||
backupOwnerReference: self
|
||||
cluster:
|
||||
name: {{ .Release.Name }}-postgres
|
||||
{{- end }}
|
||||
@@ -8,7 +8,9 @@ spec:
|
||||
type: {{ ternary "LoadBalancer" "ClusterIP" .Values.external }}
|
||||
{{- if .Values.external }}
|
||||
externalTrafficPolicy: Local
|
||||
{{- if (include "cozy-lib.network.disableLoadBalancerNodePorts" $ | fromYaml) }}
|
||||
allocateLoadBalancerNodePorts: false
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: ferretdb
|
||||
|
||||
@@ -16,12 +16,14 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: ferretdb
|
||||
image: ghcr.io/ferretdb/ferretdb:1.24.0
|
||||
image: ghcr.io/ferretdb/ferretdb:2.4.0
|
||||
ports:
|
||||
- containerPort: 27017
|
||||
env:
|
||||
- name: FERRETDB_POSTGRESQL_URL
|
||||
- name: POSTGRESQL_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-postgres-app
|
||||
key: uri
|
||||
name: {{ .Release.Name }}-postgres-superuser
|
||||
key: password
|
||||
- name: FERRETDB_POSTGRESQL_URL
|
||||
value: "postgresql://postgres:$(POSTGRESQL_PASSWORD)@{{ .Release.Name }}-postgres-rw:5432/postgres"
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-init-job
|
||||
annotations:
|
||||
"helm.sh/hook": post-install,post-upgrade
|
||||
"helm.sh/hook-weight": "-5"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-init-job
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/init-script.yaml") . | sha256sum }}
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: postgres
|
||||
image: ghcr.io/cloudnative-pg/postgresql:15.3
|
||||
command:
|
||||
- bash
|
||||
- /scripts/init.sh
|
||||
env:
|
||||
- name: PGUSER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-postgres-superuser
|
||||
key: username
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-postgres-superuser
|
||||
key: password
|
||||
- name: PGHOST
|
||||
value: {{ .Release.Name }}-postgres-rw
|
||||
- name: PGPORT
|
||||
value: "5432"
|
||||
- name: PGDATABASE
|
||||
value: postgres
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
volumeMounts:
|
||||
- mountPath: /etc/secret
|
||||
name: secret
|
||||
- mountPath: /scripts
|
||||
name: scripts
|
||||
securityContext:
|
||||
fsGroup: 26
|
||||
runAsGroup: 26
|
||||
runAsNonRoot: true
|
||||
runAsUser: 26
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
volumes:
|
||||
- name: secret
|
||||
secret:
|
||||
secretName: {{ .Release.Name }}-postgres-superuser
|
||||
- name: scripts
|
||||
secret:
|
||||
secretName: {{ .Release.Name }}-init-script
|
||||
@@ -1,131 +0,0 @@
|
||||
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }}
|
||||
{{- $passwords := dict }}
|
||||
|
||||
{{- with (index $existingSecret "data") }}
|
||||
{{- range $k, $v := . }}
|
||||
{{- $_ := set $passwords $k (b64dec $v) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $user, $u := .Values.users }}
|
||||
{{- if $u.password }}
|
||||
{{- $_ := set $passwords $user $u.password }}
|
||||
{{- else if not (index $passwords $user) }}
|
||||
{{- $_ := set $passwords $user (randAlphaNum 16) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.users }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-credentials
|
||||
stringData:
|
||||
{{- range $user, $u := .Values.users }}
|
||||
{{ quote $user }}: {{ quote (index $passwords $user) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-init-script
|
||||
stringData:
|
||||
init.sh: |
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
until pg_isready ; do sleep 5; done
|
||||
|
||||
echo "== create users"
|
||||
{{- if .Values.users }}
|
||||
psql -v ON_ERROR_STOP=1 <<\EOT
|
||||
{{- range $user, $u := .Values.users }}
|
||||
SELECT 'CREATE ROLE {{ $user }} LOGIN INHERIT;'
|
||||
WHERE NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '{{ $user }}')\gexec
|
||||
ALTER ROLE {{ $user }} WITH PASSWORD '{{ index $passwords $user }}' LOGIN INHERIT {{ ternary "REPLICATION" "NOREPLICATION" (default false $u.replication) }};
|
||||
COMMENT ON ROLE {{ $user }} IS 'user managed by helm';
|
||||
{{- end }}
|
||||
EOT
|
||||
{{- end }}
|
||||
|
||||
echo "== delete users"
|
||||
MANAGED_USERS=$(echo '\du+' | psql | awk -F'|' '$4 == " user managed by helm" {print $1}' | awk NF=NF RS= OFS=' ')
|
||||
DEFINED_USERS="{{ join " " (keys .Values.users) }}"
|
||||
DELETE_USERS=$(for user in $MANAGED_USERS; do case " $DEFINED_USERS " in *" $user "*) :;; *) echo $user;; esac; done)
|
||||
|
||||
echo "users to delete: $DELETE_USERS"
|
||||
for user in $DELETE_USERS; do
|
||||
# https://stackoverflow.com/a/51257346/2931267
|
||||
psql -v ON_ERROR_STOP=1 --echo-all <<EOT
|
||||
REASSIGN OWNED BY $user TO postgres;
|
||||
DROP OWNED BY $user;
|
||||
DROP USER $user;
|
||||
EOT
|
||||
done
|
||||
|
||||
echo "== create roles"
|
||||
psql -v ON_ERROR_STOP=1 --echo-all <<\EOT
|
||||
SELECT 'CREATE ROLE app_admin NOINHERIT;'
|
||||
WHERE NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'app_admin')\gexec
|
||||
COMMENT ON ROLE app_admin IS 'role managed by helm';
|
||||
EOT
|
||||
|
||||
echo "== grant privileges on databases to roles"
|
||||
psql -v ON_ERROR_STOP=1 --echo-all -d "app" <<\EOT
|
||||
ALTER DATABASE app OWNER TO app_admin;
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
schema_record record;
|
||||
BEGIN
|
||||
-- Loop over all schemas
|
||||
FOR schema_record IN SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('pg_catalog', 'information_schema') LOOP
|
||||
-- Changing Schema Ownership
|
||||
EXECUTE format('ALTER SCHEMA %I OWNER TO %I', schema_record.schema_name, 'app_admin');
|
||||
|
||||
-- Add rights for the admin role
|
||||
EXECUTE format('GRANT ALL ON SCHEMA %I TO %I', schema_record.schema_name, 'app_admin');
|
||||
EXECUTE format('GRANT ALL ON ALL TABLES IN SCHEMA %I TO %I', schema_record.schema_name, 'app_admin');
|
||||
EXECUTE format('GRANT ALL ON ALL SEQUENCES IN SCHEMA %I TO %I', schema_record.schema_name, 'app_admin');
|
||||
EXECUTE format('GRANT ALL ON ALL FUNCTIONS IN SCHEMA %I TO %I', schema_record.schema_name, 'app_admin');
|
||||
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON TABLES TO %I', schema_record.schema_name, 'app_admin');
|
||||
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON SEQUENCES TO %I', schema_record.schema_name, 'app_admin');
|
||||
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON FUNCTIONS TO %I', schema_record.schema_name, 'app_admin');
|
||||
END LOOP;
|
||||
END$$;
|
||||
EOT
|
||||
|
||||
echo "== setup event trigger for schema creation"
|
||||
psql -v ON_ERROR_STOP=1 --echo-all -d "app" <<\EOT
|
||||
CREATE OR REPLACE FUNCTION auto_grant_schema_privileges()
|
||||
RETURNS event_trigger LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
obj record;
|
||||
BEGIN
|
||||
FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag = 'CREATE SCHEMA' LOOP
|
||||
-- Set owner for schema
|
||||
EXECUTE format('ALTER SCHEMA %I OWNER TO %I', obj.object_identity, 'app_admin');
|
||||
|
||||
-- Set privileges for admin role
|
||||
EXECUTE format('GRANT ALL ON SCHEMA %I TO %I', obj.object_identity, 'app_admin');
|
||||
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON TABLES TO %I', obj.object_identity, 'app_admin');
|
||||
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON SEQUENCES TO %I', obj.object_identity, 'app_admin');
|
||||
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON FUNCTIONS TO %I', obj.object_identity, 'app_admin');
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
DROP EVENT TRIGGER IF EXISTS trigger_auto_grant;
|
||||
CREATE EVENT TRIGGER trigger_auto_grant ON ddl_command_end
|
||||
WHEN TAG IN ('CREATE SCHEMA')
|
||||
EXECUTE PROCEDURE auto_grant_schema_privileges();
|
||||
EOT
|
||||
|
||||
echo "== assign roles to users"
|
||||
psql -v ON_ERROR_STOP=1 --echo-all <<\EOT
|
||||
GRANT app_admin TO app;
|
||||
{{- range $user, $u := $.Values.users }}
|
||||
GRANT app_admin TO {{ $user }};
|
||||
{{- end }}
|
||||
EOT
|
||||
@@ -5,6 +5,50 @@ metadata:
|
||||
name: {{ .Release.Name }}-postgres
|
||||
spec:
|
||||
instances: {{ .Values.replicas }}
|
||||
{{- if .Values.backup.enabled }}
|
||||
backup:
|
||||
barmanObjectStore:
|
||||
destinationPath: {{ .Values.backup.destinationPath }}
|
||||
endpointURL: {{ .Values.backup.endpointURL }}
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: {{ .Release.Name }}-s3-creds
|
||||
key: AWS_ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: {{ .Release.Name }}-s3-creds
|
||||
key: AWS_SECRET_ACCESS_KEY
|
||||
retentionPolicy: {{ .Values.backup.retentionPolicy }}
|
||||
{{- end }}
|
||||
|
||||
bootstrap:
|
||||
initdb:
|
||||
postInitSQL:
|
||||
- 'CREATE EXTENSION IF NOT EXISTS documentdb CASCADE;'
|
||||
{{- if .Values.bootstrap.enabled }}
|
||||
recovery:
|
||||
source: {{ .Values.bootstrap.oldName }}
|
||||
{{- if .Values.bootstrap.recoveryTime }}
|
||||
recoveryTarget:
|
||||
targetTime: {{ .Values.bootstrap.recoveryTime }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.bootstrap.enabled }}
|
||||
externalClusters:
|
||||
- name: {{ .Values.bootstrap.oldName }}
|
||||
barmanObjectStore:
|
||||
destinationPath: {{ .Values.backup.destinationPath }}
|
||||
endpointURL: {{ .Values.backup.endpointURL }}
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: {{ .Release.Name }}-s3-creds
|
||||
key: AWS_ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: {{ .Release.Name }}-s3-creds
|
||||
key: AWS_SECRET_ACCESS_KEY
|
||||
{{- end }}
|
||||
imageName: ghcr.io/ferretdb/postgres-documentdb:17-0.105.0-ferretdb-2.4.0
|
||||
postgresUID: 999
|
||||
postgresGID: 999
|
||||
enableSuperuserAccess: true
|
||||
{{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }}
|
||||
{{- if $configMap }}
|
||||
@@ -18,14 +62,21 @@ spec:
|
||||
{{- end }}
|
||||
minSyncReplicas: {{ .Values.quorum.minSyncReplicas }}
|
||||
maxSyncReplicas: {{ .Values.quorum.maxSyncReplicas }}
|
||||
{{- if .Values.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.resources $) | nindent 4 }}
|
||||
{{- else if ne .Values.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.resourcesPreset $) | nindent 4 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 4 }}
|
||||
monitoring:
|
||||
enablePodMonitor: true
|
||||
|
||||
postgresql:
|
||||
shared_preload_libraries:
|
||||
- pg_cron
|
||||
- pg_documentdb_core
|
||||
- pg_documentdb
|
||||
parameters:
|
||||
cron.database_name: 'postgres'
|
||||
pg_hba:
|
||||
- host postgres postgres 127.0.0.1/32 trust
|
||||
- host postgres postgres ::1/128 trust
|
||||
|
||||
storage:
|
||||
size: {{ required ".Values.size is required" .Values.size }}
|
||||
{{- with .Values.storageClass }}
|
||||
@@ -46,8 +97,6 @@ spec:
|
||||
passwordSecret:
|
||||
name: {{ printf "%s-user-%s" $.Release.Name $user }}
|
||||
login: true
|
||||
inRoles:
|
||||
- app
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
@@ -1,96 +1,202 @@
|
||||
{
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external": {
|
||||
"type": "boolean",
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"default": false
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup": {
|
||||
"description": "Backup configuration",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"destinationPath": "s3://bucket/path/to/folder/",
|
||||
"enabled": false,
|
||||
"endpointURL": "http://minio-gateway-service:9000",
|
||||
"retentionPolicy": "30d",
|
||||
"s3AccessKey": "oobaiRus9pah8PhohL1ThaeTa4UVa7gu",
|
||||
"s3SecretKey": "ju3eum4dekeich9ahM1te8waeGai0oog",
|
||||
"schedule": "0 2 * * * *"
|
||||
},
|
||||
"required": [
|
||||
"destinationPath",
|
||||
"enabled",
|
||||
"endpointURL",
|
||||
"retentionPolicy",
|
||||
"s3AccessKey",
|
||||
"s3SecretKey",
|
||||
"schedule"
|
||||
],
|
||||
"properties": {
|
||||
"destinationPath": {
|
||||
"description": "Path to store the backup (i.e. s3://bucket/path/to/folder)",
|
||||
"type": "string",
|
||||
"default": "s3://bucket/path/to/folder/"
|
||||
},
|
||||
"size": {
|
||||
"type": "string",
|
||||
"description": "Persistent Volume size",
|
||||
"default": "10Gi"
|
||||
"enabled": {
|
||||
"description": "Enable regular backups, default is `false`.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"replicas": {
|
||||
"type": "number",
|
||||
"description": "Number of Postgres replicas",
|
||||
"default": 2
|
||||
"endpointURL": {
|
||||
"description": "S3 Endpoint used to upload data to the cloud",
|
||||
"type": "string",
|
||||
"default": "http://minio-gateway-service:9000"
|
||||
},
|
||||
"storageClass": {
|
||||
"type": "string",
|
||||
"description": "StorageClass used to store the data",
|
||||
"default": ""
|
||||
"retentionPolicy": {
|
||||
"description": "Retention policy",
|
||||
"type": "string",
|
||||
"default": "30d"
|
||||
},
|
||||
"quorum": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"minSyncReplicas": {
|
||||
"type": "number",
|
||||
"description": "Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed.",
|
||||
"default": 0
|
||||
},
|
||||
"maxSyncReplicas": {
|
||||
"type": "number",
|
||||
"description": "Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the number of instances).",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
"s3AccessKey": {
|
||||
"description": "Access key for S3, used for authentication",
|
||||
"type": "string",
|
||||
"default": "oobaiRus9pah8PhohL1ThaeTa4UVa7gu"
|
||||
},
|
||||
"backup": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Enable pereiodic backups",
|
||||
"default": false
|
||||
},
|
||||
"s3Region": {
|
||||
"type": "string",
|
||||
"description": "The AWS S3 region where backups are stored",
|
||||
"default": "us-east-1"
|
||||
},
|
||||
"s3Bucket": {
|
||||
"type": "string",
|
||||
"description": "The S3 bucket used for storing backups",
|
||||
"default": "s3.example.org/postgres-backups"
|
||||
},
|
||||
"schedule": {
|
||||
"type": "string",
|
||||
"description": "Cron schedule for automated backups",
|
||||
"default": "0 2 * * *"
|
||||
},
|
||||
"cleanupStrategy": {
|
||||
"type": "string",
|
||||
"description": "The strategy for cleaning up old backups",
|
||||
"default": "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
},
|
||||
"s3AccessKey": {
|
||||
"type": "string",
|
||||
"description": "The access key for S3, used for authentication",
|
||||
"default": "oobaiRus9pah8PhohL1ThaeTa4UVa7gu"
|
||||
},
|
||||
"s3SecretKey": {
|
||||
"type": "string",
|
||||
"description": "The secret key for S3, used for authentication",
|
||||
"default": "ju3eum4dekeich9ahM1te8waeGai0oog"
|
||||
},
|
||||
"resticPassword": {
|
||||
"type": "string",
|
||||
"description": "The password for Restic backup encryption",
|
||||
"default": "ChaXoveekoh6eigh4siesheeda2quai0"
|
||||
}
|
||||
}
|
||||
"s3SecretKey": {
|
||||
"description": "Secret key for S3, used for authentication",
|
||||
"type": "string",
|
||||
"default": "ju3eum4dekeich9ahM1te8waeGai0oog"
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"description": "Resources",
|
||||
"default": {}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"type": "string",
|
||||
"description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).",
|
||||
"default": "nano"
|
||||
"schedule": {
|
||||
"description": "Cron schedule for automated backups",
|
||||
"type": "string",
|
||||
"default": "0 2 * * * *"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bootstrap": {
|
||||
"description": "Bootstrap (recovery) configuration",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"enabled": false,
|
||||
"oldName": "",
|
||||
"recoveryTime": ""
|
||||
},
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Restore database cluster from a backup",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"oldName": {
|
||||
"description": "Name of database cluster before deleting",
|
||||
"type": "string"
|
||||
},
|
||||
"recoveryTime": {
|
||||
"description": "Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"quorum": {
|
||||
"description": "Configuration for the quorum-based synchronous replication",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"maxSyncReplicas": 0,
|
||||
"minSyncReplicas": 0
|
||||
},
|
||||
"required": [
|
||||
"maxSyncReplicas",
|
||||
"minSyncReplicas"
|
||||
],
|
||||
"properties": {
|
||||
"maxSyncReplicas": {
|
||||
"description": "Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the total number of replicas)",
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"minSyncReplicas": {
|
||||
"description": "Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed",
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of replicas",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each FerretDB replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU",
|
||||
"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",
|
||||
"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. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"type": "string",
|
||||
"default": "micro",
|
||||
"enum": [
|
||||
"nano",
|
||||
"micro",
|
||||
"small",
|
||||
"medium",
|
||||
"large",
|
||||
"xlarge",
|
||||
"2xlarge"
|
||||
]
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"users": {
|
||||
"description": "Users configuration",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"description": "Password for the user",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,35 @@
|
||||
## @section Common parameters
|
||||
|
||||
## @param external Enable external access from outside the cluster
|
||||
## @param size Persistent Volume size
|
||||
## @param replicas Number of Postgres replicas
|
||||
## @param storageClass StorageClass used to store the data
|
||||
##
|
||||
external: false
|
||||
size: 10Gi
|
||||
## @param replicas {int} Number of replicas
|
||||
replicas: 2
|
||||
storageClass: ""
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each FerretDB replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU
|
||||
## @field resources.memory {*quantity} Memory
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
resources: {}
|
||||
|
||||
## Configuration for the quorum-based synchronous replication
|
||||
## @param quorum.minSyncReplicas Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed.
|
||||
## @param quorum.maxSyncReplicas Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the number of instances).
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "micro"
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
storageClass: ""
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
external: false
|
||||
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param quorum {quorum} Configuration for the quorum-based synchronous replication
|
||||
## @field quorum.minSyncReplicas {int} Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed
|
||||
## @field quorum.maxSyncReplicas {int} Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the total number of replicas)
|
||||
quorum:
|
||||
minSyncReplicas: 0
|
||||
maxSyncReplicas: 0
|
||||
|
||||
## @section Configuration parameters
|
||||
|
||||
## @param users [object] Users configuration
|
||||
## @param users {map[string]user} Users configuration
|
||||
## @field user.password {*string} Password for the user
|
||||
## Example:
|
||||
## users:
|
||||
## user1:
|
||||
@@ -29,35 +39,40 @@ quorum:
|
||||
##
|
||||
users: {}
|
||||
|
||||
## @section Backup parameters
|
||||
|
||||
## @param backup.enabled Enable pereiodic backups
|
||||
## @param backup.s3Region The AWS S3 region where backups are stored
|
||||
## @param backup.s3Bucket The S3 bucket used for storing backups
|
||||
## @param backup.schedule Cron schedule for automated backups
|
||||
## @param backup.cleanupStrategy The strategy for cleaning up old backups
|
||||
## @param backup.s3AccessKey The access key for S3, used for authentication
|
||||
## @param backup.s3SecretKey The secret key for S3, used for authentication
|
||||
## @param backup.resticPassword The password for Restic backup encryption
|
||||
|
||||
## @section Backup parameters
|
||||
##
|
||||
|
||||
## @param backup {backup} Backup configuration
|
||||
## @field backup.enabled {bool} Enable regular backups, default is `false`.
|
||||
## @field backup.schedule {string} Cron schedule for automated backups
|
||||
## @field backup.retentionPolicy {string} Retention policy
|
||||
## @field backup.endpointURL {string} S3 Endpoint used to upload data to the cloud
|
||||
## @field backup.destinationPath {string} Path to store the backup (i.e. s3://bucket/path/to/folder)
|
||||
## @field backup.s3AccessKey {string} Access key for S3, used for authentication
|
||||
## @field backup.s3SecretKey {string} Secret key for S3, used for authentication
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
s3Bucket: s3.example.org/postgres-backups
|
||||
schedule: "0 2 * * *"
|
||||
cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
schedule: "0 2 * * * *"
|
||||
retentionPolicy: 30d
|
||||
endpointURL: http://minio-gateway-service:9000
|
||||
destinationPath: s3://bucket/path/to/folder/
|
||||
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
|
||||
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
|
||||
resticPassword: ChaXoveekoh6eigh4siesheeda2quai0
|
||||
|
||||
## @param resources Resources
|
||||
resources: {}
|
||||
# resources:
|
||||
# limits:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 512Mi
|
||||
|
||||
## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).
|
||||
resourcesPreset: "nano"
|
||||
|
||||
## @section Bootstrap (recovery) parameters
|
||||
##
|
||||
## @param bootstrap {bootstrap} Bootstrap (recovery) configuration
|
||||
## @field bootstrap.enabled {*bool} Restore database cluster from a backup
|
||||
## @field bootstrap.recoveryTime {*string} Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest.
|
||||
## @field bootstrap.oldName {*string} Name of database cluster before deleting
|
||||
##
|
||||
bootstrap:
|
||||
enabled: false
|
||||
# example: 2020-11-26 15:22:00.00000+00
|
||||
recoveryTime: ""
|
||||
oldName: ""
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.5.1
|
||||
version: 0.6.1
|
||||
|
||||
# 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
|
||||
|
||||
@@ -22,7 +22,7 @@ image-nginx:
|
||||
rm -f images/nginx-cache.json
|
||||
|
||||
generate:
|
||||
readme-generator -v values.yaml -s values.schema.json -r README.md
|
||||
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
|
||||
|
||||
update:
|
||||
tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/chrislim2888/IP2Location-C-Library | awk -F'[/^]' 'END{print $$3}') && \
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Managed Nginx Caching Service
|
||||
# Managed Nginx-based HTTP Cache Service
|
||||
|
||||
The Nginx Caching Service is designed to optimize web traffic and enhance web application performance. This service combines custom-built Nginx instances with HAproxy for efficient caching and load balancing.
|
||||
The Nginx-based HTTP caching service is designed to optimize web traffic and enhance web application performance.
|
||||
This service combines custom-built Nginx instances with HAProxy for efficient caching and load balancing.
|
||||
|
||||
## Deployment infromation
|
||||
## Deployment information
|
||||
|
||||
The Nginx instances include the following modules and features:
|
||||
|
||||
@@ -53,27 +54,105 @@ The deployment architecture is illustrated in the diagram below:
|
||||
|
||||
## Known issues
|
||||
|
||||
VTS module shows wrong upstream resonse time
|
||||
- https://github.com/vozlt/nginx-module-vts/issues/198
|
||||
- VTS module shows wrong upstream response time, [github.com/vozlt/nginx-module-vts#198](https://github.com/vozlt/nginx-module-vts/issues/198)
|
||||
|
||||
## Parameters
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `external` | Enable external access from outside the cluster | `false` |
|
||||
| `size` | Persistent Volume size | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `""` |
|
||||
| `haproxy.replicas` | Number of HAProxy replicas | `2` |
|
||||
| `nginx.replicas` | Number of Nginx replicas | `2` |
|
||||
| `haproxy.resources` | Resources | `{}` |
|
||||
| `haproxy.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `nano` |
|
||||
| `nginx.resources` | Resources | `{}` |
|
||||
| `nginx.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `nano` |
|
||||
| Name | Description | Type | Value |
|
||||
| -------------- | ------------------------------------------------------------ | ---------- | ------- |
|
||||
| `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` |
|
||||
|
||||
### Configuration parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ----------- | ----------------------- | ----- |
|
||||
| `endpoints` | Endpoints configuration | `[]` |
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ----------- | ----------------------------------------------- | ---------- | ----- |
|
||||
| `endpoints` | Endpoints configuration, as a list of <ip:port> | `[]string` | `[]` |
|
||||
|
||||
|
||||
### HAProxy parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------ |
|
||||
| `haproxy` | HAProxy configuration | `object` | `{}` |
|
||||
| `haproxy.replicas` | Number of HAProxy replicas | `int` | `2` |
|
||||
| `haproxy.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `haproxy.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `haproxy.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `haproxy.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `haproxy.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `haproxy.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| `haproxy.replicas` | Number of HAProxy replicas | `int` | `2` |
|
||||
| `haproxy.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `haproxy.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `haproxy.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `haproxy.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `haproxy.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `haproxy.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
|
||||
|
||||
### Nginx parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------ |
|
||||
| `nginx` | Nginx configuration | `object` | `{}` |
|
||||
| `nginx.replicas` | Number of Nginx replicas | `int` | `2` |
|
||||
| `nginx.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `nginx.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `nginx.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `nginx.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `nginx.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `nginx.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| `nginx.replicas` | Number of Nginx replicas | `int` | `2` |
|
||||
| `nginx.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `nginx.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `nginx.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `nginx.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `nginx.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `nginx.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
### resources and resourcesPreset
|
||||
|
||||
`resources` sets explicit CPU and memory configurations for each replica.
|
||||
When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
cpu: 4000m
|
||||
memory: 4Gi
|
||||
```
|
||||
|
||||
`resourcesPreset` sets named CPU and memory configurations for each replica.
|
||||
This setting is ignored if the corresponding `resources` value is set.
|
||||
|
||||
| Preset name | CPU | memory |
|
||||
|-------------|--------|---------|
|
||||
| `nano` | `250m` | `128Mi` |
|
||||
| `micro` | `500m` | `256Mi` |
|
||||
| `small` | `1` | `512Mi` |
|
||||
| `medium` | `1` | `1Gi` |
|
||||
| `large` | `2` | `2Gi` |
|
||||
| `xlarge` | `4` | `4Gi` |
|
||||
| `2xlarge` | `8` | `8Gi` |
|
||||
|
||||
|
||||
### endpoints
|
||||
|
||||
`endpoints` is a flat list of IP addresses:
|
||||
|
||||
```yaml
|
||||
endpoints:
|
||||
- 10.100.3.1:80
|
||||
- 10.100.3.11:80
|
||||
- 10.100.3.2:80
|
||||
- 10.100.3.12:80
|
||||
- 10.100.3.3:80
|
||||
- 10.100.3.13:80
|
||||
```
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/nginx-cache:0.5.1@sha256:50ac1581e3100bd6c477a71161cb455a341ffaf9e5e2f6086802e4e25271e8af
|
||||
ghcr.io/cozystack/cozystack/nginx-cache:0.6.1@sha256:b7633717cd7449c0042ae92d8ca9b36e4d69566561f5c7d44e21058e7d05c6d5
|
||||
|
||||
@@ -33,11 +33,7 @@ spec:
|
||||
containers:
|
||||
- image: haproxy:latest
|
||||
name: haproxy
|
||||
{{- if .Values.haproxy.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.haproxy.resources $) | nindent 10 }}
|
||||
{{- else if ne .Values.haproxy.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.haproxy.resourcesPreset $) | nindent 10 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.haproxy.resourcesPreset .Values.haproxy.resources $) | nindent 10 }}
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
|
||||
@@ -10,7 +10,9 @@ spec:
|
||||
type: {{ ternary "LoadBalancer" "ClusterIP" .Values.external }}
|
||||
{{- if .Values.external }}
|
||||
externalTrafficPolicy: Local
|
||||
{{- if (include "cozy-lib.network.disableLoadBalancerNodePorts" $ | fromYaml) }}
|
||||
allocateLoadBalancerNodePorts: false
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
selector:
|
||||
app: {{ .Release.Name }}-haproxy
|
||||
|
||||
@@ -52,11 +52,7 @@ spec:
|
||||
shareProcessNamespace: true
|
||||
containers:
|
||||
- name: nginx
|
||||
{{- if $.Values.nginx.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list $.Values.nginx.resources $) | nindent 10 }}
|
||||
{{- else if ne $.Values.nginx.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list $.Values.nginx.resourcesPreset $) | nindent 10 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list $.Values.nginx.resourcesPreset $.Values.nginx.resources $) | nindent 10 }}
|
||||
image: "{{ $.Files.Get "images/nginx-cache.tag" | trim }}"
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -1,67 +1,172 @@
|
||||
{
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external": {
|
||||
"type": "boolean",
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"default": false
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"endpoints": {
|
||||
"description": "Endpoints configuration, as a list of \u003cip:port\u003e",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"haproxy": {
|
||||
"description": "HAProxy configuration",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"replicas": 2,
|
||||
"resources": {},
|
||||
"resourcesPreset": "nano"
|
||||
},
|
||||
"required": [
|
||||
"replicas",
|
||||
"resources",
|
||||
"resourcesPreset"
|
||||
],
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"description": "Number of HAProxy replicas",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"size": {
|
||||
"type": "string",
|
||||
"description": "Persistent Volume size",
|
||||
"default": "10Gi"
|
||||
},
|
||||
"storageClass": {
|
||||
"type": "string",
|
||||
"description": "StorageClass used to store the data",
|
||||
"default": ""
|
||||
},
|
||||
"haproxy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"type": "number",
|
||||
"description": "Number of HAProxy replicas",
|
||||
"default": 2
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"description": "Resources",
|
||||
"default": {}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"type": "string",
|
||||
"description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).",
|
||||
"default": "nano"
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nginx": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"type": "number",
|
||||
"description": "Number of Nginx replicas",
|
||||
"default": 2
|
||||
],
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"description": "Resources",
|
||||
"default": {}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"type": "string",
|
||||
"description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).",
|
||||
"default": "nano"
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"x-kubernetes-int-or-string": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"endpoints": {
|
||||
"type": "array",
|
||||
"description": "Endpoints configuration",
|
||||
"default": [],
|
||||
"items": {}
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
"nano",
|
||||
"micro",
|
||||
"small",
|
||||
"medium",
|
||||
"large",
|
||||
"xlarge",
|
||||
"2xlarge"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nginx": {
|
||||
"description": "Nginx configuration",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"replicas": 2,
|
||||
"resources": {},
|
||||
"resourcesPreset": "nano"
|
||||
},
|
||||
"required": [
|
||||
"replicas",
|
||||
"resourcesPreset"
|
||||
],
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"description": "Number of Nginx replicas",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU",
|
||||
"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",
|
||||
"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. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
"nano",
|
||||
"micro",
|
||||
"small",
|
||||
"medium",
|
||||
"large",
|
||||
"xlarge",
|
||||
"2xlarge"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,14 @@
|
||||
|
||||
## @section Common parameters
|
||||
|
||||
## @param external Enable external access from outside the cluster
|
||||
## @param size Persistent Volume size
|
||||
## @param storageClass StorageClass used to store the data
|
||||
## @param haproxy.replicas Number of HAProxy replicas
|
||||
## @param nginx.replicas Number of Nginx replicas
|
||||
##
|
||||
external: false
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
storageClass: ""
|
||||
haproxy:
|
||||
replicas: 2
|
||||
## @param haproxy.resources Resources
|
||||
resources: {}
|
||||
# resources:
|
||||
# limits:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 512Mi
|
||||
|
||||
## @param haproxy.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).
|
||||
resourcesPreset: "nano"
|
||||
nginx:
|
||||
replicas: 2
|
||||
## @param nginx.resources Resources
|
||||
resources: {}
|
||||
# resources:
|
||||
# limits:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 512Mi
|
||||
|
||||
## @param nginx.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).
|
||||
resourcesPreset: "nano"
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
external: false
|
||||
## @section Application-specific parameters
|
||||
|
||||
## @section Configuration parameters
|
||||
|
||||
## @param endpoints Endpoints configuration
|
||||
## @param endpoints {[]string} Endpoints configuration, as a list of <ip:port>
|
||||
## Example:
|
||||
## endpoints:
|
||||
## - 10.100.3.1:80
|
||||
@@ -52,3 +19,35 @@ nginx:
|
||||
## - 10.100.3.13:80
|
||||
##
|
||||
endpoints: []
|
||||
|
||||
|
||||
## @section HAProxy parameters
|
||||
##
|
||||
## @param haproxy {haproxy} HAProxy configuration
|
||||
haproxy:
|
||||
## @field haproxy.replicas {int} Number of HAProxy replicas
|
||||
replicas: 2
|
||||
## @field haproxy.resources {resources} Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU
|
||||
## @field resources.memory {*quantity} Memory
|
||||
resources: {}
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
## @field haproxy.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "nano"
|
||||
|
||||
## @section Nginx parameters
|
||||
##
|
||||
## @param nginx {nginx} Nginx configuration
|
||||
nginx:
|
||||
## @field nginx.replicas {int} Number of Nginx replicas
|
||||
replicas: 2
|
||||
## @field nginx.resources {*resources} Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
resources: {}
|
||||
|
||||
## @field nginx.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "nano"
|
||||
|
||||
@@ -16,7 +16,7 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.7.0
|
||||
version: 0.8.1
|
||||
|
||||
# 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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
include ../../../scripts/package.mk
|
||||
PRESET_ENUM := ["nano","micro","small","medium","large","xlarge","2xlarge"]
|
||||
|
||||
generate:
|
||||
readme-generator -v values.yaml -s values.schema.json -r README.md
|
||||
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
|
||||
|
||||
@@ -4,22 +4,117 @@
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `external` | Enable external access from outside the cluster | `false` |
|
||||
| `kafka.size` | Persistent Volume size for Kafka | `10Gi` |
|
||||
| `kafka.replicas` | Number of Kafka replicas | `3` |
|
||||
| `kafka.storageClass` | StorageClass used to store the Kafka data | `""` |
|
||||
| `zookeeper.size` | Persistent Volume size for ZooKeeper | `5Gi` |
|
||||
| `zookeeper.replicas` | Number of ZooKeeper replicas | `3` |
|
||||
| `zookeeper.storageClass` | StorageClass used to store the ZooKeeper data | `""` |
|
||||
| `kafka.resources` | Resources | `{}` |
|
||||
| `kafka.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `small` |
|
||||
| `zookeeper.resources` | Resources | `{}` |
|
||||
| `zookeeper.resourcesPreset` | Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). | `micro` |
|
||||
| Name | Description | Type | Value |
|
||||
| ---------- | ----------------------------------------------- | ------ | ------- |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
|
||||
### Configuration parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| -------- | -------------------- | ----- |
|
||||
| `topics` | Topics configuration | `[]` |
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------- | -------------------- | ---------- | ----- |
|
||||
| `topics` | Topics configuration | `[]object` | `[]` |
|
||||
| `topics[i].name` | Topic name | `string` | `""` |
|
||||
| `topics[i].partitions` | Number of partitions | `int` | `0` |
|
||||
| `topics[i].replicas` | Number of replicas | `int` | `0` |
|
||||
| `topics[i].config` | Topic configuration | `object` | `{}` |
|
||||
| `topics[i].name` | Topic name | `string` | `""` |
|
||||
| `topics[i].partitions` | Number of partitions | `int` | `0` |
|
||||
| `topics[i].replicas` | Number of replicas | `int` | `0` |
|
||||
| `topics[i].config` | Topic configuration | `object` | `{}` |
|
||||
|
||||
|
||||
### Kafka configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `kafka` | Kafka configuration | `object` | `{}` |
|
||||
| `kafka.replicas` | Number of Kafka replicas | `int` | `3` |
|
||||
| `kafka.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `kafka.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `kafka.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `kafka.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `kafka.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `kafka.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `small` |
|
||||
| `kafka.size` | Persistent Volume size for Kafka | `quantity` | `10Gi` |
|
||||
| `kafka.storageClass` | StorageClass used to store the Kafka data | `string` | `""` |
|
||||
| `kafka.replicas` | Number of Kafka replicas | `int` | `3` |
|
||||
| `kafka.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `kafka.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `kafka.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `kafka.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `kafka.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `kafka.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `small` |
|
||||
| `kafka.size` | Persistent Volume size for Kafka | `quantity` | `10Gi` |
|
||||
| `kafka.storageClass` | StorageClass used to store the Kafka data | `string` | `""` |
|
||||
|
||||
|
||||
### Zookeeper configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `zookeeper` | Zookeeper configuration | `object` | `{}` |
|
||||
| `zookeeper.replicas` | Number of ZooKeeper replicas | `int` | `3` |
|
||||
| `zookeeper.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `zookeeper.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `zookeeper.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `zookeeper.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `zookeeper.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `zookeeper.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `small` |
|
||||
| `zookeeper.size` | Persistent Volume size for ZooKeeper | `quantity` | `5Gi` |
|
||||
| `zookeeper.storageClass` | StorageClass used to store the ZooKeeper data | `string` | `""` |
|
||||
| `zookeeper.replicas` | Number of ZooKeeper replicas | `int` | `3` |
|
||||
| `zookeeper.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `zookeeper.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `zookeeper.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `zookeeper.resources.cpu` | CPU | `*quantity` | `null` |
|
||||
| `zookeeper.resources.memory` | Memory | `*quantity` | `null` |
|
||||
| `zookeeper.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `small` |
|
||||
| `zookeeper.size` | Persistent Volume size for ZooKeeper | `quantity` | `5Gi` |
|
||||
| `zookeeper.storageClass` | StorageClass used to store the ZooKeeper data | `string` | `""` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
### resources and resourcesPreset
|
||||
|
||||
`resources` sets explicit CPU and memory configurations for each replica.
|
||||
When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
cpu: 4000m
|
||||
memory: 4Gi
|
||||
```
|
||||
|
||||
`resourcesPreset` sets named CPU and memory configurations for each replica.
|
||||
This setting is ignored if the corresponding `resources` value is set.
|
||||
|
||||
| Preset name | CPU | memory |
|
||||
|-------------|--------|---------|
|
||||
| `nano` | `250m` | `128Mi` |
|
||||
| `micro` | `500m` | `256Mi` |
|
||||
| `small` | `1` | `512Mi` |
|
||||
| `medium` | `1` | `1Gi` |
|
||||
| `large` | `2` | `2Gi` |
|
||||
| `xlarge` | `4` | `4Gi` |
|
||||
| `2xlarge` | `8` | `8Gi` |
|
||||
|
||||
### topics
|
||||
|
||||
```yaml
|
||||
topics:
|
||||
- name: Results
|
||||
partitions: 1
|
||||
replicas: 3
|
||||
config:
|
||||
min.insync.replicas: 2
|
||||
- name: Orders
|
||||
config:
|
||||
cleanup.policy: compact
|
||||
segment.ms: 3600000
|
||||
max.compaction.lag.ms: 5400000
|
||||
min.insync.replicas: 2
|
||||
partitions: 1
|
||||
replicas: 3
|
||||
```
|
||||
|
||||
@@ -8,11 +8,7 @@ metadata:
|
||||
spec:
|
||||
kafka:
|
||||
replicas: {{ .Values.kafka.replicas }}
|
||||
{{- if .Values.kafka.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.kafka.resources $) | nindent 6 }}
|
||||
{{- else if ne .Values.kafka.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.kafka.resourcesPreset $) | nindent 6 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.kafka.resourcesPreset .Values.kafka.resources $) | nindent 6 }}
|
||||
listeners:
|
||||
- name: plain
|
||||
port: 9092
|
||||
@@ -70,11 +66,7 @@ spec:
|
||||
key: kafka-metrics-config.yml
|
||||
zookeeper:
|
||||
replicas: {{ .Values.zookeeper.replicas }}
|
||||
{{- if .Values.zookeeper.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.zookeeper.resources $) | nindent 6 }}
|
||||
{{- else if ne .Values.zookeeper.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.zookeeper.resourcesPreset $) | nindent 6 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.zookeeper.resourcesPreset .Values.zookeeper.resources $) | nindent 6 }}
|
||||
storage:
|
||||
type: persistent-claim
|
||||
{{- with .Values.zookeeper.size }}
|
||||
|
||||
@@ -1,77 +1,222 @@
|
||||
{
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external": {
|
||||
"type": "boolean",
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"default": false
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"kafka": {
|
||||
"description": "Kafka configuration",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"replicas": 3,
|
||||
"resources": {},
|
||||
"resourcesPreset": "small",
|
||||
"size": "10Gi",
|
||||
"storageClass": ""
|
||||
},
|
||||
"required": [
|
||||
"replicas",
|
||||
"resourcesPreset",
|
||||
"size",
|
||||
"storageClass"
|
||||
],
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"description": "Number of Kafka replicas",
|
||||
"type": "integer",
|
||||
"default": 3
|
||||
},
|
||||
"kafka": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "string",
|
||||
"description": "Persistent Volume size for Kafka",
|
||||
"default": "10Gi"
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
"replicas": {
|
||||
"type": "number",
|
||||
"description": "Number of Kafka replicas",
|
||||
"default": 3
|
||||
},
|
||||
"storageClass": {
|
||||
"type": "string",
|
||||
"description": "StorageClass used to store the Kafka data",
|
||||
"default": ""
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"description": "Resources",
|
||||
"default": {}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"type": "string",
|
||||
"description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).",
|
||||
"default": "small"
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"zookeeper": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "string",
|
||||
"description": "Persistent Volume size for ZooKeeper",
|
||||
"default": "5Gi"
|
||||
],
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
"replicas": {
|
||||
"type": "number",
|
||||
"description": "Number of ZooKeeper replicas",
|
||||
"default": 3
|
||||
},
|
||||
"storageClass": {
|
||||
"type": "string",
|
||||
"description": "StorageClass used to store the ZooKeeper data",
|
||||
"default": ""
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"description": "Resources",
|
||||
"default": {}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"type": "string",
|
||||
"description": "Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).",
|
||||
"default": "micro"
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"x-kubernetes-int-or-string": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"topics": {
|
||||
"type": "array",
|
||||
"description": "Topics configuration",
|
||||
"default": [],
|
||||
"items": {}
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"type": "string",
|
||||
"default": "small",
|
||||
"enum": [
|
||||
"nano",
|
||||
"micro",
|
||||
"small",
|
||||
"medium",
|
||||
"large",
|
||||
"xlarge",
|
||||
"2xlarge"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume size for Kafka",
|
||||
"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 Kafka data",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"topics": {
|
||||
"description": "Topics configuration",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"config",
|
||||
"name",
|
||||
"partitions",
|
||||
"replicas"
|
||||
],
|
||||
"properties": {
|
||||
"config": {
|
||||
"description": "Topic configuration",
|
||||
"type": "object",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"name": {
|
||||
"description": "Topic name",
|
||||
"type": "string"
|
||||
},
|
||||
"partitions": {
|
||||
"description": "Number of partitions",
|
||||
"type": "integer"
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of replicas",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"zookeeper": {
|
||||
"description": "Zookeeper configuration",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"replicas": 3,
|
||||
"resources": {},
|
||||
"resourcesPreset": "small",
|
||||
"size": "5Gi",
|
||||
"storageClass": ""
|
||||
},
|
||||
"required": [
|
||||
"replicas",
|
||||
"resourcesPreset",
|
||||
"size",
|
||||
"storageClass"
|
||||
],
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"description": "Number of ZooKeeper replicas",
|
||||
"type": "integer",
|
||||
"default": 3
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU",
|
||||
"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",
|
||||
"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. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"type": "string",
|
||||
"default": "small",
|
||||
"enum": [
|
||||
"nano",
|
||||
"micro",
|
||||
"small",
|
||||
"medium",
|
||||
"large",
|
||||
"xlarge",
|
||||
"2xlarge"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume size for ZooKeeper",
|
||||
"default": "5Gi",
|
||||
"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 ZooKeeper data",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,17 @@
|
||||
|
||||
## @section Common parameters
|
||||
|
||||
## @param external Enable external access from outside the cluster
|
||||
## @param kafka.size Persistent Volume size for Kafka
|
||||
## @param kafka.replicas Number of Kafka replicas
|
||||
## @param kafka.storageClass StorageClass used to store the Kafka data
|
||||
## @param zookeeper.size Persistent Volume size for ZooKeeper
|
||||
## @param zookeeper.replicas Number of ZooKeeper replicas
|
||||
## @param zookeeper.storageClass StorageClass used to store the ZooKeeper data
|
||||
##
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
external: false
|
||||
kafka:
|
||||
size: 10Gi
|
||||
replicas: 3
|
||||
storageClass: ""
|
||||
## @param kafka.resources Resources
|
||||
resources: {}
|
||||
# resources:
|
||||
# limits:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 512Mi
|
||||
|
||||
## @param kafka.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).
|
||||
resourcesPreset: "small"
|
||||
|
||||
zookeeper:
|
||||
size: 5Gi
|
||||
replicas: 3
|
||||
storageClass: ""
|
||||
## @param zookeeper.resources Resources
|
||||
resources: {}
|
||||
# resources:
|
||||
# limits:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 512Mi
|
||||
|
||||
## @param zookeeper.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).
|
||||
resourcesPreset: "micro"
|
||||
|
||||
## @section Configuration parameters
|
||||
|
||||
## @param topics Topics configuration
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param topics {[]topic} Topics configuration
|
||||
## @field topic {topic} Topic
|
||||
## @field topic.name {string} Topic name
|
||||
## @field topic.partitions {int} Number of partitions
|
||||
## @field topic.replicas {int} Number of replicas
|
||||
## @field topic.config {object} Topic configuration
|
||||
## Example:
|
||||
## topics:
|
||||
## - name: Results
|
||||
@@ -64,3 +29,44 @@ zookeeper:
|
||||
## replicas: 3
|
||||
##
|
||||
topics: []
|
||||
|
||||
## @section Kafka configuration
|
||||
##
|
||||
## @param kafka {kafka} Kafka configuration
|
||||
kafka:
|
||||
## @field kafka.replicas {int} Number of Kafka replicas
|
||||
replicas: 3
|
||||
## @field kafka.resources {*resources} Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU
|
||||
## @field resources.memory {*quantity} Memory
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
resources: {}
|
||||
## @field kafka.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "small"
|
||||
## @field kafka.size {quantity} Persistent Volume size for Kafka
|
||||
size: 10Gi
|
||||
## @field kafka.storageClass {string} StorageClass used to store the Kafka data
|
||||
storageClass: ""
|
||||
|
||||
|
||||
## @section Zookeeper configuration
|
||||
##
|
||||
## @param zookeeper {zookeeper} Zookeeper configuration
|
||||
zookeeper:
|
||||
## @field zookeeper.replicas {int} Number of ZooKeeper replicas
|
||||
replicas: 3
|
||||
## @field zookeeper.resources {*resources} Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
resources: {}
|
||||
|
||||
## @field zookeeper.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "small"
|
||||
## @field zookeeper.size {quantity} Persistent Volume size for ZooKeeper
|
||||
size: 5Gi
|
||||
## @field zookeeper.storageClass {string} StorageClass used to store the ZooKeeper data
|
||||
storageClass: ""
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.24.1
|
||||
version: 0.26.3
|
||||
|
||||
# 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.32.4
|
||||
appVersion: 1.32.6
|
||||
|
||||
@@ -5,11 +5,8 @@ include ../../../scripts/common-envs.mk
|
||||
include ../../../scripts/package.mk
|
||||
|
||||
generate:
|
||||
readme-generator -v values.yaml -s values.schema.json -r README.md
|
||||
yq -o json -i '.properties.controlPlane.properties.apiServer.properties.resourcesPreset.enum = ["none","nano","micro","small","medium","large","xlarge","2xlarge"]' values.schema.json
|
||||
yq -o json -i '.properties.controlPlane.properties.controllerManager.properties.resourcesPreset.enum = ["none","nano","micro","small","medium","large","xlarge","2xlarge"]' values.schema.json
|
||||
yq -o json -i '.properties.controlPlane.properties.scheduler.properties.resourcesPreset.enum = ["none","nano","micro","small","medium","large","xlarge","2xlarge"]' values.schema.json
|
||||
yq -o json -i '.properties.controlPlane.properties.konnectivity.properties.server.properties.resourcesPreset.enum = ["none","nano","micro","small","medium","large","xlarge","2xlarge"]' values.schema.json
|
||||
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
|
||||
yq -o=json -i '.properties.version.enum = (load("files/versions.yaml") | keys)' values.schema.json
|
||||
|
||||
image: image-ubuntu-container-disk image-kubevirt-cloud-provider image-kubevirt-csi-driver image-cluster-autoscaler
|
||||
|
||||
@@ -63,6 +60,8 @@ image-kubevirt-csi-driver:
|
||||
--load=$(LOAD)
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ Tenant clusters are fully separated from the management cluster and are intended
|
||||
Within a tenant cluster, users can take advantage of LoadBalancer services and easily provision physical volumes as needed.
|
||||
The control-plane operates within containers, while the worker nodes are deployed as virtual machines, all seamlessly managed by the application.
|
||||
|
||||
Kubernetes version in tenant clusters is independent of Kubernetes in the management cluster.
|
||||
Users can select the latest patch versions from 1.28 to 1.33.
|
||||
|
||||
## Why Use a Managed Kubernetes Cluster?
|
||||
|
||||
Kubernetes has emerged as the industry standard, providing a unified and accessible API, primarily utilizing YAML for configuration.
|
||||
@@ -81,63 +84,305 @@ See the reference for components utilized in this service:
|
||||
|
||||
### Common Parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------ |
|
||||
| `host` | Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty. | `""` |
|
||||
| `controlPlane.replicas` | Number of replicas for Kubernetes control-plane components. | `2` |
|
||||
| `storageClass` | StorageClass used to store user data. | `replicated` |
|
||||
| `useCustomSecretForPatchContainerd` | if true, for patch containerd will be used secret: {{ .Release.Name }}-patch-containerd | `false` |
|
||||
| `nodeGroups` | nodeGroups configuration | `{}` |
|
||||
| Name | Description | Type | Value |
|
||||
| -------------- | ----------------------------------- | -------- | ------------ |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `replicated` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------- | ------- |
|
||||
| `version` | Kubernetes version given as vMAJOR.MINOR. Available are versions from 1.28 to 1.33. | `string` | `v1.32` |
|
||||
| `host` | Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty. | `string` | `""` |
|
||||
| `nodeGroups` | Worker nodes configuration | `map[string]object` | `{...}` |
|
||||
| `nodeGroups[name].minReplicas` | Minimum amount of replicas | `int` | `0` |
|
||||
| `nodeGroups[name].maxReplicas` | Maximum amount of replicas | `int` | `0` |
|
||||
| `nodeGroups[name].instanceType` | Virtual machine instance type | `string` | `""` |
|
||||
| `nodeGroups[name].ephemeralStorage` | Ephemeral storage size | `quantity` | `""` |
|
||||
| `nodeGroups[name].roles` | List of node's roles | `[]string` | `[]` |
|
||||
| `nodeGroups[name].resources` | Available resources for each worker node | `object` | `{}` |
|
||||
| `nodeGroups[name].resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `nodeGroups[name].resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `nodeGroups[name].resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `nodeGroups[name].resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `nodeGroups[name].gpus` | List of GPUs to attach (WARN: NVIDIA driver requires at least 4 GiB of RAM) | `[]object` | `[]` |
|
||||
| `nodeGroups[name].gpus.name` | Name of GPU, such as "nvidia.com/AD102GL_L40S" | `string` | `""` |
|
||||
| `nodeGroups[name].gpus.name` | Name of GPU, such as "nvidia.com/AD102GL_L40S" | `string` | `""` |
|
||||
| `nodeGroups[name].minReplicas` | Minimum amount of replicas | `int` | `0` |
|
||||
| `nodeGroups[name].maxReplicas` | Maximum amount of replicas | `int` | `0` |
|
||||
| `nodeGroups[name].instanceType` | Virtual machine instance type | `string` | `""` |
|
||||
| `nodeGroups[name].ephemeralStorage` | Ephemeral storage size | `quantity` | `""` |
|
||||
| `nodeGroups[name].roles` | List of node's roles | `[]string` | `[]` |
|
||||
| `nodeGroups[name].resources` | Available resources for each worker node | `object` | `{}` |
|
||||
| `nodeGroups[name].resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `nodeGroups[name].resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `nodeGroups[name].resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `nodeGroups[name].resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `nodeGroups[name].gpus` | List of GPUs to attach (WARN: NVIDIA driver requires at least 4 GiB of RAM) | `[]object` | `[]` |
|
||||
| `nodeGroups[name].gpus.name` | Name of GPU, such as "nvidia.com/AD102GL_L40S" | `string` | `""` |
|
||||
| `nodeGroups[name].gpus.name` | Name of GPU, such as "nvidia.com/AD102GL_L40S" | `string` | `""` |
|
||||
|
||||
|
||||
### Cluster Addons
|
||||
|
||||
| Name | Description | Value |
|
||||
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `addons.certManager.enabled` | Enable cert-manager, which automatically creates and manages SSL/TLS certificates. | `false` |
|
||||
| `addons.certManager.valuesOverride` | Custom values to override | `{}` |
|
||||
| `addons.cilium.valuesOverride` | Custom values to override | `{}` |
|
||||
| `addons.gatewayAPI.enabled` | Enable the Gateway API | `false` |
|
||||
| `addons.ingressNginx.enabled` | Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). | `false` |
|
||||
| `addons.ingressNginx.valuesOverride` | Custom values to override | `{}` |
|
||||
| `addons.ingressNginx.hosts` | List of domain names that the parent cluster should route to this tenant cluster. | `[]` |
|
||||
| `addons.gpuOperator.enabled` | Enable the GPU-operator | `false` |
|
||||
| `addons.gpuOperator.valuesOverride` | Custom values to override | `{}` |
|
||||
| `addons.fluxcd.enabled` | Enable FluxCD | `false` |
|
||||
| `addons.fluxcd.valuesOverride` | Custom values to override | `{}` |
|
||||
| `addons.monitoringAgents.enabled` | Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage. | `false` |
|
||||
| `addons.monitoringAgents.valuesOverride` | Custom values to override | `{}` |
|
||||
| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `{}` |
|
||||
| Name | Description | Type | Value |
|
||||
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | --------- |
|
||||
| `addons` | Cluster addons configuration | `object` | `{}` |
|
||||
| `addons.certManager` | Cert-manager: automatically creates and manages SSL/TLS certificate | `object` | `{}` |
|
||||
| `addons.certManager.enabled` | Enable cert-manager, which automatically creates and manages SSL/TLS certificates. | `bool` | `false` |
|
||||
| `addons.certManager.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.certManager.enabled` | Enable cert-manager, which automatically creates and manages SSL/TLS certificates. | `bool` | `false` |
|
||||
| `addons.certManager.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.cilium` | Cilium CNI plugin | `object` | `{}` |
|
||||
| `addons.cilium.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.cilium.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.gatewayAPI` | Gateway API | `object` | `{}` |
|
||||
| `addons.gatewayAPI.enabled` | Enable the Gateway API | `bool` | `false` |
|
||||
| `addons.gatewayAPI.enabled` | Enable the Gateway API | `bool` | `false` |
|
||||
| `addons.ingressNginx` | Ingress-NGINX Controller | `object` | `{}` |
|
||||
| `addons.ingressNginx.enabled` | Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). | `bool` | `false` |
|
||||
| `addons.ingressNginx.exposeMethod` | Method to expose the Ingress-NGINX controller. Allowed values: `Proxied`, `LoadBalancer`. | `string` | `Proxied` |
|
||||
| `addons.ingressNginx.hosts` | List of domain names that the parent cluster should route to this tenant cluster. Taken into account only when `exposeMethod` is set to `Proxied`. | `[]string` | `[]` |
|
||||
| `addons.ingressNginx.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.ingressNginx.enabled` | Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). | `bool` | `false` |
|
||||
| `addons.ingressNginx.exposeMethod` | Method to expose the Ingress-NGINX controller. Allowed values: `Proxied`, `LoadBalancer`. | `string` | `Proxied` |
|
||||
| `addons.ingressNginx.hosts` | List of domain names that the parent cluster should route to this tenant cluster. Taken into account only when `exposeMethod` is set to `Proxied`. | `[]string` | `[]` |
|
||||
| `addons.ingressNginx.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.gpuOperator` | GPU-operator: NVIDIA GPU Operator | `object` | `{}` |
|
||||
| `addons.gpuOperator.enabled` | Enable the GPU-operator | `bool` | `false` |
|
||||
| `addons.gpuOperator.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.gpuOperator.enabled` | Enable the GPU-operator | `bool` | `false` |
|
||||
| `addons.gpuOperator.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.fluxcd` | Flux CD | `object` | `{}` |
|
||||
| `addons.fluxcd.enabled` | Enable FluxCD | `bool` | `false` |
|
||||
| `addons.fluxcd.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.fluxcd.enabled` | Enable FluxCD | `bool` | `false` |
|
||||
| `addons.fluxcd.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.monitoringAgents` | MonitoringAgents | `object` | `{}` |
|
||||
| `addons.monitoringAgents.enabled` | Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage. | `bool` | `false` |
|
||||
| `addons.monitoringAgents.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.monitoringAgents.enabled` | Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage. | `bool` | `false` |
|
||||
| `addons.monitoringAgents.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler` | VerticalPodAutoscaler | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.velero` | Velero | `object` | `{}` |
|
||||
| `addons.velero.enabled` | Enable Velero for backup and recovery of a tenant Kubernetes cluster. | `bool` | `false` |
|
||||
| `addons.velero.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.velero.enabled` | Enable Velero for backup and recovery of a tenant Kubernetes cluster. | `bool` | `false` |
|
||||
| `addons.velero.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.certManager` | Cert-manager: automatically creates and manages SSL/TLS certificate | `object` | `{}` |
|
||||
| `addons.certManager.enabled` | Enable cert-manager, which automatically creates and manages SSL/TLS certificates. | `bool` | `false` |
|
||||
| `addons.certManager.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.certManager.enabled` | Enable cert-manager, which automatically creates and manages SSL/TLS certificates. | `bool` | `false` |
|
||||
| `addons.certManager.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.cilium` | Cilium CNI plugin | `object` | `{}` |
|
||||
| `addons.cilium.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.cilium.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.gatewayAPI` | Gateway API | `object` | `{}` |
|
||||
| `addons.gatewayAPI.enabled` | Enable the Gateway API | `bool` | `false` |
|
||||
| `addons.gatewayAPI.enabled` | Enable the Gateway API | `bool` | `false` |
|
||||
| `addons.ingressNginx` | Ingress-NGINX Controller | `object` | `{}` |
|
||||
| `addons.ingressNginx.enabled` | Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). | `bool` | `false` |
|
||||
| `addons.ingressNginx.exposeMethod` | Method to expose the Ingress-NGINX controller. Allowed values: `Proxied`, `LoadBalancer`. | `string` | `Proxied` |
|
||||
| `addons.ingressNginx.hosts` | List of domain names that the parent cluster should route to this tenant cluster. Taken into account only when `exposeMethod` is set to `Proxied`. | `[]string` | `[]` |
|
||||
| `addons.ingressNginx.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.ingressNginx.enabled` | Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). | `bool` | `false` |
|
||||
| `addons.ingressNginx.exposeMethod` | Method to expose the Ingress-NGINX controller. Allowed values: `Proxied`, `LoadBalancer`. | `string` | `Proxied` |
|
||||
| `addons.ingressNginx.hosts` | List of domain names that the parent cluster should route to this tenant cluster. Taken into account only when `exposeMethod` is set to `Proxied`. | `[]string` | `[]` |
|
||||
| `addons.ingressNginx.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.gpuOperator` | GPU-operator: NVIDIA GPU Operator | `object` | `{}` |
|
||||
| `addons.gpuOperator.enabled` | Enable the GPU-operator | `bool` | `false` |
|
||||
| `addons.gpuOperator.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.gpuOperator.enabled` | Enable the GPU-operator | `bool` | `false` |
|
||||
| `addons.gpuOperator.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.fluxcd` | Flux CD | `object` | `{}` |
|
||||
| `addons.fluxcd.enabled` | Enable FluxCD | `bool` | `false` |
|
||||
| `addons.fluxcd.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.fluxcd.enabled` | Enable FluxCD | `bool` | `false` |
|
||||
| `addons.fluxcd.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.monitoringAgents` | MonitoringAgents | `object` | `{}` |
|
||||
| `addons.monitoringAgents.enabled` | Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage. | `bool` | `false` |
|
||||
| `addons.monitoringAgents.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.monitoringAgents.enabled` | Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage. | `bool` | `false` |
|
||||
| `addons.monitoringAgents.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler` | VerticalPodAutoscaler | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.velero` | Velero | `object` | `{}` |
|
||||
| `addons.velero.enabled` | Enable Velero for backup and recovery of a tenant Kubernetes cluster. | `bool` | `false` |
|
||||
| `addons.velero.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.velero.enabled` | Enable Velero for backup and recovery of a tenant Kubernetes cluster. | `bool` | `false` |
|
||||
| `addons.velero.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
|
||||
|
||||
### Kubernetes Control Plane Configuration
|
||||
|
||||
| Name | Description | Value |
|
||||
| -------------------------------------------------- | ---------------------------------------------------------------------------- | -------- |
|
||||
| `controlPlane.apiServer.resources` | Explicit CPU/memory resource requests and limits for the API server. | `{}` |
|
||||
| `controlPlane.apiServer.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `medium` |
|
||||
| `controlPlane.controllerManager.resources` | Explicit CPU/memory resource requests and limits for the controller manager. | `{}` |
|
||||
| `controlPlane.controllerManager.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` |
|
||||
| `controlPlane.scheduler.resources` | Explicit CPU/memory resource requests and limits for the scheduler. | `{}` |
|
||||
| `controlPlane.scheduler.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU/memory resource requests and limits for the Konnectivity. | `{}` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` |
|
||||
| Name | Description | Type | Value |
|
||||
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------- |
|
||||
| `controlPlane` | Control Plane Configuration | `object` | `{}` |
|
||||
| `controlPlane.replicas` | Number of replicas for Kubernetes control plane components. | `int` | `2` |
|
||||
| `controlPlane.apiServer` | Control plane API server configuration. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources` | Explicit CPU and memory configuration for the API Server. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `medium` |
|
||||
| `controlPlane.apiServer.resources` | Explicit CPU and memory configuration for the API Server. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `medium` |
|
||||
| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources` | Explicit CPU and memory configuration for the Controller Manager. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.controllerManager.resources` | Explicit CPU and memory configuration for the Controller Manager. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources` | Explicit CPU and memory configuration for the Scheduler. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.scheduler.resources` | Explicit CPU and memory configuration for the Scheduler. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server` | Konnectivity server configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity.server` | Konnectivity server configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.replicas` | Number of replicas for Kubernetes control plane components. | `int` | `2` |
|
||||
| `controlPlane.apiServer` | Control plane API server configuration. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources` | Explicit CPU and memory configuration for the API Server. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `medium` |
|
||||
| `controlPlane.apiServer.resources` | Explicit CPU and memory configuration for the API Server. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `medium` |
|
||||
| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources` | Explicit CPU and memory configuration for the Controller Manager. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.controllerManager.resources` | Explicit CPU and memory configuration for the Controller Manager. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources` | Explicit CPU and memory configuration for the Scheduler. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.scheduler.resources` | Explicit CPU and memory configuration for the Scheduler. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server` | Konnectivity server configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity.server` | Konnectivity server configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | Available CPU | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Available memory (RAM) | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: nano, micro, small, medium, large, xlarge, 2xlarge. | `string` | `micro` |
|
||||
|
||||
In production environments, it's recommended to set `resources` explicitly.
|
||||
Example of `controlPlane.*.resources`:
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
### resources and resourcesPreset
|
||||
|
||||
`resources` sets explicit CPU and memory configurations for each replica.
|
||||
When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
limits:
|
||||
cpu: 4000m
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 512Mi
|
||||
cpu: 4000m
|
||||
memory: 4Gi
|
||||
```
|
||||
|
||||
Allowed values for `controlPlane.*.resourcesPreset` are `none`, `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
This value is ignored if the corresponding `resources` value is set.
|
||||
`resourcesPreset` sets named CPU and memory configurations for each replica.
|
||||
This setting is ignored if the corresponding `resources` value is set.
|
||||
|
||||
## Resources Reference
|
||||
| Preset name | CPU | memory |
|
||||
|-------------|--------|---------|
|
||||
| `nano` | `250m` | `128Mi` |
|
||||
| `micro` | `500m` | `256Mi` |
|
||||
| `small` | `1` | `512Mi` |
|
||||
| `medium` | `1` | `1Gi` |
|
||||
| `large` | `2` | `2Gi` |
|
||||
| `xlarge` | `4` | `4Gi` |
|
||||
| `2xlarge` | `8` | `8Gi` |
|
||||
|
||||
### instanceType Resources
|
||||
|
||||
@@ -301,4 +546,3 @@ Specific characteristics of this series are:
|
||||
workload.
|
||||
- *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4 starting from
|
||||
the medium size.
|
||||
|
||||
|
||||
6
packages/apps/kubernetes/files/versions.yaml
Normal file
6
packages/apps/kubernetes/files/versions.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
"v1.28": "v1.28.15"
|
||||
"v1.29": "v1.29.15"
|
||||
"v1.30": "v1.30.14"
|
||||
"v1.31": "v1.31.10"
|
||||
"v1.32": "v1.32.6"
|
||||
"v1.33": "v1.33.0"
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.24.0@sha256:3a8170433e1632e5cc2b6d9db34d0605e8e6c63c158282c38450415e700e932e
|
||||
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.26.2@sha256:3a8170433e1632e5cc2b6d9db34d0605e8e6c63c158282c38450415e700e932e
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.24.0@sha256:b478952fab735f85c3ba15835012b1de8af5578b33a8a2670eaf532ffc17681e
|
||||
ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.26.2@sha256:5335c044313b69ee13b30ca4941687e509005e55f4ae25723861edbf2fbd6dd2
|
||||
|
||||
@@ -21,6 +21,6 @@ RUN go mod vendor
|
||||
|
||||
RUN CGO_ENABLED=0 go build -mod=vendor -ldflags="-s -w" -o bin/kubevirt-cloud-controller-manager ./cmd/kubevirt-cloud-controller-manager
|
||||
|
||||
FROM registry.access.redhat.com/ubi9/ubi-micro
|
||||
FROM scratch
|
||||
COPY --from=builder /go/src/kubevirt.io/cloud-provider-kubevirt/bin/kubevirt-cloud-controller-manager /bin/kubevirt-cloud-controller-manager
|
||||
ENTRYPOINT [ "/bin/kubevirt-cloud-controller-manager" ]
|
||||
|
||||
@@ -1 +1 @@
|
||||
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.24.0@sha256:4d3728b2050d4e0adb00b9f4abbb4a020b29e1a39f24ca1447806fc81f110fa6
|
||||
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.26.2@sha256:761e7235ff9cb7f6f223f00954943e6a5af32ed6624ee592a8610122f96febb0
|
||||
|
||||
@@ -3,7 +3,7 @@ ARG builder_image=docker.io/library/golang:1.22.5
|
||||
FROM ${builder_image} AS builder
|
||||
RUN git clone https://github.com/kubevirt/csi-driver /src/kubevirt-csi-driver \
|
||||
&& cd /src/kubevirt-csi-driver \
|
||||
&& git checkout 35836e0c8b68d9916d29a838ea60cdd3fc6199cf
|
||||
&& git checkout a8d6605bc9997bcfda3fb9f1f82ba6445b4984cc
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
@@ -11,6 +11,7 @@ ENV GOOS=$TARGETOS
|
||||
ENV GOARCH=$TARGETARCH
|
||||
|
||||
WORKDIR /src/kubevirt-csi-driver
|
||||
|
||||
RUN make build
|
||||
|
||||
FROM quay.io/centos/centos:stream9
|
||||
|
||||
7
packages/apps/kubernetes/templates/_versions.tpl
Normal file
7
packages/apps/kubernetes/templates/_versions.tpl
Normal file
@@ -0,0 +1,7 @@
|
||||
{{- define "kubernetes.versionMap" }}
|
||||
{{- $versionMap := .Files.Get "files/versions.yaml" | fromYaml }}
|
||||
{{- if not (hasKey $versionMap .Values.version) }}
|
||||
{{- printf `Kubernetes version %s is not supported, allowed versions are %s` $.Values.version (keys $versionMap) | fail }}
|
||||
{{- end }}
|
||||
{{- index $versionMap .Values.version }}
|
||||
{{- end }}
|
||||
@@ -120,23 +120,11 @@ metadata:
|
||||
kamaji.clastix.io/kubeconfig-secret-key: "super-admin.svc"
|
||||
spec:
|
||||
apiServer:
|
||||
{{- if .Values.controlPlane.apiServer.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.controlPlane.apiServer.resources $) | nindent 6 }}
|
||||
{{- else if ne .Values.controlPlane.apiServer.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.controlPlane.apiServer.resourcesPreset $) | nindent 6 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.controlPlane.apiServer.resourcesPreset .Values.controlPlane.apiServer.resources $) | nindent 6 }}
|
||||
controllerManager:
|
||||
{{- if .Values.controlPlane.controllerManager.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.controlPlane.controllerManager.resources $) | nindent 6 }}
|
||||
{{- else if ne .Values.controlPlane.controllerManager.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.controlPlane.controllerManager.resourcesPreset $) | nindent 6 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.controlPlane.controllerManager.resourcesPreset .Values.controlPlane.controllerManager.resources $) | nindent 6 }}
|
||||
scheduler:
|
||||
{{- if .Values.controlPlane.scheduler.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.controlPlane.scheduler.resources $) | nindent 6 }}
|
||||
{{- else if ne .Values.controlPlane.scheduler.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.controlPlane.scheduler.resourcesPreset $) | nindent 6 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.controlPlane.scheduler.resourcesPreset .Values.controlPlane.scheduler.resources $) | nindent 6 }}
|
||||
dataStoreName: "{{ $etcd }}"
|
||||
addons:
|
||||
coreDNS:
|
||||
@@ -145,11 +133,7 @@ spec:
|
||||
konnectivity:
|
||||
server:
|
||||
port: 8132
|
||||
{{- if .Values.controlPlane.konnectivity.server.resources }}
|
||||
resources: {{- include "cozy-lib.resources.sanitize" (list .Values.controlPlane.konnectivity.server.resources $) | nindent 10 }}
|
||||
{{- else if ne .Values.controlPlane.konnectivity.server.resourcesPreset "none" }}
|
||||
resources: {{- include "cozy-lib.resources.preset" (list .Values.controlPlane.konnectivity.server.resourcesPreset $) | nindent 10 }}
|
||||
{{- end }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.controlPlane.konnectivity.server.resourcesPreset .Values.controlPlane.konnectivity.server.resources $) | nindent 10 }}
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
preferredAddressTypes:
|
||||
@@ -167,7 +151,7 @@ spec:
|
||||
labels:
|
||||
policy.cozystack.io/allow-to-etcd: "true"
|
||||
replicas: 2
|
||||
version: {{ $.Chart.AppVersion }}
|
||||
version: {{ include "kubernetes.versionMap" $ }}
|
||||
---
|
||||
apiVersion: cozystack.io/v1alpha1
|
||||
kind: WorkloadMonitor
|
||||
@@ -306,7 +290,7 @@ spec:
|
||||
kind: KubevirtMachineTemplate
|
||||
name: {{ $.Release.Name }}-{{ $groupName }}-{{ $kubevirtmachinetemplateHash }}
|
||||
namespace: {{ $.Release.Namespace }}
|
||||
version: v{{ $.Chart.AppVersion }}
|
||||
version: {{ include "kubernetes.versionMap" $}}
|
||||
---
|
||||
apiVersion: cluster.x-k8s.io/v1beta1
|
||||
kind: MachineHealthCheck
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
{{- if not .Values.useCustomSecretForPatchContainerd }}
|
||||
{{- $sourceSecret := lookup "v1" "Secret" "cozy-system" "patch-containerd" }}
|
||||
{{- if $sourceSecret }}
|
||||
apiVersion: v1
|
||||
@@ -12,4 +11,3 @@ data:
|
||||
{{ printf "%s: %s" $key ($value | quote) | indent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user