Compare commits

..

1 Commits

Author SHA1 Message Date
Andrei Kvapil
79ef4f7399 Introduce bats testing framework
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2025-05-23 23:46:52 +02:00
86 changed files with 353 additions and 1008 deletions

View File

@@ -80,7 +80,6 @@ jobs:
- name: Ensure maintenance branch release-X.Y - name: Ensure maintenance branch release-X.Y
uses: actions/github-script@v7 uses: actions/github-script@v7
with: with:
github-token: ${{ secrets.GH_PAT }}
script: | script: |
const tag = '${{ steps.get_tag.outputs.tag }}'; // e.g. v0.1.3 or v0.1.3-rc3 const tag = '${{ steps.get_tag.outputs.tag }}'; // e.g. v0.1.3 or v0.1.3-rc3
const match = tag.match(/^v(\d+)\.(\d+)\.\d+(?:[-\w\.]+)?$/); const match = tag.match(/^v(\d+)\.(\d+)\.\d+(?:[-\w\.]+)?$/);
@@ -90,45 +89,21 @@ jobs:
} }
const line = `${match[1]}.${match[2]}`; const line = `${match[1]}.${match[2]}`;
const branch = `release-${line}`; const branch = `release-${line}`;
// Get main branch commit for the tag
const ref = await github.rest.git.getRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `tags/${tag}`
});
const commitSha = ref.data.object.sha;
try { try {
await github.rest.repos.getBranch({ await github.rest.repos.getBranch({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
branch branch
}); });
console.log(`Branch '${branch}' already exists`);
await github.rest.git.updateRef({ } catch (_) {
await github.rest.git.createRef({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
ref: `heads/${branch}`, ref: `refs/heads/${branch}`,
sha: commitSha, sha: context.sha
force: true
}); });
console.log(`🔁 Force-updated '${branch}' to ${commitSha}`); console.log(`✅ Branch '${branch}' created at ${context.sha}`);
} catch (err) {
if (err.status === 404) {
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `refs/heads/${branch}`,
sha: commitSha
});
console.log(`✅ Created branch '${branch}' at ${commitSha}`);
} else {
console.error('Unexpected error --', err);
core.setFailed(`Unexpected error creating/updating branch: ${err.message}`);
throw err;
}
} }
# Get the latest published release # Get the latest published release
@@ -162,12 +137,12 @@ jobs:
with: with:
script: | script: |
const tag = '${{ steps.get_tag.outputs.tag }}'; // v0.31.5-rc.1 const tag = '${{ steps.get_tag.outputs.tag }}'; // v0.31.5-rc.1
const m = tag.match(/^v(\d+\.\d+\.\d+)(-(?:alpha|beta|rc)\.\d+)?$/); const m = tag.match(/^v(\d+\.\d+\.\d+)(-rc\.\d+)?$/);
if (!m) { if (!m) {
core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-(alpha|beta|rc).N'`); core.setFailed(`❌ tag '${tag}' must match 'vX.Y.Z' or 'vX.Y.Z-rc.N'`);
return; return;
} }
const version = m[1] + (m[2] ?? ''); // 0.31.5-rc.1 const version = m[1] + (m[2] ?? ''); // 0.31.5rc.1
const isRc = Boolean(m[2]); const isRc = Boolean(m[2]);
core.setOutput('is_rc', isRc); core.setOutput('is_rc', isRc);
const outdated = '${{ steps.semver.outputs.comparison-result }}' === '<'; const outdated = '${{ steps.semver.outputs.comparison-result }}' === '<';

View File

@@ -3,10 +3,9 @@ name: Versioned Tag
on: on:
push: push:
tags: tags:
- 'v*.*.*' # vX.Y.Z - 'v*.*.*' # vX.Y.Z
- 'v*.*.*-rc.*' # vX.Y.Z-rc.N - 'v*.*.*-rc.*' # vX.Y.Z-rc.N
- 'v*.*.*-beta.*' # vX.Y.Z-beta.N
- 'v*.*.*-alpha.*' # vX.Y.Z-alpha.N
concurrency: concurrency:
group: tags-${{ github.workflow }}-${{ github.ref }} group: tags-${{ github.workflow }}-${{ github.ref }}
@@ -43,7 +42,7 @@ jobs:
if: steps.check_release.outputs.skip == 'true' if: steps.check_release.outputs.skip == 'true'
run: echo "Release already exists, skipping workflow." run: echo "Release already exists, skipping workflow."
# Parse tag meta-data (rc?, maintenance line, etc.) # Parse tag metadata (rc?, maintenance line, etc.)
- name: Parse tag - name: Parse tag
if: steps.check_release.outputs.skip == 'false' if: steps.check_release.outputs.skip == 'false'
id: tag id: tag
@@ -51,12 +50,12 @@ jobs:
with: with:
script: | script: |
const ref = context.ref.replace('refs/tags/', ''); // e.g. v0.31.5-rc.1 const ref = context.ref.replace('refs/tags/', ''); // e.g. v0.31.5-rc.1
const m = ref.match(/^v(\d+\.\d+\.\d+)(-(?:alpha|beta|rc)\.\d+)?$/); // ['0.31.5', '-rc.1' | '-beta.1' | …] const m = ref.match(/^v(\d+\.\d+\.\d+)(-rc\.\d+)?$/); // ['0.31.5', '-rc.1']
if (!m) { if (!m) {
core.setFailed(`❌ tag '${ref}' must match 'vX.Y.Z' or 'vX.Y.Z-(alpha|beta|rc).N'`); core.setFailed(`❌ tag '${ref}' must match 'vX.Y.Z' or 'vX.Y.Z-rc.N'`);
return; return;
} }
const version = m[1] + (m[2] ?? ''); // 0.31.5-rc.1 const version = m[1] + (m[2] ?? ''); // 0.31.5rc.1
const isRc = Boolean(m[2]); const isRc = Boolean(m[2]);
const [maj, min] = m[1].split('.'); const [maj, min] = m[1].split('.');
core.setOutput('tag', ref); // v0.31.5-rc.1 core.setOutput('tag', ref); // v0.31.5-rc.1
@@ -64,7 +63,7 @@ jobs:
core.setOutput('is_rc', isRc); // true core.setOutput('is_rc', isRc); // true
core.setOutput('line', `${maj}.${min}`); // 0.31 core.setOutput('line', `${maj}.${min}`); // 0.31
# Detect base branch (main or release-X.Y) the tag was pushed from # Detect base branch (main or releaseX.Y) the tag was pushed from
- name: Get base branch - name: Get base branch
if: steps.check_release.outputs.skip == 'false' if: steps.check_release.outputs.skip == 'false'
id: get_base id: get_base
@@ -169,7 +168,7 @@ jobs:
}); });
console.log(`Draft release created for ${tag}`); console.log(`Draft release created for ${tag}`);
} else { } else {
console.log(`Re-using existing release ${tag}`); console.log(`Reusing existing release ${tag}`);
} }
core.setOutput('upload_url', rel.upload_url); core.setOutput('upload_url', rel.upload_url);
@@ -182,7 +181,7 @@ jobs:
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Create release-X.Y.Z branch and push (force-update) # Create releaseX.Y.Z branch and push (forceupdate)
- name: Create release branch - name: Create release branch
if: steps.check_release.outputs.skip == 'false' if: steps.check_release.outputs.skip == 'false'
run: | run: |

View File

@@ -1,5 +1,5 @@
This is the third release candidate for the upcoming Cozystack v0.31.0 release. This is the second release candidate for the upcoming Cozystack v0.31.0 release.
The release notes show changes accumulated since the release of previous version, Cozystack v0.30.0. The release notes show changes accumulated since the release of Cozystack v0.30.0.
Cozystack 0.31.0 further advances GPU support, monitoring, and all-around convenience features. Cozystack 0.31.0 further advances GPU support, monitoring, and all-around convenience features.
@@ -12,21 +12,18 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven
* [platform] Cozystack etcd-operator (@klinch0 in https://github.com/cozystack/cozystack/pull/850) * [platform] Cozystack etcd-operator (@klinch0 in https://github.com/cozystack/cozystack/pull/850)
* Introduce support for cross-architecture builds and Cozystack on ARM: * Introduce support for cross-architecture builds and Cozystack on ARM:
* [build] Refactor Makefiles introducing build variables. (@nbykov0 in https://github.com/cozystack/cozystack/pull/907) * [build] Refactor Makefiles introducing build variables. (@nbykov0 in https://github.com/cozystack/cozystack/pull/907)
* [build] Add support for multi-architecture and cross-platform image builds. (@nbykov0 in https://github.com/cozystack/cozystack/pull/932 and https://github.com/cozystack/cozystack/pull/970) * [build] Add support for multi-architecture and cross-platform image builds. (@nbykov0 in https://github.com/cozystack/cozystack/pull/932)
* [platform] Introduce a new controller to synchronize tenant HelmReleases and propagate configuration changes. (@klinch0 in https://github.com/cozystack/cozystack/pull/870) * [platform] Introduce a new controller to synchronize tenant HelmReleases and propagate configuration changes. (@klinch0 in https://github.com/cozystack/cozystack/pull/870)
* [platform] Introduce options `expose-services`, `expose-ingress` and `expose-external-ips` to the ingress service. (@kvaps in https://github.com/cozystack/cozystack/pull/929) * [platform] Introduce options `expose-services`, `expose-ingress` and `expose-external-ips` to the ingress service. (@kvaps in https://github.com/cozystack/cozystack/pull/929)
* [kubevirt] Enable exporting VMs. (@kvaps in https://github.com/cozystack/cozystack/pull/808) * [kubevirt] Enable exporting VMs. (@kvaps in https://github.com/cozystack/cozystack/pull/808)
* [kubevirt] Make KubeVirt's CPU allocation ratio configurable. (@lllamnyp in https://github.com/cozystack/cozystack/pull/905) * [kubevirt] Make KubeVirt's CPU allocation ratio configurable. (@lllamnyp in https://github.com/cozystack/cozystack/pull/905)
* [virtual-machine] Add support for various storages. (@kvaps in https://github.com/cozystack/cozystack/pull/974)
* [cozystack-controller] Record the IP address pool and storage class in Workload objects. (@lllamnyp in https://github.com/cozystack/cozystack/pull/831) * [cozystack-controller] Record the IP address pool and storage class in Workload objects. (@lllamnyp in https://github.com/cozystack/cozystack/pull/831)
* [cilium] Enable Cilium Gateway API. (@zdenekjanda in https://github.com/cozystack/cozystack/pull/924) * [cilium] Enable Cilium Gateway API. (@zdenekjanda in https://github.com/cozystack/cozystack/pull/924)
* [cilium] Enable user-added parameters in a tenant cluster Cilium. (@lllamnyp in https://github.com/cozystack/cozystack/pull/917) * [cilium] Enable user-added parameters in a tenant cluster Cilium. (@lllamnyp in https://github.com/cozystack/cozystack/pull/917)
* [apps] Remove user-facing config of limits and requests. (@lllamnyp in https://github.com/cozystack/cozystack/pull/935)
* Update the Cozystack release policy to include long-lived release branches and start with release candidates. Update CI workflows and docs accordingly. * Update the Cozystack release policy to include long-lived release branches and start with release candidates. Update CI workflows and docs accordingly.
* Use release branches `release-X.Y` for gathering and releasing fixes after initial `vX.Y.0` release. (@kvaps in https://github.com/cozystack/cozystack/pull/816) * Use release branches `release-X.Y` for gathering and releasing fixes after initial `vX.Y.0` release. (@kvaps in https://github.com/cozystack/cozystack/pull/816)
* Automatically create release branches after initial `vX.Y.0` release is published. (@kvaps in https://github.com/cozystack/cozystack/pull/886) * Automatically create release branches after initial `vX.Y.0` release is published. (@kvaps in https://github.com/cozystack/cozystack/pull/886)
* Introduce Release Candidate versions. Automate patch backporting by applying patches from pull requests labeled `[backport]` to the current release branch. (@kvaps in https://github.com/cozystack/cozystack/pull/841 and https://github.com/cozystack/cozystack/pull/901, @nickvolynkin in https://github.com/cozystack/cozystack/pull/890) * Introduce Release Candidate versions. Automate patch backporting by applying patches from pull requests labeled `[backport]` to the current release branch. (@kvaps in https://github.com/cozystack/cozystack/pull/841 and https://github.com/cozystack/cozystack/pull/901, @nickvolynkin in https://github.com/cozystack/cozystack/pull/890)
* Support alpha and beta pre-releases. (@kvaps in https://github.com/cozystack/cozystack/pull/978)
* Commit changes in release pipelines under `github-actions <github-actions@github.com>`. (@kvaps in https://github.com/cozystack/cozystack/pull/823) * Commit changes in release pipelines under `github-actions <github-actions@github.com>`. (@kvaps in https://github.com/cozystack/cozystack/pull/823)
* Describe the Cozystack release workflow. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/817 and https://github.com/cozystack/cozystack/pull/897) * Describe the Cozystack release workflow. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/817 and https://github.com/cozystack/cozystack/pull/897)
@@ -45,7 +42,6 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven
* [kubernetes] Fix merging `valuesOverride` for tenant clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/879) * [kubernetes] Fix merging `valuesOverride` for tenant clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/879)
* [kubernetes] Fix `ubuntu-container-disk` tag. (@kvaps in https://github.com/cozystack/cozystack/pull/887) * [kubernetes] Fix `ubuntu-container-disk` tag. (@kvaps in https://github.com/cozystack/cozystack/pull/887)
* [kubernetes] Refactor Helm manifests for tenant Kubernetes clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/866) * [kubernetes] Refactor Helm manifests for tenant Kubernetes clusters. (@kvaps in https://github.com/cozystack/cozystack/pull/866)
* [kubernetes] Fix Ingress-NGINX depends on Cert-Manager . (@kvaps in https://github.com/cozystack/cozystack/pull/976)
* [tenant] Fix an issue with accessing external IPs of a cluster from the cluster itself. (@kvaps in https://github.com/cozystack/cozystack/pull/854) * [tenant] Fix an issue with accessing external IPs of a cluster from the cluster itself. (@kvaps in https://github.com/cozystack/cozystack/pull/854)
* [cluster-api] Remove the no longer necessary workaround for Kamaji. (@kvaps in https://github.com/cozystack/cozystack/pull/867, patched in https://github.com/cozystack/cozystack/pull/956) * [cluster-api] Remove the no longer necessary workaround for Kamaji. (@kvaps in https://github.com/cozystack/cozystack/pull/867, patched in https://github.com/cozystack/cozystack/pull/956)
* [monitoring] Remove legacy label "POD" from the exclude filter in metrics. (@xy2 in https://github.com/cozystack/cozystack/pull/826) * [monitoring] Remove legacy label "POD" from the exclude filter in metrics. (@xy2 in https://github.com/cozystack/cozystack/pull/826)
@@ -66,8 +62,6 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven
* [ci] Fix release branch creation. (@kvaps in https://github.com/cozystack/cozystack/pull/884) * [ci] Fix release branch creation. (@kvaps in https://github.com/cozystack/cozystack/pull/884)
* [ci, dx] Reduce noise in the test logs by suppressing the `wget` progress bar. (@lllamnyp in https://github.com/cozystack/cozystack/pull/865) * [ci, dx] Reduce noise in the test logs by suppressing the `wget` progress bar. (@lllamnyp in https://github.com/cozystack/cozystack/pull/865)
* [ci] Revert "automatically trigger tests in releasing PR". (@kvaps in https://github.com/cozystack/cozystack/pull/900) * [ci] Revert "automatically trigger tests in releasing PR". (@kvaps in https://github.com/cozystack/cozystack/pull/900)
* [ci] Force-update release branch on tagged main commits . (@kvaps in https://github.com/cozystack/cozystack/pull/977)
* [docs] Explain that tenants cannot have dashes in the names. (@NickVolynkin in https://github.com/cozystack/cozystack/pull/980)
## Dependencies ## Dependencies
@@ -80,8 +74,7 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven
* Update tenant Kubernetes to v1.32. (@kvaps in https://github.com/cozystack/cozystack/pull/871) * Update tenant Kubernetes to v1.32. (@kvaps in https://github.com/cozystack/cozystack/pull/871)
* Update flux-operator to 0.20.0. (@kingdonb in https://github.com/cozystack/cozystack/pull/880 and https://github.com/cozystack/cozystack/pull/934) * Update flux-operator to 0.20.0. (@kingdonb in https://github.com/cozystack/cozystack/pull/880 and https://github.com/cozystack/cozystack/pull/934)
* Update multiple Cluster API components. (@kvaps in https://github.com/cozystack/cozystack/pull/867 and https://github.com/cozystack/cozystack/pull/947) * Update multiple Cluster API components. (@kvaps in https://github.com/cozystack/cozystack/pull/867 and https://github.com/cozystack/cozystack/pull/947)
* Update KamajiControlPlane to edge-25.4.1. (@kvaps in https://github.com/cozystack/cozystack/pull/953, fixed by @nbykov0 in https://github.com/cozystack/cozystack/pull/983) * Update KamajiControlPlane to edge-25.4.1. (@kvaps in https://github.com/cozystack/cozystack/pull/953)
* Update cert-manager to v1.17.2. (@kvaps in https://github.com/cozystack/cozystack/pull/975)
## Maintenance ## Maintenance
@@ -94,4 +87,4 @@ Cozystack 0.31.0 further advances GPU support, monitoring, and all-around conven
* @zdenekjanda made their first contribution in https://github.com/cozystack/cozystack/pull/924 * @zdenekjanda made their first contribution in https://github.com/cozystack/cozystack/pull/924
* @gwynbleidd2106 made their first contribution in https://github.com/cozystack/cozystack/pull/962 * @gwynbleidd2106 made their first contribution in https://github.com/cozystack/cozystack/pull/962
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.30.0...v0.31.0-rc.3 **Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.30.0...v0.31.0-rc.2

View File

@@ -1,117 +0,0 @@
#!/bin/sh
###############################################################################
# cozytest.sh - Bats-compatible test runner with live trace and enhanced #
# output, written in pure shell #
###############################################################################
set -eu
TEST_FILE=${1:?Usage: ./cozytest.sh <file.bats> [pattern]}
PATTERN=${2:-*}
LINE='----------------------------------------------------------------'
cols() { stty size 2>/dev/null | awk '{print $2}' || echo 80; }
MAXW=$(( $(cols) - 12 )); [ "$MAXW" -lt 40 ] && MAXW=70
BEGIN=$(date +%s)
timestamp() { s=$(( $(date +%s) - BEGIN )); printf '[%02d:%02d]' $((s/60)) $((s%60)); }
###############################################################################
# run_one <fn> <title> #
###############################################################################
run_one() {
fn=$1 title=$2
tmp=$(mktemp -d) || { echo "Failed to create temp directory" >&2; exit 1; }
log="$tmp/log"
echo "╭ » Run test: $title"
START=$(date +%s)
skip_next="+ $fn" # первую строку трассировки с именем функции пропустим
{
(
PS4='+ ' # prefix for set -x
set -eu -x # strict + trace
"$fn"
)
printf '__RC__%s\n' "$?"
} 2>&1 | tee "$log" | while IFS= read -r line; do
case "$line" in
'__RC__'*) : ;;
'+ '*) cmd=${line#'+ '}
[ "$cmd" = "${skip_next#+ }" ] && continue
case "$cmd" in
'set -e'|'set -x'|'set -u'|'return 0') continue ;;
esac
out=$cmd ;;
*) out=$line ;;
esac
now=$(( $(date +%s) - START ))
[ ${#out} -gt "$MAXW" ] && out="$(printf '%.*s…' "$MAXW" "$out")"
printf '┊[%02d:%02d] %s\n' $((now/60)) $((now%60)) "$out"
done
rc=$(awk '/^__RC__/ {print substr($0,7)}' "$log" | tail -n1)
[ -z "$rc" ] && rc=1
now=$(( $(date +%s) - START ))
if [ "$rc" -eq 0 ]; then
printf '╰[%02d:%02d] ✅ Test OK: %s\n' $((now/60)) $((now%60)) "$title"
else
printf '╰[%02d:%02d] ❌ Test failed: %s (exit %s)\n' \
$((now/60)) $((now%60)) "$title" "$rc"
echo "----- captured output -----------------------------------------"
grep -v '^__RC__' "$log"
echo "$LINE"
exit "$rc"
fi
rm -rf "$tmp"
}
###############################################################################
# convert .bats -> shell-functions #
###############################################################################
TMP_SH=$(mktemp) || { echo "Failed to create temp file" >&2; exit 1; }
trap 'rm -f "$TMP_SH"' EXIT
awk '
/^@test[[:space:]]+"/ {
line = substr($0, index($0, "\"") + 1)
title = substr(line, 1, index(line, "\"") - 1)
fname = "test_"
for (i = 1; i <= length(title); i++) {
c = substr(title, i, 1)
fname = fname (c ~ /[A-Za-z0-9]/ ? c : "_")
}
printf("### %s\n", title)
printf("%s() {\n", fname)
print " set -e" # ошибка → падение теста
next
}
/^}$/ {
print " return 0" # если автор не сделал exit 1 — тест ОК
print "}"
next
}
{ print }
' "$TEST_FILE" > "$TMP_SH"
[ -f "$TMP_SH" ] || { echo "Failed to generate test functions" >&2; exit 1; }
# shellcheck disable=SC1090
. "$TMP_SH"
###############################################################################
# run selected tests #
###############################################################################
awk -v pat="$PATTERN" '
/^### / {
title = substr($0, 5)
name = "test_"
for (i = 1; i <= length(title); i++) {
c = substr(title, i, 1)
name = name (c ~ /[A-Za-z0-9]/ ? c : "_")
}
if (pat == "*" || index(title, pat) > 0)
printf("%s %s\n", name, title)
}
' "$TMP_SH" | while IFS=' ' read -r fn title; do
run_one "$fn" "$title"
done

View File

@@ -1,94 +0,0 @@
#!/usr/bin/env bats
# -----------------------------------------------------------------------------
# Cozystack endtoend provisioning test (Bats)
# -----------------------------------------------------------------------------
@test "Create tenant with isolated mode enabled" {
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 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=5m --for=jsonpath='{.status.v1beta2.readyReplicas}'=2
}

View File

@@ -3,13 +3,25 @@
# Cozystack endtoend provisioning test (Bats) # Cozystack endtoend provisioning test (Bats)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
export TALOSCONFIG=$PWD/talosconfig
export KUBECONFIG=$PWD/kubeconfig
# Runs before each @test
setup() {
[ ! -f ${BATS_RUN_TMPDIR}/.skip ] || skip "skip remaining tests" ]
}
# Runs after each @test
teardown() {
[ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_RUN_TMPDIR}/.skip
}
@test "Environment variable COZYSTACK_INSTALLER_YAML is defined" { @test "Environment variable COZYSTACK_INSTALLER_YAML is defined" {
if [ -z "${COZYSTACK_INSTALLER_YAML:-}" ]; then if [ -z "${COZYSTACK_INSTALLER_YAML:-}" ]; then
echo 'COZYSTACK_INSTALLER_YAML environment variable is not set!' >&2 echo 'COZYSTACK_INSTALLER_YAML environment variable is not set!' >&2
echo >&2 echo >&2
echo 'Please export it with the following command:' >&2 echo 'Please export it with the following command:' >&2
echo ' export COZYSTACK_INSTALLER_YAML=$(helm template -n cozy-system installer packages/core/installer)' >&2 echo ' export COZYSTACK_INSTALLER_YAML=$(helm template -n cozy-system installer packages/core/installer)' >&2
exit 1
fi fi
} }
@@ -19,7 +31,6 @@
echo >&2 echo >&2
echo "Enable it with:" >&2 echo "Enable it with:" >&2
echo " echo 1 > /proc/sys/net/ipv4/ip_forward" >&2 echo " echo 1 > /proc/sys/net/ipv4/ip_forward" >&2
exit 1
fi fi
} }
@@ -112,7 +123,7 @@ EOF
} }
@test "Wait until Talos API port 50000 is reachable on all machines" { @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' timeout 60 bash -c '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" { @test "Generate Talos cluster configuration" {
@@ -211,23 +222,23 @@ EOF
done done
# Wait for Talos services to come up again # 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' timeout 60 bash -c '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" { @test "Bootstrap Talos cluster" {
# Bootstrap etcd on the first node # 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' timeout 10 bash -c 'until talosctl bootstrap -n 192.168.123.11 -e 192.168.123.11; do sleep 1; done'
# Wait until etcd is healthy # 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 180 bash -c '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' timeout 60 bash -c '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 # Retrieve kubeconfig
rm -f kubeconfig rm -f kubeconfig
talosctl kubeconfig kubeconfig -e 192.168.123.10 -n 192.168.123.10 talosctl kubeconfig kubeconfig -e 192.168.123.10 -n 192.168.123.10
# Wait until all three nodes register in Kubernetes # 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' timeout 60 bash -c 'until [ $(kubectl get node --no-headers | wc -l) -eq 3 ]; do sleep 1; done'
} }
@test "Install Cozystack" { @test "Install Cozystack" {
@@ -250,9 +261,9 @@ EOF
kubectl wait deployment/cozystack -n cozy-system --timeout=1m --for=condition=Available kubectl wait deployment/cozystack -n cozy-system --timeout=1m --for=condition=Available
# Wait until HelmReleases appear & reconcile them # Wait until HelmReleases appear & reconcile them
timeout 60 sh -ec 'until kubectl get hr -A | grep -q cozys; do sleep 1; done' timeout 60 bash -c 'until kubectl get hr -A | grep -q cozys; do sleep 1; done'
sleep 5 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 | awk 'NR>1 {print "kubectl wait --timeout=15m --for=condition=ready -n "$1" hr/"$2" &"} END {print "wait"}' | bash -x
# Fail the test if any HelmRelease is not Ready # Fail the test if any HelmRelease is not Ready
if kubectl get hr -A | grep -v " True " | grep -v NAME; then if kubectl get hr -A | grep -v " True " | grep -v NAME; then
@@ -263,14 +274,14 @@ EOF
@test "Wait for ClusterAPI provider deployments" { @test "Wait for ClusterAPI provider deployments" {
# Wait for ClusterAPI provider deployments # Wait for ClusterAPI 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' timeout 60 bash -c '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 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" { @test "Wait for LINSTOR and configure storage" {
# Linstor controller and nodes # Linstor controller and nodes
kubectl wait deployment/linstor-controller -n cozy-linstor --timeout=5m --for=condition=available 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' timeout 60 bash -c '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 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 kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data
@@ -344,7 +355,7 @@ EOF
# Patch root tenant and wait for its releases # 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}}'
timeout 60 sh -ec 'until kubectl get hr -n tenant-root etcd ingress monitoring tenant-root >/dev/null 2>&1; do sleep 1; done' timeout 60 bash -c '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 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 if ! kubectl wait hr/monitoring -n tenant-root --timeout=2m --for=condition=ready; then
@@ -356,7 +367,7 @@ EOF
kubectl patch configmap/cozystack -n cozy-system --type merge -p '{"data":{"expose-services":"api,dashboard,cdi-uploadproxy,vm-exportproxy,keycloak"}}' kubectl patch configmap/cozystack -n cozy-system --type merge -p '{"data":{"expose-services":"api,dashboard,cdi-uploadproxy,vm-exportproxy,keycloak"}}'
# NGINX ingress controller # 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' timeout 60 bash -c '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 kubectl wait deploy/root-ingress-controller -n tenant-root --timeout=5m --for=condition=available
# etcd statefulset # etcd statefulset
@@ -373,15 +384,12 @@ EOF
# Verify Grafana via ingress # Verify Grafana via ingress
ingress_ip=$(kubectl get svc root-ingress-controller -n tenant-root -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 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 curl -sS -k "https://${ingress_ip}" -H 'Host: grafana.example.org' | grep -q Found
echo "Failed to access Grafana via ingress at ${ingress_ip}" >&2
exit 1
fi
} }
@test "Keycloak OIDC stack is healthy" { @test "Keycloak OIDC stack is healthy" {
kubectl patch configmap/cozystack -n cozy-system --type merge -p '{"data":{"oidc-enabled":"true"}}' 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' timeout 120 bash -c '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 kubectl wait hr/keycloak hr/keycloak-configure hr/keycloak-operator -n cozy-keycloak --timeout=10m --for=condition=ready
} }

View File

@@ -16,15 +16,13 @@ if [ ! -f "$file" ] || [ ! -s "$file" ]; then
exit 0 exit 0
fi fi
miss_map=$(mktemp) miss_map=$(echo "$new_map" | awk 'NR==FNR { nm[$1 " " $2] = $3; next } { if (!($1 " " $2 in nm)) print $1, $2, $3}' - "$file")
trap 'rm -f "$miss_map"' EXIT
echo -n "$new_map" | awk 'NR==FNR { nm[$1 " " $2] = $3; next } { if (!($1 " " $2 in nm)) print $1, $2, $3}' - "$file" > $miss_map
# search accross all tags sorted by version # search accross all tags sorted by version
search_commits=$(git ls-remote --tags origin | awk -F/ '$3 ~ /v[0-9]+.[0-9]+.[0-9]+/ {print}' | sort -k2,2 -rV | awk '{print $1}') search_commits=$(git ls-remote --tags origin | awk -F/ '$3 ~ /v[0-9]+.[0-9]+.[0-9]+/ {print}' | sort -k2,2 -rV | awk '{print $1}')
resolved_miss_map=$( resolved_miss_map=$(
while read -r chart version commit; do echo "$miss_map" | while read -r chart version commit; do
# if version is found in HEAD, it's HEAD # if version is found in HEAD, it's HEAD
if [ "$(awk '$1 == "version:" {print $2}' ./${chart}/Chart.yaml)" = "${version}" ]; then if [ "$(awk '$1 == "version:" {print $2}' ./${chart}/Chart.yaml)" = "${version}" ]; then
echo "$chart $version HEAD" echo "$chart $version HEAD"
@@ -58,7 +56,7 @@ resolved_miss_map=$(
fi fi
echo "$chart $version $found_tag" echo "$chart $version $found_tag"
done < $miss_map done
) )
printf "%s\n" "$new_map" "$resolved_miss_map" | sort -k1,1 -k2,2 -V | awk '$1' > "$file" printf "%s\n" "$new_map" "$resolved_miss_map" | sort -k1,1 -k2,2 -V | awk '$1' > "$file"

View File

@@ -1,65 +0,0 @@
#!/bin/sh
set -e
usage() {
printf "%s\n" "Usage:" >&2 ;
printf -- "%s\n" '---' >&2 ;
printf "%s %s\n" "$0" "INPUT_DIR OUTPUT_DIR TMP_DIR [DEPENDENCY_DIR]" >&2 ;
printf -- "%s\n" '---' >&2 ;
printf "%s\n" "Takes a helm repository from INPUT_DIR, with an optional library repository in" >&2 ;
printf "%s\n" "DEPENDENCY_DIR, prepares a view of the git archive at select points in history" >&2 ;
printf "%s\n" "in TMP_DIR and packages helm charts, outputting the tarballs to OUTPUT_DIR" >&2 ;
}
if [ "x$(basename $PWD)" != "xpackages" ]
then
echo "Error: This script must run from the ./packages/ directory" >&2
echo >&2
usage
exit 1
fi
if [ "x$#" != "x3" ] && [ "x$#" != "x4" ]
then
echo "Error: This script takes 3 or 4 arguments" >&2
echo "Got $# arguments:" "$@" >&2
echo >&2
usage
exit 1
fi
input_dir=$1
output_dir=$2
tmp_dir=$3
if [ "x$#" = "x4" ]
then
dependency_dir=$4
fi
rm -rf "${output_dir:?}"
mkdir -p "${output_dir}"
while read package _ commit
do
# this lets devs build the packages from a dirty repo for quick local testing
if [ "x$commit" = "xHEAD" ]
then
helm package "${input_dir}/${package}" -d "${output_dir}"
continue
fi
git archive --format tar "${commit}" "${input_dir}/${package}" | tar -xf- -C "${tmp_dir}/"
# the library chart is not present in older commits and git archive doesn't fail gracefully if the path is not found
if [ "x${dependency_dir}" != "x" ] && git ls-tree --name-only "${commit}" "${dependency_dir}" | grep -qx "${dependency_dir}"
then
git archive --format tar "${commit}" "${dependency_dir}" | tar -xf- -C "${tmp_dir}/"
fi
helm package "${tmp_dir}/${input_dir}/${package}" -d "${output_dir}"
rm -rf "${tmp_dir:?}/${input_dir:?}/${package:?}"
if [ "x${dependency_dir}" != "x" ]
then
rm -rf "${tmp_dir:?}/${dependency_dir:?}"
fi
done < "${input_dir}/versions_map"
helm repo index "${output_dir}"

View File

@@ -1,8 +1,14 @@
OUT=../_out/repos/apps OUT=../../_out/repos/apps
TMP := $(shell mktemp -d) TMP=../../_out/repos/apps/historical
repo: repo:
cd .. && ../hack/package_chart.sh apps $(OUT) $(TMP) library rm -rf "$(OUT)"
mkdir -p "$(OUT)"
awk '$$3 != "HEAD" {print "mkdir -p $(TMP)/" $$1 "-" $$2}' versions_map | sh -ex
awk '$$3 != "HEAD" {print "git archive " $$3 " " $$1 " | tar -xf- --strip-components=1 -C $(TMP)/" $$1 "-" $$2 }' versions_map | sh -ex
helm package -d "$(OUT)" $$(find . $(TMP) -mindepth 2 -maxdepth 2 -name Chart.yaml | awk 'sub("/Chart.yaml", "")' | sort -V)
cd "$(OUT)" && helm repo index . --url http://cozystack.cozy-system.svc/repos/apps
rm -rf "$(TMP)"
fix-chartnames: fix-chartnames:
find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done

View File

@@ -16,7 +16,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.9.0 version: 0.8.0
# This is the version number of the application being deployed. This version number should be # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to # incremented each time you make changes to the application. Versions are not expected to

View File

@@ -1 +0,0 @@
../../../library/cozy-lib

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/clickhouse-backup:0.9.0@sha256:3faf7a4cebf390b9053763107482de175aa0fdb88c1e77424fd81100b1c3a205 ghcr.io/cozystack/cozystack/clickhouse-backup:0.8.0@sha256:3faf7a4cebf390b9053763107482de175aa0fdb88c1e77424fd81100b1c3a205

View File

@@ -122,9 +122,9 @@ spec:
- name: clickhouse - name: clickhouse
image: clickhouse/clickhouse-server:24.9.2.42 image: clickhouse/clickhouse-server:24.9.2.42
{{- if .Values.resources }} {{- if .Values.resources }}
resources: {{- include "cozy-lib.resources.sanitize" .Values.resources | nindent 16 }} resources: {{- toYaml .Values.resources | nindent 16 }}
{{- else if ne .Values.resourcesPreset "none" }} {{- else if ne .Values.resourcesPreset "none" }}
resources: {{- include "cozy-lib.resources.preset" .Values.resourcesPreset | nindent 16 }} resources: {{- include "resources.preset" (dict "type" .Values.resourcesPreset "Release" .Release) | nindent 16 }}
{{- end }} {{- end }}
volumeMounts: volumeMounts:
- name: data-volume-template - name: data-volume-template

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/postgres-backup:0.12.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f ghcr.io/cozystack/cozystack/postgres-backup:0.11.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f

View File

@@ -11,9 +11,6 @@ spec:
{{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }}
{{- if $rawConstraints }} {{- if $rawConstraints }}
{{- $rawConstraints | fromYaml | toYaml | nindent 2 }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }}
labelSelector:
matchLabels:
cnpg.io/cluster: {{ .Release.Name }}-postgres
{{- end }} {{- end }}
{{- end }} {{- end }}
minSyncReplicas: {{ .Values.quorum.minSyncReplicas }} minSyncReplicas: {{ .Values.quorum.minSyncReplicas }}

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/nginx-cache:0.5.0@sha256:158c35dd6a512bd14e86a423be5c8c7ca91ac71999c73cce2714e4db60a2db43 ghcr.io/cozystack/cozystack/nginx-cache:0.5.0@sha256:785bd69cb593dc1509875d1e3128dac1a013b099fbb02f39330298d798706a0e

View File

@@ -16,7 +16,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.21.0 version: 0.20.0
# This is the version number of the application being deployed. This version number should be # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to # incremented each time you make changes to the application. Versions are not expected to

View File

@@ -1,199 +1,77 @@
# Managed Kubernetes Service # Managed Kubernetes Service
## Managed Kubernetes in Cozystack ## Overview
Whenever you want to deploy a custom containerized application in Cozystack, it's best to deploy it to a managed Kubernetes cluster. The Managed Kubernetes Service offers a streamlined solution for efficiently managing server workloads. Kubernetes has emerged as the industry standard, providing a unified and accessible API, primarily utilizing YAML for configuration. This means that teams can easily understand and work with Kubernetes, streamlining infrastructure management.
Cozystack deploys and manages Kubernetes-as-a-service as standalone applications within each tenants isolated environment. The Kubernetes leverages robust software design patterns, enabling continuous recovery in any scenario through the reconciliation method. Additionally, it ensures seamless scaling across a multitude of servers, addressing the challenges posed by complex and outdated APIs found in traditional virtualization platforms. This managed service eliminates the need for developing custom solutions or modifying source code, saving valuable time and effort.
In Cozystack, such clusters are named tenant Kubernetes clusters, while the base Cozystack cluster is called a management or root cluster.
Tenant clusters are fully separated from the management cluster and are intended for deploying tenant-specific or customer-developed applications.
Within a tenant cluster, users can take advantage of LoadBalancer services and easily provision physical volumes as needed. ## Deployment Details
The control-plane operates within containers, while the worker nodes are deployed as virtual machines, all seamlessly managed by the application.
## Why Use a Managed Kubernetes Cluster? The managed Kubernetes service deploys a standard Kubernetes cluster utilizing the Cluster API, Kamaji as control-plane provicer and the KubeVirt infrastructure provider. This ensures a consistent and reliable setup for workloads.
Kubernetes has emerged as the industry standard, providing a unified and accessible API, primarily utilizing YAML for configuration. Within this 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.
This means that teams can easily understand and work with Kubernetes, streamlining infrastructure management.
Kubernetes leverages robust software design patterns, enabling continuous recovery in any scenario through the reconciliation method. - Docs: https://github.com/clastix/kamaji
Additionally, it ensures seamless scaling across a multitude of servers, - Docs: https://cluster-api.sigs.k8s.io/
addressing the challenges posed by complex and outdated APIs found in traditional virtualization platforms. - GitHub: https://github.com/clastix/kamaji
This managed service eliminates the need for developing custom solutions or modifying source code, saving valuable time and effort. - GitHub: https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt
- GitHub: https://github.com/kubevirt/csi-driver
The Managed Kubernetes Service in Cozystack offers a streamlined solution for efficiently managing server workloads.
## Starting Work ## How-Tos
Once the tenant Kubernetes cluster is ready, you can get a kubeconfig file to work with it. How to access to deployed cluster:
It can be done via UI or a `kubectl` request:
- Open the Cozystack dashboard, switch to your tenant, find and open the application page. Copy one of the config files from the **Secrets** section. ```
- Run the following command (using the management cluster kubeconfig): kubectl get secret -n <namespace> kubernetes-<clusterName>-admin-kubeconfig -o go-template='{{ printf "%s\n" (index .data "super-admin.conf" | base64decode) }}' > test
```
```bash
kubectl get secret -n tenant-<name> kubernetes-<clusterName>-admin-kubeconfig -o go-template='{{ printf "%s\n" (index .data "admin.conf" | base64decode) }}' > admin.conf
```
There are several kubeconfig options available:
- `admin.conf` — The standard kubeconfig for accessing your new cluster.
You can create additional Kubernetes users using this configuration.
- `admin.svc` — Same token as `admin.conf`, but with the API server address set to the internal service name.
Use it for applications running inside the cluster that need API access.
- `super-admin.conf` — Similar to `admin.conf`, but with extended administrative permissions.
Intended for troubleshooting and cluster maintenance tasks.
- `super-admin.svc` — Same as `super-admin.conf`, but pointing to the internal API server address.
## Implementation Details
A tenant Kubernetes cluster in Cozystack is essentially Kubernetes-in-Kubernetes.
Deploying it involves the following components:
- **Kamaji Control Plane**: [Kamaji](https://kamaji.clastix.io/) is an open-source project that facilitates the deployment
of Kubernetes control planes as pods within a root cluster.
Each control plane pod includes essential components like `kube-apiserver`, `controller-manager`, and `scheduler`,
allowing for efficient multi-tenancy and resource utilization.
- **Etcd Cluster**: A dedicated etcd cluster is deployed using Ænix's [etcd-operator](https://github.com/aenix-io/etcd-operator).
It provides reliable and scalable key-value storage for the Kubernetes control plane.
- **Worker Nodes**: Virtual Machines are provisioned to serve as worker nodes using KubeVirt.
These nodes are configured to join the tenant Kubernetes cluster, enabling the deployment and management of workloads.
- **Cluster API**: Cozystack is using the [Kubernetes Cluster API](https://cluster-api.sigs.k8s.io/) to provision the components of a cluster.
This architecture ensures isolated, scalable, and efficient tenant Kubernetes environments.
See the reference for components utilized in this service:
- [Kamaji Control Plane](https://kamaji.clastix.io)
- [Kamaji — Cluster API](https://kamaji.clastix.io/cluster-api/)
- [github.com/clastix/kamaji](https://github.com/clastix/kamaji)
- [KubeVirt](https://kubevirt.io/)
- [github.com/kubevirt/kubevirt](https://github.com/kubevirt/kubevirt)
- [github.com/aenix-io/etcd-operator](https://github.com/aenix-io/etcd-operator)
- [Kubernetes Cluster API](https://cluster-api.sigs.k8s.io/)
- [github.com/kubernetes-sigs/cluster-api-provider-kubevirt](https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt)
- [github.com/kubevirt/csi-driver](https://github.com/kubevirt/csi-driver)
## Parameters ## Parameters
### Common Parameters ### Common parameters
| Name | Description | Value | | Name | Description | Value |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------ | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| `host` | Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty. | `""` | | `host` | The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host). | `""` |
| `controlPlane.replicas` | Number of replicas for Kubernetes control-plane components. | `2` | | `controlPlane.replicas` | Number of replicas for Kubernetes control-plane components | `2` |
| `storageClass` | StorageClass used to store user data. | `replicated` | | `storageClass` | StorageClass used to store user data | `replicated` |
| `nodeGroups` | nodeGroups configuration | `{}` | | `nodeGroups` | nodeGroups configuration | `{}` |
### Cluster Addons ### Cluster Addons
| Name | Description | Value | | Name | Description | Value |
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `addons.certManager.enabled` | Enable cert-manager, which automatically creates and manages SSL/TLS certificates. | `false` | | `addons.certManager.enabled` | Enables the cert-manager | `false` |
| `addons.certManager.valuesOverride` | Custom values to override | `{}` | | `addons.certManager.valuesOverride` | Custom values to override | `{}` |
| `addons.cilium.valuesOverride` | Custom values to override | `{}` | | `addons.cilium.valuesOverride` | Custom values to override | `{}` |
| `addons.gatewayAPI.enabled` | Enable the Gateway API | `false` | | `addons.gatewayAPI.enabled` | Enables the Gateway API | `false` |
| `addons.ingressNginx.enabled` | Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). | `false` | | `addons.ingressNginx.enabled` | Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role) | `false` |
| `addons.ingressNginx.valuesOverride` | Custom values to override | `{}` | | `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.ingressNginx.hosts` | List of domain names that should be passed through to the cluster by upper cluster | `[]` |
| `addons.gpuOperator.enabled` | Enable the GPU-operator | `false` | | `addons.gpuOperator.enabled` | Enables the gpu-operator | `false` |
| `addons.gpuOperator.valuesOverride` | Custom values to override | `{}` | | `addons.gpuOperator.valuesOverride` | Custom values to override | `{}` |
| `addons.fluxcd.enabled` | Enable FluxCD | `false` | | `addons.fluxcd.enabled` | Enables Flux CD | `false` |
| `addons.fluxcd.valuesOverride` | Custom values to override | `{}` | | `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.enabled` | Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage | `false` |
| `addons.monitoringAgents.valuesOverride` | Custom values to override | `{}` | | `addons.monitoringAgents.valuesOverride` | Custom values to override | `{}` |
| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `{}` | | `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `{}` |
### Kubernetes Control Plane Configuration ### Kubernetes control plane configuration
| Name | Description | Value | | Name | Description | Value |
| -------------------------------------------------- | ---------------------------------------------------------------------------- | ------- | | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `controlPlane.apiServer.resources` | Explicit CPU/memory resource requests and limits for the API server. | `{}` | | `controlPlane.apiServer.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` |
| `controlPlane.apiServer.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `small` | | `controlPlane.apiServer.resources` | Resources | `{}` |
| `controlPlane.controllerManager.resources` | Explicit CPU/memory resource requests and limits for the controller manager. | `{}` | | `controlPlane.controllerManager.resources` | Resources | `{}` |
| `controlPlane.controllerManager.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` | | `controlPlane.controllerManager.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` |
| `controlPlane.scheduler.resources` | Explicit CPU/memory resource requests and limits for the scheduler. | `{}` | | `controlPlane.scheduler.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` |
| `controlPlane.scheduler.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` | | `controlPlane.scheduler.resources` | Resources | `{}` |
| `controlPlane.konnectivity.server.resources` | Explicit CPU/memory resource requests and limits for the Konnectivity. | `{}` | | `controlPlane.konnectivity.server.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` |
| `controlPlane.konnectivity.server.resourcesPreset` | Use a common resources preset when `resources` is not set explicitly. | `micro` | | `controlPlane.konnectivity.server.resources` | Resources | `{}` |
In production environments, it's recommended to set `resources` explicitly.
Example of `controlPlane.*.resources`:
```yaml ## U Series
resources:
limits:
cpu: 4000m
memory: 4Gi
requests:
cpu: 100m
memory: 512Mi
```
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.
## Resources Reference
### instanceType Resources
The following instanceType resources are provided by Cozystack:
| Name | vCPUs | Memory |
|---------------|-------|--------|
| `cx1.2xlarge` | 8 | 16Gi |
| `cx1.4xlarge` | 16 | 32Gi |
| `cx1.8xlarge` | 32 | 64Gi |
| `cx1.large` | 2 | 4Gi |
| `cx1.medium` | 1 | 2Gi |
| `cx1.xlarge` | 4 | 8Gi |
| `gn1.2xlarge` | 8 | 32Gi |
| `gn1.4xlarge` | 16 | 64Gi |
| `gn1.8xlarge` | 32 | 128Gi |
| `gn1.xlarge` | 4 | 16Gi |
| `m1.2xlarge` | 8 | 64Gi |
| `m1.4xlarge` | 16 | 128Gi |
| `m1.8xlarge` | 32 | 256Gi |
| `m1.large` | 2 | 16Gi |
| `m1.xlarge` | 4 | 32Gi |
| `n1.2xlarge` | 16 | 32Gi |
| `n1.4xlarge` | 32 | 64Gi |
| `n1.8xlarge` | 64 | 128Gi |
| `n1.large` | 4 | 8Gi |
| `n1.medium` | 4 | 4Gi |
| `n1.xlarge` | 8 | 16Gi |
| `o1.2xlarge` | 8 | 32Gi |
| `o1.4xlarge` | 16 | 64Gi |
| `o1.8xlarge` | 32 | 128Gi |
| `o1.large` | 2 | 8Gi |
| `o1.medium` | 1 | 4Gi |
| `o1.micro` | 1 | 1Gi |
| `o1.nano` | 1 | 512Mi |
| `o1.small` | 1 | 2Gi |
| `o1.xlarge` | 4 | 16Gi |
| `rt1.2xlarge` | 8 | 32Gi |
| `rt1.4xlarge` | 16 | 64Gi |
| `rt1.8xlarge` | 32 | 128Gi |
| `rt1.large` | 2 | 8Gi |
| `rt1.medium` | 1 | 4Gi |
| `rt1.micro` | 1 | 1Gi |
| `rt1.small` | 1 | 2Gi |
| `rt1.xlarge` | 4 | 16Gi |
| `u1.2xlarge` | 8 | 32Gi |
| `u1.2xmedium` | 2 | 4Gi |
| `u1.4xlarge` | 16 | 64Gi |
| `u1.8xlarge` | 32 | 128Gi |
| `u1.large` | 2 | 8Gi |
| `u1.medium` | 1 | 4Gi |
| `u1.micro` | 1 | 1Gi |
| `u1.nano` | 1 | 512Mi |
| `u1.small` | 1 | 2Gi |
| `u1.xlarge` | 4 | 16Gi |
### U Series: Universal
The U Series is quite neutral and provides resources for The U Series is quite neutral and provides resources for
general purpose applications. general purpose applications.
@@ -204,7 +82,7 @@ attitude towards workloads.
VMs of instance types will share physical CPU cores on a VMs of instance types will share physical CPU cores on a
time-slice basis with other VMs. time-slice basis with other VMs.
#### U Series Characteristics ### U Series Characteristics
Specific characteristics of this series are: Specific characteristics of this series are:
- *Burstable CPU performance* - The workload has a baseline compute - *Burstable CPU performance* - The workload has a baseline compute
@@ -213,14 +91,14 @@ Specific characteristics of this series are:
- *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4, for less - *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4, for less
noise per node. noise per node.
### O Series: Overcommitted ## O Series
The O Series is based on the U Series, with the only difference The O Series is based on the U Series, with the only difference
being that memory is overcommitted. being that memory is overcommitted.
*O* is the abbreviation for "Overcommitted". *O* is the abbreviation for "Overcommitted".
#### O Series Characteristics ### UO Series Characteristics
Specific characteristics of this series are: Specific characteristics of this series are:
- *Burstable CPU performance* - The workload has a baseline compute - *Burstable CPU performance* - The workload has a baseline compute
@@ -231,7 +109,7 @@ Specific characteristics of this series are:
- *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4, for less - *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4, for less
noise per node. noise per node.
### CX Series: Compute Exclusive ## CX Series
The CX Series provides exclusive compute resources for compute The CX Series provides exclusive compute resources for compute
intensive applications. intensive applications.
@@ -245,7 +123,7 @@ the IO threading from cores dedicated to the workload.
In addition, in this series, the NUMA topology of the used In addition, in this series, the NUMA topology of the used
cores is provided to the VM. cores is provided to the VM.
#### CX Series Characteristics ### CX Series Characteristics
Specific characteristics of this series are: Specific characteristics of this series are:
- *Hugepages* - Hugepages are used in order to improve memory - *Hugepages* - Hugepages are used in order to improve memory
@@ -260,14 +138,14 @@ Specific characteristics of this series are:
optimize guest sided cache utilization. optimize guest sided cache utilization.
- *vCPU-To-Memory Ratio (1:2)* - A vCPU-to-Memory ratio of 1:2. - *vCPU-To-Memory Ratio (1:2)* - A vCPU-to-Memory ratio of 1:2.
### M Series: Memory ## M Series
The M Series provides resources for memory intensive The M Series provides resources for memory intensive
applications. applications.
*M* is the abbreviation of "Memory". *M* is the abbreviation of "Memory".
#### M Series Characteristics ### M Series Characteristics
Specific characteristics of this series are: Specific characteristics of this series are:
- *Hugepages* - Hugepages are used in order to improve memory - *Hugepages* - Hugepages are used in order to improve memory
@@ -278,7 +156,7 @@ Specific characteristics of this series are:
- *vCPU-To-Memory Ratio (1:8)* - A vCPU-to-Memory ratio of 1:8, for much - *vCPU-To-Memory Ratio (1:8)* - A vCPU-to-Memory ratio of 1:8, for much
less noise per node. less noise per node.
### RT Series: RealTime ## RT Series
The RT Series provides resources for realtime applications, like Oslat. The RT Series provides resources for realtime applications, like Oslat.
@@ -287,7 +165,7 @@ The RT Series provides resources for realtime applications, like Oslat.
This series of instance types requires nodes capable of running This series of instance types requires nodes capable of running
realtime applications. realtime applications.
#### RT Series Characteristics ### RT Series Characteristics
Specific characteristics of this series are: Specific characteristics of this series are:
- *Hugepages* - Hugepages are used in order to improve memory - *Hugepages* - Hugepages are used in order to improve memory
@@ -301,3 +179,57 @@ Specific characteristics of this series are:
- *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4 starting from - *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4 starting from
the medium size. the medium size.
## Resources
The following instancetype resources are provided by Cozystack:
Name | vCPUs | Memory
-----|-------|-------
cx1.2xlarge | 8 | 16Gi
cx1.4xlarge | 16 | 32Gi
cx1.8xlarge | 32 | 64Gi
cx1.large | 2 | 4Gi
cx1.medium | 1 | 2Gi
cx1.xlarge | 4 | 8Gi
gn1.2xlarge | 8 | 32Gi
gn1.4xlarge | 16 | 64Gi
gn1.8xlarge | 32 | 128Gi
gn1.xlarge | 4 | 16Gi
m1.2xlarge | 8 | 64Gi
m1.4xlarge | 16 | 128Gi
m1.8xlarge | 32 | 256Gi
m1.large | 2 | 16Gi
m1.xlarge | 4 | 32Gi
n1.2xlarge | 16 | 32Gi
n1.4xlarge | 32 | 64Gi
n1.8xlarge | 64 | 128Gi
n1.large | 4 | 8Gi
n1.medium | 4 | 4Gi
n1.xlarge | 8 | 16Gi
o1.2xlarge | 8 | 32Gi
o1.4xlarge | 16 | 64Gi
o1.8xlarge | 32 | 128Gi
o1.large | 2 | 8Gi
o1.medium | 1 | 4Gi
o1.micro | 1 | 1Gi
o1.nano | 1 | 512Mi
o1.small | 1 | 2Gi
o1.xlarge | 4 | 16Gi
rt1.2xlarge | 8 | 32Gi
rt1.4xlarge | 16 | 64Gi
rt1.8xlarge | 32 | 128Gi
rt1.large | 2 | 8Gi
rt1.medium | 1 | 4Gi
rt1.micro | 1 | 1Gi
rt1.small | 1 | 2Gi
rt1.xlarge | 4 | 16Gi
u1.2xlarge | 8 | 32Gi
u1.2xmedium | 2 | 4Gi
u1.4xlarge | 16 | 64Gi
u1.8xlarge | 32 | 128Gi
u1.large | 2 | 8Gi
u1.medium | 1 | 4Gi
u1.micro | 1 | 1Gi
u1.nano | 1 | 512Mi
u1.small | 1 | 2Gi
u1.xlarge | 4 | 16Gi

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/cluster-autoscaler:0.21.0@sha256:7605161dcb8ebab8070a9f277452f6f96b33c4184c4a57f9f57f9876367e5f1f ghcr.io/cozystack/cozystack/cluster-autoscaler:0.20.0@sha256:8dbbe95fe8b933a1d1a3c638120f386fec0c4950092d3be5ddd592375bb8a760

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.21.0@sha256:4bee0705f0e1a6c93f4f5b343c988f2e05031844656ca0ff9ef12c88738687d3 ghcr.io/cozystack/cozystack/kubevirt-cloud-provider:0.20.0@sha256:41fcdbd2f667f68bf554dd184ce362e65b88f350dc7b938c86079b719f5e5099

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.21.0@sha256:fb6d3ce9d6d948285a6d399c852e15259d6922162ec7c44177d2274243f59d1f ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.20.0@sha256:61580fea56b745580989d85e3ef2563e9bb1accc9c4185f8e636bacd02551319

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.32@sha256:184b81529ae72684279799b12f436cc7a511d8ff5bd1e9a30478799c7707c625 ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.32@sha256:186af6f71891bfc6d6948454802c08922baa508c30e7f79e330b7d26ffceff03

View File

@@ -31,16 +31,6 @@ spec:
{{- end }} {{- end }}
cluster.x-k8s.io/deployment-name: {{ $.Release.Name }}-{{ .groupName }} cluster.x-k8s.io/deployment-name: {{ $.Release.Name }}-{{ .groupName }}
spec: spec:
{{- $configMap := lookup "v1" "ConfigMap" "cozy-system" "cozystack-scheduling" }}
{{- if $configMap }}
{{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }}
{{- if $rawConstraints }}
{{- $rawConstraints | fromYaml | toYaml | nindent 10 }}
labelSelector:
matchLabels:
cluster.x-k8s.io/cluster-name: {{ $.Release.Name }}
{{- end }}
{{- end }}
domain: domain:
{{- if and .group.resources .group.resources.cpu }} {{- if and .group.resources .group.resources.cpu }}
cpu: cpu:

View File

@@ -6,11 +6,6 @@ ingress-nginx:
hostNetwork: true hostNetwork: true
service: service:
enabled: false enabled: false
{{- if not .Values.addons.certManager.enabled }}
admissionWebhooks:
certManager:
enabled: false
{{- end }}
nodeSelector: nodeSelector:
node-role.kubernetes.io/ingress-nginx: "" node-role.kubernetes.io/ingress-nginx: ""
{{- end }} {{- end }}

View File

@@ -4,7 +4,7 @@
"properties": { "properties": {
"host": { "host": {
"type": "string", "type": "string",
"description": "Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty.", "description": "The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host).",
"default": "" "default": ""
}, },
"controlPlane": { "controlPlane": {
@@ -12,20 +12,15 @@
"properties": { "properties": {
"replicas": { "replicas": {
"type": "number", "type": "number",
"description": "Number of replicas for Kubernetes control-plane components.", "description": "Number of replicas for Kubernetes control-plane components",
"default": 2 "default": 2
}, },
"apiServer": { "apiServer": {
"type": "object", "type": "object",
"properties": { "properties": {
"resources": {
"type": "object",
"description": "Explicit CPU/memory resource requests and limits for the API server.",
"default": {}
},
"resourcesPreset": { "resourcesPreset": {
"type": "string", "type": "string",
"description": "Use a common resources preset when `resources` is not set explicitly.", "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", "default": "small",
"enum": [ "enum": [
"none", "none",
@@ -37,6 +32,11 @@
"xlarge", "xlarge",
"2xlarge" "2xlarge"
] ]
},
"resources": {
"type": "object",
"description": "Resources",
"default": {}
} }
} }
}, },
@@ -45,12 +45,12 @@
"properties": { "properties": {
"resources": { "resources": {
"type": "object", "type": "object",
"description": "Explicit CPU/memory resource requests and limits for the controller manager.", "description": "Resources",
"default": {} "default": {}
}, },
"resourcesPreset": { "resourcesPreset": {
"type": "string", "type": "string",
"description": "Use a common resources preset when `resources` is not set explicitly.", "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", "default": "micro",
"enum": [ "enum": [
"none", "none",
@@ -68,14 +68,9 @@
"scheduler": { "scheduler": {
"type": "object", "type": "object",
"properties": { "properties": {
"resources": {
"type": "object",
"description": "Explicit CPU/memory resource requests and limits for the scheduler.",
"default": {}
},
"resourcesPreset": { "resourcesPreset": {
"type": "string", "type": "string",
"description": "Use a common resources preset when `resources` is not set explicitly.", "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", "default": "micro",
"enum": [ "enum": [
"none", "none",
@@ -87,6 +82,11 @@
"xlarge", "xlarge",
"2xlarge" "2xlarge"
] ]
},
"resources": {
"type": "object",
"description": "Resources",
"default": {}
} }
} }
}, },
@@ -96,14 +96,9 @@
"server": { "server": {
"type": "object", "type": "object",
"properties": { "properties": {
"resources": {
"type": "object",
"description": "Explicit CPU/memory resource requests and limits for the Konnectivity.",
"default": {}
},
"resourcesPreset": { "resourcesPreset": {
"type": "string", "type": "string",
"description": "Use a common resources preset when `resources` is not set explicitly.", "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", "default": "micro",
"enum": [ "enum": [
"none", "none",
@@ -115,6 +110,11 @@
"xlarge", "xlarge",
"2xlarge" "2xlarge"
] ]
},
"resources": {
"type": "object",
"description": "Resources",
"default": {}
} }
} }
} }
@@ -124,7 +124,7 @@
}, },
"storageClass": { "storageClass": {
"type": "string", "type": "string",
"description": "StorageClass used to store user data.", "description": "StorageClass used to store user data",
"default": "replicated" "default": "replicated"
}, },
"addons": { "addons": {
@@ -135,7 +135,7 @@
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"description": "Enable cert-manager, which automatically creates and manages SSL/TLS certificates.", "description": "Enables the cert-manager",
"default": false "default": false
}, },
"valuesOverride": { "valuesOverride": {
@@ -160,7 +160,7 @@
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"description": "Enable the Gateway API", "description": "Enables the Gateway API",
"default": false "default": false
} }
} }
@@ -170,7 +170,7 @@
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"description": "Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role).", "description": "Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role)",
"default": false "default": false
}, },
"valuesOverride": { "valuesOverride": {
@@ -180,7 +180,7 @@
}, },
"hosts": { "hosts": {
"type": "array", "type": "array",
"description": "List of domain names that the parent cluster should route to this tenant cluster.", "description": "List of domain names that should be passed through to the cluster by upper cluster",
"default": [], "default": [],
"items": {} "items": {}
} }
@@ -191,7 +191,7 @@
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"description": "Enable the GPU-operator", "description": "Enables the gpu-operator",
"default": false "default": false
}, },
"valuesOverride": { "valuesOverride": {
@@ -206,7 +206,7 @@
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"description": "Enable FluxCD", "description": "Enables Flux CD",
"default": false "default": false
}, },
"valuesOverride": { "valuesOverride": {
@@ -221,7 +221,7 @@
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"description": "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.", "description": "Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage",
"default": false "default": false
}, },
"valuesOverride": { "valuesOverride": {

View File

@@ -1,8 +1,8 @@
## @section Common Parameters ## @section Common parameters
## @param host Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty. ## @param host The hostname used to access the Kubernetes cluster externally (defaults to using the cluster name as a subdomain for the tenant host).
## @param controlPlane.replicas Number of replicas for Kubernetes control-plane components. ## @param controlPlane.replicas Number of replicas for Kubernetes control-plane components
## @param storageClass StorageClass used to store user data. ## @param storageClass StorageClass used to store user data
## ##
host: "" host: ""
storageClass: replicated storageClass: replicated
@@ -37,7 +37,7 @@ addons:
## Cert-manager: automatically creates and manages SSL/TLS certificate ## Cert-manager: automatically creates and manages SSL/TLS certificate
## ##
certManager: certManager:
## @param addons.certManager.enabled Enable cert-manager, which automatically creates and manages SSL/TLS certificates. ## @param addons.certManager.enabled Enables the cert-manager
## @param addons.certManager.valuesOverride Custom values to override ## @param addons.certManager.valuesOverride Custom values to override
enabled: false enabled: false
valuesOverride: {} valuesOverride: {}
@@ -51,17 +51,17 @@ addons:
## Gateway API ## Gateway API
## ##
gatewayAPI: gatewayAPI:
## @param addons.gatewayAPI.enabled Enable the Gateway API ## @param addons.gatewayAPI.enabled Enables the Gateway API
enabled: false enabled: false
## Ingress-NGINX Controller ## Ingress-NGINX Controller
## ##
ingressNginx: ingressNginx:
## @param addons.ingressNginx.enabled Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). ## @param addons.ingressNginx.enabled Enable Ingress-NGINX controller (expect nodes with 'ingress-nginx' role)
## @param addons.ingressNginx.valuesOverride Custom values to override ## @param addons.ingressNginx.valuesOverride Custom values to override
## ##
enabled: false enabled: false
## @param addons.ingressNginx.hosts List of domain names that the parent cluster should route to this tenant cluster. ## @param addons.ingressNginx.hosts List of domain names that should be passed through to the cluster by upper cluster
## e.g: ## e.g:
## hosts: ## hosts:
## - example.org ## - example.org
@@ -73,7 +73,7 @@ addons:
## GPU-operator: NVIDIA GPU Operator ## GPU-operator: NVIDIA GPU Operator
## ##
gpuOperator: gpuOperator:
## @param addons.gpuOperator.enabled Enable the GPU-operator ## @param addons.gpuOperator.enabled Enables the gpu-operator
## @param addons.gpuOperator.valuesOverride Custom values to override ## @param addons.gpuOperator.valuesOverride Custom values to override
enabled: false enabled: false
valuesOverride: {} valuesOverride: {}
@@ -81,7 +81,7 @@ addons:
## Flux CD ## Flux CD
## ##
fluxcd: fluxcd:
## @param addons.fluxcd.enabled Enable FluxCD ## @param addons.fluxcd.enabled Enables Flux CD
## @param addons.fluxcd.valuesOverride Custom values to override ## @param addons.fluxcd.valuesOverride Custom values to override
## ##
enabled: false enabled: false
@@ -90,7 +90,7 @@ addons:
## MonitoringAgents ## MonitoringAgents
## ##
monitoringAgents: monitoringAgents:
## @param 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. ## @param addons.monitoringAgents.enabled Enables MonitoringAgents (fluentbit, vmagents for sending logs and metrics to storage) if tenant monitoring enabled, send to tenant storage, else to root storage
## @param addons.monitoringAgents.valuesOverride Custom values to override ## @param addons.monitoringAgents.valuesOverride Custom values to override
## ##
enabled: false enabled: false
@@ -103,15 +103,15 @@ addons:
## ##
valuesOverride: {} valuesOverride: {}
## @section Kubernetes Control Plane Configuration ## @section Kubernetes control plane configuration
## ##
controlPlane: controlPlane:
replicas: 2 replicas: 2
apiServer: apiServer:
## @param controlPlane.apiServer.resources Explicit CPU/memory resource requests and limits for the API server. ## @param controlPlane.apiServer.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).
## @param controlPlane.apiServer.resourcesPreset Use a common resources preset when `resources` is not set explicitly. ## @param controlPlane.apiServer.resources Resources
## e.g: ## e.g:
## resources: ## resources:
## limits: ## limits:
@@ -125,20 +125,20 @@ controlPlane:
resources: {} resources: {}
controllerManager: controllerManager:
## @param controlPlane.controllerManager.resources Explicit CPU/memory resource requests and limits for the controller manager. ## @param controlPlane.controllerManager.resources Resources
## @param controlPlane.controllerManager.resourcesPreset Use a common resources preset when `resources` is not set explicitly. ## @param controlPlane.controllerManager.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" resourcesPreset: "micro"
resources: {} resources: {}
scheduler: scheduler:
## @param controlPlane.scheduler.resources Explicit CPU/memory resource requests and limits for the scheduler. ## @param controlPlane.scheduler.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).
## @param controlPlane.scheduler.resourcesPreset Use a common resources preset when `resources` is not set explicitly. ## @param controlPlane.scheduler.resources Resources
resourcesPreset: "micro" resourcesPreset: "micro"
resources: {} resources: {}
konnectivity: konnectivity:
server: server:
## @param controlPlane.konnectivity.server.resources Explicit CPU/memory resource requests and limits for the Konnectivity. ## @param controlPlane.konnectivity.server.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).
## @param controlPlane.konnectivity.server.resourcesPreset Use a common resources preset when `resources` is not set explicitly. ## @param controlPlane.konnectivity.server.resources Resources
resourcesPreset: "micro" resourcesPreset: "micro"
resources: {} resources: {}

View File

@@ -16,7 +16,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.12.0 version: 0.11.0
# This is the version number of the application being deployed. This version number should be # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to # incremented each time you make changes to the application. Versions are not expected to

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/postgres-backup:0.12.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f ghcr.io/cozystack/cozystack/postgres-backup:0.11.0@sha256:10179ed56457460d95cd5708db2a00130901255fa30c4dd76c65d2ef5622b61f

View File

@@ -17,9 +17,6 @@ spec:
{{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }}
{{- if $rawConstraints }} {{- if $rawConstraints }}
{{- $rawConstraints | fromYaml | toYaml | nindent 2 }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }}
labelSelector:
matchLabels:
cnpg.io/cluster: {{ .Release.Name }}
{{- end }} {{- end }}
{{- end }} {{- end }}
postgresql: postgresql:

View File

@@ -4,55 +4,36 @@ A tenant is the main unit of security on the platform. The closest analogy would
Tenants can be created recursively and are subject to the following rules: Tenants can be created recursively and are subject to the following rules:
### Tenant naming ### Higher-level tenants can access lower-level ones.
Tenant names must be alphanumeric. Higher-level tenants can view and manage the applications of all their children.
Using dashes (`-`) in tenant names is not allowed, unlike with other services.
This limitation exists to keep consistent naming in tenants, nested tenants, and services deployed in them.
For example: ### Each tenant has its own domain
- The root tenant is named `root`, but internally it's referenced as `tenant-root`. By default (unless otherwise specified), it inherits the domain of its parent with a prefix of its name, for example, if the parent had the domain `example.org`, then `tenant-foo` would get the domain `foo.example.org` by default.
- A nested tenant could be named `foo`, which would result in `tenant-foo` in service names and URLs.
- However, a tenant can not be named `foo-bar`, because parsing names such as `tenant-foo-bar` would be ambiguous.
### Unique domains
Each tenant has its own domain.
By default, (unless otherwise specified), it inherits the domain of its parent with a prefix of its name.
For example, if the parent had the domain `example.org`, then `tenant-foo` would get the domain `foo.example.org` by default.
Kubernetes clusters created in this tenant namespace would get domains like: `kubernetes-cluster.foo.example.org` Kubernetes clusters created in this tenant namespace would get domains like: `kubernetes-cluster.foo.example.org`
Example: Example:
```text ```
tenant-root (example.org) tenant-root (example.org)
└── tenant-foo (foo.example.org) └── tenant-foo (foo.example.org)
└── kubernetes-cluster1 (kubernetes-cluster1.foo.example.org) └── kubernetes-cluster1 (kubernetes-cluster1.foo.example.org)
``` ```
### Nesting tenants and reusing parent services ### Lower-level tenants can access the cluster services of their parent (provided they do not run their own)
Tenants can be nested. Thus, you can create `tenant-u1` with a set of services like `etcd`, `ingress`, `monitoring`. And create another tenant namespace `tenant-u2` inside of `tenant-u1`.
A tenant administrator can create nested tenants using the "Tenant" application from the catalogue.
Higher-level tenants can view and manage the applications of all their children tenants.
If a tenant does not run their own cluster services, it can access ones of its parent.
For example, you create:
- Tenant `tenant-u1` with a set of services like `etcd`, `ingress`, `monitoring`.
- Tenant `tenant-u2` nested in `tenant-u1`.
Let's see what will happen when you run Kubernetes and Postgres under `tenant-u2` namespace. Let's see what will happen when you run Kubernetes and Postgres under `tenant-u2` namespace.
Since `tenant-u2` does not have its own cluster services like `etcd`, `ingress`, and `monitoring`, Since `tenant-u2` does not have its own cluster services like `etcd`, `ingress`, and `monitoring`, the applications will use the cluster services of the parent tenant.
the applications running in `tenant-u2` will use the cluster services of the parent tenant.
This in turn means: This in turn means:
- The Kubernetes cluster data will be stored in `etcd` for `tenant-u1`. - The Kubernetes cluster data will be stored in etcd for `tenant-u1`.
- Access to the cluster will be through the common `ingress` of `tenant-u1`. - Access to the cluster will be through the common ingress of `tenant-u1`.
- Essentially, all metrics will be collected in the `monitoring` from `tenant-u1`, and only that tenant will have access to them. - Essentially, all metrics will be collected in the monitoring from `tenant-u1`, and only it will have access to them.
Example: Example:
``` ```

View File

@@ -9,7 +9,7 @@ clickhouse 0.6.0 1ec10165
clickhouse 0.6.1 c62a83a7 clickhouse 0.6.1 c62a83a7
clickhouse 0.6.2 8267072d clickhouse 0.6.2 8267072d
clickhouse 0.7.0 93bdf411 clickhouse 0.7.0 93bdf411
clickhouse 0.9.0 HEAD clickhouse 0.8.0 HEAD
ferretdb 0.1.0 e9716091 ferretdb 0.1.0 e9716091
ferretdb 0.1.1 91b0499a ferretdb 0.1.1 91b0499a
ferretdb 0.2.0 6c5cf5bf ferretdb 0.2.0 6c5cf5bf
@@ -64,9 +64,7 @@ kubernetes 0.17.0 1fbbfcd0
kubernetes 0.17.1 fd240701 kubernetes 0.17.1 fd240701
kubernetes 0.18.0 721c12a7 kubernetes 0.18.0 721c12a7
kubernetes 0.19.0 93bdf411 kubernetes 0.19.0 93bdf411
kubernetes 0.20.0 609e7ede kubernetes 0.20.0 HEAD
kubernetes 0.20.1 f9f8bb2f
kubernetes 0.21.0 HEAD
mysql 0.1.0 263e47be mysql 0.1.0 263e47be
mysql 0.2.0 c24a103f mysql 0.2.0 c24a103f
mysql 0.3.0 53f2365e mysql 0.3.0 53f2365e
@@ -100,8 +98,7 @@ postgres 0.8.0 4e68e65c
postgres 0.9.0 8267072d postgres 0.9.0 8267072d
postgres 0.10.0 721c12a7 postgres 0.10.0 721c12a7
postgres 0.10.1 93bdf411 postgres 0.10.1 93bdf411
postgres 0.11.0 f9f8bb2f postgres 0.11.0 HEAD
postgres 0.12.0 HEAD
rabbitmq 0.1.0 263e47be rabbitmq 0.1.0 263e47be
rabbitmq 0.2.0 53f2365e rabbitmq 0.2.0 53f2365e
rabbitmq 0.3.0 6c5cf5bf rabbitmq 0.3.0 6c5cf5bf
@@ -160,8 +157,7 @@ virtual-machine 0.8.0 3fa4dd3a
virtual-machine 0.8.1 93c46161 virtual-machine 0.8.1 93c46161
virtual-machine 0.8.2 de19450f virtual-machine 0.8.2 de19450f
virtual-machine 0.9.0 721c12a7 virtual-machine 0.9.0 721c12a7
virtual-machine 0.9.1 93bdf411 virtual-machine 0.9.1 HEAD
virtual-machine 0.10.0 HEAD
vm-disk 0.1.0 d971f2ff vm-disk 0.1.0 d971f2ff
vm-disk 0.1.1 HEAD vm-disk 0.1.1 HEAD
vm-instance 0.1.0 1ec10165 vm-instance 0.1.0 1ec10165
@@ -172,7 +168,7 @@ vm-instance 0.4.1 0ab39f20
vm-instance 0.5.0 3fa4dd3a vm-instance 0.5.0 3fa4dd3a
vm-instance 0.5.1 de19450f vm-instance 0.5.1 de19450f
vm-instance 0.6.0 721c12a7 vm-instance 0.6.0 721c12a7
vm-instance 0.7.0 HEAD vm-instance 0.6.1 HEAD
vpn 0.1.0 263e47be vpn 0.1.0 263e47be
vpn 0.2.0 53f2365e vpn 0.2.0 53f2365e
vpn 0.3.0 6c5cf5bf vpn 0.3.0 6c5cf5bf

View File

@@ -17,10 +17,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.10.0 version: 0.9.1
# This is the version number of the application being deployed. This version number should be # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to # incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using. # follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes. # It is recommended to use it with quotes.
appVersion: 0.10.0 appVersion: 0.9.0

View File

@@ -9,4 +9,4 @@ generate:
&& yq -i -o json ".properties.instanceProfile.optional=true | .properties.instanceProfile.enum = $${PREFERENCES}" values.schema.json && yq -i -o json ".properties.instanceProfile.optional=true | .properties.instanceProfile.enum = $${PREFERENCES}" values.schema.json
yq -i -o json '.properties.externalPorts.items.type = "integer"' values.schema.json yq -i -o json '.properties.externalPorts.items.type = "integer"' values.schema.json
yq -i -o json '.properties.systemDisk.properties.image.enum = ["ubuntu", "cirros", "alpine", "fedora", "talos"]' values.schema.json yq -i -o json '.properties.systemDisk.properties.image.enum = ["ubuntu", "cirros", "alpine", "fedora", "talos"]' values.schema.json
yq -i -o json '.properties.externalMethod.enum = ["PortList", "WholeIP"]' values.schema.json yq -i -o json '.properties.externalMethod.enum = ["WholeIP", "PortList"]' values.schema.json

View File

@@ -39,7 +39,7 @@ virtctl ssh <user>@<vm>
| Name | Description | Value | | Name | Description | Value |
| ------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------ | | ------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------ |
| `external` | Enable external access from outside the cluster | `false` | | `external` | Enable external access from outside the cluster | `false` |
| `externalMethod` | specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` | `PortList` | | `externalMethod` | specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` | `WholeIP` |
| `externalPorts` | Specify ports to forward from outside the cluster | `[]` | | `externalPorts` | Specify ports to forward from outside the cluster | `[]` |
| `running` | Determines if the virtual machine should be running | `true` | | `running` | Determines if the virtual machine should be running | `true` |
| `instanceType` | Virtual Machine instance type | `u1.medium` | | `instanceType` | Virtual Machine instance type | `u1.medium` |

View File

@@ -17,7 +17,7 @@ spec:
selector: selector:
{{- include "virtual-machine.selectorLabels" . | nindent 4 }} {{- include "virtual-machine.selectorLabels" . | nindent 4 }}
ports: ports:
{{- if and (eq .Values.externalMethod "WholeIP") (not .Values.externalPorts) }} {{- if eq .Values.externalMethod "WholeIP" }}
- port: 65535 - port: 65535
{{- else }} {{- else }}
{{- range .Values.externalPorts }} {{- range .Values.externalPorts }}

View File

@@ -27,7 +27,10 @@ spec:
- metadata: - metadata:
name: {{ include "virtual-machine.fullname" . }} name: {{ include "virtual-machine.fullname" . }}
spec: spec:
storage: pvc:
volumeMode: Block
accessModes:
- ReadWriteMany
resources: resources:
requests: requests:
storage: {{ .Values.systemDisk.storage | quote }} storage: {{ .Values.systemDisk.storage | quote }}

View File

@@ -10,10 +10,10 @@
"externalMethod": { "externalMethod": {
"type": "string", "type": "string",
"description": "specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList`", "description": "specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList`",
"default": "PortList", "default": "WholeIP",
"enum": [ "enum": [
"PortList", "WholeIP",
"WholeIP" "PortList"
] ]
}, },
"externalPorts": { "externalPorts": {

View File

@@ -4,7 +4,7 @@
## @param externalMethod specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` ## @param externalMethod specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList`
## @param externalPorts [array] Specify ports to forward from outside the cluster ## @param externalPorts [array] Specify ports to forward from outside the cluster
external: false external: false
externalMethod: PortList externalMethod: WholeIP
externalPorts: externalPorts:
- 22 - 22

View File

@@ -17,10 +17,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.7.0 version: 0.6.1
# This is the version number of the application being deployed. This version number should be # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to # incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using. # follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes. # It is recommended to use it with quotes.
appVersion: 0.7.0 appVersion: 0.6.0

View File

@@ -9,4 +9,4 @@ generate:
PREFERENCES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/preferences.yaml | yq 'split(" ") | . + [""]' -o json) \ PREFERENCES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/preferences.yaml | yq 'split(" ") | . + [""]' -o json) \
&& yq -i -o json ".properties.instanceProfile.optional=true | .properties.instanceProfile.enum = $${PREFERENCES}" values.schema.json && yq -i -o json ".properties.instanceProfile.optional=true | .properties.instanceProfile.enum = $${PREFERENCES}" values.schema.json
yq -i -o json '.properties.externalPorts.items.type = "integer"' values.schema.json yq -i -o json '.properties.externalPorts.items.type = "integer"' values.schema.json
yq -i -o json '.properties.externalMethod.enum = ["PortList", "WholeIP"]' values.schema.json yq -i -o json '.properties.externalMethod.enum = ["WholeIP", "PortList"]' values.schema.json

View File

@@ -39,7 +39,7 @@ virtctl ssh <user>@<vm>
| Name | Description | Value | | Name | Description | Value |
| ------------------ | ---------------------------------------------------------------------------------------------------------- | ----------- | | ------------------ | ---------------------------------------------------------------------------------------------------------- | ----------- |
| `external` | Enable external access from outside the cluster | `false` | | `external` | Enable external access from outside the cluster | `false` |
| `externalMethod` | specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` | `PortList` | | `externalMethod` | specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` | `WholeIP` |
| `externalPorts` | Specify ports to forward from outside the cluster | `[]` | | `externalPorts` | Specify ports to forward from outside the cluster | `[]` |
| `running` | Determines if the virtual machine should be running | `true` | | `running` | Determines if the virtual machine should be running | `true` |
| `instanceType` | Virtual Machine instance type | `u1.medium` | | `instanceType` | Virtual Machine instance type | `u1.medium` |

View File

@@ -17,7 +17,7 @@ spec:
selector: selector:
{{- include "virtual-machine.selectorLabels" . | nindent 4 }} {{- include "virtual-machine.selectorLabels" . | nindent 4 }}
ports: ports:
{{- if and (eq .Values.externalMethod "WholeIP") (not .Values.externalPorts) }} {{- if eq .Values.externalMethod "WholeIP" }}
- port: 65535 - port: 65535
{{- else }} {{- else }}
{{- range .Values.externalPorts }} {{- range .Values.externalPorts }}

View File

@@ -10,10 +10,10 @@
"externalMethod": { "externalMethod": {
"type": "string", "type": "string",
"description": "specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList`", "description": "specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList`",
"default": "PortList", "default": "WholeIP",
"enum": [ "enum": [
"PortList", "WholeIP",
"WholeIP" "PortList"
] ]
}, },
"externalPorts": { "externalPorts": {

View File

@@ -4,7 +4,7 @@
## @param externalMethod specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList` ## @param externalMethod specify method to passthrough the traffic to the virtual machine. Allowed values: `WholeIP` and `PortList`
## @param externalPorts [array] Specify ports to forward from outside the cluster ## @param externalPorts [array] Specify ports to forward from outside the cluster
external: false external: false
externalMethod: PortList externalMethod: WholeIP
externalPorts: externalPorts:
- 22 - 22

View File

@@ -1,2 +1,2 @@
cozystack: cozystack:
image: ghcr.io/cozystack/cozystack/installer:v0.31.0@sha256:b70804d0a8662aeaaff23c876635ea6393f9c1e580932b54064bb2525faaa7ff image: ghcr.io/cozystack/cozystack/installer:v0.31.0-rc.2@sha256:05d812a6ac1df86c614b528e8d171af05c0080545ceee383d6cb043f415a4372

View File

@@ -30,13 +30,8 @@ image-e2e-sandbox:
yq -i '.e2e.image = strenv(IMAGE)' values.yaml yq -i '.e2e.image = strenv(IMAGE)' values.yaml
rm -f images/e2e-sandbox.json rm -f images/e2e-sandbox.json
test: test-cluster test-apps ## Run the end-to-end tests in existing sandbox test: ## Run the end-to-end tests in existing sandbox.
docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && export COZYSTACK_INSTALLER_YAML=$$(helm template -n cozy-system installer ./packages/core/installer) && hack/e2e.bats'
test-cluster: ## Run the end-to-end for creating a cluster
docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && export COZYSTACK_INSTALLER_YAML=$$(helm template -n cozy-system installer ./packages/core/installer) && hack/cozytest.sh hack/e2e-cluster.bats'
test-apps: ## Run the end-to-end tests for apps
docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && hack/cozytest.sh hack/e2e-apps.bats'
delete: ## Remove sandbox from existing Kubernetes cluster. delete: ## Remove sandbox from existing Kubernetes cluster.
docker rm -f "${SANDBOX_NAME}" || true docker rm -f "${SANDBOX_NAME}" || true
@@ -45,10 +40,5 @@ exec: ## Opens an interactive shell in the sandbox container.
docker exec -ti "${SANDBOX_NAME}" bash docker exec -ti "${SANDBOX_NAME}" bash
apply: delete apply: delete
docker run \ docker run -d --rm --name "${SANDBOX_NAME}" --privileged "$$(yq .e2e.image values.yaml)" sleep infinity
-d --rm --name "${SANDBOX_NAME}" --privileged \
-e TALOSCONFIG=/workspace/talosconfig \
-e KUBECONFIG=/workspace/kubeconfig \
"$$(yq .e2e.image values.yaml)" \
sleep infinity
docker cp "${ROOT_DIR}" "${SANDBOX_NAME}":/workspace docker cp "${ROOT_DIR}" "${SANDBOX_NAME}":/workspace

View File

@@ -8,7 +8,7 @@ ARG TARGETOS
ARG TARGETARCH ARG TARGETARCH
RUN apt update -q RUN apt update -q
RUN apt install -yq --no-install-recommends genisoimage ca-certificates qemu-kvm qemu-utils iproute2 iptables wget xz-utils netcat curl jq make git RUN apt install -yq --no-install-recommends genisoimage ca-certificates qemu-kvm qemu-utils iproute2 iptables wget xz-utils netcat curl jq make git bats
RUN curl -sSL "https://github.com/siderolabs/talos/releases/download/v${TALOSCTL_VERSION}/talosctl-${TARGETOS}-${TARGETARCH}" -o /usr/local/bin/talosctl \ RUN curl -sSL "https://github.com/siderolabs/talos/releases/download/v${TALOSCTL_VERSION}/talosctl-${TARGETOS}-${TARGETARCH}" -o /usr/local/bin/talosctl \
&& chmod +x /usr/local/bin/talosctl && chmod +x /usr/local/bin/talosctl
RUN curl -sSL "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl" -o /usr/local/bin/kubectl \ RUN curl -sSL "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl" -o /usr/local/bin/kubectl \

View File

@@ -1,2 +1,2 @@
e2e: e2e:
image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0@sha256:199af20b56a89ee0b495cdca98a05a0c41418da5570438c061acb3133fc9f003 image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.31.0-rc.2@sha256:2d35b2cce2f093c5c3145a08d9981e2bf28cf45a6804117d50bd6345a15ecd1a

View File

@@ -1,8 +1,14 @@
OUT=../_out/repos/extra OUT=../../_out/repos/extra
TMP := $(shell mktemp -d) TMP=../../_out/repos/extra/historical
repo: repo:
cd .. && ../hack/package_chart.sh extra $(OUT) $(TMP) library rm -rf "$(OUT)"
mkdir -p "$(OUT)"
awk '$$3 != "HEAD" {print "mkdir -p $(TMP)/" $$1 "-" $$2}' versions_map | sh -ex
awk '$$3 != "HEAD" {print "git archive " $$3 " " $$1 " | tar -xf- --strip-components=1 -C $(TMP)/" $$1 "-" $$2 }' versions_map | sh -ex
helm package -d "$(OUT)" $$(find . $(TMP) -mindepth 2 -maxdepth 2 -name Chart.yaml | awk 'sub("/Chart.yaml", "")' | sort -V)
cd "$(OUT)" && helm repo index . --url http://cozystack.cozy-system.svc/repos/extra
rm -rf "$(TMP)"
fix-chartnames: fix-chartnames:
find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/matchbox:v0.31.0@sha256:77d6aa48c3b175ab3ef84d3bb057634dcf4be8b99c4cea06a265d297d8f57943 ghcr.io/cozystack/cozystack/matchbox:v0.31.0-rc.2@sha256:78e5a28badd3c804e55e5c1376f12dad77e04b9f6f80637596939ba348f7104b

View File

@@ -3,4 +3,4 @@ name: monitoring
description: Monitoring and observability stack description: Monitoring and observability stack
icon: /logos/monitoring.svg icon: /logos/monitoring.svg
type: application type: application
version: 1.10.0 version: 1.9.2

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/grafana:1.10.0@sha256:c63978e1ed0304e8518b31ddee56c4e8115541b997d8efbe1c0a74da57140399 ghcr.io/cozystack/cozystack/grafana:1.9.2@sha256:c63978e1ed0304e8518b31ddee56c4e8115541b997d8efbe1c0a74da57140399

View File

@@ -10,9 +10,6 @@ spec:
{{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }}
{{- if $rawConstraints }} {{- if $rawConstraints }}
{{- $rawConstraints | fromYaml | toYaml | nindent 2 }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }}
labelSelector:
matchLabels:
cnpg.io/cluster: alerta-db
{{- end }} {{- end }}
{{- end }} {{- end }}
storage: storage:

View File

@@ -11,9 +11,6 @@ spec:
{{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }}
{{- if $rawConstraints }} {{- if $rawConstraints }}
{{- $rawConstraints | fromYaml | toYaml | nindent 2 }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }}
labelSelector:
matchLabels:
cnpg.io/cluster: grafana-db
{{- end }} {{- end }}
{{- end }} {{- end }}
monitoring: monitoring:

View File

@@ -38,8 +38,7 @@ monitoring 1.8.0 8c460528
monitoring 1.8.1 8267072d monitoring 1.8.1 8267072d
monitoring 1.9.0 45a7416c monitoring 1.9.0 45a7416c
monitoring 1.9.1 fd240701 monitoring 1.9.1 fd240701
monitoring 1.9.2 f9f8bb2f monitoring 1.9.2 HEAD
monitoring 1.10.0 HEAD
seaweedfs 0.1.0 71514249 seaweedfs 0.1.0 71514249
seaweedfs 0.2.0 5fb9cfe3 seaweedfs 0.2.0 5fb9cfe3
seaweedfs 0.2.1 fde4bcfa seaweedfs 0.2.1 fde4bcfa

View File

@@ -1,8 +0,0 @@
OUT=../_out/repos/library
TMP := $(shell mktemp -d)
repo:
cd .. && ../hack/package_chart.sh library $(OUT) $(TMP)
fix-chartnames:
find . -maxdepth 2 -name Chart.yaml | awk -F/ '{print $$2}' | while read i; do sed -i "s/^name: .*/name: $$i/" "$$i/Chart.yaml"; done

View File

@@ -1,23 +0,0 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@@ -1,18 +0,0 @@
apiVersion: v2
name: cozy-lib
description: Common Cozystack templates
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: library
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

View File

@@ -1,6 +0,0 @@
include ../../../scripts/common-envs.mk
include ../../../scripts/package.mk
generate:
readme-generator -v values.yaml -s values.schema.json -r README.md

View File

@@ -1 +0,0 @@
## Parameters

View File

@@ -1,49 +0,0 @@
{{/*
Copyright Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: APACHE-2.0
*/}}
{{/* vim: set filetype=mustache: */}}
{{/*
Return a resource request/limit object based on a given preset.
These presets are for basic testing and not meant to be used in production
{{ include "cozy-lib.resources.preset" "nano" -}}
*/}}
{{- define "cozy-lib.resources.preset" -}}
{{- $presets := dict
"nano" (dict
"requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi")
"limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi")
)
"micro" (dict
"requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi")
"limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi")
)
"small" (dict
"requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi")
"limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi")
)
"medium" (dict
"requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi")
"limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi")
)
"large" (dict
"requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi")
"limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi")
)
"xlarge" (dict
"requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi")
"limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi")
)
"2xlarge" (dict
"requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi")
"limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi")
)
}}
{{- if hasKey $presets . -}}
{{- index $presets . | toYaml -}}
{{- else -}}
{{- printf "ERROR: Preset key '%s' invalid. Allowed values are %s" . (join "," (keys $presets)) | fail -}}
{{- end -}}
{{- end -}}

View File

@@ -1,53 +0,0 @@
{{- /*
A sanitized resource map is a dict with resource-name => resource-quantity.
If not in such a form, requests are used, then limits. All resources are set
to have equal requests and limits, except CPU, that has only requests. The
template expects to receive a dict {"requests":{...}, "limits":{...}} as
input, e.g. {{ include "cozy-lib.resources.sanitize" .Values.resources }}.
Example input:
==============
limits:
cpu: 100m
memory: 1024Mi
requests:
cpu: 200m
memory: 512Mi
memory: 256Mi
devices.com/nvidia: "1"
Example output:
===============
limits:
devices.com/nvidia: "1"
memory: 256Mi
requests:
cpu: 200m
devices.com/nvidia: "1"
memory: 256Mi
*/}}
{{- define "cozy-lib.resources.sanitize" }}
{{- $sanitizedMap := dict }}
{{- if hasKey . "limits" }}
{{- range $k, $v := .limits }}
{{- $_ := set $sanitizedMap $k $v }}
{{- end }}
{{- end }}
{{- if hasKey . "requests" }}
{{- range $k, $v := .requests }}
{{- $_ := set $sanitizedMap $k $v }}
{{- end }}
{{- end }}
{{- range $k, $v := . }}
{{- if not (or (eq $k "requests") (eq $k "limits")) }}
{{- $_ := set $sanitizedMap $k $v }}
{{- end }}
{{- end }}
{{- $output := dict "requests" dict "limits" dict }}
{{- range $k, $v := $sanitizedMap }}
{{- $_ := set $output.requests $k $v }}
{{- if not (eq $k "cpu") }}
{{- $_ := set $output.limits $k $v }}
{{- end }}
{{- end }}
{{- $output | toYaml }}
{{- end }}

View File

@@ -1,5 +0,0 @@
{
"title": "Chart Values",
"type": "object",
"properties": {}
}

View File

@@ -1 +0,0 @@
{}

View File

@@ -1 +1 @@
ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:fc06d53f54b12cae8947fbd9ea444b41c2c8605718aa4a5c1e76e26b5e2ca518 ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:a219040fed290492f047818e5c5a864a30112ff418ad4b12b24de9709302427a

View File

@@ -6,7 +6,7 @@ annotations:
fingerprint: 1020CF3C033D4F35BAE1C19E1226061C665DF13E fingerprint: 1020CF3C033D4F35BAE1C19E1226061C665DF13E
url: https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg url: https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg
apiVersion: v2 apiVersion: v2
appVersion: v1.17.2 appVersion: v1.16.3
description: A Helm chart for cert-manager description: A Helm chart for cert-manager
home: https://cert-manager.io home: https://cert-manager.io
icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png
@@ -23,4 +23,4 @@ maintainers:
name: cert-manager name: cert-manager
sources: sources:
- https://github.com/cert-manager/cert-manager - https://github.com/cert-manager/cert-manager
version: v1.17.2 version: v1.16.3

View File

@@ -19,7 +19,7 @@ Before installing the chart, you must first install the cert-manager CustomResou
This is performed in a separate step to allow you to easily uninstall and reinstall cert-manager without deleting your installed custom resources. This is performed in a separate step to allow you to easily uninstall and reinstall cert-manager without deleting your installed custom resources.
```bash ```bash
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.crds.yaml $ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.3/cert-manager.crds.yaml
``` ```
To install the chart with the release name `cert-manager`: To install the chart with the release name `cert-manager`:
@@ -29,7 +29,7 @@ To install the chart with the release name `cert-manager`:
$ helm repo add jetstack https://charts.jetstack.io --force-update $ helm repo add jetstack https://charts.jetstack.io --force-update
## Install the cert-manager helm chart ## Install the cert-manager helm chart
$ helm install cert-manager --namespace cert-manager --version v1.17.2 jetstack/cert-manager $ helm install cert-manager --namespace cert-manager --version v1.16.3 jetstack/cert-manager
``` ```
In order to begin issuing certificates, you will need to set up a ClusterIssuer In order to begin issuing certificates, you will need to set up a ClusterIssuer
@@ -65,7 +65,7 @@ If you want to completely uninstall cert-manager from your cluster, you will als
delete the previously installed CustomResourceDefinition resources: delete the previously installed CustomResourceDefinition resources:
```console ```console
$ kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.crds.yaml $ kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.3/cert-manager.crds.yaml
``` ```
## Configuration ## Configuration
@@ -316,13 +316,7 @@ If not set and create is true, a name is generated using the fullname template.
#### **serviceAccount.annotations** ~ `object` #### **serviceAccount.annotations** ~ `object`
Optional additional annotations to add to the controller's Service Account. Templates are allowed for both keys and values. Optional additional annotations to add to the controller's Service Account.
Example using templating:
```yaml
annotations:
"{{ .Chart.Name }}-helm-chart/version": "{{ .Chart.Version }}"
```
#### **serviceAccount.labels** ~ `object` #### **serviceAccount.labels** ~ `object`
@@ -370,24 +364,17 @@ config:
kubernetesAPIQPS: 9000 kubernetesAPIQPS: 9000
kubernetesAPIBurst: 9000 kubernetesAPIBurst: 9000
numberOfConcurrentWorkers: 200 numberOfConcurrentWorkers: 200
enableGatewayAPI: true
# Feature gates as of v1.17.0. Listed with their default values.
# See https://cert-manager.io/docs/cli/controller/
featureGates: featureGates:
AdditionalCertificateOutputFormats: true # BETA - default=true AdditionalCertificateOutputFormats: true
AllAlpha: false # ALPHA - default=false DisallowInsecureCSRUsageDefinition: true
AllBeta: false # BETA - default=false ExperimentalCertificateSigningRequestControllers: true
ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false ExperimentalGatewayAPISupport: true
ExperimentalGatewayAPISupport: true # BETA - default=true LiteralCertificateSubject: true
LiteralCertificateSubject: true # BETA - default=true SecretsFilteredCaching: true
NameConstraints: true # BETA - default=true ServerSideApply: true
OtherNames: false # ALPHA - default=false StableCertificateRequestName: true
SecretsFilteredCaching: true # BETA - default=true UseCertificateRequestBasicConstraints: true
ServerSideApply: false # ALPHA - default=false ValidateCAA: true
StableCertificateRequestName: true # BETA - default=true
UseCertificateRequestBasicConstraints: false # ALPHA - default=false
UseDomainQualifiedFinalizer: true # BETA - default=false
ValidateCAA: false # ALPHA - default=false
# Configure the metrics server for TLS # Configure the metrics server for TLS
# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls
metricsTLSConfig: metricsTLSConfig:

View File

@@ -53,12 +53,6 @@ spec:
prometheus.io/port: '9402' prometheus.io/port: '9402'
{{- end }} {{- end }}
spec: spec:
{{- if not .Values.cainjector.serviceAccount.create }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
serviceAccountName: {{ template "cainjector.serviceAccountName" . }} serviceAccountName: {{ template "cainjector.serviceAccountName" . }}
{{- if hasKey .Values.cainjector "automountServiceAccountToken" }} {{- if hasKey .Values.cainjector "automountServiceAccountToken" }}
automountServiceAccountToken: {{ .Values.cainjector.automountServiceAccountToken }} automountServiceAccountToken: {{ .Values.cainjector.automountServiceAccountToken }}

View File

@@ -1,4 +1,3 @@
{{- if .Values.cainjector.enabled }}
{{- if and .Values.prometheus.enabled (not .Values.prometheus.podmonitor.enabled) }} {{- if and .Values.prometheus.enabled (not .Values.prometheus.podmonitor.enabled) }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
@@ -29,4 +28,3 @@ spec:
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: "cainjector" app.kubernetes.io/component: "cainjector"
{{- end }} {{- end }}
{{- end }}

View File

@@ -514,6 +514,7 @@ spec:
type: object type: object
required: required:
- create - create
- passwordSecretRef
properties: properties:
alias: alias:
description: |- description: |-
@@ -525,25 +526,17 @@ spec:
Create enables JKS keystore creation for the Certificate. Create enables JKS keystore creation for the Certificate.
If true, a file named `keystore.jks` will be created in the target If true, a file named `keystore.jks` will be created in the target
Secret resource, encrypted using the password stored in Secret resource, encrypted using the password stored in
`passwordSecretRef` or `password`. `passwordSecretRef`.
The keystore file will be updated immediately. The keystore file will be updated immediately.
If the issuer provided a CA certificate, a file named `truststore.jks` If the issuer provided a CA certificate, a file named `truststore.jks`
will also be created in the target Secret resource, encrypted using the will also be created in the target Secret resource, encrypted using the
password stored in `passwordSecretRef` password stored in `passwordSecretRef`
containing the issuing Certificate Authority containing the issuing Certificate Authority
type: boolean type: boolean
password:
description: |-
Password provides a literal password used to encrypt the JKS keystore.
Mutually exclusive with passwordSecretRef.
One of password or passwordSecretRef must provide a password with a non-zero length.
type: string
passwordSecretRef: passwordSecretRef:
description: |- description: |-
PasswordSecretRef is a reference to a non-empty key in a Secret resource PasswordSecretRef is a reference to a key in a Secret resource
containing the password used to encrypt the JKS keystore. containing the password used to encrypt the JKS keystore.
Mutually exclusive with password.
One of password or passwordSecretRef must provide a password with a non-zero length.
type: object type: object
required: required:
- name - name
@@ -566,31 +559,24 @@ spec:
type: object type: object
required: required:
- create - create
- passwordSecretRef
properties: properties:
create: create:
description: |- description: |-
Create enables PKCS12 keystore creation for the Certificate. Create enables PKCS12 keystore creation for the Certificate.
If true, a file named `keystore.p12` will be created in the target If true, a file named `keystore.p12` will be created in the target
Secret resource, encrypted using the password stored in Secret resource, encrypted using the password stored in
`passwordSecretRef` or in `password`. `passwordSecretRef`.
The keystore file will be updated immediately. The keystore file will be updated immediately.
If the issuer provided a CA certificate, a file named `truststore.p12` will If the issuer provided a CA certificate, a file named `truststore.p12` will
also be created in the target Secret resource, encrypted using the also be created in the target Secret resource, encrypted using the
password stored in `passwordSecretRef` containing the issuing Certificate password stored in `passwordSecretRef` containing the issuing Certificate
Authority Authority
type: boolean type: boolean
password:
description: |-
Password provides a literal password used to encrypt the PKCS#12 keystore.
Mutually exclusive with passwordSecretRef.
One of password or passwordSecretRef must provide a password with a non-zero length.
type: string
passwordSecretRef: passwordSecretRef:
description: |- description: |-
PasswordSecretRef is a reference to a non-empty key in a Secret resource PasswordSecretRef is a reference to a key in a Secret resource
containing the password used to encrypt the PKCS#12 keystore. containing the password used to encrypt the PKCS12 keystore.
Mutually exclusive with password.
One of password or passwordSecretRef must provide a password with a non-zero length.
type: object type: object
required: required:
- name - name
@@ -1390,9 +1376,6 @@ spec:
resource ID of the managed identity, can not be used at the same time as clientID resource ID of the managed identity, can not be used at the same time as clientID
Cannot be used for Azure Managed Service Identity Cannot be used for Azure Managed Service Identity
type: string type: string
tenantID:
description: tenant ID of the managed identity, can not be used at the same time as resourceID
type: string
resourceGroupName: resourceGroupName:
description: resource group the DNS zone is located in description: resource group the DNS zone is located in
type: string type: string
@@ -4706,9 +4689,6 @@ spec:
resource ID of the managed identity, can not be used at the same time as clientID resource ID of the managed identity, can not be used at the same time as clientID
Cannot be used for Azure Managed Service Identity Cannot be used for Azure Managed Service Identity
type: string type: string
tenantID:
description: tenant ID of the managed identity, can not be used at the same time as resourceID
type: string
resourceGroupName: resourceGroupName:
description: resource group the DNS zone is located in description: resource group the DNS zone is located in
type: string type: string
@@ -8435,9 +8415,6 @@ spec:
resource ID of the managed identity, can not be used at the same time as clientID resource ID of the managed identity, can not be used at the same time as clientID
Cannot be used for Azure Managed Service Identity Cannot be used for Azure Managed Service Identity
type: string type: string
tenantID:
description: tenant ID of the managed identity, can not be used at the same time as resourceID
type: string
resourceGroupName: resourceGroupName:
description: resource group the DNS zone is located in description: resource group the DNS zone is located in
type: string type: string

View File

@@ -52,12 +52,6 @@ spec:
prometheus.io/port: '9402' prometheus.io/port: '9402'
{{- end }} {{- end }}
spec: spec:
{{- if not .Values.serviceAccount.create }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
serviceAccountName: {{ template "cert-manager.serviceAccountName" . }} serviceAccountName: {{ template "cert-manager.serviceAccountName" . }}
{{- if hasKey .Values "automountServiceAccountToken" }} {{- if hasKey .Values "automountServiceAccountToken" }}
automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} automountServiceAccountToken: {{ .Values.automountServiceAccountToken }}

View File

@@ -11,9 +11,7 @@ metadata:
namespace: {{ include "cert-manager.namespace" . }} namespace: {{ include "cert-manager.namespace" . }}
{{- with .Values.serviceAccount.annotations }} {{- with .Values.serviceAccount.annotations }}
annotations: annotations:
{{- range $k, $v := . }} {{- toYaml . | nindent 4 }}
{{- printf "%s: %s" (tpl $k $) (tpl $v $) | nindent 4 }}
{{- end }}
{{- end }} {{- end }}
labels: labels:
app: {{ include "cert-manager.name" . }} app: {{ include "cert-manager.name" . }}

View File

@@ -52,12 +52,6 @@ spec:
prometheus.io/port: '9402' prometheus.io/port: '9402'
{{- end }} {{- end }}
spec: spec:
{{- if not .Values.webhook.serviceAccount.create }}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
serviceAccountName: {{ template "webhook.serviceAccountName" . }} serviceAccountName: {{ template "webhook.serviceAccountName" . }}
{{- if hasKey .Values.webhook "automountServiceAccountToken" }} {{- if hasKey .Values.webhook "automountServiceAccountToken" }}
automountServiceAccountToken: {{ .Values.webhook.automountServiceAccountToken }} automountServiceAccountToken: {{ .Values.webhook.automountServiceAccountToken }}

View File

@@ -579,7 +579,7 @@
}, },
"helm-values.config": { "helm-values.config": {
"default": {}, "default": {},
"description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n enableGatewayAPI: true\n # Feature gates as of v1.17.0. Listed with their default values.\n # See https://cert-manager.io/docs/cli/controller/\n featureGates:\n AdditionalCertificateOutputFormats: true # BETA - default=true\n AllAlpha: false # ALPHA - default=false\n AllBeta: false # BETA - default=false\n ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false\n ExperimentalGatewayAPISupport: true # BETA - default=true\n LiteralCertificateSubject: true # BETA - default=true\n NameConstraints: true # BETA - default=true\n OtherNames: false # ALPHA - default=false\n SecretsFilteredCaching: true # BETA - default=true\n ServerSideApply: false # ALPHA - default=false\n StableCertificateRequestName: true # BETA - default=true\n UseCertificateRequestBasicConstraints: false # ALPHA - default=false\n UseDomainQualifiedFinalizer: true # BETA - default=false\n ValidateCAA: false # ALPHA - default=false\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", "description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n featureGates:\n AdditionalCertificateOutputFormats: true\n DisallowInsecureCSRUsageDefinition: true\n ExperimentalCertificateSigningRequestControllers: true\n ExperimentalGatewayAPISupport: true\n LiteralCertificateSubject: true\n SecretsFilteredCaching: true\n ServerSideApply: true\n StableCertificateRequestName: true\n UseCertificateRequestBasicConstraints: true\n ValidateCAA: true\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics",
"type": "object" "type": "object"
}, },
"helm-values.containerSecurityContext": { "helm-values.containerSecurityContext": {
@@ -1223,7 +1223,7 @@
"type": "object" "type": "object"
}, },
"helm-values.serviceAccount.annotations": { "helm-values.serviceAccount.annotations": {
"description": "Optional additional annotations to add to the controller's Service Account. Templates are allowed for both keys and values.\nExample using templating:\nannotations:\n \"{{ .Chart.Name }}-helm-chart/version\": \"{{ .Chart.Version }}\"", "description": "Optional additional annotations to add to the controller's Service Account.",
"type": "object" "type": "object"
}, },
"helm-values.serviceAccount.automountServiceAccountToken": { "helm-values.serviceAccount.automountServiceAccountToken": {

View File

@@ -190,10 +190,7 @@ serviceAccount:
# +docs:property # +docs:property
# name: "" # name: ""
# Optional additional annotations to add to the controller's Service Account. Templates are allowed for both keys and values. # Optional additional annotations to add to the controller's Service Account.
# Example using templating:
# annotations:
# "{{ .Chart.Name }}-helm-chart/version": "{{ .Chart.Version }}"
# +docs:property # +docs:property
# annotations: {} # annotations: {}
@@ -230,24 +227,17 @@ enableCertificateOwnerRef: false
# kubernetesAPIQPS: 9000 # kubernetesAPIQPS: 9000
# kubernetesAPIBurst: 9000 # kubernetesAPIBurst: 9000
# numberOfConcurrentWorkers: 200 # numberOfConcurrentWorkers: 200
# enableGatewayAPI: true
# # Feature gates as of v1.17.0. Listed with their default values.
# # See https://cert-manager.io/docs/cli/controller/
# featureGates: # featureGates:
# AdditionalCertificateOutputFormats: true # BETA - default=true # AdditionalCertificateOutputFormats: true
# AllAlpha: false # ALPHA - default=false # DisallowInsecureCSRUsageDefinition: true
# AllBeta: false # BETA - default=false # ExperimentalCertificateSigningRequestControllers: true
# ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false # ExperimentalGatewayAPISupport: true
# ExperimentalGatewayAPISupport: true # BETA - default=true # LiteralCertificateSubject: true
# LiteralCertificateSubject: true # BETA - default=true # SecretsFilteredCaching: true
# NameConstraints: true # BETA - default=true # ServerSideApply: true
# OtherNames: false # ALPHA - default=false # StableCertificateRequestName: true
# SecretsFilteredCaching: true # BETA - default=true # UseCertificateRequestBasicConstraints: true
# ServerSideApply: false # ALPHA - default=false # ValidateCAA: true
# StableCertificateRequestName: true # BETA - default=true
# UseCertificateRequestBasicConstraints: false # ALPHA - default=false
# UseDomainQualifiedFinalizer: true # BETA - default=false
# ValidateCAA: false # ALPHA - default=false
# # Configure the metrics server for TLS # # Configure the metrics server for TLS
# # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls
# metricsTLSConfig: # metricsTLSConfig:

View File

@@ -1,2 +1,2 @@
cozystackAPI: cozystackAPI:
image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0@sha256:9940cffabedb510397e3c330887aee724c4d232c011df60f4c16891fcfe1d9bf image: ghcr.io/cozystack/cozystack/cozystack-api:v0.31.0-rc.2@sha256:d3794a5ebd49ee28ef7108213d3bb5053f5247ef62855f4731c7cafb8059a635

View File

@@ -1,5 +1,5 @@
cozystackController: cozystackController:
image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0@sha256:e8bf79e7287757bad94f9766524ecc8c9700a046e669e8a0e5a591e782fc393d image: ghcr.io/cozystack/cozystack/cozystack-controller:v0.31.0-rc.2@sha256:fb7cfdf62a128103954f0cb711b2d21650c0d2f7ff639d41a56f68d454a1e4ea
debug: false debug: false
disableTelemetry: false disableTelemetry: false
cozystackVersion: "v0.31.0" cozystackVersion: "v0.31.0-rc.2"

View File

@@ -76,7 +76,7 @@ data:
"kubeappsNamespace": {{ .Release.Namespace | quote }}, "kubeappsNamespace": {{ .Release.Namespace | quote }},
"helmGlobalNamespace": {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }}, "helmGlobalNamespace": {{ include "kubeapps.helmGlobalPackagingNamespace" . | quote }},
"carvelGlobalNamespace": {{ .Values.kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace | quote }}, "carvelGlobalNamespace": {{ .Values.kubeappsapis.pluginConfig.kappController.packages.v1alpha1.globalPackagingNamespace | quote }},
"appVersion": "v0.31.0", "appVersion": "v0.31.0-rc.2",
"authProxyEnabled": {{ .Values.authProxy.enabled }}, "authProxyEnabled": {{ .Values.authProxy.enabled }},
"oauthLoginURI": {{ .Values.authProxy.oauthLoginURI | quote }}, "oauthLoginURI": {{ .Values.authProxy.oauthLoginURI | quote }},
"oauthLogoutURI": {{ .Values.authProxy.oauthLogoutURI | quote }}, "oauthLogoutURI": {{ .Values.authProxy.oauthLogoutURI | quote }},

View File

@@ -19,7 +19,7 @@ kubeapps:
image: image:
registry: ghcr.io/cozystack/cozystack registry: ghcr.io/cozystack/cozystack
repository: dashboard repository: dashboard
tag: v0.31.0 tag: v0.31.0-rc.2
digest: "sha256:a83fe4654f547469cfa469a02bda1273c54bca103a41eb007fdb2e18a7a91e93" digest: "sha256:a83fe4654f547469cfa469a02bda1273c54bca103a41eb007fdb2e18a7a91e93"
redis: redis:
master: master:
@@ -35,8 +35,8 @@ kubeapps:
image: image:
registry: ghcr.io/cozystack/cozystack registry: ghcr.io/cozystack/cozystack
repository: kubeapps-apis repository: kubeapps-apis
tag: v0.31.0 tag: v0.31.0-rc.2
digest: "sha256:bf0522511089b3653e40726b875b6b4edea7a2efa1f9ac13b10dd723b91b9525" digest: "sha256:db4f33e9ca6969459c9baf0131c2c342cb6c366df16df7361e7cbdeb4a854cea"
pluginConfig: pluginConfig:
flux: flux:
packages: packages:

View File

@@ -1,7 +1,7 @@
# Build the manager binary # Build the manager binary
FROM golang:1.24 as builder FROM golang:1.24 as builder
ARG VERSION=edge-25.4.1 ARG VERSION=edge-25.3.2
ARG TARGETOS ARG TARGETOS
ARG TARGETARCH ARG TARGETARCH

View File

@@ -3,7 +3,7 @@ kamaji:
deploy: false deploy: false
image: image:
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
tag: v0.31.0@sha256:5f828637ebd1717a5c2b828352fff7fc14c218c7bbfc2cb2ce55737f9b5bf500 tag: v0.31.0-rc.2@sha256:beb066f5c45cda520e5028222ec26a5e39c2c3c63bc9016e8a6ec49a2379e00c
repository: ghcr.io/cozystack/cozystack/kamaji repository: ghcr.io/cozystack/cozystack/kamaji
resources: resources:
limits: limits:

View File

@@ -11,9 +11,6 @@ spec:
{{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }} {{- $rawConstraints := get $configMap.data "globalAppTopologySpreadConstraints" }}
{{- if $rawConstraints }} {{- if $rawConstraints }}
{{- $rawConstraints | fromYaml | toYaml | nindent 2 }} {{- $rawConstraints | fromYaml | toYaml | nindent 2 }}
labelSelector:
matchLabels:
cnpg.io/cluster: keycloak-db
{{- end }} {{- end }}
{{- end }} {{- end }}
monitoring: monitoring:

View File

@@ -1,3 +1,3 @@
portSecurity: true portSecurity: true
routes: "" routes: ""
image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0@sha256:b7bf296d906ae8820adfcf41fc438f0ef025cda45a43c005c5097fe0206bce21 image: ghcr.io/cozystack/cozystack/kubeovn-webhook:v0.31.0-rc.2@sha256:f9b464a94bd1a1fa116bbf77c4bbece3931d03dac1489eb820f94d98176ed5c9

View File

@@ -16,8 +16,6 @@ image-controller image-speaker:
$(eval VERSION := $(shell yq '.appVersion' charts/metallb/Chart.yaml)) $(eval VERSION := $(shell yq '.appVersion' charts/metallb/Chart.yaml))
docker buildx build images/metallb \ docker buildx build images/metallb \
--provenance false \ --provenance false \
--builder=$(BUILDER) \
--platform=$(PLATFORM) \
--target $(TARGET) \ --target $(TARGET) \
--build-arg VERSION=$(VERSION) \ --build-arg VERSION=$(VERSION) \
--tag $(REGISTRY)/metallb-$(TARGET):$(VERSION) \ --tag $(REGISTRY)/metallb-$(TARGET):$(VERSION) \
@@ -25,8 +23,8 @@ image-controller image-speaker:
--cache-to type=inline \ --cache-to type=inline \
--metadata-file images/$(TARGET).json \ --metadata-file images/$(TARGET).json \
--push=$(PUSH) \ --push=$(PUSH) \
--label "org.opencontainers.image.source=https://github.com/cozystack/cozystack" \ --label "org.opencontainers.image.source=https://github.com/cozystack/cozystack"
--load=$(LOAD) --load=1
REPOSITORY="$(REGISTRY)/metallb-$(TARGET)" \ REPOSITORY="$(REGISTRY)/metallb-$(TARGET)" \
yq -i '.metallb.$(TARGET).image.repository = strenv(REPOSITORY)' values.yaml yq -i '.metallb.$(TARGET).image.repository = strenv(REPOSITORY)' values.yaml
TAG=$(VERSION)@$$(yq e '."containerimage.digest"' images/$(TARGET).json -o json -r) \ TAG=$(VERSION)@$$(yq e '."containerimage.digest"' images/$(TARGET).json -o json -r) \

View File

@@ -4,8 +4,8 @@ metallb:
controller: controller:
image: image:
repository: ghcr.io/cozystack/cozystack/metallb-controller repository: ghcr.io/cozystack/cozystack/metallb-controller
tag: v0.14.9@sha256:d8fa1a8147f844fb6add20a2147e9be6d1c26424748439c2648a0f6d8e10804d tag: v0.14.9@sha256:73c3156d913a2ff15a26ca42fcbeee6fa115602bcdb78870dcfab9359acd9cb3
speaker: speaker:
image: image:
repository: ghcr.io/cozystack/cozystack/metallb-speaker repository: ghcr.io/cozystack/cozystack/metallb-speaker
tag: v0.14.9@sha256:ae39d960704a5c66d3758b75b0a088eb8a41ad34afcf88889d27269ad0147fd1 tag: v0.14.9@sha256:9af9f0a6922784f066653f2c0d940d5f2de7ffea132d2df488457b61465b7716