├── .github
├── ISSUE_TEMPLATE
│ └── file-issues-on-main-kairos-repo.md
└── workflows
│ ├── lint.yml
│ ├── publish.yaml
│ └── test.yaml
├── Earthfile
├── LICENSE
├── LocalAI
├── Dockerfile
├── assets
│ └── localai.yaml
└── run.sh
├── README.md
├── argocd
├── Dockerfile
├── assets
│ └── argocd.yaml
└── run.sh
├── calico
├── Dockerfile
├── assets
│ └── calico.yaml
└── run.sh
├── cert-manager
├── Dockerfile
└── run.sh
├── coco
├── Dockerfile
├── assets
│ ├── containerd-override.conf
│ ├── k3s-config.yaml
│ ├── k3s-override.conf
│ └── plan.yaml
└── run.sh
├── earthly.ps1
├── earthly.sh
├── flux
├── Dockerfile
├── flux-bootstrap.service
├── flux-bootstrap.sh
└── run.sh
├── kairos
├── Dockerfile
├── assets
│ ├── crd.yaml
│ ├── entangle-proxy.yaml
│ ├── entangle.yaml
│ └── osbuilder.yaml
└── run.sh
├── kubevirt
├── Dockerfile
├── assets
│ ├── cdi-cr.yaml
│ ├── cdi-operator.yaml
│ ├── kubevirt-cr.yaml
│ └── kubevirt-operator.yaml
├── kubevirt-manager-manifests
│ ├── cdi-cr.yaml
│ ├── kubevirt-cr.yaml
│ ├── kubevirt-manager-bundled.yaml
│ ├── kubevirt-manager-deployment.yaml
│ ├── kubevirt-manager-ingress.yaml
│ ├── kubevirt-manager-ns.yaml
│ ├── kubevirt-manager-pc.yaml
│ ├── kubevirt-manager-rbac.yaml
│ └── kubevirt-manager-service.yaml
└── run.sh
├── kyverno
├── Dockerfile
├── assets
│ └── kyverno.yaml
└── run.sh
├── longhorn
├── Dockerfile
├── assets
│ └── longhorn.yaml
└── run.sh
├── metallb
├── Dockerfile
├── assets
│ ├── addresspool.yaml
│ └── metallb.yaml
└── run.sh
├── multus
├── Dockerfile
├── manifests.yaml
└── run.sh
├── nginx
├── Dockerfile
├── assets
│ └── ingress-nginx.yaml
└── run.sh
├── openamt
├── Dockerfile
└── run.sh
├── renovate.json
├── spinkube
├── Dockerfile
└── run.sh
├── system-upgrade-controller
├── Dockerfile
├── assets
│ └── system-upgrade-controller.yaml
└── run.sh
└── tests
├── argocd_test.go
├── calico_test.go
├── cert-manager_test.go
├── go.mod
├── go.sum
├── kairos_test.go
├── kubevirt_test.go
├── kyverno_test.go
├── localai_test.go
├── longhorn_test.go
├── metallb_test.go
├── multus_test.go
├── nginx_test.go
├── suite_test.go
└── system-upgrade-controller_test.go
/.github/ISSUE_TEMPLATE/file-issues-on-main-kairos-repo.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: File issues on main Kairos repo
3 | about: Tell users to file their issues on the main Kairos repo
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | :warning: All Kairos issues are tracked in our main repo, please file your issue there, thanks! :warning:
11 |
12 | https://github.com/kairos-io/kairos/issues
13 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: Lint
2 | on:
3 | push:
4 | branches:
5 | - main
6 | pull_request:
7 |
8 | jobs:
9 | lint:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
14 | with:
15 | fetch-depth: 0
16 | - name: Run Lint checks
17 | run: |
18 | ./earthly.sh +lint
19 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | name: Publish
2 |
3 | on:
4 | push:
5 | tags:
6 | - v*
7 | branches:
8 | - main
9 |
10 | concurrency:
11 | group: ci-publish-${{ github.head_ref || github.ref }}-${{ github.repository }}
12 | cancel-in-progress: true
13 |
14 | jobs:
15 | images:
16 | runs-on: ubuntu-latest
17 | permissions:
18 | id-token: write
19 | strategy:
20 | matrix:
21 | bundles:
22 | - calico
23 | - cert-manager
24 | - flux
25 | - coco
26 | - kubevirt
27 | - kairos
28 | - longhorn
29 | - kyverno
30 | - metallb
31 | - multus
32 | - nginx
33 | - spinkube
34 | - system-upgrade-controller
35 | - argocd
36 | - "LocalAI"
37 | env:
38 | REGISTRY: quay.io
39 | REGISTRY_USER: ${{ secrets.REGISTRY_USERNAME }}
40 | REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
41 | steps:
42 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
43 | - uses: docker-practice/actions-setup-docker@master
44 | - uses: earthly/actions-setup@v1
45 | with:
46 | version: "latest"
47 | - run: echo $REGISTRY_PASSWORD | docker login -u $REGISTRY_USER --password-stdin $REGISTRY
48 | - run: earthly --ci --push +build --BUNDLE=${{ matrix.bundles }}
49 |
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | name: Test
2 | on:
3 | pull_request:
4 | push:
5 | branches:
6 | - main
7 |
8 | concurrency:
9 | group: ci-test-${{ github.head_ref || github.ref }}-${{ github.repository }}
10 | cancel-in-progress: true
11 |
12 | jobs:
13 | test:
14 | strategy:
15 | matrix:
16 | bundles:
17 | - calico
18 | - cert-manager
19 | - kubevirt
20 | - longhorn
21 | - metallb
22 | - multus
23 | - nginx
24 | - kairos
25 | - kyverno
26 | - system-upgrade-controller
27 | - argocd
28 | - "LocalAI"
29 | - flux
30 | - coco
31 | runs-on: ubuntu-latest
32 | steps:
33 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
34 | - uses: docker-practice/actions-setup-docker@master
35 | - run: ./earthly.sh --ci --push +test --BUNDLE=${{ matrix.bundles }}
36 |
--------------------------------------------------------------------------------
/Earthfile:
--------------------------------------------------------------------------------
1 | VERSION 0.6
2 | FROM alpine
3 | ARG BUNDLE
4 | ARG VERSION="latest"
5 | ARG IMAGE_REPOSITORY=quay.io/kairos/community-bundles
6 |
7 | # renovate: datasource=docker depName=renovate/renovate versioning=docker
8 | ARG RENOVATE_VERSION=37
9 | # renovate: datasource=docker depName=koalaman/shellcheck-alpine versioning=docker
10 | ARG SHELLCHECK_VERSION=v0.9.0
11 |
12 | version:
13 | FROM alpine
14 | RUN apk add git
15 |
16 | COPY . ./
17 |
18 | RUN echo $(git describe --exact-match --tags || echo "v0.0.0-$(git log --oneline -n 1 | cut -d" " -f1)") > VERSION
19 |
20 | SAVE ARTIFACT VERSION VERSION
21 |
22 | build:
23 | COPY +version/VERSION ./
24 | ARG VERSION=$(cat VERSION)
25 | FROM DOCKERFILE -f ${BUNDLE}/Dockerfile ./${BUNDLE}
26 | SAVE IMAGE --push $IMAGE_REPOSITORY:${BUNDLE}_${VERSION}
27 |
28 | rootfs:
29 | FROM +build
30 | SAVE ARTIFACT /. rootfs
31 |
32 | test:
33 | FROM quay.io/kairos/core-alpine-opensuse-leap
34 | RUN apk add go
35 | ENV GOPATH=/go
36 | ENV PATH=$PATH:$GOPATH/bin
37 | COPY (+rootfs/rootfs --BUNDLE=$BUNDLE) /bundle
38 | COPY . .
39 | RUN cd tests && \
40 | go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo && \
41 | ginkgo --label-filter="${BUNDLE}" -v ./...
42 |
43 | renovate-validate:
44 | ARG RENOVATE_VERSION
45 | FROM renovate/renovate:$RENOVATE_VERSION
46 | WORKDIR /usr/src/app
47 | COPY renovate.json .
48 | RUN renovate-config-validator
49 |
50 | shellcheck-lint:
51 | ARG SHELLCHECK_VERSION
52 | FROM koalaman/shellcheck-alpine:$SHELLCHECK_VERSION
53 | WORKDIR /mnt
54 | COPY . .
55 | RUN find . -name "*.sh" -print | xargs -r -n1 shellcheck
56 |
57 | lint:
58 | BUILD +renovate-validate
59 | BUILD +shellcheck-lint
60 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/LocalAI/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM scratch
2 | COPY ./run.sh /
3 | COPY ./assets /assets
4 |
--------------------------------------------------------------------------------
/LocalAI/assets/localai.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: localai
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: localai
10 | namespace: localai
11 | spec:
12 | chart: local-ai
13 | repo: https://go-skynet.github.io/helm-charts/
14 | version: "@VERSION@"
15 | valuesContent: |-
16 | service:
17 | type: "@SERVICETYPE@"
18 |
--------------------------------------------------------------------------------
/LocalAI/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 | VERSION="3.4.2"
8 |
9 | templ() {
10 | local file="$3"
11 | local value="$2"
12 | local sentinel="$1"
13 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
14 | }
15 |
16 | mkdir -p "${K3S_MANIFEST_DIR}"
17 |
18 | # Set the service type
19 | serviceType=$(kairos-agent config get localai.serviceType | tr -d '\n')
20 | if [[ -z "$serviceType" ]]; then
21 | serviceType="ClusterIP"
22 | fi
23 | templ "SERVICETYPE" "${serviceType}" assets/localai.yaml
24 |
25 | # Set the version of the helm chart
26 | for FILE in assets/*; do
27 | templ "VERSION" "${VERSION}" "${FILE}"
28 | done;
29 |
30 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Kairos Community Bundles
9 |
10 |
11 |
12 | Welcome to the community-bundles repository! This repository builds and pushes Kairos community bundles that can be consumed by Kairos core or derivative images (such as [provider-kairos](https://github.com/kairos-io/provider-kairos) ) to extend Kairos configurations and settings, and to add cloud-config keywords.
13 |
14 | Please note that these community bundles are not officially supported and are provided on a best-effort basis by the community.
15 |
16 | ## Table of Contents
17 |
18 | - [Table of Contents](#table-of-contents)
19 | - [Usage](#usage)
20 | - [Bundles](#bundles)
21 | - [Calico](#calico)
22 | - [Cert-manager](#cert-manager)
23 | - [Flux](#flux)
24 | - [Kairos](#kairos)
25 | - [Kyverno](#kyverno)
26 | - [Kubevirt](#kubevirt)
27 | - [Longhorn](#longhorn)
28 | - [MetalLB](#metallb)
29 | - [Multus](#multus)
30 | - [Nginx](#nginx)
31 | - [SpinKube](#spinkube)
32 | - [System upgrade controller](#system-upgrade-controller)
33 | - [ArgoCD](#argocd)
34 | - [Development](#development)
35 |
36 | ## Usage
37 |
38 | To use a community bundle, you can load it with the bundles block in the Kairos configuration file, like this:
39 |
40 | ```yaml
41 | bundles:
42 | - targets:
43 | - run://quay.io/kairos/community-bundles:
44 | ```
45 |
46 | Here is an example of how you might use a community bundle in a Kairos core image:
47 |
48 | ```yaml
49 | #cloud-config
50 | install:
51 | device: "auto"
52 | auto: true
53 | reboot: true
54 | image: "docker:quay.io/kairos/kairos-opensuse:v1.4.0-k3sv1.26.0-k3s1"
55 |
56 | users:
57 | - name: "kairos"
58 | passwd: "kairos"
59 | ssh_authorized_keys:
60 | - ...
61 |
62 | bundles:
63 | - targets:
64 | - run://quay.io/kairos/community-bundles:kubevirt
65 |
66 | k3s:
67 | enabled: true
68 | ```
69 |
70 | ## Bundles
71 |
72 | ### Calico
73 |
74 | The calico bundle deploys [Project Calico](https://docs.tigera.io/calico/latest/about/).
75 |
76 | To configure the bundle, use the `calico` block:
77 |
78 | ```yaml
79 | #cloud-config
80 |
81 | # Specify the bundle to use
82 | bundles:
83 | - targets:
84 | - run://quay.io/kairos/community-bundles:calico_latest
85 |
86 | # Specify calico settings
87 | calico:
88 | values:
89 | installation:
90 | cni:
91 | type: Calico
92 | calicoNetwork:
93 | bgp: Disabled
94 | ipPools:
95 | - cidr: 10.244.0.0/16
96 | encapsulation: VXLAN
97 | version: 3.25.0
98 | ```
99 |
100 | Note that specifying `values` and `version` are optional. Specifying `values` allows you to
101 | [customize the Helm Chart](https://docs.tigera.io/calico/latest/getting-started/kubernetes/helm#customize-the-helm-chart).
102 |
103 | ### Cert-manager
104 |
105 | The cert-manager bundle deploys [cert-manager](https://cert-manager.io/docs/installation/).
106 |
107 | The bundle does add a `certManager` block, that allow to change the version (currently only available `v1.11.0`):
108 |
109 | ```yaml
110 | #cloud-config
111 |
112 | # Specify the bundle to use
113 | bundles:
114 | - targets:
115 | - run://quay.io/kairos/community-bundles:cert-manager_latest
116 |
117 | # Specify cert-manager settings
118 | certManager:
119 | version: v1.11.0
120 | ```
121 |
122 | ### Flux
123 |
124 | This installs [FluxCD](https://fluxcd.io/flux/cmd/flux_bootstrap/) and supports
125 | automatically bootstrapping the cluster. Only one node will do the bootstrap.
126 | It will time out after trying for 30 minutes and it requires `systemd`.
127 |
128 | ```yaml
129 | #cloud-config
130 |
131 | k3s:
132 | enabled: true
133 |
134 | bundles:
135 | - targets:
136 | - run://quay.io/kairos/community-bundles:flux_latest
137 |
138 | # Specify command-line arguments as keys under a key of `bitbucket_server`,
139 | # `git`, `github` or `gitlab` for the provider to boostrap from. An example for
140 | # `github` is shown below.
141 | flux:
142 | env:
143 | # Override default $KUBECONFIG of /etc/rancher/k3s/k3s.yaml if needed
144 | # KUBECONFIG: /home/csagan/.kube/config
145 | GITHUB_TOKEN: abcde1234
146 | github:
147 | owner: csagan
148 | repository: fleet-infra
149 | path: clusters/cosmos
150 | components-extra: image-reflector-controller,image-automation-controller
151 | ```
152 |
153 | ### Kairos
154 |
155 | The Kairos bundle deploys the [Kairos helm-charts](https://github.com/kairos-io/helm-charts). It installs the `kairos-crds` chart, and allows to enable [entangle-proxy](https://kairos.io/docs/reference/entangle/), [osbuilder](https://kairos.io/docs/advanced/build/), and [entangle](https://kairos.io/docs/reference/entangle/).
156 |
157 | By default the bundle will install only the CRDs, components needs to be explicitly enabled:
158 |
159 | ```yaml
160 | #cloud-config
161 |
162 | # Specify the bundle to use
163 | bundles:
164 | - targets:
165 | - run://quay.io/kairos/community-bundles:kairos_latest
166 |
167 | # Specify kairos bundle setting
168 | kairos:
169 | osbuilder:
170 | enable: true
171 | version: ... #optional
172 | entangle:
173 | enable: true
174 | version: ... #optional
175 | entangleProxy:
176 | enable: true
177 | version: ... #optional
178 | ```
179 |
180 | ### Kyverno
181 |
182 | The Kyverno bundle deploys [Kyverno](https://kyverno.io/docs/introduction/).
183 |
184 | To configure the bundle, use the `kyverno` block:
185 |
186 | ```yaml
187 | #cloud-config
188 |
189 | # Specify the bundle to use
190 | bundles:
191 | - targets:
192 | - run://quay.io/kairos/community-bundles:kyverno_latest
193 |
194 | # Specify kyverno settings
195 | kyverno:
196 | values: ....
197 | version: ...
198 | ```
199 |
200 | Note that specifying `values` and `version` are optional. Specifying `values` allows you to
201 | [customize the Helm Chart](https://github.com/kyverno/kyverno/blob/main/charts/kyverno/values.yaml).
202 |
203 | ### Kubevirt
204 |
205 | The Kubevirt bundle deploys [Kubevirt](https://github.com/kubevirt/kubevirt) and optionally [kubevirt-manager](https://kubevirt-manager.io/)
206 |
207 | The bundle does add a `kubevirt` block, that allow to enable `kubevirt-manager`:
208 |
209 | ```yaml
210 | #cloud-config
211 |
212 | # Specify the bundle to use
213 | bundles:
214 | - targets:
215 | - run://quay.io/kairos/community-bundles:kubevirt_latest
216 |
217 | # Specify kubevirt settings
218 | kubevirt:
219 | manager: true
220 | ```
221 |
222 | ### Longhorn
223 |
224 | The longhorn bundle deploys [Longhorn](https://longhorn.io/docs/).
225 |
226 | To configure the bundle, use the `longhorn` block:
227 |
228 | ```yaml
229 | #cloud-config
230 |
231 | # Specify the bundle to use
232 | bundles:
233 | - targets:
234 | - run://quay.io/kairos/community-bundles:longhorn_latest
235 |
236 | # Specify longhorn settings
237 | longhorn:
238 | values:
239 | defaultSettings:
240 | backupstorePollInterval: 600
241 | version: 1.4.0
242 | ```
243 |
244 | Note that specifying `values` and `version` are optional. Specifying `values` allows you to
245 | [customize the Helm Chart](https://longhorn.io/docs/latest/advanced-resources/deploy/customizing-default-settings/#using-helm).
246 |
247 | ### MetalLB
248 |
249 | The MetalLB bundle deploys [MetalLB](https://metallb.universe.tf/installation/) in the cluster, available after boostrap.
250 |
251 | The bundle does add a `metallb` block, that allow to set up the MetalLB version and the address pool in the Kairos configuration file:
252 |
253 | ```yaml
254 | #cloud-config
255 |
256 | # Specify the bundle to use
257 | bundles:
258 | - targets:
259 | - run://quay.io/kairos/community-bundles:metallb_latest
260 |
261 | # Specify metallb settings
262 | metallb:
263 | version: 0.13.7
264 | address_pool: 192.168.1.10-192.168.1.20
265 | ```
266 |
267 | Note, you might want to disable the default LoadBalancer of k3s, a full example can be:
268 |
269 | ```yaml
270 | #cloud-config
271 |
272 | hostname: kairoslab-{{ trunc 4 .MachineID }}
273 | users:
274 | - name: kairos
275 | ssh_authorized_keys:
276 | # Add your github user here!
277 | - github:mudler
278 |
279 | k3s:
280 | enabled: true
281 | args:
282 | - --disable=servicelb
283 |
284 | # Specify the bundle to use
285 | bundles:
286 | - targets:
287 | - run://quay.io/kairos/community-bundles:metallb_latest
288 |
289 | # Specify metallb settings
290 | metallb:
291 | version: 0.13.7
292 | address_pool: 192.168.1.10-192.168.1.20
293 | ```
294 |
295 | ### Multus
296 |
297 | The Multus bundle deploys [Multus CNI](https://github.com/k8snetworkplumbingwg/multus-cni), along with specified [CNI plugins](https://www.cni.dev/plugins/current/).
298 |
299 | The only created resources are the ClusterRole and the associated ClusterRoleBinding. Instead of creating a service account, it sets up a _normal user_ using an [X509 client certificate](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs). This client certificate has a validity of 3650 days by default which can be overwritten by the configuration.
300 |
301 | To configure the bundle, use the `multus` block:
302 |
303 | ```yaml
304 | # Specify the bundle to use
305 | bundles:
306 | - targets:
307 | - run://quay.io/kairos/community-bundles:multus_latest
308 |
309 | # Specify multus settings. Here are the defaults:
310 | multus:
311 | # List of additional CNI plugins to install. May also be a
312 | # whitelist-delimited list.
313 | # See https://www.cni.dev/plugins/current/ for available plugins.
314 | cni_plugins: []
315 |
316 | # Full path to the directory the plugins will be installed.
317 | cni_bin_dir: /opt/cni/bin
318 |
319 | # Full path to the directory where multus will be installed.
320 | multus_bin_dir: /var/lib/rancher/k3s/data/current/bin
321 |
322 | # Full path to the directory where the configuration files will be written.
323 | cni_conf_dir: /var/lib/rancher/k3s/agent/etc/cni/net.d
324 |
325 | # Full path to the directory containing certificate authority (CA) files.
326 | ca_path: /var/lib/rancher/k3s/server/tls
327 |
328 | # Duration (in days) during which the generated certificate will be valid
329 | # for.
330 | crt_validity: 3650
331 |
332 | # URL of the Kubernetes API
333 | cluster_server: https://127.0.0.1:6443
334 |
335 | # Whether or not to isolate the NetworkAttachmentDefinition resources so that
336 | # the pods referring to them must be in the same namespace.
337 | namespace_isolation: false
338 |
339 | # When namespace isolation is enabled, list of namespaces that are to be
340 | # considered “global” and allow their NetworkAttachmentDefinitions to be
341 | # referred to by pods in other namespaces. May also be a coma-delimited list.
342 | global_namespaces: []
343 |
344 | # Full path to the CNI configuration wrapped by Multus. If left unset, scan
345 | # the multus.cni_conf_dir directory, sort the filenames alphabetically and
346 | # use the first file result.
347 | primary_config: ~
348 | ```
349 |
350 | ### Nginx
351 |
352 | The Nginx bundle deploys [Ingress-Nginx-Controller](https://kubernetes.github.io/ingress-nginx/) in the cluster, available after boostrap.
353 |
354 | The bundle does add a `nginx` block, that allow to set up the nginx version and helm chart [values](https://github.com/kubernetes/ingress-nginx/blob/main/charts/ingress-nginx/values.yaml) in the Kairos configuration file:
355 |
356 | ```yaml
357 | #cloud-config
358 |
359 | # Specify the bundle to use
360 | bundles:
361 | - targets:
362 | - run://quay.io/kairos/community-bundles:nginx_latest
363 |
364 | # Specify nginx settings
365 | nginx:
366 | version: 4.7.3
367 | ```
368 |
369 | ```yaml
370 | #cloud-config
371 |
372 | # Specify the bundle to use
373 | bundles:
374 | - targets:
375 | - run://quay.io/kairos/community-bundles:nginx_latest
376 |
377 | # Specify nginx settings
378 | nginx:
379 | values:
380 | commonLabels:
381 | myLabel: abc123
382 | ```
383 |
384 | Note, you might want to disable the default Ingress-Controller of k3s, a full example can be:
385 |
386 | ```yaml
387 | #cloud-config
388 |
389 | hostname: kairoslab-{{ trunc 4 .MachineID }}
390 | users:
391 | - name: kairos
392 | ssh_authorized_keys:
393 | # Add your github user here!
394 | - github:mudler
395 |
396 | k3s:
397 | enabled: true
398 | args:
399 | - --disable=traefik
400 |
401 | # Specify the bundle to use
402 | bundles:
403 | - targets:
404 | - run://quay.io/kairos/community-bundles:nginx_latest
405 |
406 | # Specify nginx settings
407 | nginx:
408 | version: 4.7.3
409 | ```
410 |
411 | ### SpinKube
412 |
413 | > **WARNING**: This will not work with Kairos distributions that don't use `systemd` (i.e. Alpine).
414 |
415 | The SpinKube bundle deploys [SpinKube](https://spinkube.dev) to a running k3s cluster.
416 |
417 | The bundle has a `spinkube` block that allows you to install `cert-manager`, which is required by SpinKube:
418 |
419 | ```yaml
420 | bundles:
421 | - targets:
422 | - run://quay.io/kairos/community-bundles:spinkube_latest
423 |
424 | spinkube:
425 | installCertManager: true
426 | ```
427 |
428 | If you don't want to use the bundle's `cert-manager` installation, be sure to check [SpinKube](https://www.spinkube.dev/docs/install/)'s documentation for which version of `cert-manager` to use.
429 |
430 | ### System upgrade controller
431 |
432 | The System upgrade controller bundle deploys [System upgrade controller](https://github.com/rancher/system-upgrade-controller).
433 |
434 | The bundle does add a `suc` block, that allow to change the version:
435 |
436 | ```yaml
437 | #cloud-config
438 |
439 | # Specify the bundle to use
440 | bundles:
441 | - targets:
442 | - run://quay.io/kairos/community-bundles:system-upgrade-controller_latest
443 |
444 | # Specify system-upgrade-controller settings
445 | suc:
446 | version: v0.10.0
447 | ```
448 |
449 | ### ArgoCD
450 |
451 | The ArgoCD bundle deploys [ArgoCD](https://argo-cd.readthedocs.io/en/stable/).
452 |
453 | To configure the bundle, use the `argocd` block:
454 |
455 | ```yaml
456 | #cloud-config
457 |
458 | # Specify the bundle to use
459 | bundles:
460 | - targets:
461 | - run://quay.io/kairos/community-bundles:argocd_latest
462 |
463 | # Specify argocd settings
464 | argocd:
465 | values:
466 | redis-ha:
467 | enabled: true
468 | controller:
469 | replicas: 1
470 | server:
471 | autoscaling:
472 | enabled: true
473 | minReplicas: 2
474 | version: 7.5.2
475 | ```
476 |
477 | ## Development
478 |
479 | If you want to build and test a bundle, you can use earthly by running the following commands:
480 |
481 | ```
482 | # build
483 | ./earthly.sh +build --BUNDLE=
484 | # test
485 | ./earthly.sh +test --BUNDLE=
486 | ```
487 |
488 | We also provide a version of the `earthly.sh` script for Windows (`earthly.ps1`).
489 |
--------------------------------------------------------------------------------
/argocd/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | # renovate: datasource=github-releases depName=argoproj/argo-cd
3 | ENV VERSION=2.10.2
4 | ARG TARGETARCH
5 | RUN if [[ "$TARGETARCH" = "amd64" ]]; then \
6 | export CHECKSUM=a8da9fa1ea7b7072007f535d39526ad0c4a8b8eb58779b48774126335c576187; \
7 | elif [[ "$TARGETARCH" = "arm64" ]]; then \
8 | export CHECKSUM=8314c9fda218145344cb0af68ceb8f31338bf11ab4ec315ba553cf6268e17444; \
9 | fi && \
10 | echo "CHECKSUM=${CHECKSUM}" > /tmp/checksum_env
11 | RUN source /tmp/checksum_env && echo "CHECKSUM is: ${CHECKSUM}"
12 | ADD "https://github.com/argoproj/argo-cd/releases/download/v${VERSION}/argocd-linux-${TARGETARCH}" /tmp
13 | RUN DOWNLOAD_FILE="/tmp/argocd-linux-${TARGETARCH}" && \
14 | DOWNLOAD_CHECKSUM=$(sha256sum "${DOWNLOAD_FILE}" | awk '{print $1}') && \
15 | if [[ ${DOWNLOAD_CHECKSUM} != ${CHECKSUM} ]]; then \
16 | echo "Checksum does not match"; \
17 | exit 1; \
18 | fi
19 |
20 | FROM --platform=$BUILDPLATFORM scratch
21 | ARG TARGETARCH
22 | COPY ./run.sh /
23 | COPY --from=build /tmp/argocd-linux-${TARGETARCH} .
24 | COPY ./assets /assets
25 |
--------------------------------------------------------------------------------
/argocd/assets/argocd.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: argocd
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: argocd
10 | namespace: argocd
11 | spec:
12 | name: argocd
13 | chart: argo-cd
14 | repo: https://argoproj.github.io/argo-helm
15 | valuesContent: |-
16 | @VALUES@
17 | version: "@VERSION@"
18 |
--------------------------------------------------------------------------------
/argocd/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 | BIN=/usr/local/bin/
7 |
8 | getConfig() {
9 | local key=$1
10 | _value=$(kairos-agent config get "${key} | @json" | tr -d '\n')
11 | # Remove the quotes wrapping the value.
12 | _value=${_value:1:${#_value}-2}
13 | if [ "${_value}" != "null" ]; then
14 | echo "${_value}"
15 | fi
16 | echo
17 | }
18 |
19 | VALUES="{}"
20 | VERSION="7.5.2" # Chart Version
21 |
22 | templ() {
23 | local file="$3"
24 | local value=$2
25 | local sentinel=$1
26 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
27 | }
28 |
29 | readConfig() {
30 | _values=$(getConfig argocd.values)
31 | if [ "$_values" != "" ]; then
32 | VALUES=$_values
33 | fi
34 | _version=$(getConfig argocd.version)
35 | if [ "$_version" != "" ]; then
36 | VERSION=$_version
37 | fi
38 | }
39 |
40 | mkdir -p "${K3S_MANIFEST_DIR}"
41 | mkdir -p $BIN
42 |
43 | readConfig
44 |
45 | # Copy manifests, and template them
46 | for FILE in assets/*; do
47 | templ "VALUES" "${VALUES}" "${FILE}"
48 | templ "VERSION" "${VERSION}" "${FILE}"
49 | done;
50 |
51 | # get system arch
52 | ARCH=$(uname -m)
53 |
54 | if [ "$ARCH" == "x86_64" ]; then
55 | SYSTEM_ARCH="amd64"
56 | else
57 | if [ "$ARCH" == "aarch64" ]; then
58 | SYSTEM_ARCH="arm64"
59 | fi
60 | fi
61 |
62 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
63 | cp argocd-linux-"$SYSTEM_ARCH" $BIN/argocd
64 | sudo chmod +x $BIN/argocd
65 |
--------------------------------------------------------------------------------
/calico/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | FROM scratch
3 | COPY ./run.sh /
4 | COPY ./assets /assets
5 |
--------------------------------------------------------------------------------
/calico/assets/calico.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: tigera-operator
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: calico
10 | namespace: tigera-operator
11 | spec:
12 | name: calico
13 | chart: tigera-operator
14 | repo: https://docs.tigera.io/calico/charts
15 | valuesContent: |-
16 | @VALUES@
17 | version: "@VERSION@"
18 |
--------------------------------------------------------------------------------
/calico/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 | VALUES="{}"
8 | # renovate: depName=tigera-operator repoUrl=https://docs.tigera.io/calico/charts
9 | VERSION="v3.28.2"
10 |
11 | templ() {
12 | local file="$3"
13 | local value="$2"
14 | local sentinel="$1"
15 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
16 | }
17 |
18 | _version=$(kairos-agent config get "calico.version" | tr -d '\n')
19 | if [ "$_version" != "null" ]; then
20 | VERSION=$_version
21 | fi
22 | _values=$(kairos-agent config get "calico.values | @json" | tr -d '\n')
23 | # Remove the quotes wrapping the value.
24 | _values=${_values:1:${#_values}-2}
25 | if [ "$_values" != "null" ]; then
26 | VALUES=$_values
27 | fi
28 |
29 | # Copy manifests, and template them
30 | for FILE in assets/*; do
31 | templ "VALUES" "${VALUES}" "${FILE}"
32 | templ "VERSION" "${VERSION}" "${FILE}"
33 | done;
34 |
35 | mkdir -p "${K3S_MANIFEST_DIR}"
36 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
37 |
--------------------------------------------------------------------------------
/cert-manager/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | RUN mkdir /assets
3 | RUN wget https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml -O /assets/cert-manager-v1.11.0.yaml
4 | FROM scratch
5 | COPY ./run.sh /
6 | COPY --from=build /assets /assets
7 |
--------------------------------------------------------------------------------
/cert-manager/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 | getConfig() {
8 | local l="$1"
9 | key=$(kairos-agent config get "${l}" | tr -d '\n')
10 | if [ "$key" != "null" ]; then
11 | echo "${key}"
12 | fi
13 | echo
14 | }
15 |
16 | VERSION="v1.11.0"
17 |
18 | templ() {
19 | local file="$3"
20 | local value="$2"
21 | local sentinel="$1"
22 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
23 | }
24 |
25 | readConfig() {
26 | _version="$(getConfig 'certManager.version')"
27 | if [ "$_version" != "" ]; then
28 | VERSION=$_version
29 | fi
30 | }
31 |
32 | mkdir -p "${K3S_MANIFEST_DIR}"
33 |
34 | readConfig
35 |
36 | cp -rf "assets/cert-manager-${VERSION}.yaml" "${K3S_MANIFEST_DIR}/cert-manager.yaml"
37 |
--------------------------------------------------------------------------------
/coco/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 |
3 | # TODO: How do we handle different architectures?
4 | WORKDIR /assets
5 | RUN wget https://github.com/confidential-containers/containerd/releases/download/v1.6.8.1/containerd-1.6.8.1-linux-amd64.tar.gz -O containerd.tar.gz
6 | RUN tar xvf containerd.tar.gz
7 | RUN rm containerd.tar.gz
8 |
9 | RUN wget https://raw.githubusercontent.com/containerd/containerd/release/1.6/containerd.service
10 |
11 | FROM scratch
12 | COPY ./run.sh /
13 | COPY --from=build /assets/ /assets
14 | COPY assets/. /assets
15 |
--------------------------------------------------------------------------------
/coco/assets/containerd-override.conf:
--------------------------------------------------------------------------------
1 | [Service]
2 | ExecStart=
3 | ExecStart=/usr/local/bin/containerd --config /etc/containerd/config.toml --root /etc/coco/run/ --address /etc/coco/run/containerd.sock
4 |
5 | Environment="PATH=/var/lib/rancher/k3s/data/current/bin:/sbin:/usr/sbin:/usr/local/sbin:/root/bin:/usr/local/bin:/usr/bin:/bin"
6 |
--------------------------------------------------------------------------------
/coco/assets/k3s-config.yaml:
--------------------------------------------------------------------------------
1 | # https://docs.k3s.io/installation/configuration#configuration-file
2 | container-runtime-endpoint: /etc/coco/run/containerd.sock
3 |
--------------------------------------------------------------------------------
/coco/assets/k3s-override.conf:
--------------------------------------------------------------------------------
1 | [Service]
2 | Environment=K3S_CONFIG_FILE=/etc/coco/k3s-config.yaml
3 | ExecStart=
4 | ExecStart=/usr/bin/k3s server --kubelet-arg cgroup-driver=systemd
5 |
6 | [Unit]
7 | After=containerd.service
8 |
--------------------------------------------------------------------------------
/coco/assets/plan.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Secret
3 | metadata:
4 | name: custom-script
5 | namespace: system-upgrade
6 | type: Opaque
7 | stringData:
8 | coco-install.sh: |
9 | #!/bin/sh
10 | set -e
11 |
12 | if [ -d "/host/etc/containerd/.sentinel" ]; then
13 | echo "Containerd folder was populated"
14 | exit 0
15 | fi
16 | export COCO_DEPLOY=true
17 | mount --rbind /host/dev /dev
18 | mount --rbind /host/run /run
19 | nsenter -i -m -t 1 -- kairos-agent install-bundle run://@IMAGE@
20 | exit 0
21 | ---
22 | apiVersion: upgrade.cattle.io/v1
23 | kind: Plan
24 | metadata:
25 | name: coco
26 | namespace: system-upgrade
27 | spec:
28 | concurrency: 1
29 | # This is the version (tag) of the image.
30 | # The version is referred to the kairos version plus the k3s version.
31 | version: "v1.0.0-rc2-k3sv1.23.9-k3s1"
32 | nodeSelector:
33 | matchExpressions:
34 | - { key: kubernetes.io/hostname, operator: Exists }
35 | serviceAccountName: system-upgrade
36 | cordon: false
37 | upgrade:
38 | image: quay.io/kairos/kairos-opensuse-leap
39 | command:
40 | - "/bin/bash"
41 | - "-c"
42 | args:
43 | - bash /host/run/system-upgrade/secrets/custom-script/coco-install.sh
44 | secrets:
45 | - name: custom-script
46 | path: /host/run/system-upgrade/secrets/custom-script
47 |
--------------------------------------------------------------------------------
/coco/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -x
4 |
5 | # This script will setup enclave-cc runtime to allow running confidential
6 | # containers on the kairos cluster
7 | # More here:
8 | # https://github.com/confidential-containers/enclave-cc
9 | # https://github.com/confidential-containers/documentation/blob/main/quickstart.md
10 | #
11 | # It works in 2 "modes":
12 | # 1. when kairos first installs, it simply puts the plan.yaml in a place where
13 | # k3s will see it an deploy it as soon as it's up and running.
14 | # 2. when the plan actually runs, it will install this bundle but this time with
15 | # COCO_DEPLOY set to "true". This will run the deployCoco function which puts the
16 | # customized containerd binary in place and makes sure k3s uses that containerd
17 | # (through a socket). Also it copies the containerd configuration generated by
18 | # k3s, to the standard location from which our containerd will read it and to which
19 | # the coco operator will append the `kata` plugin settings.
20 | # (We copy /var/lib/rancher/k3s/agent/etc/containerd/config.toml to /etc/containerd/config.toml)
21 |
22 | getConfig() {
23 | local l=$1
24 | key=$(kairos-agent config get "${l}" | tr -d '\n')
25 | if [ "$key" != "null" ]; then
26 | echo "${key}"
27 | fi
28 | echo
29 | }
30 |
31 | deployCoco() {
32 | mkdir -p /usr/local/bin
33 | cp -f assets/bin/* /usr/local/bin/
34 |
35 | # Setting an override for k3s service so that we can point to our config
36 | mkdir -p /etc/systemd/system/k3s.service.d
37 | # zz- to run apply override last
38 |
39 | # TODO: This flag: --kubelet-arg cgroup-driver=systemd
40 | # should probalby not be set when in alpine (or other non-systemd systems)
41 | # because maybe k3s decides to not put `SystemdCgroup = true` in the config.toml
42 | # in those cases.
43 | # https://kubernetes.io/docs/setup/production-environment/container-runtimes/#systemd-cgroup-driver
44 | cp assets/k3s-override.conf /etc/systemd/system/k3s.service.d/zz-coco-override.conf
45 |
46 | # NOTE: Make sure the paths we write to are persisted by adding this to the
47 | # kairos config:
48 | # install:
49 | # bind_mounts:
50 | # - /etc/coco
51 | # - /etc/containerd
52 | # Put our k3s config in place
53 | mkdir -p /etc/coco
54 | cp assets/k3s-config.yaml /etc/coco/
55 |
56 | cp assets/containerd.service /etc/systemd/system/
57 | mkdir -p /etc/systemd/system/containerd.service.d
58 | cp assets/containerd-override.conf /etc/systemd/system/containerd.service.d/
59 |
60 | mkdir -p /etc/containerd/
61 | cp -rf /var/lib/rancher/k3s/agent/etc/containerd/config.toml /etc/containerd/config.toml
62 |
63 | systemctl enable --now containerd.service
64 |
65 | touch /etc/containerd/.sentinel
66 |
67 | # Delete the plan (just in case, though is should not run again)
68 | rm -rf /var/lib/rancher/k3s/server/manifests/plan.yaml
69 |
70 | systemctl daemon-reload # read new definitions
71 |
72 | # NOTE: User should now reboot manually
73 |
74 |
75 | # TODO:
76 | # - In the config.toml generated by k3s, there is a line that point to the shims bin directory:
77 | #
78 | # [plugins."io.containerd.grpc.v1.cri".cni]
79 | # bin_dir = "/var/lib/rancher/k3s/data/599b4f3127975cf230091dd1fbb1c60fb7fa3ce1782b287fd8269855a279a757/bin"
80 | # conf_dir = "/var/lib/rancher/k3s/agent/etc/cni/net.d"
81 | #
82 | # This is where `containerd-shim-runc-v2` is but we should probably be using the
83 | # binary we install in '/usr/local/bin`.
84 | # How do we make use of our binary keeping the rest intact?
85 | }
86 |
87 |
88 | # This is the default functionality of this bundle. It applies a Plan on the cluster
89 | # so that when it starts, it runs the function above to migrate the cluster
90 | # to a "coco" one. The reason for doing this, is that we need to let k3s generate
91 | # the containerd config.json so that we can append our runtimes to it.
92 | # k3s won't generate a config for containerd if we specify "container-runtime-endpoint".
93 | # https://github.com/k3s-io/k3s/blob/85b261096cc494b3795e659b8a5d86fff9251164/pkg/agent/run.go#L113
94 | #
95 | # BUNDLE_TARGET:
96 | # https://github.com/kairos-io/kairos-sdk/commit/7a148fe5bb90c4ed5faceb534d72d6fc9852e8c0#diff-8e10d3eee9260dce2bf6cf7f8147d8052f350fb37c6c3e01c48d04852984b2efR183
97 | installDeployPlan() {
98 | cp assets/plan.yaml /var/lib/rancher/k3s/server/manifests/
99 | sed -i "s|@IMAGE@|${BUNDLE_TARGET}|g" /var/lib/rancher/k3s/server/manifests/plan.yaml
100 | }
101 |
102 | if [ -n "$COCO_DEPLOY" ]; then
103 | deployCoco
104 | else
105 | installDeployPlan
106 | fi
107 |
--------------------------------------------------------------------------------
/earthly.ps1:
--------------------------------------------------------------------------------
1 | docker run --privileged -v /var/run/docker.sock:/var/run/docker.sock --rm -t -v ${pwd}:/workspace -v earthly-tmp:/tmp/earthly:rw earthly/earthly:v0.8.15 --allow-privileged @args
--------------------------------------------------------------------------------
/earthly.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | docker run --privileged -v /var/run/docker.sock:/var/run/docker.sock --rm -t -v "$(pwd)":/workspace -v earthly-tmp:/tmp/earthly:rw earthly/earthly:v0.8.15 --allow-privileged "$@"
4 |
--------------------------------------------------------------------------------
/flux/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine AS build
2 | # renovate: datasource=github-releases depName=fluxcd/flux2
3 | ENV VERSION=2.1.2
4 | ENV CHECKSUM=61b360b50d6cfc34410730b1cebeb75f5eda2b484e47b9a083412f51ad56de68
5 |
6 | ADD https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_amd64.tar.gz /tmp
7 | RUN DOWNLOAD_FILE="/tmp/flux_${VERSION}_linux_amd64.tar.gz" && \
8 | DOWNLOAD_CHECKSUM=$(sha256sum "${DOWNLOAD_FILE}" | awk '{print $1}') && \
9 | if [[ ${DOWNLOAD_CHECKSUM} != ${CHECKSUM} ]]; then \
10 | echo "Checksum does not match"; \
11 | exit 1; \
12 | fi && \
13 | tar xzf "${DOWNLOAD_FILE}" -C / && \
14 | rm "${DOWNLOAD_FILE}"
15 |
16 | FROM scratch
17 | COPY --from=build flux .
18 | COPY flux-bootstrap.service .
19 | COPY flux-bootstrap.sh .
20 | COPY run.sh .
21 |
--------------------------------------------------------------------------------
/flux/flux-bootstrap.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Bootstrap cluster with Flux
3 | Documentation=https://github.com/kairos-io/community-bundles/blob/main/README.md#flux
4 | After=k3s.service
5 |
6 | [Service]
7 | Type=oneshot
8 | Restart=no
9 | ExecStart=/usr/local/bin/flux-bootstrap.sh
10 | User=root
11 | Group=root
12 | RemainAfterExit=yes
13 |
14 | [Install]
15 | WantedBy=k3s.service
16 |
--------------------------------------------------------------------------------
/flux/flux-bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Override with the `flux.env.KUBECONFIG` key if necessary
4 | export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
5 |
6 | # Seconds
7 | short=5
8 | long=900
9 |
10 | configmap=flux-bootstrap
11 |
12 | info () {
13 | echo $'\e[36mINFO\e[0m: ' "$1"
14 | }
15 |
16 | warn() {
17 | echo $'\e[33mWARN\e[0m:' "$1"
18 | }
19 |
20 | error() {
21 | echo $'\e[31mERROR\e[0m:' "$1"
22 | }
23 |
24 | cleanup() {
25 | info "Removing bootstrap configmap"
26 | timeout $short kubectl delete configmap -n default $configmap
27 | }
28 |
29 | # Don't bootstrap if the cluster is already bootstrapped
30 | if flux version &>/dev/null; then
31 | info "Flux is already bootstrapped, exiting..."
32 | exit 0
33 | fi
34 |
35 | # Determine what VCS we need to bootstrap
36 | # Starting in kairos 2.8.15, kairos-agent command returns empty string instead of "null"
37 | for vcs in bitbucket_server git github gitlab; do
38 | # kairos-agent used to return `null` when a key wasn't set, now returns empty.
39 | # we handle both
40 | value=$(kairos-agent config get flux.$vcs 2>/dev/null)
41 | if [[ $value != "null" && -n $value ]]; then
42 | version_control=$vcs
43 | break
44 | fi
45 | done
46 |
47 | if [[ "${version_control}x" == "x" ]]; then
48 | error "Unable to determine what version control provider to use, exiting..."
49 | exit 1
50 | fi
51 |
52 | # Get flux envs and settings for our VCS
53 | mapfile -t envs < <(kairos-agent config get "flux.env" 2>/dev/null)
54 | mapfile -t args < <(kairos-agent config get "flux.$version_control" 2>/dev/null)
55 | declare -a cmdline
56 |
57 | for setting in "${envs[@]}"; do
58 | if [[ $setting != "null" ]] && [[ $setting != "" ]]; then
59 | env=$(echo "$setting" | cut -d: -f1)
60 | value=$(echo "$setting" | sed -n 's/^[^:]*: *//p')
61 | if [[ "${value}x" != "x" ]]; then
62 | export "$env"="$value"
63 | fi
64 | fi
65 | done
66 |
67 | # Set commandline args
68 | for setting in "${args[@]}"; do
69 | if [[ $setting != "null" ]] && [[ $setting != "" ]]; then
70 | arg=$(echo "$setting" | cut -d: -f1)
71 | value=$(echo "$setting" | sed -n 's/^[^:]*: *//p')
72 | if [[ "${value}x" != "x" ]]; then
73 | cmdline+=("--$arg" "$value")
74 | fi
75 | fi
76 | done
77 |
78 | # Try to bootstrap Flux for 30 minutes, sleep 15 seconds between attempts
79 | minutes=30
80 | sleep=15
81 | retry_attempt=1
82 | total_attempts=$(( minutes * 60 / sleep ))
83 | active="false"
84 |
85 | if [[ "${#cmdline[@]}" -eq 0 ]]; then
86 | info "Flux was not configured in cloud-config, not bootstrapping"
87 | exit 0
88 | else
89 | while [[ $retry_attempt -le $total_attempts ]]; do
90 | if [[ "$active" != "true" ]]; then
91 | # Ensure only one host tries to bootstrap, whichever makes the configmap first
92 | if ! timeout $short kubectl version &> /dev/null; then
93 | info "Kubernetes API not ready yet, sleeping"
94 | else
95 | if ! timeout $short kubectl create configmap $configmap --from-literal=hostname="$(hostname)"; then
96 | warn "Unable to create configmap, another node may be active"
97 | fi
98 |
99 | # The configmap exists but we must finally check if the hostname matches
100 | if [[ "$(timeout $short kubectl get configmap -n default $configmap -o jsonpath='{.data.hostname}')" != "$(hostname)" ]]; then
101 | error "Flux bootstrap ConfigMap exists but another node is active, exiting..."
102 | exit 3
103 | fi
104 |
105 | # We must be the active node
106 | active="true"
107 | fi
108 | fi
109 |
110 | if [[ "$active" == "true" ]]; then
111 | if timeout $long flux bootstrap "${version_control/_/-}" "${cmdline[@]}"; then
112 | cleanup
113 | exit 0
114 | fi
115 | fi
116 |
117 | warn "Install attempt $retry_attempt (of $total_attempts) failed, retrying in $sleep seconds"
118 | (( retry_attempt = retry_attempt + 1 ))
119 | sleep $sleep
120 | done
121 | fi
122 |
123 | error "Failed to bootstrap with Flux, timed out ($minutes minutes)"
124 | exit 4
125 |
--------------------------------------------------------------------------------
/flux/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -x
3 |
4 | bin=/usr/local/bin/
5 | system=/etc/systemd/system/
6 |
7 | mkdir -p "$bin"
8 | cp flux "$bin"
9 | cp flux-bootstrap.sh "$bin"
10 | cp flux-bootstrap.service "$system"
11 | systemctl enable flux-bootstrap
--------------------------------------------------------------------------------
/kairos/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | FROM scratch
3 | COPY ./run.sh /
4 | COPY ./assets /assets
5 |
--------------------------------------------------------------------------------
/kairos/assets/crd.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: kairos
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: kairos-crds
10 | namespace: kairos
11 | spec:
12 | chart: kairos-crds
13 | repo: https://kairos-io.github.io/helm-charts
14 | version: "@VERSION@"
15 |
--------------------------------------------------------------------------------
/kairos/assets/entangle-proxy.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: entangle
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: entangle
10 | namespace: entangle
11 | spec:
12 | chart: entangle
13 | repo: https://kairos-io.github.io/helm-charts
14 | version: "@VERSION@"
15 |
--------------------------------------------------------------------------------
/kairos/assets/entangle.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: entangle
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: entangle
10 | namespace: entangle
11 | spec:
12 | chart: entangle
13 | repo: https://kairos-io.github.io/helm-charts
14 | version: "@VERSION@"
15 |
--------------------------------------------------------------------------------
/kairos/assets/osbuilder.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: osbuilder
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: osbuilder
10 | namespace: osbuilder
11 | spec:
12 | chart: osbuilder
13 | repo: https://kairos-io.github.io/helm-charts
14 | version: "@VERSION@"
15 |
--------------------------------------------------------------------------------
/kairos/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 | getConfig() {
8 | local l=$1
9 | key=$(kairos-agent config get "${l}" | tr -d '\n')
10 | if [ "$key" != "null" ]; then
11 | echo "${key}"
12 | fi
13 | echo
14 | }
15 |
16 | # renovate: depName=entangle repoUrl=https://kairos-io.github.io/helm-charts
17 | ENTANGLE_VERSION="0.2.4"
18 | ENTANGLE_ENABLE=""
19 | # renovate: depName=entangle-proxy repoUrl=https://kairos-io.github.io/helm-charts
20 | ENTANGLEPROXY_VERSION="0.0.5"
21 | ENTANGLEPROXY_ENABLE=""
22 | # renovate: depName=osbuilder repoUrl=https://kairos-io.github.io/helm-charts
23 | OSBUILDER_VERSION="0.6.0"
24 | OSBUILDER_ENABLE=""
25 |
26 | CRDS_VERSION="0.0.13"
27 |
28 | templ() {
29 | local file="$3"
30 | local value="$2"
31 | local sentinel="$1"
32 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
33 | }
34 |
35 | readConfig() {
36 | _version=$(getConfig kairos.crds.version)
37 | if [ "$_version" != "" ]; then
38 | CRDS_VERSION=$_version
39 | fi
40 | _enable=$(getConfig kairos.entangle.enable)
41 | if [ "$_enable" != "" ]; then
42 | ENTANGLE_ENABLE=$_enable
43 | fi
44 | _version=$(getConfig kairos.entangle.version)
45 | if [ "$_version" != "" ]; then
46 | ENTANGLE_VERSION=$_version
47 | fi
48 | _enable=$(getConfig kairos.entangleProxy.enable)
49 | if [ "$_enable" != "" ]; then
50 | ENTANGLEPROXY_ENABLE=$_enable
51 | fi
52 | _version=$(getConfig kairos.entangleProxy.version)
53 | if [ "$_version" != "" ]; then
54 | ENTANGLEPROXY_VERSION=$_version
55 | fi
56 | _enable=$(getConfig kairos.osbuilder.enable)
57 | if [ "$_enable" != "" ]; then
58 | OSBUILDER_ENABLE=$_enable
59 | fi
60 | _version=$(getConfig kairos.osbuilder.version)
61 | if [ "$_version" != "" ]; then
62 | OSBUILDER_VERSION=$_version
63 | fi
64 | }
65 |
66 | mkdir -p "${K3S_MANIFEST_DIR}"
67 |
68 | readConfig
69 |
70 | # Copy manifests, and template them
71 |
72 | templ "VERSION" "${CRDS_VERSION}" assets/crd.yaml
73 | cp -rf assets/crd.yaml "${K3S_MANIFEST_DIR}/kairos-crds.yaml"
74 |
75 | if [ "$ENTANGLE_ENABLE" == "true" ]; then
76 | SRC="assets/entangle.yaml"
77 | FILE=$K3S_MANIFEST_DIR/kairos-entangle.yaml
78 | templ "VERSION" "${ENTANGLE_VERSION}" "${SRC}"
79 | cp -rf "${SRC}" "${FILE}"
80 | fi
81 |
82 | if [ "$ENTANGLEPROXY_ENABLE" == "true" ]; then
83 | SRC="assets/entangle-proxy.yaml"
84 | FILE=$K3S_MANIFEST_DIR/kairos-entangle-proxy.yaml
85 | templ "VERSION" "${ENTANGLEPROXY_VERSION}" "${SRC}"
86 | cp -rf "${SRC}" "${FILE}"
87 | fi
88 |
89 | if [ "$OSBUILDER_ENABLE" == "true" ]; then
90 | SRC="assets/osbuilder.yaml"
91 | FILE="${K3S_MANIFEST_DIR}/kairos-osbuilder.yaml"
92 | templ "VERSION" "${OSBUILDER_VERSION}" "${SRC}"
93 | cp -rf "${SRC}" "${FILE}"
94 | fi
95 |
--------------------------------------------------------------------------------
/kubevirt/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | FROM scratch
3 | COPY ./run.sh /
4 | COPY ./assets /assets
5 | COPY ./kubevirt-manager-manifests /kubevirt-manager-manifests
--------------------------------------------------------------------------------
/kubevirt/assets/cdi-cr.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: cdi.kubevirt.io/v1beta1
2 | kind: CDI
3 | metadata:
4 | name: cdi
5 | spec:
6 | imagePullPolicy: IfNotPresent
7 | infra:
8 | nodeSelector:
9 | kubernetes.io/os: linux
10 | tolerations:
11 | - key: CriticalAddonsOnly
12 | operator: Exists
13 | workload:
14 | nodeSelector:
15 | kubernetes.io/os: linux
16 |
--------------------------------------------------------------------------------
/kubevirt/assets/kubevirt-cr.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kubevirt.io/v1
3 | kind: KubeVirt
4 | metadata:
5 | name: kubevirt
6 | namespace: kubevirt
7 | spec:
8 | certificateRotateStrategy: {}
9 | configuration:
10 | developerConfiguration:
11 | featureGates: []
12 | customizeComponents: {}
13 | imagePullPolicy: IfNotPresent
14 | workloadUpdateStrategy: {}
15 |
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/cdi-cr.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: cdi.kubevirt.io/v1beta1
2 | kind: CDI
3 | metadata:
4 | name: cdi
5 | spec:
6 | config:
7 | featureGates:
8 | - HonorWaitForFirstConsumer
9 | imagePullPolicy: IfNotPresent
10 | infra:
11 | nodeSelector:
12 | kubernetes.io/os: linux
13 | tolerations:
14 | - key: CriticalAddonsOnly
15 | operator: Exists
16 | workload:
17 | nodeSelector:
18 | kubernetes.io/os: linux
19 |
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/kubevirt-cr.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: kubevirt.io/v1
3 | kind: KubeVirt
4 | metadata:
5 | name: kubevirt
6 | namespace: kubevirt
7 | spec:
8 | certificateRotateStrategy: {}
9 | configuration:
10 | developerConfiguration:
11 | featureGates:
12 | - ExpandDisks
13 | customizeComponents: {}
14 | imagePullPolicy: IfNotPresent
15 | workloadUpdateStrategy: {}
16 |
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/kubevirt-manager-bundled.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Namespace
4 | metadata:
5 | name: kubevirt-manager
6 | labels:
7 | app: kubevirt-manager
8 | kubevirt-manager.io/version: 1.1.2
9 |
10 | ---
11 | apiVersion: v1
12 | kind: ServiceAccount
13 | metadata:
14 | name: kubevirt-manager
15 | namespace: kubevirt-manager
16 | labels:
17 | app: kubevirt-manager
18 | kubevirt-manager.io/version: 1.1.2
19 |
20 | ---
21 | apiVersion: rbac.authorization.k8s.io/v1
22 | kind: ClusterRole
23 | metadata:
24 | name: kubevirt-manager
25 |
26 | rules:
27 | - apiGroups: [""]
28 | resources: ["nodes", "namespaces"]
29 | verbs: ["get", "list"]
30 | - apiGroups: [""]
31 | resources: ["customresourcedefinitions"]
32 | verbs: ["get", "list"]
33 | - apiGroups: [""]
34 | resources: ["persistentvolumeclaims", "persistentvolumes", "services"]
35 | verbs: ["*"]
36 | - apiGroups: ["storage.k8s.io"]
37 | resources: ["storageclasses"]
38 | verbs: ["get", "list"]
39 | - apiGroups: ["apiextensions.k8s.io"]
40 | resources: ["customresourcedefinitions"]
41 | verbs: ["get", "list"]
42 | - apiGroups: ["k8s.cni.cncf.io"]
43 | resources: ["network-attachment-definitions"]
44 | verbs: ["get", "list"]
45 | - apiGroups: ["kubevirt.io"]
46 | resources: ["virtualmachines", "virtualmachineinstances"]
47 | verbs: ["*"]
48 | - apiGroups: ["subresources.kubevirt.io"]
49 | resources: ["*"]
50 | verbs: ["get", "list", "update", "patch"]
51 | - apiGroups: ["instancetype.kubevirt.io"]
52 | resources: ["*"]
53 | verbs: ["*"]
54 | - apiGroups: ["cdi.kubevirt.io"]
55 | resources: ["*"]
56 | verbs: ["*"]
57 | - apiGroups: ["pool.kubevirt.io"]
58 | resources: ["*"]
59 | verbs: ["*"]
60 | - apiGroups: ["scheduling.k8s.io"]
61 | resources: ["priorityclasses"]
62 | verbs: ["get", "list"]
63 |
64 | ---
65 | apiVersion: rbac.authorization.k8s.io/v1
66 | kind: ClusterRoleBinding
67 | metadata:
68 | name: kubevirt-manager
69 | labels:
70 | app: kubevirt-manager
71 | kubevirt-manager.io/version: 1.1.2
72 | roleRef:
73 | apiGroup: rbac.authorization.k8s.io
74 | kind: ClusterRole
75 | name: kubevirt-manager
76 | subjects:
77 | - kind: ServiceAccount
78 | name: kubevirt-manager
79 | namespace: kubevirt-manager
80 |
81 | ---
82 | apiVersion: scheduling.k8s.io/v1
83 | kind: PriorityClass
84 | description: Priority class for VMs which should not be preemtited.
85 | metadata:
86 | name: vm-standard
87 | labels:
88 | app: kubevirt-manager
89 | kubevirt-manager.io/version: 1.1.2
90 | kubevirt-manager.io/managed: "true"
91 | preemptionPolicy: Never
92 | value: 999999999
93 |
94 | ---
95 | apiVersion: scheduling.k8s.io/v1
96 | kind: PriorityClass
97 | description: Priority class for VMs which are allowed to be preemtited.
98 | metadata:
99 | name: vm-preemptible
100 | labels:
101 | app: kubevirt-manager
102 | kubevirt-manager.io/version: 1.1.2
103 | kubevirt-manager.io/managed: "true"
104 | preemptionPolicy: PreemptLowerPriority
105 | value: 1000000
106 |
107 | ---
108 | apiVersion: apps/v1
109 | kind: Deployment
110 | metadata:
111 | name: kubevirt-manager
112 | namespace: kubevirt-manager
113 | labels:
114 | app: kubevirt-manager
115 | kubevirt-manager.io/version: 1.1.2
116 | spec:
117 | selector:
118 | matchLabels:
119 | app: kubevirt-manager
120 | kubevirt-manager.io/version: 1.1.2
121 | replicas: 1
122 | strategy:
123 | type: Recreate
124 | template:
125 | metadata:
126 | labels:
127 | app: kubevirt-manager
128 | kubevirt-manager.io/version: 1.1.2
129 | spec:
130 | containers:
131 | - name: kubevirtmgr
132 | image: kubevirtmanager/kubevirt-manager:1.1.2
133 | imagePullPolicy: IfNotPresent
134 | ports:
135 | - name: http
136 | containerPort: 8080
137 | securityContext:
138 | allowPrivilegeEscalation: false
139 | readOnlyRootFilesystem: true
140 | runAsUser: 10000
141 | runAsGroup: 30000
142 | volumeMounts:
143 | - name: cache-volume
144 | mountPath: /var/cache/nginx
145 | - name: run-volume
146 | mountPath: /var/run
147 | serviceAccountName: kubevirt-manager
148 | restartPolicy: Always
149 | volumes:
150 | - name: cache-volume
151 | emptyDir: {}
152 | - name: run-volume
153 | emptyDir: {}
154 |
155 | ---
156 | apiVersion: v1
157 | kind: Service
158 | metadata:
159 | name: kubevirt-manager
160 | namespace: kubevirt-manager
161 | labels:
162 | app: kubevirt-manager
163 | kubevirt-manager.io/version: 1.1.2
164 | spec:
165 | type: ClusterIP
166 | selector:
167 | app: kubevirt-manager
168 | ports:
169 | - protocol: TCP
170 | port: 8080
171 | targetPort: 8080
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/kubevirt-manager-deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: kubevirt-manager
5 | namespace: kubevirt-manager
6 | labels:
7 | app: kubevirt-manager
8 | kubevirt-manager.io/version: 1.1.2
9 | spec:
10 | selector:
11 | matchLabels:
12 | app: kubevirt-manager
13 | kubevirt-manager.io/version: 1.1.2
14 | replicas: 1
15 | strategy:
16 | type: Recreate
17 | template:
18 | metadata:
19 | labels:
20 | app: kubevirt-manager
21 | kubevirt-manager.io/version: 1.1.2
22 | spec:
23 | containers:
24 | - name: kubevirtmgr
25 | image: kubevirtmanager/kubevirt-manager:1.1.2
26 | imagePullPolicy: IfNotPresent
27 | ports:
28 | - name: http
29 | containerPort: 8080
30 | securityContext:
31 | allowPrivilegeEscalation: false
32 | readOnlyRootFilesystem: true
33 | runAsUser: 10000
34 | runAsGroup: 30000
35 | volumeMounts:
36 | - name: cache-volume
37 | mountPath: /var/cache/nginx
38 | - name: run-volume
39 | mountPath: /var/run
40 | serviceAccountName: kubevirt-manager
41 | restartPolicy: Always
42 | volumes:
43 | - name: cache-volume
44 | emptyDir: {}
45 | - name: run-volume
46 | emptyDir: {}
47 |
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/kubevirt-manager-ingress.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: networking.k8s.io/v1
2 | kind: Ingress
3 | metadata:
4 | name: kubevirt-manager
5 | namespace: kubevirt-manager
6 | annotations:
7 | nginx.org/location-snippets: |
8 | proxy_set_header Upgrade $http_upgrade;
9 | proxy_set_header Connection $connection_upgrade;
10 | spec:
11 | ingressClassName: my-ingress-class
12 | tls:
13 | - hosts:
14 | - my-host.com
15 | rules:
16 | - host: my-host.com
17 | http:
18 | paths:
19 | - path: /
20 | pathType: Prefix
21 | backend:
22 | service:
23 | name: kubevirt-manager
24 | port:
25 | number: 8080
26 |
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/kubevirt-manager-ns.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: kubevirt-manager
5 | labels:
6 | app: kubevirt-manager
7 | kubevirt-manager.io/version: 1.1.2
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/kubevirt-manager-pc.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: scheduling.k8s.io/v1
2 | kind: PriorityClass
3 | description: Priority class for VMs which should not be preemtited.
4 | metadata:
5 | name: vm-standard
6 | labels:
7 | app: kubevirt-manager
8 | kubevirt-manager.io/version: 1.1.2
9 | kubevirt-manager.io/managed: "true"
10 | preemptionPolicy: Never
11 | value: 999999999
12 |
13 | ---
14 | apiVersion: scheduling.k8s.io/v1
15 | kind: PriorityClass
16 | description: Priority class for VMs which are allowed to be preemtited.
17 | metadata:
18 | name: vm-preemptible
19 | labels:
20 | app: kubevirt-manager
21 | kubevirt-manager.io/version: 1.1.2
22 | kubevirt-manager.io/managed: "true"
23 | preemptionPolicy: PreemptLowerPriority
24 | value: 1000000
25 |
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/kubevirt-manager-rbac.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ServiceAccount
3 | metadata:
4 | name: kubevirt-manager
5 | namespace: kubevirt-manager
6 | labels:
7 | app: kubevirt-manager
8 | kubevirt-manager.io/version: 1.1.2
9 |
10 | ---
11 | apiVersion: rbac.authorization.k8s.io/v1
12 | kind: ClusterRole
13 | metadata:
14 | name: kubevirt-manager
15 | rules:
16 | - apiGroups: [""]
17 | resources: ["nodes", "namespaces"]
18 | verbs: ["get", "list"]
19 | - apiGroups: [""]
20 | resources: ["customresourcedefinitions"]
21 | verbs: ["get", "list"]
22 | - apiGroups: [""]
23 | resources: ["persistentvolumeclaims", "persistentvolumes", "services"]
24 | verbs: ["*"]
25 | - apiGroups: ["storage.k8s.io"]
26 | resources: ["storageclasses"]
27 | verbs: ["get", "list"]
28 | - apiGroups: ["apiextensions.k8s.io"]
29 | resources: ["customresourcedefinitions"]
30 | verbs: ["get", "list"]
31 | - apiGroups: ["k8s.cni.cncf.io"]
32 | resources: ["network-attachment-definitions"]
33 | verbs: ["get", "list"]
34 | - apiGroups: ["kubevirt.io"]
35 | resources: ["virtualmachines", "virtualmachineinstances"]
36 | verbs: ["*"]
37 | - apiGroups: ["subresources.kubevirt.io"]
38 | resources: ["*"]
39 | verbs: ["get", "list", "update", "patch"]
40 | - apiGroups: ["instancetype.kubevirt.io"]
41 | resources: ["*"]
42 | verbs: ["*"]
43 | - apiGroups: ["cdi.kubevirt.io"]
44 | resources: ["*"]
45 | verbs: ["*"]
46 | - apiGroups: ["pool.kubevirt.io"]
47 | resources: ["*"]
48 | verbs: ["*"]
49 | - apiGroups: ["scheduling.k8s.io"]
50 | resources: ["priorityclasses"]
51 | verbs: ["get", "list"]
52 |
53 | ---
54 | apiVersion: rbac.authorization.k8s.io/v1
55 | kind: ClusterRoleBinding
56 | metadata:
57 | name: kubevirt-manager
58 | labels:
59 | app: kubevirt-manager
60 | kubevirt-manager.io/version: 1.1.1
61 | roleRef:
62 | apiGroup: rbac.authorization.k8s.io
63 | kind: ClusterRole
64 | name: kubevirt-manager
65 | subjects:
66 | - kind: ServiceAccount
67 | name: kubevirt-manager
68 | namespace: kubevirt-manager
69 |
--------------------------------------------------------------------------------
/kubevirt/kubevirt-manager-manifests/kubevirt-manager-service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: kubevirt-manager
5 | namespace: kubevirt-manager
6 | labels:
7 | app: kubevirt-manager
8 | kubevirt-manager.io/version: 1.1.2
9 | spec:
10 | type: ClusterIP
11 | selector:
12 | app: kubevirt-manager
13 | ports:
14 | - protocol: TCP
15 | port: 8080
16 | targetPort: 8080
--------------------------------------------------------------------------------
/kubevirt/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 | getConfig() {
8 | local l=$1
9 | key=$(kairos-agent config get "${l}" | tr -d '\n')
10 | if [ "$key" != "null" ]; then
11 | echo "${key}"
12 | fi
13 | echo
14 | }
15 |
16 | KUBEVIRT_MANAGER="false"
17 |
18 | templ() {
19 | local file="$3"
20 | local value="$2"
21 | local sentinel="$1"
22 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
23 | }
24 |
25 | readConfig() {
26 | _manager=$(getConfig kubevirt.manager)
27 | if [ "$_manager" != "" ]; then
28 | KUBEVIRT_MANAGER=$_manager
29 | fi
30 | }
31 |
32 | mkdir -p "${K3S_MANIFEST_DIR}"
33 |
34 | readConfig
35 |
36 | # Copy manifests from kubevirt
37 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
38 |
39 | if [ "$KUBEVIRT_MANAGER" == "true" ]; then
40 | cp -rf kubevirt-manager-manifests/* "${K3S_MANIFEST_DIR}"
41 | fi
42 |
--------------------------------------------------------------------------------
/kyverno/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | FROM scratch
3 | COPY ./run.sh /
4 | COPY ./assets /assets
5 |
--------------------------------------------------------------------------------
/kyverno/assets/kyverno.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: kyverno
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: kyverno
10 | namespace: kyverno
11 | spec:
12 | name: kyverno
13 | chart: kyverno
14 | repo: https://kyverno.github.io/kyverno/
15 | valuesContent: |-
16 | @VALUES@
17 | version: "@VERSION@"
18 |
--------------------------------------------------------------------------------
/kyverno/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 |
8 | getConfig() {
9 | local key=$1
10 | _value=$(kairos-agent config get "${key} | @json" | tr -d '\n')
11 | # Remove the quotes wrapping the value.
12 | _value=${_value:1:${#_value}-2}
13 | if [ "${_value}" != "null" ]; then
14 | echo "${_value}"
15 | fi
16 | echo
17 | }
18 |
19 | VALUES="{}"
20 | # renovate: depName=kyverno repoUrl=https://kyverno.github.io/kyverno/
21 | VERSION="3.2.7"
22 |
23 | templ() {
24 | local file="$3"
25 | local value=$2
26 | local sentinel=$1
27 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
28 | }
29 |
30 | readConfig() {
31 | _values=$(getConfig kyverno.values)
32 | if [ "$_values" != "" ]; then
33 | VALUES=$_values
34 | fi
35 | _version=$(getConfig kyverno.version)
36 | if [ "$_version" != "" ]; then
37 | VERSION=$_version
38 | fi
39 | }
40 |
41 | mkdir -p "${K3S_MANIFEST_DIR}"
42 |
43 | readConfig
44 |
45 | # Copy manifests, and template them
46 | for FILE in assets/*; do
47 | templ "VALUES" "${VALUES}" "${FILE}"
48 | templ "VERSION" "${VERSION}" "${FILE}"
49 | done;
50 |
51 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
52 |
--------------------------------------------------------------------------------
/longhorn/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | FROM scratch
3 | COPY ./run.sh /
4 | COPY ./assets /assets
5 |
--------------------------------------------------------------------------------
/longhorn/assets/longhorn.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: longhorn-system
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: longhorn
10 | namespace: longhorn-system
11 | spec:
12 | chart: longhorn
13 | repo: https://charts.longhorn.io
14 | valuesContent: |-
15 | @VALUES@
16 | version: @VERSION@
17 |
--------------------------------------------------------------------------------
/longhorn/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 |
8 | getConfig() {
9 | local key=$1
10 | _value=$(kairos-agent config get "${key} | @json" | tr -d '\n')
11 | # Remove the quotes wrapping the value.
12 | _value=${_value:1:${#_value}-2}
13 | if [ "${_value}" != "null" ]; then
14 | echo "${_value}"
15 | fi
16 | echo
17 | }
18 |
19 | VALUES="{}"
20 | # renovate: depName=longhorn repoUrl=https://charts.longhorn.io
21 | VERSION="1.5.3"
22 |
23 | templ() {
24 | local file="$3"
25 | local value=$2
26 | local sentinel=$1
27 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
28 | }
29 |
30 | readConfig() {
31 | _values=$(getConfig longhorn.values)
32 | if [ "$_values" != "" ]; then
33 | VALUES=$_values
34 | fi
35 | _version=$(getConfig longhorn.version)
36 | if [ "$_version" != "" ]; then
37 | VERSION=$_version
38 | fi
39 | }
40 |
41 | mkdir -p "${K3S_MANIFEST_DIR}"
42 |
43 | readConfig
44 |
45 | # Copy manifests, and template them
46 | for FILE in assets/*; do
47 | templ "VALUES" "${VALUES}" "${FILE}"
48 | templ "VERSION" "${VERSION}" "${FILE}"
49 | done;
50 |
51 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
52 |
--------------------------------------------------------------------------------
/metallb/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | FROM scratch
3 | COPY ./run.sh /
4 | COPY ./assets /assets
5 |
--------------------------------------------------------------------------------
/metallb/assets/addresspool.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: metallb.io/v1beta1
2 | kind: IPAddressPool
3 | metadata:
4 | name: default
5 | namespace: metallb-system
6 | spec:
7 | addresses:
8 | - @ADDRESS_POOL@
9 | ---
10 | apiVersion: metallb.io/v1beta1
11 | kind: L2Advertisement
12 | metadata:
13 | name: default
14 | namespace: metallb-system
15 | spec:
16 | ipAddressPools:
17 | - default
--------------------------------------------------------------------------------
/metallb/assets/metallb.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: metallb-system
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: metallb
10 | namespace: metallb-system
11 | spec:
12 | chart: metallb
13 | repo: https://metallb.github.io/metallb
14 | version: "@VERSION@"
15 |
--------------------------------------------------------------------------------
/metallb/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 | getConfig() {
8 | local l=$1
9 | key=$(kairos-agent config get "${l}" | tr -d '\n')
10 | if [ "$key" != "null" ]; then
11 | echo "${key}"
12 | fi
13 | echo
14 | }
15 |
16 | # renovate: depName=metallb repoUrl=https://metallb.github.io/metallb
17 | VERSION="0.14.9"
18 | ADDRESS_POOL="192.168.1.10-192.168.1.20"
19 |
20 | templ() {
21 | local file="$3"
22 | local value="$2"
23 | local sentinel="$1"
24 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
25 | }
26 |
27 | readConfig() {
28 | _version=$(getConfig metallb.version)
29 | if [ "$_version" != "" ]; then
30 | VERSION=$_version
31 | fi
32 | _addresspool=$(getConfig metallb.address_pool)
33 | if [ "$_version" != "" ]; then
34 | ADDRESS_POOL=$_addresspool
35 | fi
36 | }
37 |
38 | mkdir -p "${K3S_MANIFEST_DIR}"
39 |
40 | readConfig
41 |
42 | # Copy manifests, and template them
43 | for FILE in assets/*; do
44 | templ "VERSION" "${VERSION}" "${FILE}"
45 | templ "ADDRESS_POOL" "${ADDRESS_POOL}" "${FILE}"
46 | done;
47 |
48 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
49 |
--------------------------------------------------------------------------------
/multus/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as builder
2 |
3 | ARG TARGETARCH
4 |
5 | # renovate: datasource=github-releases depName=k8snetworkplumbingwg/multus-cni extractVersion=^v(?.*)$
6 | ARG MULTUS_VERSION=4.0.2
7 |
8 | # renovate: datasource=github-releases depName=containernetworking/plugins extractVersion=^v(?.*)$
9 | ARG PLUGINS_VERSION=1.3.0
10 |
11 | WORKDIR /build
12 |
13 | RUN apk add curl && \
14 | curl -fsSL --remote-name-all \
15 | https://github.com/k8snetworkplumbingwg/multus-cni/releases/download/v${MULTUS_VERSION}/{checksums.txt,multus-cni_${MULTUS_VERSION}_linux_${TARGETARCH}.tar.gz} \
16 | https://github.com/containernetworking/plugins/releases/download/v${PLUGINS_VERSION}/cni-plugins-linux-${TARGETARCH}-v${PLUGINS_VERSION}.tgz{.sha256,} && \
17 | grep ${TARGETARCH} checksums.txt | sha256sum -cs && \
18 | sha256sum -cs cni-plugins-linux-${TARGETARCH}-v${PLUGINS_VERSION}.tgz.sha256 && \
19 | tar -xf multus-cni_${MULTUS_VERSION}_linux_${TARGETARCH}.tar.gz --strip-components 1 \
20 | multus-cni_${MULTUS_VERSION}_linux_${TARGETARCH}/multus && \
21 | mkdir plugins && \
22 | tar -xC plugins -f cni-plugins-linux-${TARGETARCH}-v${PLUGINS_VERSION}.tgz
23 |
24 | FROM scratch
25 |
26 | COPY --from=builder /build/multus /multus
27 | COPY --from=builder /build/plugins /plugins
28 | COPY ./manifests.yaml /
29 | COPY ./run.sh /
30 |
--------------------------------------------------------------------------------
/multus/manifests.yaml:
--------------------------------------------------------------------------------
1 | # Taken from https://github.com/k8snetworkplumbingwg/multus-cni/blob/v4.0.2/deployments/multus-daemonset.yml
2 | ---
3 | apiVersion: apiextensions.k8s.io/v1
4 | kind: CustomResourceDefinition
5 | metadata:
6 | name: network-attachment-definitions.k8s.cni.cncf.io
7 | spec:
8 | group: k8s.cni.cncf.io
9 | scope: Namespaced
10 | names:
11 | plural: network-attachment-definitions
12 | singular: network-attachment-definition
13 | kind: NetworkAttachmentDefinition
14 | shortNames:
15 | - net-attach-def
16 | versions:
17 | - name: v1
18 | served: true
19 | storage: true
20 | schema:
21 | openAPIV3Schema:
22 | description: >-
23 | NetworkAttachmentDefinition is a CRD schema specified by the Network
24 | Plumbing Working Group to express the intent for attaching pods to one or
25 | more logical or physical networks. More information available at:
26 | https://github.com/k8snetworkplumbingwg/multi-net-spec
27 | type: object
28 | properties:
29 | apiVersion:
30 | description: >-
31 | APIVersion defines the versioned schema of this representation of an
32 | object. Servers should convert recognized schemas to the latest
33 | internal value, and may reject unrecognized values. More info:
34 | https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
35 | type: string
36 | kind:
37 | description: >-
38 | Kind is a string value representing the REST resource this object
39 | represents. Servers may infer this from the endpoint the client
40 | submits requests to. Cannot be updated. In CamelCase. More info:
41 | https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
42 | type: string
43 | metadata:
44 | type: object
45 | spec:
46 | description: >-
47 | NetworkAttachmentDefinition spec defines the desired state of a
48 | network attachment
49 | type: object
50 | properties:
51 | config:
52 | description: >-
53 | NetworkAttachmentDefinition config is a JSON-formatted CNI
54 | configuration
55 | type: string
56 | ---
57 | apiVersion: rbac.authorization.k8s.io/v1
58 | kind: ClusterRole
59 | metadata:
60 | name: multus
61 | rules:
62 | - apiGroups: ["k8s.cni.cncf.io"]
63 | resources: ["*"]
64 | verbs: ["*"]
65 | - apiGroups: [""]
66 | resources: [pods, pods/status]
67 | verbs: [get, update]
68 | - apiGroups: ["", events.k8s.io]
69 | resources: [events]
70 | verbs: [create, patch, update]
71 | ---
72 | apiVersion: rbac.authorization.k8s.io/v1
73 | kind: ClusterRoleBinding
74 | metadata:
75 | name: multus
76 | roleRef:
77 | apiGroup: rbac.authorization.k8s.io
78 | kind: ClusterRole
79 | name: multus
80 | subjects:
81 | - kind: User
82 | name: multus
83 | apiGroup: rbac.authorization.k8s.io
84 |
--------------------------------------------------------------------------------
/multus/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests}
6 | CNI_BIN_DIR=/opt/cni/bin
7 | MULTUS_BIN_DIR=/var/lib/rancher/k3s/data/current/bin
8 | CNI_CONF_DIR=/var/lib/rancher/k3s/agent/etc/cni/net.d
9 | CA_PATH=/var/lib/rancher/k3s/server/tls
10 |
11 | getConfig() {
12 | local l=$1
13 | key=$(kairos-agent config get "${l}")
14 | if [[ $key != "null" ]]; then
15 | echo "${key}"
16 | fi
17 | echo
18 | }
19 |
20 | CNI_PLUGINS=
21 | CRT_VALIDITY=3650
22 | NAMESPACE_ISOLATION=false
23 | GLOBAL_NAMESPACES=
24 | PRIMARY_CONFIG=
25 |
26 | readConfig() {
27 | _cni_plugins=$(getConfig multus.cni_plugins[]?)
28 | if [[ $_cni_plugins != "" ]]; then
29 | CNI_PLUGINS=$_cni_plugins
30 | fi
31 |
32 | _crt_validity=$(getConfig multus.crt_validity)
33 | if [[ $_crt_validity != "" ]]; then
34 | CRT_VALIDITY=$_crt_validity
35 | fi
36 |
37 | _namespace_isolation=$(getConfig multus.namespace_isolation)
38 | if [[ $_namespace_isolation != "" ]]; then
39 | NAMESPACE_ISOLATION=$_namespace_isolation
40 | fi
41 |
42 | _global_namespaces=$(getConfig multus.global_namespaces[]?)
43 | if [[ $_global_namespaces != "" ]]; then
44 | GLOBAL_NAMESPACES=${_global_namespaces//[[:space:]]/,}
45 | fi
46 |
47 | _primary_config=$(getConfig multus.primary_config)
48 | if [[ $_primary_config != "" ]]; then
49 | PRIMARY_CONFIG=$_primary_config
50 | else
51 | for config in "${CNI_CONF_DIR}"/*.conflist; do
52 | if [[ $config != "${CNI_CONF_DIR}/00-multus.conflist" ]]; then
53 | PRIMARY_CONFIG=$config
54 | break;
55 | fi
56 | done
57 | fi
58 | }
59 |
60 | createDirectories() {
61 | mkdir -p \
62 | "${CNI_BIN_DIR}" \
63 | "${MULTUS_BIN_DIR}" \
64 | "${K3S_MANIFEST_DIR}" \
65 | "${CNI_CONF_DIR}/multus.d"
66 | }
67 |
68 | install() {
69 | cp multus "${MULTUS_BIN_DIR}"
70 | }
71 |
72 | installPlugins() {
73 | for plugin in $CNI_PLUGINS; do
74 | cp "plugins/${plugin}" "${CNI_BIN_DIR}"
75 | done
76 | }
77 |
78 | createManifests() {
79 | cp manifests.yaml "${K3S_MANIFEST_DIR}/multus.yaml"
80 | }
81 |
82 | createKubeConfig() {
83 | openssl ecparam -name prime256v1 -genkey -noout -out multus.key
84 | openssl req -new -key multus.key -out multus.csr -subj /CN=multus
85 | openssl x509 -req \
86 | -in multus.csr \
87 | -CA "${CA_PATH}/client-ca.crt" \
88 | -CAkey "${CA_PATH}/client-ca.key" \
89 | -CAcreateserial \
90 | -out multus.crt \
91 | -days "${CRT_VALIDITY}"
92 |
93 | cat > "${CNI_CONF_DIR}/multus.d/multus.kubeconfig" < "${CNI_CONF_DIR}/00-multus.conflist" \
120 | --arg namespaceIsolation "${NAMESPACE_ISOLATION}" \
121 | --arg globalNamespaces "${GLOBAL_NAMESPACES}" \
122 | --arg kubeconfig "${CNI_CONF_DIR}/multus.d/multus.kubeconfig" \
123 | '
124 | {
125 | cniVersion: .cniVersion,
126 | name: "multus-cni-network",
127 | plugins: [{
128 | type: "multus",
129 | capabilities: [.plugins[].capabilities] | add,
130 | namespaceIsolation: ($namespaceIsolation == "true"),
131 | globalNamespaces: $globalNamespaces,
132 | kubeconfig: $kubeconfig,
133 | delegates: [.]
134 | }]
135 | }
136 | '
137 |
138 | chmod 600 "${CNI_CONF_DIR}/00-multus.conflist"
139 | }
140 |
141 | readConfig
142 | createDirectories
143 | install
144 | installPlugins
145 | createManifests
146 | createKubeConfig
147 | createConfig
148 |
--------------------------------------------------------------------------------
/nginx/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | FROM scratch
3 | COPY ./run.sh /
4 | COPY ./assets /assets
5 |
--------------------------------------------------------------------------------
/nginx/assets/ingress-nginx.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: ingress-nginx
5 | ---
6 | apiVersion: helm.cattle.io/v1
7 | kind: HelmChart
8 | metadata:
9 | name: ingress-nginx
10 | namespace: ingress-nginx
11 | spec:
12 | repo: https://kubernetes.github.io/ingress-nginx
13 | chart: ingress-nginx
14 | valuesContent: |-
15 | @VALUES@
16 | version: "@VERSION@"
17 | targetNamespace: ingress-nginx
18 |
--------------------------------------------------------------------------------
/nginx/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 | VALUES="{}"
8 | # renovate: depName=ingress-nginx repoUrl=https://kubernetes.github.io/ingress-nginx
9 | VERSION="4.11.3"
10 |
11 | templ() {
12 | local file="$3"
13 | local value="$2"
14 | local sentinel="$1"
15 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
16 | }
17 |
18 | _version=$(kairos-agent config get "nginx.version" | tr -d '\n')
19 | if [ "$_version" != "null" ]; then
20 | VERSION=$_version
21 | fi
22 | _values=$(kairos-agent config get "nginx.values | @json" | tr -d '\n')
23 | # Remove the quotes wrapping the value.
24 | _values=${_values:1:${#_values}-2}
25 | if [ "$_values" != "null" ]; then
26 | VALUES=$_values
27 | fi
28 |
29 | templ "VERSION" "${VERSION}" "assets/ingress-nginx.yaml"
30 | templ "VALUES" "${VALUES}" "assets/ingress-nginx.yaml"
31 |
32 | mkdir -p "${K3S_MANIFEST_DIR}"
33 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
34 |
--------------------------------------------------------------------------------
/openamt/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ghcr.io/kairos-io/openamt:v0.1.0-beta1 as src
2 | FROM scratch
3 |
4 | COPY --from=src /* /
5 | COPY ./run.sh /
6 |
--------------------------------------------------------------------------------
/openamt/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | if [ -n "$(kairos-agent config get amt | head -n1)" ]
6 | then
7 | kairos-agent config get amt | ./agent-provider-amt
8 | fi
9 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": ["config:base"],
4 | "schedule": [
5 | "after 11pm every weekday",
6 | "before 7am every weekday",
7 | "every weekend"
8 | ],
9 | "timezone": "Europe/Brussels",
10 | "packageRules": [
11 | {
12 | "matchUpdateTypes": ["patch"],
13 | "automerge": true
14 | }
15 | ],
16 | "regexManagers": [
17 | {
18 | "fileMatch": ["^Earthfile$", "Dockerfile$"],
19 | "matchStrings": [
20 | "#\\s*renovate:\\s*datasource=(?[^\\s]+)\\s+depName=(?[^\\s]+)(\\s+versioning=(?[^\\s]+))?(\\s+extractVersion=(?[^\\n]+))?(\\s+extractVersionTemplate=(?[^\\n]+))?\\n(ARG|ENV)\\s+([^\\s]+)?VERSION=(?[^\\n]+)(\\n(ARG|ENV)\\s+([^\\s]+)?)"
21 | ],
22 | "versioningTemplate": "{{#if versioning}}{{versioning}}{{else}}semver{{/if}}"
23 | },
24 | {
25 | "fileMatch": ["^earthly\\.(sh|ps1)$"],
26 | "datasourceTemplate": "docker",
27 | "depNameTemplate": "earthly/earthly",
28 | "matchStrings": ["earthly\\/earthly:(?.*?)\\s"],
29 | "versioningTemplate": "semver-coerced"
30 | },
31 | {
32 | "datasourceTemplate": "helm",
33 | "fileMatch": ["^.+/run\\.sh$"],
34 | "matchStrings": [
35 | "#\\s*renovate:\\s*depName=(?.*?)(\\s+repoUrl=(?.*?))?\\s([A-Z0-9_]*)VERSION=\"(?.*?)\"\\s"
36 | ]
37 | },
38 | {
39 | "datasourceTemplate": "helm",
40 | "fileMatch": ["^tests/.+_test\\.go$"],
41 | "matchStrings": [
42 | "//\\s*renovate:\\s*depName=(?.*?)(\\s+repoUrl=(?.*?))?\\s+.*version: \\\\\"(?.*?)\\\\\"\""
43 | ]
44 | }
45 | ],
46 | "ignorePaths": []
47 | }
48 |
--------------------------------------------------------------------------------
/spinkube/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:3.19 AS builder
2 |
3 | ARG spin_operator_version=0.4.0
4 | ARG kwasm_installer_version=0.17.0
5 | ARG cert_manager_version=1.14.5
6 |
7 | RUN apk update && apk add --no-cache helm
8 |
9 | WORKDIR /assets
10 |
11 | # This follows the SpinKube documentation:
12 | # https://www.spinkube.dev/docs/install/installing-with-helm/
13 | RUN < kwasm-operator-${kwasm_installer_version}.yaml
24 |
25 | # Spin Operator CRDs
26 | wget -O spin-operator-${spin_operator_version}.crds.yaml https://github.com/spinkube/spin-operator/releases/download/v${spin_operator_version}/spin-operator.crds.yaml
27 |
28 | # Spin Operator Runtime Class
29 | wget -O spin-operator-${spin_operator_version}.runtime-class.yaml https://github.com/spinkube/spin-operator/releases/download/v${spin_operator_version}/spin-operator.runtime-class.yaml
30 |
31 | # Spin Operator Shim Executor
32 | wget -O spin-operator-${spin_operator_version}.shim-executor.yaml https://github.com/spinkube/spin-operator/releases/download/v${spin_operator_version}/spin-operator.shim-executor.yaml
33 |
34 | # Spin Operator (namespace set in run.sh, as is the wait command)
35 | helm template spin-operator \
36 | --namespace spin-operator \
37 | --version ${spin_operator_version} \
38 | oci://ghcr.io/spinkube/charts/spin-operator \
39 | > spin-operator-${spin_operator_version}.yaml
40 | EOR
41 |
42 | FROM scratch
43 | COPY --from=builder /assets ./assets
44 | COPY run.sh .
--------------------------------------------------------------------------------
/spinkube/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This follows the SpinKube documentation:
4 | # https://www.spinkube.dev/docs/install/installing-with-helm/
5 |
6 | set -ex
7 |
8 | manifest_dir=assets
9 |
10 | spin_operator_version=0.4.0
11 | kwasm_installer_version=0.17.0
12 | cert_manager_version=1.14.5
13 |
14 | _install_cert_manager=$(kairos-agent config get "spinkube.installCertManager" | tr -d '\n')
15 | if [ "$_install_cert_manager" = "true" ]; then
16 | sudo k3s kubectl apply -f "$manifest_dir/cert-manager-$cert_manager_version.yaml"
17 |
18 | # Wait for the various cert-manager resources to be ready before proceeding
19 | sudo k3s kubectl wait --for=condition=available --timeout=300s deployment/cert-manager -n cert-manager
20 | sudo k3s kubectl wait --for=condition=available --timeout=300s deployment/cert-manager-webhook -n cert-manager
21 | sudo k3s kubectl wait --for=condition=available --timeout=300s deployment/cert-manager-cainjector -n cert-manager
22 | fi
23 |
24 | # Check to make sure the kwasm namespace doesn't already exist
25 | if ! sudo k3s kubectl get namespace kwasm > /dev/null 2>&1; then
26 | sudo k3s kubectl create namespace kwasm
27 | fi
28 |
29 | # Check to make sure the spin-operator namespace doesn't already exist
30 | if ! sudo k3s kubectl get namespace spin-operator > /dev/null 2>&1; then
31 | sudo k3s kubectl create namespace spin-operator
32 | fi
33 |
34 | # Install Kwasm Operator
35 | sudo k3s kubectl apply --namespace kwasm -f "$manifest_dir/kwasm-operator-$kwasm_installer_version.yaml"
36 |
37 | # Provision Nodes
38 | sudo k3s kubectl annotate node --all kwasm.sh/kwasm-node=true
39 |
40 | # Install Spin Operator Resources
41 | sudo k3s kubectl apply -f "$manifest_dir/spin-operator-$spin_operator_version.crds.yaml"
42 | sudo k3s kubectl apply -f "$manifest_dir/spin-operator-$spin_operator_version.runtime-class.yaml"
43 | sudo k3s kubectl apply -f "$manifest_dir/spin-operator-$spin_operator_version.shim-executor.yaml"
44 |
45 | # Install Spin Operator
46 | sudo k3s kubectl apply --namespace spin-operator -f "$manifest_dir/spin-operator-$spin_operator_version.yaml"
47 | # Wait for the spin-operator-controller-manager to be ready
48 | sudo k3s kubectl wait --namespace spin-operator --for=condition=available --timeout=300s deployment/spin-operator-controller-manager
--------------------------------------------------------------------------------
/system-upgrade-controller/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine as build
2 | FROM scratch
3 | COPY ./run.sh /
4 | COPY ./assets /assets
5 |
--------------------------------------------------------------------------------
/system-upgrade-controller/assets/system-upgrade-controller.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: system-upgrade
5 | ---
6 | apiVersion: v1
7 | kind: ServiceAccount
8 | metadata:
9 | name: system-upgrade
10 | namespace: system-upgrade
11 | ---
12 | apiVersion: rbac.authorization.k8s.io/v1
13 | kind: ClusterRoleBinding
14 | metadata:
15 | name: system-upgrade
16 | roleRef:
17 | apiGroup: rbac.authorization.k8s.io
18 | kind: ClusterRole
19 | name: cluster-admin
20 | subjects:
21 | - kind: ServiceAccount
22 | name: system-upgrade
23 | namespace: system-upgrade
24 | ---
25 | apiVersion: v1
26 | data:
27 | SYSTEM_UPGRADE_CONTROLLER_DEBUG: "false"
28 | SYSTEM_UPGRADE_CONTROLLER_THREADS: "2"
29 | SYSTEM_UPGRADE_JOB_ACTIVE_DEADLINE_SECONDS: "900"
30 | SYSTEM_UPGRADE_JOB_BACKOFF_LIMIT: "99"
31 | SYSTEM_UPGRADE_JOB_IMAGE_PULL_POLICY: Always
32 | SYSTEM_UPGRADE_JOB_KUBECTL_IMAGE: rancher/kubectl:v1.21.9
33 | SYSTEM_UPGRADE_JOB_PRIVILEGED: "true"
34 | SYSTEM_UPGRADE_JOB_TTL_SECONDS_AFTER_FINISH: "900"
35 | SYSTEM_UPGRADE_PLAN_POLLING_INTERVAL: 15m
36 | kind: ConfigMap
37 | metadata:
38 | name: default-controller-env
39 | namespace: system-upgrade
40 | ---
41 | apiVersion: apps/v1
42 | kind: Deployment
43 | metadata:
44 | name: system-upgrade-controller
45 | namespace: system-upgrade
46 | spec:
47 | selector:
48 | matchLabels:
49 | upgrade.cattle.io/controller: system-upgrade-controller
50 | template:
51 | metadata:
52 | labels:
53 | upgrade.cattle.io/controller: system-upgrade-controller
54 | spec:
55 | affinity:
56 | nodeAffinity:
57 | requiredDuringSchedulingIgnoredDuringExecution:
58 | nodeSelectorTerms:
59 | - matchExpressions:
60 | - key: node-role.kubernetes.io/master
61 | operator: Exists
62 | containers:
63 | - env:
64 | - name: SYSTEM_UPGRADE_CONTROLLER_NAME
65 | valueFrom:
66 | fieldRef:
67 | fieldPath: metadata.labels['upgrade.cattle.io/controller']
68 | - name: SYSTEM_UPGRADE_CONTROLLER_NAMESPACE
69 | valueFrom:
70 | fieldRef:
71 | fieldPath: metadata.namespace
72 | envFrom:
73 | - configMapRef:
74 | name: default-controller-env
75 | image: rancher/system-upgrade-controller:@VERSION@
76 | imagePullPolicy: IfNotPresent
77 | name: system-upgrade-controller
78 | volumeMounts:
79 | - mountPath: /etc/ssl
80 | name: etc-ssl
81 | - mountPath: /etc/pki
82 | name: etc-pki
83 | - mountPath: /etc/ca-certificates
84 | name: etc-ca-certificates
85 | - mountPath: /tmp
86 | name: tmp
87 | serviceAccountName: system-upgrade
88 | tolerations:
89 | - key: CriticalAddonsOnly
90 | operator: Exists
91 | - effect: NoSchedule
92 | key: node-role.kubernetes.io/master
93 | operator: Exists
94 | - effect: NoSchedule
95 | key: node-role.kubernetes.io/controlplane
96 | operator: Exists
97 | - effect: NoSchedule
98 | key: node-role.kubernetes.io/control-plane
99 | operator: Exists
100 | - effect: NoExecute
101 | key: node-role.kubernetes.io/etcd
102 | operator: Exists
103 | volumes:
104 | - hostPath:
105 | path: /etc/ssl
106 | type: Directory
107 | name: etc-ssl
108 | - hostPath:
109 | path: /etc/pki
110 | type: DirectoryOrCreate
111 | name: etc-pki
112 | - hostPath:
113 | path: /etc/ca-certificates
114 | type: DirectoryOrCreate
115 | name: etc-ca-certificates
116 | - emptyDir: {}
117 | name: tmp
--------------------------------------------------------------------------------
/system-upgrade-controller/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | K3S_MANIFEST_DIR=${K3S_MANIFEST_DIR:-/var/lib/rancher/k3s/server/manifests/}
6 |
7 | getConfig() {
8 | local l="$1"
9 | key=$(kairos-agent config get "${l}" | tr -d '\n')
10 | if [ "$key" != "null" ]; then
11 | echo "${key}"
12 | fi
13 | echo
14 | }
15 |
16 | VERSION="v0.10.0"
17 |
18 | templ() {
19 | local file="$3"
20 | local value="$2"
21 | local sentinel="$1"
22 | sed -i "s/@${sentinel}@/${value}/g" "${file}"
23 | }
24 |
25 | readConfig() {
26 | _version=$(getConfig suc.version)
27 | if [ "$_version" != "" ]; then
28 | VERSION=$_version
29 | fi
30 | }
31 |
32 | mkdir -p "${K3S_MANIFEST_DIR}"
33 |
34 | readConfig
35 |
36 | # Copy manifests, and template them
37 | for FILE in assets/*; do
38 | templ "VERSION" "${VERSION}" "${FILE}"
39 | done;
40 |
41 | cp -rf assets/* "${K3S_MANIFEST_DIR}"
42 |
--------------------------------------------------------------------------------
/tests/argocd_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("argocd test", Label("argocd"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("Deploy argocd with default version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "argocd.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | Expect(content).To(MatchRegexp("version: \".*?\""))
26 | })
27 |
28 | It("Specifiy version for argocd", func() {
29 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
30 | argocd:
31 | version: 1`), 0655)
32 | Expect(err).ToNot(HaveOccurred())
33 |
34 | runBundle()
35 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "argocd.yaml"))
36 | content := string(dat)
37 | Expect(err).ToNot(HaveOccurred())
38 | Expect(content).To(ContainSubstring("version: \"1\""))
39 | })
40 |
41 | It("Deploy argocd with default values", func() {
42 | runBundle()
43 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "argocd.yaml"))
44 | content := string(dat)
45 | Expect(err).ToNot(HaveOccurred())
46 | Expect(content).To(ContainSubstring("valuesContent: |-\n {}"))
47 | })
48 |
49 | It("Specifiy installation values for argocd", func() {
50 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
51 | argocd:
52 | values:
53 | installation:
54 | calicoNetwork:
55 | bgp: Disabled
56 | `), 0655)
57 | Expect(err).ToNot(HaveOccurred())
58 |
59 | runBundle()
60 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "argocd.yaml"))
61 | content := string(dat)
62 | Expect(err).ToNot(HaveOccurred())
63 | Expect(content).To(ContainSubstring("valuesContent: |-\n {\"installation\":{\"calicoNetwork\":{\"bgp\":\"Disabled\"}}}"))
64 | })
65 | })
66 |
--------------------------------------------------------------------------------
/tests/calico_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("calico test", Label("calico"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("Deploy calico with default version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "calico.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | // renovate: depName=tigera-operator repoUrl=https://docs.tigera.io/calico/charts
26 | Expect(content).To(ContainSubstring("version: \"v3.28.2\""))
27 | })
28 |
29 | It("Specifiy major version for calico", func() {
30 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
31 | calico:
32 | version: 1`), 0655)
33 | Expect(err).ToNot(HaveOccurred())
34 |
35 | runBundle()
36 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "calico.yaml"))
37 | content := string(dat)
38 | Expect(err).ToNot(HaveOccurred())
39 | Expect(content).To(ContainSubstring("version: \"1\""))
40 | })
41 |
42 | It("Specifiy full version for calico", func() {
43 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
44 | calico:
45 | version: 1.2.3`), 0655)
46 | Expect(err).ToNot(HaveOccurred())
47 |
48 | runBundle()
49 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "calico.yaml"))
50 | content := string(dat)
51 | Expect(err).ToNot(HaveOccurred())
52 | Expect(content).To(ContainSubstring("version: \"1.2.3\""))
53 | })
54 |
55 | It("Deploy calico with default values", func() {
56 | runBundle()
57 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "calico.yaml"))
58 | content := string(dat)
59 | Expect(err).ToNot(HaveOccurred())
60 | Expect(content).To(ContainSubstring("valuesContent: |-\n {}"))
61 | })
62 |
63 | It("Specifiy installation values for calico", func() {
64 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
65 | calico:
66 | values:
67 | installation:
68 | calicoNetwork:
69 | bgp: Disabled
70 | `), 0655)
71 | Expect(err).ToNot(HaveOccurred())
72 |
73 | runBundle()
74 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "calico.yaml"))
75 | content := string(dat)
76 | Expect(err).ToNot(HaveOccurred())
77 | Expect(content).To(ContainSubstring("valuesContent: |-\n {\"installation\":{\"calicoNetwork\":{\"bgp\":\"Disabled\"}}}"))
78 | })
79 | })
80 |
--------------------------------------------------------------------------------
/tests/cert-manager_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("cert-manager test", Label("cert-manager"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("deploys cert-manager operator version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "cert-manager.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | Expect(content).To(ContainSubstring("clusterissuers.cert-manager.io"))
26 | })
27 |
28 | It("Specify version for cert-manager", func() {
29 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
30 | certManager:
31 | version: v1.11.0`), 0655)
32 | Expect(err).ToNot(HaveOccurred())
33 | runBundle()
34 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "cert-manager.yaml"))
35 | content := string(dat)
36 | Expect(err).ToNot(HaveOccurred())
37 | Expect(content).To(ContainSubstring("clusterissuers.cert-manager.io"))
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/tests/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/kairos-io/community-bundles/tests
2 |
3 | go 1.19
4 |
5 | require (
6 | github.com/onsi/ginkgo/v2 v2.20.1
7 | github.com/onsi/gomega v1.34.1
8 | gopkg.in/yaml.v3 v3.0.1
9 | )
10 |
11 | require (
12 | github.com/go-logr/logr v1.4.2 // indirect
13 | github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
14 | github.com/google/go-cmp v0.6.0 // indirect
15 | github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
16 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
17 | golang.org/x/net v0.28.0 // indirect
18 | golang.org/x/sys v0.23.0 // indirect
19 | golang.org/x/text v0.17.0 // indirect
20 | golang.org/x/tools v0.24.0 // indirect
21 | )
22 |
--------------------------------------------------------------------------------
/tests/go.sum:
--------------------------------------------------------------------------------
1 | github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
2 | github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
3 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
4 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
5 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
6 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
7 | github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
8 | github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
9 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
10 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
11 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
12 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
13 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
14 | github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
15 | github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
16 | github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
17 | github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
18 | github.com/onsi/ginkgo/v2 v2.6.1 h1:1xQPCjcqYw/J5LchOcp4/2q/jzJFjiAOc25chhnDw+Q=
19 | github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
20 | github.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw=
21 | github.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
22 | github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo=
23 | github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
24 | github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE=
25 | github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk=
26 | github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
27 | github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
28 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
29 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
30 | golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
31 | golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
32 | golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
33 | golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
34 | golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
35 | golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
36 | golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
37 | golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
38 | golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
39 | golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
40 | golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
41 | golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
42 | golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4=
43 | golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
44 | golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
45 | golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
46 | google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
47 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
48 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
49 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
50 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
51 |
--------------------------------------------------------------------------------
/tests/kairos_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("kairos test", Label("kairos"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("Deploy kairos crds with default version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kairos-crds.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | Expect(content).To(ContainSubstring("version: \"0.0.13\""))
26 | })
27 |
28 | It("Specifiy version for calico", func() {
29 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
30 | kairos:
31 | crds:
32 | version: "magrathea"
33 | osbuilder:
34 | enable: true
35 | version: "foobar"
36 | entangle:
37 | enable: true
38 | version: "baz"
39 | entangleProxy:
40 | enable: true
41 | version: "42.1.1"
42 | `), 0655)
43 | Expect(err).ToNot(HaveOccurred())
44 | runBundle()
45 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kairos-crds.yaml"))
46 | content := string(dat)
47 | Expect(err).ToNot(HaveOccurred())
48 | Expect(content).To(ContainSubstring("version: \"magrathea\""))
49 |
50 | dat, err = os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kairos-osbuilder.yaml"))
51 | content = string(dat)
52 | Expect(err).ToNot(HaveOccurred())
53 | Expect(content).To(ContainSubstring("version: \"foobar\""), content)
54 |
55 | dat, err = os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kairos-entangle.yaml"))
56 | content = string(dat)
57 | Expect(err).ToNot(HaveOccurred())
58 | Expect(content).To(ContainSubstring("version: \"baz\""), content)
59 |
60 | dat, err = os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kairos-entangle-proxy.yaml"))
61 | content = string(dat)
62 | Expect(err).ToNot(HaveOccurred())
63 | Expect(content).To(ContainSubstring("version: \"42.1.1\""), content)
64 | })
65 | })
66 |
--------------------------------------------------------------------------------
/tests/kubevirt_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("kubevirt test", Label("kubevirt"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("deploys kubevirt operator version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kubevirt-operator.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | Expect(content).To(ContainSubstring("quay.io/kubevirt/virt-operator"))
26 | _, err = os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kubevirt-manager-ns.yaml"))
27 | Expect(err).To(HaveOccurred())
28 | })
29 |
30 | It("Add manager", func() {
31 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
32 | kubevirt:
33 | manager: true`), 0655)
34 | Expect(err).ToNot(HaveOccurred())
35 | runBundle()
36 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kubevirt-manager-ns.yaml"))
37 | content := string(dat)
38 | Expect(err).ToNot(HaveOccurred())
39 | Expect(content).To(ContainSubstring("kubevirt-manager.io/version: 1.1.2"))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/tests/kyverno_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("kyverno test", Label("kyverno"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("Deploy kyverno with default version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kyverno.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | Expect(content).To(MatchRegexp("version: \".*?\""))
26 | })
27 |
28 | It("Specifiy version for kyverno", func() {
29 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
30 | kyverno:
31 | version: 1`), 0655)
32 | Expect(err).ToNot(HaveOccurred())
33 |
34 | runBundle()
35 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kyverno.yaml"))
36 | content := string(dat)
37 | Expect(err).ToNot(HaveOccurred())
38 | Expect(content).To(ContainSubstring("version: \"1\""))
39 | })
40 |
41 | It("Deploy kyverno with default values", func() {
42 | runBundle()
43 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kyverno.yaml"))
44 | content := string(dat)
45 | Expect(err).ToNot(HaveOccurred())
46 | Expect(content).To(ContainSubstring("valuesContent: |-\n {}"))
47 | })
48 |
49 | It("Specifiy installation values for kyverno", func() {
50 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
51 | kyverno:
52 | values:
53 | installation:
54 | calicoNetwork:
55 | bgp: Disabled
56 | `), 0655)
57 | Expect(err).ToNot(HaveOccurred())
58 |
59 | runBundle()
60 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "kyverno.yaml"))
61 | content := string(dat)
62 | Expect(err).ToNot(HaveOccurred())
63 | Expect(content).To(ContainSubstring("valuesContent: |-\n {\"installation\":{\"calicoNetwork\":{\"bgp\":\"Disabled\"}}}"))
64 | })
65 | })
66 |
--------------------------------------------------------------------------------
/tests/localai_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("localai test", Label("LocalAI"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("sets default version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "localai.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | // renovate: depName=local-ai repoUrl=https://go-skynet.github.io/helm-charts/
26 | Expect(content).To(MatchRegexp("version: \".*?\""))
27 | })
28 |
29 | It("sets the service type", func() {
30 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
31 | localai:
32 | serviceType: LoadBalancer`), 0655)
33 | Expect(err).ToNot(HaveOccurred())
34 |
35 | runBundle()
36 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "localai.yaml"))
37 | content := string(dat)
38 | Expect(err).ToNot(HaveOccurred())
39 | Expect(content).To(ContainSubstring("type: \"LoadBalancer\""))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/tests/longhorn_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("longhorn test", Label("longhorn"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("Specifiy version for longhorn", func() {
21 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
22 | longhorn:
23 | version: 1`), 0655)
24 | Expect(err).ToNot(HaveOccurred())
25 |
26 | runBundle()
27 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "longhorn.yaml"))
28 | content := string(dat)
29 | Expect(err).ToNot(HaveOccurred())
30 | Expect(content).To(ContainSubstring("version: 1"))
31 | })
32 |
33 | It("Deploy longhorn with default values", func() {
34 | runBundle()
35 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "longhorn.yaml"))
36 | content := string(dat)
37 | Expect(err).ToNot(HaveOccurred())
38 | Expect(content).To(ContainSubstring("valuesContent: |-\n {}"))
39 | })
40 |
41 | It("Specifiy installation values for longhorn", func() {
42 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
43 | longhorn:
44 | values:
45 | defaultSettings:
46 | backupstorePollInterval: 600
47 | `), 0655)
48 | Expect(err).ToNot(HaveOccurred())
49 |
50 | runBundle()
51 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "longhorn.yaml"))
52 | content := string(dat)
53 | Expect(err).ToNot(HaveOccurred())
54 | Expect(content).To(ContainSubstring("valuesContent: |-\n {\"defaultSettings\":{\"backupstorePollInterval\":600}}"))
55 | })
56 | })
57 |
--------------------------------------------------------------------------------
/tests/metallb_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("metallb test", Label("metallb"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("sets default version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "metallb.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | // renovate: depName=metallb repoUrl=https://metallb.github.io/metallb
26 | Expect(content).To(MatchRegexp("version: \".*?\""))
27 | dat, err = os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "addresspool.yaml"))
28 | content = string(dat)
29 | Expect(err).ToNot(HaveOccurred())
30 | Expect(content).To(ContainSubstring("- 192.168.1.10-192.168.1.20"))
31 | })
32 |
33 | It("set version", func() {
34 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
35 | metallb:
36 | version: 1`), 0655)
37 | Expect(err).ToNot(HaveOccurred())
38 |
39 | runBundle()
40 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "metallb.yaml"))
41 | content := string(dat)
42 | Expect(err).ToNot(HaveOccurred())
43 | Expect(content).To(ContainSubstring("version: \"1\""))
44 | })
45 | })
46 |
--------------------------------------------------------------------------------
/tests/multus_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "os"
7 |
8 | . "github.com/onsi/ginkgo/v2"
9 | . "github.com/onsi/gomega"
10 | "gopkg.in/yaml.v3"
11 | )
12 |
13 | var _ = Describe("multus test", Label("multus"), func() {
14 |
15 | BeforeEach(func() {
16 | prepareBundle()
17 | SH("apk add openssl jq")
18 | SH("mkdir -p /opt/cni/bin")
19 | SH("mkdir -p /var/lib/rancher/k3s/data/current/bin")
20 | SH("mkdir -p /var/lib/rancher/k3s/agent/etc/cni/net.d/multus.d")
21 | SH("mkdir -p /var/lib/rancher/k3s/server/tls")
22 | SH(`
23 | cd /var/lib/rancher/k3s/server/tls/ &&
24 | openssl genrsa -out server-ca.key 4096 &&
25 | openssl genrsa -out client-ca.key 4096 &&
26 | openssl req -x509 -new -nodes -sha256 -days 1 -subj /CN=server-ca -key server-ca.key -out server-ca.crt &&
27 | openssl req -x509 -new -nodes -sha256 -days 1 -subj /CN=client-ca -key client-ca.key -out client-ca.crt`)
28 |
29 | err := os.WriteFile("/var/lib/rancher/k3s/agent/etc/cni/net.d/foo.conflist", []byte(`{
30 | "name": "cbr0",
31 | "cniVersion": "1.0.0",
32 | "plugins": [
33 | { "type": "portmap", "capabilities": { "portMappings": true } },
34 | { "type": "bandwidth", "capabilities": { "bandwidth": true } }
35 | ]
36 | }`), 0655)
37 | Expect(err).ToNot(HaveOccurred())
38 | })
39 | AfterEach(func() {
40 | cleanBundle()
41 | SH("rm -rfv /opt/cni")
42 | SH("rm -rfv /var/lib/rancher/k3s/data/current/bin")
43 | SH("rm -rfv /var/lib/rancher/k3s/agent/etc/cni")
44 | SH("rm -rfv /var/lib/rancher/k3s/server/tls")
45 | })
46 |
47 | It("installs multus", func() {
48 | runBundle()
49 | Expect("/var/lib/rancher/k3s/data/current/bin/multus").To(BeARegularFile())
50 | })
51 |
52 | It("installs specified plugins", func() {
53 | err := os.WriteFile("/oem/multus.yaml", []byte(`#cloud-config
54 | multus:
55 | cni_plugins:
56 | - portmap
57 | - macvlan`), 0655)
58 | Expect(err).ToNot(HaveOccurred())
59 |
60 | cfg, _ := SH("kairos-agent config get multus")
61 | fmt.Println(cfg)
62 | runBundle()
63 | Expect("/opt/cni/bin/portmap").To(BeARegularFile())
64 | Expect("/opt/cni/bin/macvlan").To(BeARegularFile())
65 | Expect("/opt/cni/bin/dhcp").ToNot(BeARegularFile())
66 | })
67 |
68 | It("creates manifests", func() {
69 | runBundle()
70 | dat, err := os.ReadFile("/var/lib/rancher/k3s/server/manifests/multus.yaml")
71 | content := string(dat)
72 | Expect(err).ToNot(HaveOccurred())
73 | Expect(content).To(MatchRegexp("(?m)^kind: CustomResourceDefinition$"))
74 | Expect(content).To(MatchRegexp("(?m)^kind: ClusterRole$"))
75 | Expect(content).To(MatchRegexp("(?m)^kind: ClusterRoleBinding$"))
76 | })
77 |
78 | It("creates a kubeconfig", func() {
79 | runBundle()
80 | dat, err := os.ReadFile("/var/lib/rancher/k3s/agent/etc/cni/net.d/multus.d/multus.kubeconfig")
81 | Expect(err).ToNot(HaveOccurred())
82 | err = yaml.Unmarshal(dat, struct{}{})
83 | Expect(err).ToNot(HaveOccurred())
84 | })
85 |
86 | It("wraps an existing config", func() {
87 | runBundle()
88 | dat, err := os.ReadFile("/var/lib/rancher/k3s/agent/etc/cni/net.d/00-multus.conflist")
89 | Expect(err).ToNot(HaveOccurred())
90 |
91 | config := &struct {
92 | CniVersion string
93 | Plugins []struct {
94 | Capabilities map[string]bool
95 | Delegates []struct{ Name string }
96 | }
97 | }{}
98 |
99 | json.Unmarshal(dat, &config)
100 | Expect(config.CniVersion).To(Equal("1.0.0"))
101 | Expect(config.Plugins[0].Capabilities).To(Equal(map[string]bool{
102 | "portMappings": true,
103 | "bandwidth": true,
104 | }))
105 | })
106 | })
107 |
--------------------------------------------------------------------------------
/tests/nginx_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | const (
12 | manifestDir = "/var/lib/rancher/k3s/server/manifests"
13 | manifestFile = "ingress-nginx.yaml"
14 | )
15 |
16 | var _ = Describe("nginx test", Label("nginx"), func() {
17 |
18 | BeforeEach(func() {
19 | prepareBundle()
20 | })
21 | AfterEach(func() {
22 | cleanBundle()
23 | })
24 |
25 | It("sets default version", func() {
26 | runBundle()
27 | dat, err := os.ReadFile(filepath.Join(manifestDir, manifestFile))
28 | content := string(dat)
29 | Expect(err).ToNot(HaveOccurred())
30 | // renovate: depName=ingress-nginx repoUrl=https://kubernetes.github.io/ingress-nginx
31 | Expect(content).To(ContainSubstring("version: \"4.11.3\""))
32 | })
33 |
34 | It("set major version", func() {
35 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
36 | nginx:
37 | version: 1`), 0655)
38 | Expect(err).ToNot(HaveOccurred())
39 |
40 | runBundle()
41 | dat, err := os.ReadFile(filepath.Join(manifestDir, manifestFile))
42 | content := string(dat)
43 | Expect(err).ToNot(HaveOccurred())
44 | Expect(content).To(ContainSubstring("version: \"1\""))
45 | })
46 |
47 | It("set full version", func() {
48 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
49 | nginx:
50 | version: 1.2.3`), 0655)
51 | Expect(err).ToNot(HaveOccurred())
52 |
53 | runBundle()
54 | dat, err := os.ReadFile(filepath.Join(manifestDir, manifestFile))
55 | content := string(dat)
56 | Expect(err).ToNot(HaveOccurred())
57 | Expect(content).To(ContainSubstring("version: \"1.2.3\""))
58 | })
59 |
60 | It("deploy with default values", func() {
61 | runBundle()
62 | dat, err := os.ReadFile(filepath.Join(manifestDir, manifestFile))
63 | content := string(dat)
64 | Expect(err).ToNot(HaveOccurred())
65 | Expect(content).To(ContainSubstring("valuesContent: |-\n {}"))
66 | })
67 |
68 | It("specifiy values", func() {
69 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
70 | nginx:
71 | values:
72 | commonLabels:
73 | myLabel: abc123`), 0655)
74 | Expect(err).ToNot(HaveOccurred())
75 |
76 | runBundle()
77 | dat, err := os.ReadFile(filepath.Join(manifestDir, manifestFile))
78 | content := string(dat)
79 | Expect(err).ToNot(HaveOccurred())
80 | Expect(content).To(ContainSubstring("valuesContent: |-\n {\"commonLabels\":{\"myLabel\":\"abc123\"}}"))
81 | })
82 | })
83 |
--------------------------------------------------------------------------------
/tests/suite_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "os/exec"
7 | "testing"
8 |
9 | . "github.com/onsi/ginkgo/v2"
10 | . "github.com/onsi/gomega"
11 | )
12 |
13 | func SH(c string) (string, error) {
14 | cmd := exec.Command("/bin/sh", "-c", c)
15 | cmd.Env = os.Environ()
16 | o, err := cmd.CombinedOutput()
17 | return string(o), err
18 | }
19 |
20 | func TestSuite(t *testing.T) {
21 | RegisterFailHandler(Fail)
22 | RunSpecs(t, "Kubemedia Test Suite")
23 | }
24 |
25 | func runBundle() {
26 | out, err := SH("cd /bundle && ./run.sh")
27 | fmt.Println(out)
28 | ExpectWithOffset(1, err).ToNot(HaveOccurred(), out)
29 | }
30 |
31 | func prepareBundle() {
32 | SH("cp -rf /bundle /bundle.bak")
33 | SH("mkdir /oem")
34 | }
35 |
36 | func cleanBundle() {
37 | SH("rm -rfv /oem")
38 | SH("rm -rfv /var/lib/rancher/k3s/server/manifests/")
39 | SH("rm -rf /bundle")
40 | SH("cp -rf /bundle.bak /bundle")
41 | }
42 |
--------------------------------------------------------------------------------
/tests/system-upgrade-controller_test.go:
--------------------------------------------------------------------------------
1 | package bundles_test
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 |
7 | . "github.com/onsi/ginkgo/v2"
8 | . "github.com/onsi/gomega"
9 | )
10 |
11 | var _ = Describe("system-upgrade-controller test", Label("system-upgrade-controller"), func() {
12 |
13 | BeforeEach(func() {
14 | prepareBundle()
15 | })
16 | AfterEach(func() {
17 | cleanBundle()
18 | })
19 |
20 | It("deploys default suc operator version", func() {
21 | runBundle()
22 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "system-upgrade-controller.yaml"))
23 | content := string(dat)
24 | Expect(err).ToNot(HaveOccurred())
25 | Expect(content).To(ContainSubstring("rancher/system-upgrade-controller"))
26 | })
27 |
28 | It("Specific version", func() {
29 | err := os.WriteFile("/oem/foo.yaml", []byte(`#cloud-config
30 | suc:
31 | version: foobar`), 0655)
32 | Expect(err).ToNot(HaveOccurred())
33 | runBundle()
34 | dat, err := os.ReadFile(filepath.Join("/var/lib/rancher/k3s/server/manifests", "system-upgrade-controller.yaml"))
35 | content := string(dat)
36 | Expect(err).ToNot(HaveOccurred())
37 | Expect(content).To(ContainSubstring("rancher/system-upgrade-controller:foobar"))
38 | })
39 | })
40 |
--------------------------------------------------------------------------------